diff --git a/src/helpers/ast/to-string.js b/src/helpers/ast/to-string.js index 4d8dd956..fe6da267 100644 --- a/src/helpers/ast/to-string.js +++ b/src/helpers/ast/to-string.js @@ -3,7 +3,7 @@ import * as t from "babel-types"; // Helper to transform a literal into an string literal. export default function toString(literal, restricted = false) { let string; - if (literal.isStringLiteral()) { + if (literal.isStringLiteral() || literal.isTemplateLiteral()) { return literal.node; } diff --git a/src/helpers/build-children.js b/src/helpers/build-children.js index 37f4087e..3a679754 100644 --- a/src/helpers/build-children.js +++ b/src/helpers/build-children.js @@ -5,6 +5,22 @@ import iDOMMethod from "./idom-method"; import isLiteralOrSpecial from "./is-literal-or-special"; import toString from "./ast/to-string"; + +// String concatenations are special cased, so template literals don't +// require a call to renderArbitrary. +function isStringConcatenation(path) { + if (!(path.isBinaryExpression() && path.node.operator === '+')) { + return false; + } + + const left = path.get("left"); + const right = path.get("right"); + return left.isStringLiteral() || + right.isStringLiteral() || + isStringConcatenation(left) || + isStringConcatenation(right); +} + // Transforms the children into an array of iDOM function calls export default function buildChildren(children, plugin) { let renderArbitraryRef; @@ -38,6 +54,8 @@ export default function buildChildren(children, plugin) { } node = toFunctionCall(iDOMMethod("text", plugin), [value]); + } else if (isStringConcatenation(child)) { + node = toFunctionCall(iDOMMethod("text", plugin), [child.node]); } else if (wasInExpressionContainer && !replacedElements.has(node)) { // Arbitrary expressions, e.g. variables, need to be inspected at runtime // to determine how to render them. diff --git a/test/fixtures/text/child-template-literal/actual.js b/test/fixtures/text/child-template-literal/actual.js new file mode 100644 index 00000000..a742e43f --- /dev/null +++ b/test/fixtures/text/child-template-literal/actual.js @@ -0,0 +1,9 @@ +function render() { + return
+ {`${i}`} + {`text ${i}`} + {`${i} text`} + {`text ${i} text`} + {"text" - i} +
; +} diff --git a/test/fixtures/text/child-template-literal/expected.js b/test/fixtures/text/child-template-literal/expected.js new file mode 100644 index 00000000..bae0a278 --- /dev/null +++ b/test/fixtures/text/child-template-literal/expected.js @@ -0,0 +1,33 @@ +var _hasOwn = Object.prototype.hasOwnProperty; + +var _forOwn = function _forOwn(object, iterator) { + for (var prop in object) { + if (_hasOwn.call(object, prop)) iterator(object[prop], prop); + } +}; + +var _renderArbitrary = function _renderArbitrary(child) { + var type = typeof child; + + if (type === "number" || type === "string" || type === "object" && child instanceof String) { + text(child); + } else if (type === "function" && child.__jsxDOMWrapper) { + child(); + } else if (Array.isArray(child)) { + child.forEach(_renderArbitrary); + } else if (type === "object" && String(child) === "[object Object]") { + _forOwn(child, _renderArbitrary); + } +}; + +function render() { + elementOpen("div"); + text("" + i); + text("text " + i); + text(i + " text"); + text("text " + i + " text"); + + _renderArbitrary("text" - i); + + return elementClose("div"); +} \ No newline at end of file