Template literal print fixes (#1188)

* when writing a TemplateLiteral, it should not transpile unless generated

* proper escaping for template literals

* add printing test for TemplateLiteral node
This commit is contained in:
Michael Rawlings 2018-12-10 17:01:19 -08:00 committed by GitHub
parent a52b5c6cbe
commit 37e0c912ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 108 additions and 26 deletions

View File

@ -30,7 +30,10 @@ class HtmlJsParser {
if (part.type === "placeholder") {
value += "${" + part.value + "}";
} else {
value += part.replace(/`/g, "\\`");
value += part.replace(
/`|\\|\${/g,
match => "\\" + match
);
}
});
event.value = "$nonstandard`" + value + "`";

View File

@ -36,13 +36,19 @@ module.exports = function(node, codegen, vdomUtil) {
var body = codegen.generateCode(node.body);
var tagName = codegen.generateCode(node.tagNameExpression);
var attributes = codegen.generateCode(node.getAttributes());
var properties = codegen.generateCode(node.getProperties());
var dynamicAttributes = codegen.generateCode(node.dynamicAttributes);
var key = node.key;
var key = codegen.generateCode(node.key);
var properties = node.getProperties();
var isAutoKeyed = node.isAutoKeyed;
var runtimeFlags = node.runtimeFlags;
var nextConstId = node.nextConstId;
if (properties) {
Object.keys(properties).forEach(
key => (properties[key] = codegen.generateCode(properties[key]))
);
}
var builder = codegen.builder;
var isKeyStatic = vdomUtil.isStaticValue(key);

View File

@ -38,35 +38,39 @@ class TemplateLiteral extends Node {
}
writeCode(writer) {
for (let i = 0; i <= this.quasis.length; i++) {
const quasi = this.quasis[i];
const expr = this.expressions[i];
if (quasi || i === 0) {
if (i > 0) writer.write("+");
writer.write(JSON.stringify(quasi));
}
if (expr) {
writer.write("+");
writer.write("(");
writer.write(expr);
writer.write(")");
}
}
writer.write("\n");
}
toString() {
let code = "";
let quote = this.nonstandard ? '"' : "`";
let escape = new RegExp(quote, "g");
for (let i = 0; i <= this.quasis.length; i++) {
const quasi = this.quasis[i];
const expr = this.expressions[i];
if (quasi) code += quasi.replace(escape, `\\${quote}`);
if (quasi) code += escapeQuasi(quasi, quote);
if (expr) code += "${" + expr.toString() + "}";
}
return quote + code + quote;
writer.write(quote + code + quote);
writer.write("\n");
}
}
function escapeQuasi(quasi, quote) {
if (!quasi) return "";
return quasi.replace(/["`\\\n\r\u2028\u2029]|\${/g, match => {
switch (match) {
case quote:
case "${":
case "\\":
return "\\" + match;
case "\n":
return "\\n";
case "\r":
return "\\r";
case "\u2028":
return "\\u2028";
case "\u2029":
return "\\u2029";
default:
return match;
}
});
}
module.exports = TemplateLiteral;

View File

@ -24,7 +24,12 @@ module.exports = function migrator(elNode, context) {
value:
attr.value == null
? attr.name
: `${attr.name} = ${printJS(attr.value, context)}`
: `${attr.name} = ${printJS(
attr.value,
context,
null,
true
)}`
})
);
});

View File

@ -1,6 +1,9 @@
const CodeWriter = require("../../../compiler/CodeWriter");
const CodeGenerator = require("../../../compiler/CodeGenerator");
module.exports = function(node, context, options) {
const codeGenerator = new CodeGenerator(context);
node = codeGenerator.generateCode(node);
const writer = new CodeWriter(
Object.assign({}, context.options, options),
context.builder

View File

@ -0,0 +1,8 @@
`hello ${name}`
`hello \${name}`
`hello \\${name}`
`hello "\`"`
"hello ${name}"
"hello \${name}"
"hello \\${name}"
"hello \"`\""

View File

@ -0,0 +1,52 @@
"use strict";
module.exports = function(builder) {
var templateLiteral = builder.templateLiteral(
["hello ", ""],
[builder.identifier("name")]
);
var templateLiteralEscape = builder.templateLiteral(["hello ${name}"], []);
var templateLiteralEscape2 = builder.templateLiteral(
["hello \\", ""],
[builder.identifier("name")]
);
var templateLiteralEscapeQuotes = builder.templateLiteral(
['hello "`"'],
[]
);
var nsTemplateLiteral = builder.templateLiteral(
["hello ", ""],
[builder.identifier("name")]
);
var nsTemplateLiteralEscape = builder.templateLiteral(
["hello ${name}"],
[]
);
var nsTemplateLiteralEscape2 = builder.templateLiteral(
["hello \\", ""],
[builder.identifier("name")]
);
var nsTemplateLiteralEscapeQuotes = builder.templateLiteral(
['hello "`"'],
[]
);
nsTemplateLiteral.nonstandard = true;
nsTemplateLiteralEscape.nonstandard = true;
nsTemplateLiteralEscape2.nonstandard = true;
nsTemplateLiteralEscapeQuotes.nonstandard = true;
return [
templateLiteral,
templateLiteralEscape,
templateLiteralEscape2,
templateLiteralEscapeQuotes,
nsTemplateLiteral,
nsTemplateLiteralEscape,
nsTemplateLiteralEscape2,
nsTemplateLiteralEscapeQuotes
];
};
module.exports.skipCodegen = true;

View File

@ -30,6 +30,7 @@ autotest("fixtures", fixture => {
test(done => {
var main = require(resolve("index.js"));
var generateCodeFunc = main;
var skipCodegen = main.skipCodegen === true;
var context = new CompileContext(
"dummy",
@ -40,7 +41,7 @@ autotest("fixtures", fixture => {
var codeWriter = createCodeWriter(context);
var ast = generateCodeFunc(builder, codegen);
var finalAST = codegen.generateCode(ast);
var finalAST = skipCodegen ? ast : codegen.generateCode(ast);
codeWriter.write(finalAST);