Skip to content

Commit

Permalink
Code execution in templates
Browse files Browse the repository at this point in the history
  • Loading branch information
CMEONE committed Mar 12, 2021
1 parent fc65c57 commit 6c14e79
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 17 deletions.
1 change: 1 addition & 0 deletions example/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ tApp.route("#/template", function(request) {
statement5: 6,
statement6: 8,
statement7: 7,
testVal: 10
});
});

Expand Down
5 changes: 5 additions & 0 deletions example/views/template.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ <h3>{{list.header}}</h3>
<li>{{list.elements.1}}</li>
<li>{{list.elements.2}}</li>
</ul>
<p>1 + 1 = {{{ 1 + 1 }}} ({{\{ 1 + 1 }}})</p>
<p>10 + 5 = {{{ testVal += 3; testVal + 2; }}} ({{\{ testVal += 3; testVal + 2; }}})</p>
<p>10 + 3 = {{{ testVal }}} ({{\{ testVal }}})</p>
<p>testVal before: {{ testVal }} ({\{ testVal }}, notice how these values in {\{ }} are pre-rendered safely before code execution)</p>
<p>testVal after: {{{ testVal }}} ({{\{ testVal }}})</p>
<p>More if statements (using {\% if %}):</p>
<p>If, else if, else if, else</p>
{% if statement == 0 %}
Expand Down
76 changes: 59 additions & 17 deletions tApp.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class tApp {
static database;
static currentHash = "/";
static get version() {
return "v0.8.10";
return "v0.8.11";
}
static configure(params) {
if(params == null) {
Expand Down Expand Up @@ -361,6 +361,37 @@ class tApp {
});
});
}
static eval(code) {
return (function(code) {
return eval(code);
})(code);
}
static optionsToEval(data) {
let evalStr = "";
let keys = Object.keys(data);
for(let i = 0; i < keys.length; i++) {
try {
evalStr += "let " + keys[i] + " = " + JSON.stringify(data[keys[i]]) + ";";
} catch(err) {
evalStr += "let " + keys[i] + " = " + data[keys[i]] + ";";
}
}
return evalStr;
}
static restoreOptions(data) {
let evalStr = "let _____returnOptions = {};";
let keys = Object.keys(data);
for(let i = 0; i < keys.length; i++) {
evalStr += "_____returnOptions." + keys[i] + " = " + keys[i] + ";";
}
return evalStr;
}
static evalInContext(code, data) {
if(data == null) {
data = {};
}
return tApp.eval(tApp.optionsToEval(data) + "let _____result = (function() {return eval(\"" + code.replaceAll("\"", "\\\"") + "\")})();" + tApp.restoreOptions(data) + "[_____result, _____returnOptions]");
}
static templateToHTML(html, options) {
function convertTemplate(template, parameters, prefix) {
let keys = Object.keys(parameters);
Expand Down Expand Up @@ -395,20 +426,11 @@ class tApp {
returnStr = returnStr.substring(0, index + 1);
return returnStr;
}
function optionsToEval(data) {
let evalStr = "";
let keys = Object.keys(data);
for(let i = 0; i < keys.length; i++) {
try {
evalStr += "let " + keys[i] + " = " + JSON.stringify(data[keys[i]]) + ";";
} catch(err) {
evalStr += "let " + keys[i] + " = " + data[keys[i]] + ";";
}
}
return evalStr;
}
html = html.replaceAll("{{\\{", "{{\\\\{");
html = html.replaceAll("{{{", "{{\\{");
html = convertTemplate(html, options, "");
html = html.replaceAll("{\\{", "{{");
html = html.replaceAll("{\\\\{", "{\\{");
let splitLines = html.split("\n");
let tokenStack = [];
let stateStack = [];
Expand All @@ -424,14 +446,14 @@ class tApp {
tokenStack.push("IF");
let condition = trim(parsedStatement.substring(2));
stateStack.push({
result: eval(optionsToEval(options) + condition)
result: tApp.eval(tApp.optionsToEval(options) + condition)
});
stateStack[stateStack.length - 1].executed = stateStack[stateStack.length - 1].result;
} else if(["elseif ", "elseif\t", "elseif("].includes(parsedStatement.substring(0, 7))) {
if(tokenStack[tokenStack.length - 1] == "IF") {
if(!stateStack[stateStack.length - 1].executed) {
let condition = trim(parsedStatement.substring(6));
stateStack[stateStack.length - 1].result = eval(optionsToEval(options) + condition);
stateStack[stateStack.length - 1].result = tApp.eval(tApp.optionsToEval(options) + condition);
stateStack[stateStack.length - 1].executed = stateStack[stateStack.length - 1].result;
} else {
stateStack[stateStack.length - 1].result = false;
Expand All @@ -448,12 +470,32 @@ class tApp {
}
}
} else if(tokenStack[tokenStack.length - 1] == "IF" && stateStack[stateStack.length - 1].result) {
newHTML += splitLines[i] + "\n";
let newRes = splitLines[i];
let it = newRes.matchAll(new RegExp("{{{[\\s|\\t]*(.+?(?=}}}))[\\s|\\t]*}}}", "g"));
let next = it.next();
while(!next.done) {
console.log(next.value[1]);
let contextEval = tApp.evalInContext(trim(next.value[1]), options);
options = contextEval[1];
newRes = newRes.replace(next.value[0], contextEval[0]);
next = it.next();
}
newHTML += newRes + "\n";
} else if(tokenStack[tokenStack.length - 1] == null) {
newHTML += splitLines[i] + "\n";
let newRes = splitLines[i];
let it = newRes.matchAll(new RegExp("{{{[\\s|\\t]*(.+?(?=}}}))[\\s|\\t]*}}}", "g"));
let next = it.next();
while(!next.done) {
let contextEval = tApp.evalInContext(trim(next.value[1]), options);
options = contextEval[1];
newRes = newRes.replace(next.value[0], contextEval[0]);
next = it.next();
}
newHTML += newRes + "\n";
}
}
newHTML = newHTML.replaceAll("{\\%", "{%");
newHTML = newHTML.replaceAll("{{\\{", "{{{");
return newHTML;
}
static renderTemplateHTML(html, options) {
Expand Down

0 comments on commit 6c14e79

Please sign in to comment.