diff --git a/src/compile/Compiler.ts b/src/compile/Compiler.ts index bb2ffd1d5e9b..be5ca6c65195 100644 --- a/src/compile/Compiler.ts +++ b/src/compile/Compiler.ts @@ -310,7 +310,7 @@ export default class Compiler { : `_svelteTransitionManager`; inlineHelpers += `\n\nvar ${this.alias(name)} = window.${global} || (window.${global} = ${code});\n\n`; - } else if (name === 'escaped' || name === 'missingComponent') { + } else if (name === 'escaped' || name === 'missingComponent' || name === 'invalidAttributeNameCharacter') { // vars are an awkward special case... would be nice to avoid this const alias = this.alias(name); inlineHelpers += `\n\nconst ${alias} = ${code};` diff --git a/src/shared/ssr.js b/src/shared/ssr.js index 63a5659cf401..11942bdb4b0e 100644 --- a/src/shared/ssr.js +++ b/src/shared/ssr.js @@ -1,12 +1,23 @@ +// https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 +// https://infra.spec.whatwg.org/#noncharacter +export const invalidAttributeNameCharacter = /[\s'"<\/=\u{FDD0}-\u{FDEF}\u{FFFE}\u{FFFF}\u{1FFFE}\u{1FFFF}\u{2FFFE}\u{2FFFF}\u{3FFFE}\u{3FFFF}\u{4FFFE}\u{4FFFF}\u{5FFFE}\u{5FFFF}\u{6FFFE}\u{6FFFF}\u{7FFFE}\u{7FFFF}\u{8FFFE}\u{8FFFF}\u{9FFFE}\u{9FFFF}\u{AFFFE}\u{AFFFF}\u{BFFFE}\u{BFFFF}\u{CFFFE}\u{CFFFF}\u{DFFFE}\u{DFFFF}\u{EFFFE}\u{EFFFF}\u{FFFFE}\u{FFFFF}\u{10FFFE}\u{10FFFF}]/u; + export function spread(args) { const attributes = Object.assign({}, ...args); let str = ''; Object.keys(attributes).forEach(name => { + if (invalidAttributeNameCharacter.test(name)) return; + const value = attributes[name]; if (value === undefined) return; if (value === true) str += " " + name; - str += " " + name + "=" + JSON.stringify(value); + + const escaped = String(value) + .replace(/"/g, '"') + .replace(/'/g, '''); + + str += " " + name + "=" + JSON.stringify(escaped); }); return str; diff --git a/test/server-side-rendering/samples/attribute-escaped-quotes-spread/_expected.html b/test/server-side-rendering/samples/attribute-escaped-quotes-spread/_expected.html new file mode 100644 index 000000000000..bc31ce8bc352 --- /dev/null +++ b/test/server-side-rendering/samples/attribute-escaped-quotes-spread/_expected.html @@ -0,0 +1,4 @@ +
\ No newline at end of file diff --git a/test/server-side-rendering/samples/attribute-escaped-quotes-spread/main.html b/test/server-side-rendering/samples/attribute-escaped-quotes-spread/main.html new file mode 100644 index 000000000000..669d7664acff --- /dev/null +++ b/test/server-side-rendering/samples/attribute-escaped-quotes-spread/main.html @@ -0,0 +1,16 @@ +
+ + \ No newline at end of file diff --git a/test/server-side-rendering/samples/attribute-escaped-quotes/_expected.html b/test/server-side-rendering/samples/attribute-escaped-quotes/_expected.html new file mode 100644 index 000000000000..c3c9405d7b10 --- /dev/null +++ b/test/server-side-rendering/samples/attribute-escaped-quotes/_expected.html @@ -0,0 +1,3 @@ +
\ No newline at end of file diff --git a/test/server-side-rendering/samples/attribute-escaped-quotes/main.html b/test/server-side-rendering/samples/attribute-escaped-quotes/main.html new file mode 100644 index 000000000000..47e3466ab0de --- /dev/null +++ b/test/server-side-rendering/samples/attribute-escaped-quotes/main.html @@ -0,0 +1,12 @@ +
+ + \ No newline at end of file