From 2fa784ecc394e46bc139fb2340068494237a698d Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sun, 25 Jun 2017 20:03:17 -0400 Subject: [PATCH] handle @foo and #foo edge cases --- src/generators/dom/index.ts | 5 ++- src/generators/server-side-rendering/index.ts | 7 ++-- .../visitors/Component.ts | 3 +- .../server-side-rendering/visitors/Text.ts | 2 +- .../runtime/samples/sigil-static-#/_config.js | 3 ++ test/runtime/samples/sigil-static-#/main.html | 1 + .../runtime/samples/sigil-static-@/_config.js | 3 ++ test/runtime/samples/sigil-static-@/main.html | 1 + test/server-side-rendering/index.js | 33 +++++++------------ 9 files changed, 29 insertions(+), 29 deletions(-) create mode 100644 test/runtime/samples/sigil-static-#/_config.js create mode 100644 test/runtime/samples/sigil-static-#/main.html create mode 100644 test/runtime/samples/sigil-static-@/_config.js create mode 100644 test/runtime/samples/sigil-static-@/main.html diff --git a/src/generators/dom/index.ts b/src/generators/dom/index.ts index 2b4dcc4f34..bb1487ba66 100644 --- a/src/generators/dom/index.ts +++ b/src/generators/dom/index.ts @@ -254,11 +254,14 @@ export default function dom( let result = builder .toString() - .replace(/@(\w+)\b/g, (match: string, name: string) => { + .replace(/(\\)?@(\w*)/g, (match: string, escaped: string, name: string) => { + if (escaped) return match.slice(1); + if (name in shared) { if (options.dev && `${name}Dev` in shared) name = `${name}Dev`; usedHelpers.add(name); } + return generator.alias(name); }); diff --git a/src/generators/server-side-rendering/index.ts b/src/generators/server-side-rendering/index.ts index 01c347361e..bac659d0f2 100644 --- a/src/generators/server-side-rendering/index.ts +++ b/src/generators/server-side-rendering/index.ts @@ -2,7 +2,6 @@ import deindent from '../../utils/deindent'; import Generator from '../Generator'; import Block from './Block'; import visit from './visit'; -import stringify from '../../utils/stringify'; import { removeNode, removeObjectKey } from '../../utils/removeNode'; import { Parsed, Node, CompileOptions } from '../../interfaces'; @@ -84,7 +83,7 @@ export default function ssr( var ${name} = {}; - ${name}.filename = ${stringify(options.filename)}; + ${name}.filename = ${JSON.stringify(options.filename)}; ${name}.data = function () { return ${templateProperties.data ? `@template.data()` : `{}`}; @@ -124,7 +123,7 @@ export default function ssr( deindent` components.push({ filename: ${name}.filename, - css: ${stringify(generator.css)}, + css: ${JSON.stringify(generator.css)}, map: null // TODO }); `} @@ -169,7 +168,7 @@ export default function ssr( function __escape ( html ) { return String( html ).replace( /["'&<>]/g, match => escaped[ match ] ); } - `.replace(/@(\w+)/g, (match, name) => generator.alias(name)); + `.replace(/(\\)?@(\w*)/g, (match: string, escaped: string, name: string) => escaped ? match.slice(1) : generator.alias(name)); return generator.generate(result, options, { name, format }); } diff --git a/src/generators/server-side-rendering/visitors/Component.ts b/src/generators/server-side-rendering/visitors/Component.ts index e704c6d0e9..75785d6ffd 100644 --- a/src/generators/server-side-rendering/visitors/Component.ts +++ b/src/generators/server-side-rendering/visitors/Component.ts @@ -4,7 +4,6 @@ import { SsrGenerator } from '../index'; import Block from '../Block'; import { Node } from '../../../interfaces'; import getObject from '../../../utils/getObject'; -import stringify from '../../../utils/stringify'; import getTailSnippet from '../../../utils/getTailSnippet'; export default function visitComponent( @@ -42,7 +41,7 @@ export default function visitComponent( } else if (attribute.value.length === 1) { const chunk = attribute.value[0]; if (chunk.type === 'Text') { - value = isNaN(chunk.data) ? stringify(chunk.data) : chunk.data; + value = isNaN(chunk.data) ? JSON.stringify(chunk.data) : chunk.data; } else { const { snippet } = block.contextualise(chunk.expression); value = snippet; diff --git a/src/generators/server-side-rendering/visitors/Text.ts b/src/generators/server-side-rendering/visitors/Text.ts index dd59a384cb..b7aad398f2 100644 --- a/src/generators/server-side-rendering/visitors/Text.ts +++ b/src/generators/server-side-rendering/visitors/Text.ts @@ -7,5 +7,5 @@ export default function visitText( block: Block, node: Node ) { - generator.append(node.data.replace(/(\${|`|\\)/g, '\\$1')); + generator.append(node.data.replace(/(\${|`|\\)/g, '\\$1').replace(/([^\\])?([@#])/g, '$1\\$2')); } diff --git a/test/runtime/samples/sigil-static-#/_config.js b/test/runtime/samples/sigil-static-#/_config.js new file mode 100644 index 0000000000..747ddc2a94 --- /dev/null +++ b/test/runtime/samples/sigil-static-#/_config.js @@ -0,0 +1,3 @@ +export default { + html: `#foo` +}; \ No newline at end of file diff --git a/test/runtime/samples/sigil-static-#/main.html b/test/runtime/samples/sigil-static-#/main.html new file mode 100644 index 0000000000..5529b9b4ce --- /dev/null +++ b/test/runtime/samples/sigil-static-#/main.html @@ -0,0 +1 @@ +#foo \ No newline at end of file diff --git a/test/runtime/samples/sigil-static-@/_config.js b/test/runtime/samples/sigil-static-@/_config.js new file mode 100644 index 0000000000..ada3a602ab --- /dev/null +++ b/test/runtime/samples/sigil-static-@/_config.js @@ -0,0 +1,3 @@ +export default { + html: `@foo` +}; \ No newline at end of file diff --git a/test/runtime/samples/sigil-static-@/main.html b/test/runtime/samples/sigil-static-@/main.html new file mode 100644 index 0000000000..d88b8ee03d --- /dev/null +++ b/test/runtime/samples/sigil-static-@/main.html @@ -0,0 +1 @@ +@foo \ No newline at end of file diff --git a/test/server-side-rendering/index.js b/test/server-side-rendering/index.js index 57c5c217f4..1d2c801ae1 100644 --- a/test/server-side-rendering/index.js +++ b/test/server-side-rendering/index.js @@ -34,7 +34,7 @@ describe("ssr", () => { // add .solo to a sample directory name to only run that test, or // .show to always show the output. or both const solo = /\.solo/.test(dir); - let show = /\.show/.test(dir); + const show = /\.show/.test(dir); if (solo && process.env.CI) { throw new Error("Forgot to remove `solo: true` from test"); @@ -42,36 +42,27 @@ describe("ssr", () => { (solo ? it.only : it)(dir, () => { dir = path.resolve("test/server-side-rendering/samples", dir); - const component = require(`${dir}/main.html`); + try { + const component = require(`${dir}/main.html`); - const expectedHtml = tryToReadFile(`${dir}/_expected.html`); - const expectedCss = tryToReadFile(`${dir}/_expected.css`) || ""; + const expectedHtml = tryToReadFile(`${dir}/_expected.html`); + const expectedCss = tryToReadFile(`${dir}/_expected.css`) || ""; - const data = tryToLoadJson(`${dir}/data.json`); - let html; - let css; - let error; + const data = tryToLoadJson(`${dir}/data.json`); - try { - html = component.render(data); - css = component.renderCss().css; - } catch (e) { - show = true; - error = e; - } + const html = component.render(data); + const css = component.renderCss().css; - if (show) showOutput(dir, { generate: "ssr" }); - if (error) throw error; + fs.writeFileSync(`${dir}/_actual.html`, html); + if (css) fs.writeFileSync(`${dir}/_actual.css`, css); - fs.writeFileSync(`${dir}/_actual.html`, html); - if (css) fs.writeFileSync(`${dir}/_actual.css`, css); - - try { assert.htmlEqual(html, expectedHtml); assert.equal( css.replace(/^\s+/gm, ""), expectedCss.replace(/^\s+/gm, "") ); + + if (show) showOutput(dir, { generate: 'ssr' }); } catch (err) { showOutput(dir, { generate: 'ssr' }); throw err;