Marko v3: Better handling of escaping for custom tags input

This commit is contained in:
Patrick Steele-Idem 2016-01-11 13:15:26 -07:00
parent 5d123c2013
commit 294c6335be
16 changed files with 66 additions and 64 deletions

View File

@ -288,7 +288,11 @@ class Generator {
let startPos = this._code.length; let startPos = this._code.length;
this.generateCode(node); if (Array.isArray(node) || (node instanceof Container)) {
this.generateStatements(node);
} else {
this.generateCode(node);
}
if (this._code.length === startPos) { if (this._code.length === startPos) {
// No code was generated. Remove any code that was previously added // No code was generated. Remove any code that was previously added

View File

@ -38,7 +38,7 @@ class CompileError {
pos = ''; pos = '';
} }
var str = pos + this.message; var str = pos + this.message;
if (this.node) { if (pos == null && this.node) {
str += ' (' + this.node.toString() + ')'; str += ' (' + this.node.toString() + ')';
} }
return str; return str;

View File

@ -20,9 +20,9 @@ class HtmlJsParser {
onattributeplaceholder(event) { onattributeplaceholder(event) {
// placeholder within attribute // placeholder within attribute
if (event.escape) { if (event.escape) {
event.expression = 'escapeXml(' + event.expression + ')'; event.expression = '$escapeXml(' + event.expression + ')';
} else { } else {
event.expression = 'noEscapeXml(' + event.expression + ')'; event.expression = '$noEscapeXml(' + event.expression + ')';
} }
}, },

View File

@ -3,6 +3,7 @@
var HtmlElement = require('./HtmlElement'); var HtmlElement = require('./HtmlElement');
var path = require('path'); var path = require('path');
var removeDashes = require('../util/removeDashes'); var removeDashes = require('../util/removeDashes');
var removeEscapeFunctions = require('../util/removeEscapeFunctions');
function removeExt(filename) { function removeExt(filename) {
var ext = path.extname(filename); var ext = path.extname(filename);
@ -20,6 +21,11 @@ function buildInputProps(node, context) {
var attrName = attr.name; var attrName = attr.name;
var attrDef = attr.def || context.taglibLookup.getAttribute(node.tagName, attr.name); var attrDef = attr.def || context.taglibLookup.getAttribute(node.tagName, attr.name);
var attrValue = removeEscapeFunctions(attr.value);
if (!attrDef) {
return; // Skip over attributes that are not supported
}
var propName; var propName;
var parentPropName; var parentPropName;
@ -52,9 +58,9 @@ function buildInputProps(node, context) {
if (parentPropName) { if (parentPropName) {
let parent = inputProps[parentPropName] = (inputProps[parentPropName] = {}); let parent = inputProps[parentPropName] = (inputProps[parentPropName] = {});
parent[propName] = attr.value; parent[propName] = attrValue;
} else { } else {
inputProps[propName] = attr.value; inputProps[propName] = attrValue;
} }
}); });

View File

@ -9,7 +9,7 @@ class FunctionCall extends Node {
this.callee = def.callee; this.callee = def.callee;
ok(this.callee, '"callee" is required'); ok(this.callee, '"callee" is required');
this.args = def.args; this.args = def.args;
if (this.args && !Array.isArray(this.args)) { if (this.args && !Array.isArray(this.args)) {

View File

@ -3,8 +3,8 @@ var Node = require('./Node');
var Literal = require('./Literal'); var Literal = require('./Literal');
var ok = require('assert').ok; var ok = require('assert').ok;
var escapeXmlAttr = require('raptor-util/escapeXml').attr; var escapeXmlAttr = require('raptor-util/escapeXml').attr;
var compiler = require('../');
var parseExpression = require('../util/parseExpression'); var parseExpression = require('../util/parseExpression');
var removeEscapeFunctions = require('../util/removeEscapeFunctions');
function isStringLiteral(node) { function isStringLiteral(node) {
return node.type === 'Literal' && typeof node.value === 'string'; return node.type === 'Literal' && typeof node.value === 'string';
@ -13,18 +13,12 @@ function isStringLiteral(node) {
function isNoEscapeXml(node) { function isNoEscapeXml(node) {
return node.type === 'FunctionCall' && return node.type === 'FunctionCall' &&
node.callee.type === 'Identifier' && node.callee.type === 'Identifier' &&
node.callee.name === 'noEscapeXml'; node.callee.name === '$noEscapeXml';
}
function isEscapeXml(node) {
return node.type === 'FunctionCall' &&
node.callee.type === 'Identifier' &&
node.callee.name === 'escapeXml';
} }
function isStringExpression(node) { function isStringExpression(node) {
return node.type === 'FunctionCall' && node.callee.type === 'Identifier' && return node.type === 'FunctionCall' && node.callee.type === 'Identifier' &&
(node.callee.name === 'noEscapeXml' || node.callee.name === 'escapeXml'); (node.callee.name === '$noEscapeXml' || node.callee.name === '$escapeXml');
} }
function flattenAttrConcats(node) { function flattenAttrConcats(node) {
@ -61,33 +55,6 @@ function flattenAttrConcats(node) {
return final.concats; return final.concats;
} }
// function handleEscaping(node) {
//
// function handleEscapingHelper(node, escaping) {
// if (node.type === 'Literal') {
// } else if (isEscapeXml(node)) {
// return handleEscapingHelper(node.arguments[0], true);
// } else if (isNoEscapeXml(node)) {
// return handleEscapingHelper(node.arguments[0], escaping false);
// }
// }
//
// var finalNode = handleEscapingHelper(node, true /* default to escaping */);
// return finalNode;
// }
function removeEscapeFunctions(node) {
var walker = compiler.createWalker({
enter: function(node, parent) {
if (isNoEscapeXml(node) || isEscapeXml(node)) {
return node.args[0];
}
}
});
return walker.walk(node);
}
function generateCodeForExpressionAttr(name, value, codegen) { function generateCodeForExpressionAttr(name, value, codegen) {
var flattenedConcats = flattenAttrConcats(value); var flattenedConcats = flattenAttrConcats(value);
var hasLiteral = false; var hasLiteral = false;

View File

@ -157,9 +157,11 @@ class HtmlElement extends Node {
if (openTagOnly) { if (openTagOnly) {
codegen.generateCode(startTag); codegen.generateCode(startTag);
} else { } else {
codegen.generateCode(startTag); return [
codegen.generateCode(body); startTag,
codegen.generateCode(endTag); body,
endTag
];
} }
} }
} }

View File

@ -0,0 +1,17 @@
var compiler = require('../');
function removeEscapeFunctions(node) {
var walker = compiler.createWalker({
enter: function(node, parent) {
if (node.type === 'FunctionCall' &&
node.callee.type === 'Identifier' &&
(node.callee.name === '$noEscapeXml' || node.callee.name === '$escapeXml')) {
return node.args[0];
}
}
});
return walker.walk(node);
}
module.exports = removeEscapeFunctions;

View File

@ -1 +0,0 @@
<ul><li>Hello world! adult=false</li><li>Hello universe! adult=true</li><li>Hello Dynamic: universe! adult=false</li></ul>

View File

@ -1,13 +0,0 @@
<var name="dynamic" value="data.dynamic"/>
<ul>
<li>
<test-simpleHello name="world"/>
</li>
<li>
<test-simpleHello name="${dynamic}" adult="true"/>
</li>
<li>
<test-simpleHello name="Dynamic: ${dynamic}" adult="false"/>
</li>
</ul>

View File

@ -1,3 +0,0 @@
exports.templateData = {
"dynamic": "universe"
};

View File

@ -0,0 +1 @@
<ul><li>Hello <World>!</li><li>Hello <Frank>! (adult)</li><li>Hello Foo <Frank>! (child)</li></ul>

View File

@ -0,0 +1,13 @@
<var dynamic='<Frank>'/>
<ul>
<li>
<test-hello name="<World>"/>
</li>
<li>
<test-hello name="${dynamic}" adult=true/>
</li>
<li>
<test-hello name="Foo ${dynamic}" adult=false/>
</li>
</ul>

View File

@ -0,0 +1 @@
exports.templateData = {};

View File

@ -1,4 +1,5 @@
{ {
"renderer": "./renderer.js", "renderer": "./renderer.js",
"@name": "string" "@name": "string",
"@adult": "boolean"
} }

View File

@ -1,7 +1,14 @@
exports.render = function(input, out) { exports.render = function(input, out) {
out.write('Hello ' + input.name + '!'); out.write('Hello ' + input.name + '!');
if (input.adult === true) {
out.write(' (adult)');
} else if (input.adult === false) {
out.write(' (child)');
}
if (input.renderBody) { if (input.renderBody) {
out.write(' BODY: '); out.write(' BODY: ');
input.renderBody(out); input.renderBody(out);
} }
}; };