ceri-compiler
Version:
compiles template strings for ceriJS
167 lines (156 loc) • 4.44 kB
JavaScript
var camelize, htmlparser, marker, parseAttr, parseDirective, spliceStr, templateArgs;
htmlparser = require("htmlparser2");
marker = "####";
camelize = (str) => {
return str.replace(/-(\w)/g, (_, c) => {
if (c) {
return c.toUpperCase();
} else {
return '';
}
});
};
spliceStr = (str, index, count, add) => {
if (index < 0) {
index = str.length + index;
if (index < 0) {
index = 0;
}
}
return str.slice(0, index) + (add || "") + str.slice(index + count);
};
templateArgs = [];
templateArgs.toArg = (depth, nr) => {
return String.fromCharCode(96 + nr) + (depth ? String.fromCharCode(96 + depth) : "");
};
templateArgs.toArgs = (tmp) => {
var arr, i;
if ((i = tmp.args) != null) {
arr = [];
while (i) {
arr.unshift(templateArgs.toArg(tmp.depth, i--));
}
}
return arr;
};
parseAttr = require("./compile1_parseAttr")(camelize, spliceStr, marker, templateArgs);
parseDirective = require("./compile1_parseDirective")(camelize, marker);
module.exports = (template) => {
var addOptions, currentLevel, lastLevel, options, parseTemplateArgs, parser, result, wasTemplate;
result = "function(){return [";
parseTemplateArgs = (args) => {
var arr;
if ((arr = templateArgs.toArgs(args)) != null) {
return result = spliceStr(result, args.position, 0, arr.join(','));
}
};
templateArgs.push({
position: 9
});
lastLevel = 0;
currentLevel = 0;
wasTemplate = false;
options = [];
addOptions = (bracket) => {
var opt;
if (options.length > 0) {
opt = options.pop();
if (opt) {
result += `${JSON.stringify(opt)},`;
} else {
result += "null,";
}
if (bracket) {
return result += "[";
}
}
};
parser = new htmlparser.Parser({
onopentag: (name, attr) => {
var sep;
if (parseDirective(name, attr, options)) {
return;
}
currentLevel++;
if (currentLevel === lastLevel) {
sep = ",";
} else {
addOptions(name !== "template");
sep = "";
}
if (name === "slot") {
name = attr.name;
if (name == null) {
name = "default";
}
return result += `${sep}\"${name}\"`;
} else if (name === "template") {
result += "function(){return [";
return templateArgs.push({
position: result.length - 10,
depth: templateArgs.length
});
} else {
options.push(parseAttr(attr));
return result += `${sep}this.el(\"${name}\",`;
}
},
ontext: (txt) => {
var base, base1, opt;
if (options.length > 0 && txt.trim()) {
opt = options[options.length - 1];
if (opt == null) {
opt = {};
}
if (opt.text == null) {
opt.text = {};
}
if (txt.indexOf("{{") > -1) {
txt = txt.replace(/{{/g, "\"+(").replace(/}}/g, ")+\"");
if ((base = opt.text)[":"] == null) {
base[":"] = `${marker}function(){return \"${txt}\";}${marker}`.replace(/\+""/g, "").replace(/""\+/g, "");
}
} else {
if ((base1 = opt.text)["#"] == null) {
base1["#"] = txt;
}
}
return options[options.length - 1] = opt;
}
},
onclosetag: (name) => {
if (parseDirective(name)) {
return;
}
addOptions(true);
lastLevel = currentLevel;
currentLevel--;
if (name === "template") {
result += "]})";
wasTemplate = true;
return parseTemplateArgs(templateArgs.pop());
} else {
if (wasTemplate) {
return wasTemplate = false;
} else if (name !== "slot") {
return result += "])";
}
}
}
});
parser.write(template);
parser.end();
result += "]}";
parseTemplateArgs(templateArgs.pop());
// unescape marked function
result = result.replace(new RegExp(`\"${marker}(.*?)${marker}\"`, "g"), (a, b) => {
var m;
if (((m = b.match(/return/g)) != null) && m.length > 1) { // remove default return if one is used in expression
b = b.replace(/function\(\)\{return /, "function(){");
}
return b.replace(/\\"/g, "\"").replace(/[^\\]@/g, (a) => { // unescape qoutes
return a.replace("@", "this."); // replace unescaped @ by this.
}).replace(/\\\\@/g, "@"); // replace escaped @
});
return result;
};