aemfed
Version:
Upload front-end changes into AEM, refresh relevant resources in the page and get instant notifications from the error.log, all for easier and faster development.
241 lines (240 loc) • 9.86 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = __importDefault(require("fs"));
const less_tree_1 = __importDefault(require("less-tree"));
const path_1 = __importDefault(require("path"));
const recursive_readdir_1 = __importDefault(require("recursive-readdir"));
const tree_model_1 = __importDefault(require("tree-model"));
class StyleTree {
constructor(relativeJcrPath) {
this.tree = new tree_model_1.default();
this.jcrRootDir = path_1.default.resolve(relativeJcrPath);
}
init() {
const model = {
children: [],
filePath: "",
id: "",
isMissing: false,
type: "root"
};
const sw = Date.now();
return new Promise((resolve, reject) => {
recursive_readdir_1.default(this.jcrRootDir, (err, files) => {
console.log("Read file tree: " + (Date.now() - sw) + " ms");
if (err) {
reject(err);
return;
}
let swInner = Date.now();
const rootFilesRegex = /((css|js)\.txt|(\.content\.xml))$/i;
const contentXmlFilesRelative = [];
const jsTxtFilesRelative = [];
const cssTxtFilesRelative = [];
const otherFilesRelative = [];
files.forEach(filePath => {
const filePathRelative = path_1.default.relative(this.jcrRootDir, filePath);
let match;
if ((match = rootFilesRegex.exec(filePathRelative)) !== null) {
if (match[3]) {
contentXmlFilesRelative.push(filePathRelative);
}
else if (match[2] === "css") {
cssTxtFilesRelative.push(filePathRelative);
}
else if (match[2] === "js") {
jsTxtFilesRelative.push(filePathRelative);
}
else {
otherFilesRelative.push(filePathRelative);
}
}
});
swInner = Date.now();
cssTxtFilesRelative.forEach(cssTxtFileRelative => {
const contentFileRelative = path_1.default.join(path_1.default.dirname(cssTxtFileRelative), ".content.xml");
if (contentXmlFilesRelative.indexOf(contentFileRelative) === -1) {
return;
}
const cssTxtModel = this.getCssTxtModel(cssTxtFileRelative);
model.children.push(cssTxtModel);
});
swInner = Date.now();
this.rootNode = this.tree.parse(model);
console.log("Build style tree: " + (Date.now() - sw) + " ms");
resolve();
});
});
}
findClientlibs(filePathRelative) {
return this.findClientlibsInternal(this.rootNode, filePathRelative);
}
getCssTxtModel(cssTxtFileRelative) {
const basePathRelative = path_1.default.dirname(cssTxtFileRelative);
const cssTxtModel = {
children: [],
filePath: cssTxtFileRelative,
id: cssTxtFileRelative,
isMissing: false,
type: "csstxt"
};
try {
const contents = fs_1.default.readFileSync(path_1.default.join(this.jcrRootDir, cssTxtFileRelative), "utf8");
const arrayOfLines = contents.match(/[^\r\n]+/g);
if (arrayOfLines && arrayOfLines.length > 0) {
let prefix = "";
arrayOfLines.forEach((line) => {
const baseMatch = /#base=(.*)/.exec(line);
if (baseMatch !== null) {
prefix = baseMatch[1];
}
else {
const sourceLine = line.trim();
if (sourceLine.indexOf("//") !== 0) {
const sourceFileRelative = path_1.default.isAbsolute(sourceLine)
? path_1.default.relative(path_1.default.sep, sourceLine)
: path_1.default.join(basePathRelative, prefix, sourceLine);
const sourceModel = this.getSourceModel(sourceFileRelative);
cssTxtModel.children.push(sourceModel);
}
}
});
}
else {
}
}
catch (err) {
cssTxtModel.isMissing = true;
}
return cssTxtModel;
}
getSourceModel(sourceFileRelative) {
sourceFileRelative = path_1.default.normalize(sourceFileRelative);
const sourceModel = {
children: [],
filePath: sourceFileRelative,
id: sourceFileRelative,
isMissing: false,
type: "source"
};
if (path_1.default.extname(sourceFileRelative) === ".less") {
sourceModel.type = "less";
const newLessTree = this._getLessTree(sourceFileRelative);
const importModels = this.lessTree2Model(newLessTree);
sourceModel.children = importModels.children;
sourceModel.isMissing = importModels.isMissing;
}
return sourceModel;
}
lessTree2Model(newLessTree) {
const filePathRelative = path_1.default.relative(this.jcrRootDir, newLessTree.path);
const model = {
children: [],
filePath: filePathRelative,
id: filePathRelative,
isMissing: !newLessTree.contents,
type: "less-import"
};
if (newLessTree.children) {
newLessTree.children.forEach(child => {
const childModel = this.lessTree2Model(child);
model.children.push(childModel);
});
}
return model;
}
findClientlibsInternal(rootNode, filePathRelative) {
let pathIndex;
(function (pathIndex) {
pathIndex[pathIndex["root"] = 0] = "root";
pathIndex[pathIndex["clientlib"] = 1] = "clientlib";
pathIndex[pathIndex["less"] = 2] = "less";
pathIndex[pathIndex["import"] = 3] = "import";
})(pathIndex || (pathIndex = {}));
const sw = Date.now();
this._getLessTree("", true);
const clientlibCssPathsRelative = [];
const nodes = rootNode.all(node => node.model.filePath === filePathRelative);
nodes.forEach(node => {
const nodePath = node.getPath();
if (nodePath && nodePath.length > pathIndex.clientlib) {
const clientlibNode = nodePath[pathIndex.clientlib];
const clientlibCss = path_1.default.dirname(clientlibNode.model.filePath) + ".css";
if (clientlibCssPathsRelative.indexOf(clientlibCss) === -1) {
clientlibCssPathsRelative.push(clientlibCss);
}
}
if (node.hasChildren() || node.model.isMissing) {
this.updateClientlibs(rootNode, node);
}
});
if (nodes.length === 0 && path_1.default.basename(filePathRelative) === "css.txt") {
console.log("Missing css.txt, so add", filePathRelative);
this.updateClientlibs(rootNode, filePathRelative);
}
return clientlibCssPathsRelative;
}
updateClientlibs(rootNode, node) {
let newModel;
if (typeof node === "string") {
if (path_1.default.basename(node) === "css.txt") {
console.log("updateClientlibs add new csstxt");
newModel = this.getCssTxtModel(node);
}
}
else {
if (["less", "less-import"].indexOf(node.model.type) > -1) {
newModel = this.getSourceModel(node.model.filePath);
}
else if (["csstxt"].indexOf(node.model.type) > -1) {
console.log("updateClientlibs csstxt");
newModel = this.getCssTxtModel(node.model.filePath);
}
}
if (newModel) {
const newNode = this.tree.parse(newModel);
if (typeof node === "string") {
rootNode.addChild(newNode);
}
else {
const parentNode = node.parent;
const index = node.getIndex();
node.drop();
if (parentNode) {
parentNode.addChildAtIndex(newNode, index);
}
}
return newModel;
}
}
copyFileSync(srcFile, destFile) {
let BUF_LENGTH;
let buff;
let bytesRead;
let fdr;
let fdw;
let pos;
BUF_LENGTH = 64 * 1024;
buff = new Buffer(BUF_LENGTH);
fdr = fs_1.default.openSync(srcFile, "r");
fdw = fs_1.default.openSync(destFile, "w");
bytesRead = 1;
pos = 0;
while (bytesRead > 0) {
bytesRead = fs_1.default.readSync(fdr, buff, 0, BUF_LENGTH, pos);
fs_1.default.writeSync(fdw, buff, 0, bytesRead);
pos += bytesRead;
}
fs_1.default.closeSync(fdr);
return fs_1.default.closeSync(fdw);
}
_getLessTree(fileRelative, resetCache) {
resetCache = !!resetCache;
const tree = less_tree_1.default(path_1.default.join(this.jcrRootDir, fileRelative), this.jcrRootDir, resetCache);
return tree;
}
}
exports.StyleTree = StyleTree;