Skip to content

Commit

Permalink
Ensure ~ operator converts to string
Browse files Browse the repository at this point in the history
Ensure that the binary concatenation operator (~) always produces a string value.
We do that by utilizing the string template syntax instead of the binary plus (+) operator
in the transpiled code.

To make the generated code more efficient and easier to read we'll also collapse
sibling template literals into a single.

fixes #123
  • Loading branch information
pago committed Jun 25, 2019
1 parent f61c830 commit ed5f71f
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@
{{ a+b }}
{{ a-b }}
{{ a~b }}
{{ a~b~c }}
{{ "a"~b }}
{{ a~"b" }}
{{ "a"~"b" }}
{{ "a"~"b"~"c" }}
{{ a*b }}
{{ a/b }}
{{ a%b }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ _embed$1.renderHello = function (_context) {
_embed$1.renderTest = function (_context) {};
_template.renderHello = function (_context) {
elementOpen(\\"div\\", null, null, \\"class\\", \\"test-\\" + _context.foo + \\" bar\\");
elementOpen(\\"div\\", null, null, \\"class\\", \`test-\${_context.foo} bar\`);
_embed$3.render(createSubContext(_context, {
foo: \\"bar\\"
Expand Down Expand Up @@ -239,7 +239,12 @@ _template.render = function (_context) {
text(range(_context.a, _context.b));
text(_context.a + _context.b);
text(_context.a - _context.b);
text(_context.a + _context.b);
text(\`\${_context.a}\${_context.b}\`);
text(\`\${_context.a}\${_context.b}\${_context.c}\`);
text(\`a\${_context.b}\`);
text(\`\${_context.a}b\`);
text(\\"ab\\");
text(\\"abc\\");
text(_context.a * _context.b);
text(_context.a / _context.b);
text(_context.a % _context.b);
Expand Down Expand Up @@ -620,7 +625,7 @@ _template.render = function (_context) {
foo = _sequence[0];
for (; _index < _length; _index++, foo = _sequence[_index]) {
elementOpen(\\"span\\", \\"\\" + foo, null, \\"class\\", \\"qtp-item__star icon-ic icon-icn_star--white \\" + foo);
elementOpen(\\"span\\", \\"\\" + foo, null, \\"class\\", \`qtp-item__star icon-ic icon-icn_star--white \${foo}\`);
_include();
Expand Down Expand Up @@ -666,7 +671,7 @@ _template.render = function (_context) {
});
for (; _index < _length; _index++) {
elementOpen(\\"span\\", \\"\\" + _context$1.foo, null, \\"class\\", \\"qtp-item__star icon-ic icon-icn_star--white \\" + _context$1.foo);
elementOpen(\\"span\\", \\"\\" + _context$1.foo, null, \\"class\\", \`qtp-item__star icon-ic icon-icn_star--white \${_context$1.foo}\`);
_include(_context$1);
Expand Down Expand Up @@ -1650,8 +1655,8 @@ _template.render = function (_context) {
foo: \\"bar\\"
}
});
component(AsyncComponent, \\"\\" + (\\"bar-\\" + _context.part), {
promisedComponent: () => import( /* webpackPrefetch: true */\\"./parts/\\" + _context.part + \\".twig\\"),
component(AsyncComponent, \\"\\" + \`bar-\${_context.part}\`, {
promisedComponent: () => import( /* webpackPrefetch: true */\`./parts/\${_context.part}.twig\`),
delayLoadingAnimation: 1000,
whileLoading: () => {
text(\\" Loading... \\");
Expand All @@ -1666,7 +1671,7 @@ _template.render = function (_context) {
}
});
component(AsyncComponent, \\"bar\\", {
promisedComponent: () => import( /* webpackChunkName: \\"bar\\", webpackPrefetch: true */\\"./parts/\\" + _context.part + \\".twig\\"),
promisedComponent: () => import( /* webpackChunkName: \\"bar\\", webpackPrefetch: true */\`./parts/\${_context.part}.twig\`),
delayLoadingAnimation: 1000,
whileLoading: () => {
text(\\" Loading... \\");
Expand All @@ -1677,7 +1682,7 @@ _template.render = function (_context) {
}
});
component(AsyncComponent, \\"bar\\", {
promisedComponent: () => import( /* webpackChunkName: \\"bar\\", webpackPrefetch: true */\\"./parts/\\" + _context.part + \\".twig\\"),
promisedComponent: () => import( /* webpackChunkName: \\"bar\\", webpackPrefetch: true */\`./parts/\${_context.part}.twig\`),
delayLoadingAnimation: 1000,
whileLoading: () => {
elementOpen(\\"strong\\", null, null);
Expand Down Expand Up @@ -1725,7 +1730,10 @@ _template.render = function (_context) {
bClickoutClientside = false;
sBtnModifiers = \\"\\";
elementOpen(\\"section\\", \\"f-%v2ak\\", _statics$9, \\"itemscope\\", true);
elementOpenStart(\\"div\\", \\"K$/#=(h\\", _statics$8, \\"class\\", \\"item__deal-best-link ov-hidden font-dark js_item_bestprice\\\\n \\" + (!_context.isItemAvailable ? \\"no_availability\\" : !_context.bestPriceDeal ? \\"incomplete\\" : \\"\\") + \\"\\\\n \\" + (_context.bestPriceDeal ? \\"js_cClickoutLink\\" : \\"\\") + \\"\\\\n \\" + (_context.saving >= 20 ? \\"reduced\\" : \\"\\"), \\"itemscope\\", true);
elementOpenStart(\\"div\\", \\"K$/#=(h\\", _statics$8, \\"class\\", \`item__deal-best-link ov-hidden font-dark js_item_bestprice
\${!_context.isItemAvailable ? \\"no_availability\\" : !_context.bestPriceDeal ? \\"incomplete\\" : \\"\\"}
\${_context.bestPriceDeal ? \\"js_cClickoutLink\\" : \\"\\"}
\${_context.saving >= 20 ? \\"reduced\\" : \\"\\"}\`, \\"itemscope\\", true);
for (let _i = 0, _a = process.env.NODE_ENV === \\"production\\" || Array.isArray((_context.bestPriceDeal ? attrs({
onclick: \\"\\",
Expand Down Expand Up @@ -1788,7 +1796,7 @@ _template.render = function (_context) {
\\"data-topdeal-path-name\\": _context.pathName,
\\"data-topdeal-overall-liking\\": _context.overallLiking
};
flagModifiers = flagModifiers + \\" top_deals js_top_deals \\" + _context.topDealCriterion;
flagModifiers = \`\${flagModifiers} top_deals js_top_deals \${_context.topDealCriterion}\`;
dataVariables = merge(dataVariables, {
\\"data-topdeal-log\\": \\"1\\"
});
Expand All @@ -1803,7 +1811,7 @@ _template.render = function (_context) {
_include({
\\"styleModifier\\": flagModifiers,
\\"dataVariables\\": dataVariables,
\\"text\\": \\"-\\" + _context.saving + \\"%\\"
\\"text\\": \`-\${_context.saving}%\`
});
}
}
Expand All @@ -1828,14 +1836,14 @@ _template.render = function (_context) {
if (_context.maxPriceDeal) {
elementVoid(\\"meta\\", \\"ECmr>3o\\", _statics$2, \\"content\\", _context.maxPriceDeal.displayPrice);
elementVoid(\\"meta\\", \\"e_NpGiT\\", _statics$3, \\"content\\", _context.bestPriceDeal.displayPrice);
elementOpen(\\"s\\", null, null, \\"class\\", \\"item__price-striked block cur-pointer--hover\\" + (!_context.isBigFontSiteInBestPrice ? \\" long_digit\\" : \\"\\"));
elementOpen(\\"s\\", null, null, \\"class\\", \`item__price-striked block cur-pointer--hover\${!_context.isBigFontSiteInBestPrice ? \\" long_digit\\" : \\"\\"}\`);
text(_context.maxPriceDeal.price);
elementClose(\\"s\\");
} else {
elementVoid(\\"meta\\", \\"1ntl?'O\\", _statics$4, \\"content\\", _context.bestPriceDeal.displayPrice);
}
elementOpen(\\"strong\\", null, null, \\"class\\", \\"item__best-price block cur-pointer--hover price\\" + (_context.maxPriceDeal ? \\"_min\\" : \\" single\\") + (!_context.isBigFontSiteInBestPrice ? \\" long_digit\\" : \\"\\"));
elementOpen(\\"strong\\", null, null, \\"class\\", \`item__best-price block cur-pointer--hover price\${_context.maxPriceDeal ? \\"_min\\" : \\" single\\"}\${!_context.isBigFontSiteInBestPrice ? \\" long_digit\\" : \\"\\"}\`);
text(_context.bestPriceDeal.price);
elementClose(\\"strong\\");
Expand All @@ -1856,7 +1864,7 @@ _template.render = function (_context) {
}
if (false) {
sBtnModifiers = sBtnModifiers + \\" alt\\";
sBtnModifiers = \`\${sBtnModifiers} alt\`;
}
} else if (_context.state == 1) {
elementOpen(\\"p\\", \\"$J_dRYB\\", _statics$6);
Expand Down Expand Up @@ -2087,7 +2095,7 @@ export const _template = {};
const _statics = [\\"class\\", \\"qtp-item__text\\"];
_template.render = function (_context) {
elementOpen(\\"div\\", \\"S9hzS{)\\", _statics, \\"data-test\\", \\"Speceless testing:\\" + _context.formattedIncentive + \\"foo\\");
elementOpen(\\"div\\", \\"S9hzS{)\\", _statics, \\"data-test\\", \`Speceless testing:\${_context.formattedIncentive}foo\`);
text(\\"Receive \\");
text(_context.formattedIncentive);
text(\\" cash back for testing this hotel.\\\\n Or just \\");
Expand Down Expand Up @@ -2191,7 +2199,7 @@ _template.render = function (_context) {
elementClose(\\"div\\");
elementOpen(\\"div\\", null, null, \\"style\\", styles({
\\"color\\": _context.color,
[\\"border-\\" + _context.borderSide]: _context.border,
[\`border-\${_context.borderSide}\`]: _context.border,
[_context.position]: _context.positionValue
}));
text(\\"Lorem Ipsum\\");
Expand Down Expand Up @@ -2341,7 +2349,7 @@ exports[`Compiler should fail transforming wrong include.template 1`] = `
3 | </div>
4 |
The Include Statement expected a StringLiteral but got a BinaryExpression.
The Include Statement expected a StringLiteral but got a TemplateLiteral.
Includes only support static strings as argument.
To include a template asynchronously you can use the \\"mount async\\" statement:
Expand Down Expand Up @@ -2455,7 +2463,7 @@ export const _template = {};
_template.render = function (_context) {
text({
a: \\"foo\\",
[\\"b\\" + _context.a]: \\"bar\\",
[\`b\${_context.a}\`]: \\"bar\\",
2: 4,
[_context.a]: _context.foo
});
Expand Down Expand Up @@ -2512,7 +2520,7 @@ export const _template = {};
const _statics = [\\"class\\", \\"foo\\"];
_template.render = function (_context) {
elementOpenStart(\\"div\\", \\"\\" + (_context._i + _context._len), _statics);
elementOpenStart(\\"div\\", \\"\\" + \`\${_context._i}\${_context._len}\`, _statics);
for (let _i$1 = 0, _a = process.env.NODE_ENV === \\"production\\" || Array.isArray(_context.dataAttributes) ? _context.dataAttributes : (() => {
throw new Error(\\"Dynamic attributes have to be an array, found \\" + typeof _context.dataAttributes + \\" instead\\");
Expand Down
62 changes: 56 additions & 6 deletions packages/melody-compiler/src/convert/expressions.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,62 @@ export default {
BinaryConcatExpression: {
exit(path) {
const node = path.node;
path.replaceWithJS({
type: 'BinaryExpression',
operator: '+',
left: node.left,
right: node.right,
});
if (t.isStringLiteral(node.left)) {
if (t.isStringLiteral(node.right)) {
path.replaceWithJS(
t.stringLiteral(node.left.value + node.right.value)
);
} else {
path.replaceWithJS(
t.templateLiteral(
[t.templateElement({cooked: node.left.value, raw: node.left.value}), t.templateElement({cooked: '', raw: ''})],
[node.right]
)
);
}
} else if (t.isTemplateLiteral(node.left)) {
if (t.isStringLiteral(node.right)) {
// we need to append the new value to the last quasi
// to keep things predictable and pure we start by cloning the existing structure
const quasis = node.left.quasis.map(quasi => t.templateElement({ cooked: quasi.value.cooked, raw: quasi.value.raw }));
const last = quasis[quasis.length - 1];
last.value.cooked += node.right.value;
last.value.raw += node.right.value;
path.replaceWithJS(
t.templateLiteral(
quasis,
node.left.expressions
)
);
} else {
path.replaceWithJS(
t.templateLiteral(
[...node.left.quasis, t.templateElement({cooked: '', raw: ''})],
[...node.left.expressions, node.right]
)
);
}
} else if (t.isStringLiteral(node.right)) {
path.replaceWithJS(
t.templateLiteral(
[t.templateElement({cooked: '', raw: ''}), t.templateElement({cooked: node.right.value, raw: node.right.value})],
[node.left]
)
);
} else {
path.replaceWithJS(
t.templateLiteral(
[t.templateElement({cooked: '', raw: ''}), t.templateElement({cooked: '', raw: ''}), t.templateElement({cooked: '', raw: ''})],
[node.left, node.right]
)
);
}
// path.replaceWithJS({
// type: 'BinaryExpression',
// operator: '+',
// left: node.left,
// right: node.right,
// });
},
},
BinaryPowerExpression: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ _embed$1.renderHello = function (_context) {
_embed$1.renderTest = function (_context) {};
_template.renderHello = function (_context) {
return <div className={\\"test-\\" + _context.foo + \\" bar\\"}>{_embed$3.render(createSubContext(_context, {
return <div className={\`test-\${_context.foo} bar\`}>{_embed$3.render(createSubContext(_context, {
foo: \\"bar\\"
}))}</div>;
};
Expand Down Expand Up @@ -428,7 +428,7 @@ _template.render = function (_context) {
foo = _sequence[0];
for (; _index < _length; _index++, foo = _sequence[_index]) {
_child[_child.length] = <span key={foo} className={\\"qtp-item__star icon-ic icon-icn_star--white \\" + foo}>{_include()}</span>;
_child[_child.length] = <span key={foo} className={\`qtp-item__star icon-ic icon-icn_star--white \${foo}\`}>{_include()}</span>;
}
}
return <div>{_child}</div>;
Expand Down Expand Up @@ -472,7 +472,7 @@ _template.render = function (_context) {
});
for (; _index < _length; _index++) {
_child[_child.length] = <span key={_context$1.foo} className={\\"qtp-item__star icon-ic icon-icn_star--white \\" + _context$1.foo}>{_include(_context$1)}</span>;
_child[_child.length] = <span key={_context$1.foo} className={\`qtp-item__star icon-ic icon-icn_star--white \${_context$1.foo}\`}>{_include(_context$1)}</span>;
_context$1.loop.index0++;
_context$1.loop.index++;
_context$1.loop.revindex--;
Expand Down Expand Up @@ -623,7 +623,7 @@ _template.render = function (_context) {
\\"data-topdeal-path-name\\": _context.pathName,
\\"data-topdeal-overall-liking\\": _context.overallLiking
};
flagModifiers = flagModifiers + \\" top_deals js_top_deals \\" + _context.topDealCriterion;
flagModifiers = \`\${flagModifiers} top_deals js_top_deals \${_context.topDealCriterion}\`;
dataVariables = merge(dataVariables, {
\\"data-topdeal-log\\": \\"1\\"
});
Expand All @@ -637,7 +637,7 @@ _template.render = function (_context) {
_child$4 = _include({
\\"styleModifier\\": flagModifiers,
\\"dataVariables\\": dataVariables,
\\"text\\": \\"-\\" + _context.saving + \\"%\\"
\\"text\\": \`-\${_context.saving}%\`
});
}
}
Expand All @@ -663,12 +663,12 @@ _template.render = function (_context) {
if (_context.maxPriceDeal) {
_child$10 = <meta itemProp=\\"maxPrice\\" content={_context.maxPriceDeal.displayPrice} />;
_child$11 = <meta itemProp=\\"minPrice\\" content={_context.bestPriceDeal.displayPrice} />;
_child$12 = <s className={\\"item__price-striked block cur-pointer--hover\\" + (!_context.isBigFontSiteInBestPrice ? \\" long_digit\\" : \\"\\")}>{_context.maxPriceDeal.price}</s>;
_child$12 = <s className={\`item__price-striked block cur-pointer--hover\${!_context.isBigFontSiteInBestPrice ? \\" long_digit\\" : \\"\\"}\`}>{_context.maxPriceDeal.price}</s>;
} else {
_child$14 = <meta itemProp=\\"price\\" content={_context.bestPriceDeal.displayPrice} />;
}
_child$15 = <strong className={\\"item__best-price block cur-pointer--hover price\\" + (_context.maxPriceDeal ? \\"_min\\" : \\" single\\") + (!_context.isBigFontSiteInBestPrice ? \\" long_digit\\" : \\"\\")}>{_context.bestPriceDeal.price}</strong>;
_child$15 = <strong className={\`item__best-price block cur-pointer--hover price\${_context.maxPriceDeal ? \\"_min\\" : \\" single\\"}\${!_context.isBigFontSiteInBestPrice ? \\" long_digit\\" : \\"\\"}\`}>{_context.bestPriceDeal.price}</strong>;
if (false) {
let _child$18, _child$19;
Expand All @@ -687,7 +687,7 @@ _template.render = function (_context) {
}
if (false) {
sBtnModifiers = sBtnModifiers + \\" alt\\";
sBtnModifiers = \`\${sBtnModifiers} alt\`;
}
} else if (_context.state == 1) {
_child$20 = <p className=\\"font-trv-maincolor-04-lighter cur-disabled--hover\\">unavailable_deal</p>;
Expand Down Expand Up @@ -716,7 +716,10 @@ _template.render = function (_context) {
\\"data-teb\\": _context.bestPriceDeal.expressBookingAvailable && tEB_SAME_WINDOW_CLICKOUT ? \\"1\\" : \\"\\",
\\"data-alternative\\": _context.isAlternativeHotel ? \\"1\\" : \\"0\\",
\\"data-dbid\\": _context.bestPriceDeal.debuggingId != null && _context.bestPriceDeal.debuggingId !== '' ? _context.bestPriceDeal.debuggingId : \\"\\"
} : []} className={\\"item__deal-best-link ov-hidden font-dark js_item_bestprice\\\\n \\" + (!_context.isItemAvailable ? \\"no_availability\\" : !_context.bestPriceDeal ? \\"incomplete\\" : \\"\\") + \\"\\\\n \\" + (_context.bestPriceDeal ? \\"js_cClickoutLink\\" : \\"\\") + \\"\\\\n \\" + (_context.saving >= 20 ? \\"reduced\\" : \\"\\")} itemProp=\\"priceSpecification\\" itemScope itemType=\\"http://schema.org/PriceSpecification\\">{_child$1}{_child$3}{_child$4}{_child$5}{_child$22}</div>;
} : []} className={\`item__deal-best-link ov-hidden font-dark js_item_bestprice
\${!_context.isItemAvailable ? \\"no_availability\\" : !_context.bestPriceDeal ? \\"incomplete\\" : \\"\\"}
\${_context.bestPriceDeal ? \\"js_cClickoutLink\\" : \\"\\"}
\${_context.saving >= 20 ? \\"reduced\\" : \\"\\"}\`} itemProp=\\"priceSpecification\\" itemScope itemType=\\"http://schema.org/PriceSpecification\\">{_child$1}{_child$3}{_child$4}{_child$5}{_child$22}</div>;
return <section className=\\"item__deal-best\\" itemProp=\\"makesOffer\\" itemScope itemType=\\"http://schema.org/Offer\\">{_child}</section>;
};
Expand Down Expand Up @@ -785,7 +788,7 @@ exports[`Compiler should correctly transform spaceless.template 1`] = `
export const _template = {};
_template.render = function (_context) {
return <div className=\\"qtp-item__text\\" data-test={\\"Speceless testing:\\" + _context.formattedIncentive + \\"foo\\"}>Receive {_context.formattedIncentive} cash back for testing this hotel.
return <div className=\\"qtp-item__text\\" data-test={\`Speceless testing:\${_context.formattedIncentive}foo\`}>Receive {_context.formattedIncentive} cash back for testing this hotel.
Or just <span>be</span> happy!</div>;
};
Expand Down Expand Up @@ -838,7 +841,7 @@ _template.render = function (_context) {
})}>Lorem Ipsum</div>;
return <div style={styles({
\\"color\\": _context.color,
[\\"border-\\" + _context.borderSide]: _context.border,
[\`border-\${_context.borderSide}\`]: _context.border,
[_context.position]: _context.positionValue
})}>Lorem Ipsum</div>;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,12 +184,12 @@ _template.render = function (_context) {
for (; _index < _length; _index++, item = _sequence[_index]) {
let className;
className = \\"li-\\" + _context.id;
className = \`li-\${_context.id}\`;
let _prop = className,
_child$1;
className = \\"span-\\" + _context.id;
className = \`span-\${_context.id}\`;
_child$1 = <span className={className}>{item.label}</span>;
_child[_child.length] = <li key={item.id} className={_prop}>{_child$1}</li>;
}
Expand Down

0 comments on commit ed5f71f

Please sign in to comment.