From ed5f71f77961382cf2eafc85275fc827e8fdd2b0 Mon Sep 17 00:00:00 2001 From: pago Date: Tue, 25 Jun 2019 08:06:57 +0200 Subject: [PATCH 1/4] Ensure ~ operator converts to string 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 --- .../__fixtures__/success/expressions.template | 5 ++ .../__snapshots__/CompilerSpec.js.snap | 46 ++++++++------ .../src/convert/expressions.js | 62 +++++++++++++++++-- .../__snapshots__/CompilerSpec.js.snap | 25 ++++---- .../__tests__/__snapshots__/JSXSpec.js.snap | 4 +- 5 files changed, 104 insertions(+), 38 deletions(-) diff --git a/packages/melody-compiler/__tests__/__fixtures__/success/expressions.template b/packages/melody-compiler/__tests__/__fixtures__/success/expressions.template index 87640ad..66b59a3 100644 --- a/packages/melody-compiler/__tests__/__fixtures__/success/expressions.template +++ b/packages/melody-compiler/__tests__/__fixtures__/success/expressions.template @@ -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 }} diff --git a/packages/melody-compiler/__tests__/__snapshots__/CompilerSpec.js.snap b/packages/melody-compiler/__tests__/__snapshots__/CompilerSpec.js.snap index bf016ef..5bba7a1 100644 --- a/packages/melody-compiler/__tests__/__snapshots__/CompilerSpec.js.snap +++ b/packages/melody-compiler/__tests__/__snapshots__/CompilerSpec.js.snap @@ -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\\" @@ -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); @@ -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(); @@ -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); @@ -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... \\"); @@ -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... \\"); @@ -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); @@ -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: \\"\\", @@ -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\\" }); @@ -1803,7 +1811,7 @@ _template.render = function (_context) { _include({ \\"styleModifier\\": flagModifiers, \\"dataVariables\\": dataVariables, - \\"text\\": \\"-\\" + _context.saving + \\"%\\" + \\"text\\": \`-\${_context.saving}%\` }); } } @@ -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\\"); @@ -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); @@ -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 \\"); @@ -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\\"); @@ -2341,7 +2349,7 @@ exports[`Compiler should fail transforming wrong include.template 1`] = ` 3 | 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: @@ -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 }); @@ -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\\"); diff --git a/packages/melody-compiler/src/convert/expressions.js b/packages/melody-compiler/src/convert/expressions.js index a494804..52235bc 100644 --- a/packages/melody-compiler/src/convert/expressions.js +++ b/packages/melody-compiler/src/convert/expressions.js @@ -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: { diff --git a/packages/melody-plugin-jsx/__tests__/__snapshots__/CompilerSpec.js.snap b/packages/melody-plugin-jsx/__tests__/__snapshots__/CompilerSpec.js.snap index 9e72387..a4b51fd 100644 --- a/packages/melody-plugin-jsx/__tests__/__snapshots__/CompilerSpec.js.snap +++ b/packages/melody-plugin-jsx/__tests__/__snapshots__/CompilerSpec.js.snap @@ -75,7 +75,7 @@ _embed$1.renderHello = function (_context) { _embed$1.renderTest = function (_context) {}; _template.renderHello = function (_context) { - return
{_embed$3.render(createSubContext(_context, { + return
{_embed$3.render(createSubContext(_context, { foo: \\"bar\\" }))}
; }; @@ -428,7 +428,7 @@ _template.render = function (_context) { foo = _sequence[0]; for (; _index < _length; _index++, foo = _sequence[_index]) { - _child[_child.length] = {_include()}; + _child[_child.length] = {_include()}; } } return
{_child}
; @@ -472,7 +472,7 @@ _template.render = function (_context) { }); for (; _index < _length; _index++) { - _child[_child.length] = {_include(_context$1)}; + _child[_child.length] = {_include(_context$1)}; _context$1.loop.index0++; _context$1.loop.index++; _context$1.loop.revindex--; @@ -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\\" }); @@ -637,7 +637,7 @@ _template.render = function (_context) { _child$4 = _include({ \\"styleModifier\\": flagModifiers, \\"dataVariables\\": dataVariables, - \\"text\\": \\"-\\" + _context.saving + \\"%\\" + \\"text\\": \`-\${_context.saving}%\` }); } } @@ -663,12 +663,12 @@ _template.render = function (_context) { if (_context.maxPriceDeal) { _child$10 = ; _child$11 = ; - _child$12 = {_context.maxPriceDeal.price}; + _child$12 = {_context.maxPriceDeal.price}; } else { _child$14 = ; } - _child$15 = {_context.bestPriceDeal.price}; + _child$15 = {_context.bestPriceDeal.price}; if (false) { let _child$18, _child$19; @@ -687,7 +687,7 @@ _template.render = function (_context) { } if (false) { - sBtnModifiers = sBtnModifiers + \\" alt\\"; + sBtnModifiers = \`\${sBtnModifiers} alt\`; } } else if (_context.state == 1) { _child$20 =

unavailable_deal

; @@ -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}
; + } : []} 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}; return
{_child}
; }; @@ -785,7 +788,7 @@ exports[`Compiler should correctly transform spaceless.template 1`] = ` export const _template = {}; _template.render = function (_context) { - return
Receive {_context.formattedIncentive} cash back for testing this hotel. + return
Receive {_context.formattedIncentive} cash back for testing this hotel. Or just be happy!
; }; @@ -838,7 +841,7 @@ _template.render = function (_context) { })}>Lorem Ipsum
; return
Lorem Ipsum
; }; diff --git a/packages/melody-plugin-jsx/__tests__/__snapshots__/JSXSpec.js.snap b/packages/melody-plugin-jsx/__tests__/__snapshots__/JSXSpec.js.snap index 604d5fb..06319a6 100644 --- a/packages/melody-plugin-jsx/__tests__/__snapshots__/JSXSpec.js.snap +++ b/packages/melody-plugin-jsx/__tests__/__snapshots__/JSXSpec.js.snap @@ -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 = {item.label}; _child[_child.length] =
  • {_child$1}
  • ; } From 438ae4cc37ec434370fe618a451527cde133b22f Mon Sep 17 00:00:00 2001 From: pago Date: Tue, 25 Jun 2019 08:10:20 +0200 Subject: [PATCH 2/4] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f65ae2..ebaa277 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Warn about usage of non-breaking space [#107](https://github.com/trivago/melody/pull/107) - Fixed bindings of dispatchCustomEvent in `melody-streams` [#117](https://github.com/trivago/melody/pull/117) - Fixed `combineRefs` unsubscription in `melody-streams` [#120](https://github.com/trivago/melody/pull/120) +- Fixed `~` operator must convert value to string [#123](https://github.com/trivago/melody/pull/123) ### Chore & Maintenance - Removes `Chai` and `Sinon` support, Migrates tests to use `Jest`'s matchers. [#103](https://github.com/trivago/melody/pull/103) From c9149fc746d4594eb7d803f4c376358ff204a3d7 Mon Sep 17 00:00:00 2001 From: pago Date: Fri, 28 Jun 2019 11:27:59 +0200 Subject: [PATCH 3/4] Remove unused code from a comment --- packages/melody-compiler/src/convert/expressions.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/melody-compiler/src/convert/expressions.js b/packages/melody-compiler/src/convert/expressions.js index 52235bc..a4a9b41 100644 --- a/packages/melody-compiler/src/convert/expressions.js +++ b/packages/melody-compiler/src/convert/expressions.js @@ -91,12 +91,6 @@ export default { ) ); } - // path.replaceWithJS({ - // type: 'BinaryExpression', - // operator: '+', - // left: node.left, - // right: node.right, - // }); }, }, BinaryPowerExpression: { From 42f95e8a9d2eb19120722cede9c9b395e4e81c17 Mon Sep 17 00:00:00 2001 From: pago Date: Fri, 28 Jun 2019 12:33:51 +0200 Subject: [PATCH 4/4] Reinstalled node_modules The correct Babel version includes spaces after { and before } when using template literal expressions. --- .../__snapshots__/CompilerSpec.js.snap | 46 +++++++++---------- .../__snapshots__/CompilerSpec.js.snap | 26 +++++------ .../__tests__/__snapshots__/JSXSpec.js.snap | 4 +- 3 files changed, 38 insertions(+), 38 deletions(-) diff --git a/packages/melody-compiler/__tests__/__snapshots__/CompilerSpec.js.snap b/packages/melody-compiler/__tests__/__snapshots__/CompilerSpec.js.snap index 5bba7a1..85f437e 100644 --- a/packages/melody-compiler/__tests__/__snapshots__/CompilerSpec.js.snap +++ b/packages/melody-compiler/__tests__/__snapshots__/CompilerSpec.js.snap @@ -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\\" @@ -239,10 +239,10 @@ _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}\${_context.c}\`); - text(\`a\${_context.b}\`); - text(\`\${_context.a}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); @@ -625,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(); @@ -671,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); @@ -1655,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... \\"); @@ -1671,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... \\"); @@ -1682,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); @@ -1731,9 +1731,9 @@ _template.render = function (_context) { 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 - \${!_context.isItemAvailable ? \\"no_availability\\" : !_context.bestPriceDeal ? \\"incomplete\\" : \\"\\"} - \${_context.bestPriceDeal ? \\"js_cClickoutLink\\" : \\"\\"} - \${_context.saving >= 20 ? \\"reduced\\" : \\"\\"}\`, \\"itemscope\\", true); + \${ !_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: \\"\\", @@ -1796,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\\" }); @@ -1811,7 +1811,7 @@ _template.render = function (_context) { _include({ \\"styleModifier\\": flagModifiers, \\"dataVariables\\": dataVariables, - \\"text\\": \`-\${_context.saving}%\` + \\"text\\": \`-\${ _context.saving }%\` }); } } @@ -1836,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\\"); @@ -1864,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); @@ -2095,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 \\"); @@ -2199,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\\"); @@ -2463,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 }); @@ -2520,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\\"); diff --git a/packages/melody-plugin-jsx/__tests__/__snapshots__/CompilerSpec.js.snap b/packages/melody-plugin-jsx/__tests__/__snapshots__/CompilerSpec.js.snap index a4b51fd..4e2351e 100644 --- a/packages/melody-plugin-jsx/__tests__/__snapshots__/CompilerSpec.js.snap +++ b/packages/melody-plugin-jsx/__tests__/__snapshots__/CompilerSpec.js.snap @@ -75,7 +75,7 @@ _embed$1.renderHello = function (_context) { _embed$1.renderTest = function (_context) {}; _template.renderHello = function (_context) { - return
    {_embed$3.render(createSubContext(_context, { + return
    {_embed$3.render(createSubContext(_context, { foo: \\"bar\\" }))}
    ; }; @@ -428,7 +428,7 @@ _template.render = function (_context) { foo = _sequence[0]; for (; _index < _length; _index++, foo = _sequence[_index]) { - _child[_child.length] = {_include()}; + _child[_child.length] = {_include()}; } } return
    {_child}
    ; @@ -472,7 +472,7 @@ _template.render = function (_context) { }); for (; _index < _length; _index++) { - _child[_child.length] = {_include(_context$1)}; + _child[_child.length] = {_include(_context$1)}; _context$1.loop.index0++; _context$1.loop.index++; _context$1.loop.revindex--; @@ -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\\" }); @@ -637,7 +637,7 @@ _template.render = function (_context) { _child$4 = _include({ \\"styleModifier\\": flagModifiers, \\"dataVariables\\": dataVariables, - \\"text\\": \`-\${_context.saving}%\` + \\"text\\": \`-\${ _context.saving }%\` }); } } @@ -663,12 +663,12 @@ _template.render = function (_context) { if (_context.maxPriceDeal) { _child$10 = ; _child$11 = ; - _child$12 = {_context.maxPriceDeal.price}; + _child$12 = {_context.maxPriceDeal.price}; } else { _child$14 = ; } - _child$15 = {_context.bestPriceDeal.price}; + _child$15 = {_context.bestPriceDeal.price}; if (false) { let _child$18, _child$19; @@ -687,7 +687,7 @@ _template.render = function (_context) { } if (false) { - sBtnModifiers = \`\${sBtnModifiers} alt\`; + sBtnModifiers = \`\${ sBtnModifiers } alt\`; } } else if (_context.state == 1) { _child$20 =

    unavailable_deal

    ; @@ -717,9 +717,9 @@ _template.render = function (_context) { \\"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 - \${!_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}
    ; + \${ !_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}; return
    {_child}
    ; }; @@ -788,7 +788,7 @@ exports[`Compiler should correctly transform spaceless.template 1`] = ` export const _template = {}; _template.render = function (_context) { - return
    Receive {_context.formattedIncentive} cash back for testing this hotel. + return
    Receive {_context.formattedIncentive} cash back for testing this hotel. Or just be happy!
    ; }; @@ -841,7 +841,7 @@ _template.render = function (_context) { })}>Lorem Ipsum
    ; return
    Lorem Ipsum
    ; }; diff --git a/packages/melody-plugin-jsx/__tests__/__snapshots__/JSXSpec.js.snap b/packages/melody-plugin-jsx/__tests__/__snapshots__/JSXSpec.js.snap index 06319a6..3dc5ff5 100644 --- a/packages/melody-plugin-jsx/__tests__/__snapshots__/JSXSpec.js.snap +++ b/packages/melody-plugin-jsx/__tests__/__snapshots__/JSXSpec.js.snap @@ -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 = {item.label}; _child[_child.length] =
  • {_child$1}
  • ; }