Trying to make a minimal version #152
Answered
by
brianjenkins94
brianjenkins94
asked this question in
Q&A
Replies: 1 comment
-
// TODO: Rewrite this using the regex sticky flag
function parse(template) {
template = template
.replace(/(?<!:)\/\/.*?$/gmu, "") // comments
.replace(/\\/gu, "\\\\") // backslashes
.replace(/"/gu, "\\\"") // double quotes
.replace(/`/gu, "\\`") // backticks
.replace(/\$\{/gu, "\\${"); // substitutions
const buffer = [];
const openTagRegex = /(.*?)<%\s*(=|-)?\s*/gsu;
const closeTagRegex = /'|"|`|\/\*|(\s*%>)/gu;
let index = 0;
let match;
while (match = openTagRegex.exec(template)) {
index = match[0].length + match.index;
const prefix = match[2] ?? "";
buffer.push(match[1]);
closeTagRegex.lastIndex = index;
let closeTag;
while (closeTag = closeTagRegex.exec(template)) {
if (closeTag[1] !== undefined) {
const value = template.substring(index, closeTag.index);
index = closeTagRegex.lastIndex;
openTagRegex.lastIndex = index;
buffer.push({
"type": {
"": "execute",
"-": "raw",
"=": "interpolate"
}[prefix],
"value": value
});
break;
}
}
}
if (index < template.length) {
buffer.push(template.substring(index));
}
return buffer;
}
function compile(nodes) {
const buffer = ["const buffer = [];"];
for (const node of nodes) {
if (typeof node === "string") {
buffer.push("buffer.push(`" + node + "`);");
} else {
let { type, value } = node;
switch (type) {
case "interpolate":
if (/[&<>"']/gu.test(value)) {
value = value.replace(/[&<>"']/gu, function(character) {
return {
"&": "&",
"<": "<",
">": ">",
"\"": """,
"'": "'"
}[character];
});
}
case "raw":
buffer.push("buffer.push(`" + value + "`);");
break;
case "execute":
buffer.push(value);
break;
default:
}
}
}
buffer.push("return buffer.join(\"\\n\");");
return buffer.join("\n");
}
function render(template, data = {}) {
// eslint-disable-next-line no-new-func, @typescript-eslint/no-implied-eval
return new Function(...Object.keys(data), compile(parse(template)))(...Object.values(data));
}
console.log(render("<%= foo %>\n<%= bar %>\n<%= baz %>\n<%= 2 + 2 %>\n<%- \"<br />\" %>", {
"foo": "bar",
"bar": "baz",
"baz": "foo"
})); |
Beta Was this translation helpful? Give feedback.
0 replies
Answer selected by
brianjenkins94
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
But I can't make sense of this:
https://github.com/eta-dev/eta/blob/master/src/compile-string.ts#L25-L41
Beta Was this translation helpful? Give feedback.
All reactions