diff --git a/.changeset/neat-boats-shake.md b/.changeset/neat-boats-shake.md new file mode 100644 index 000000000000..0df653d14c69 --- /dev/null +++ b/.changeset/neat-boats-shake.md @@ -0,0 +1,5 @@ +--- +"svelte": patch +--- + +fix: only escape characters in SSR template diff --git a/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js b/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js index d197ae3e8567..1492a9045a39 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js @@ -32,10 +32,11 @@ function t_string(value) { /** * @param {import('estree').Expression} value + * @param {boolean} [needs_escaping] * @returns {import('./types').TemplateExpression} */ -function t_expression(value) { - return { type: 'expression', value }; +function t_expression(value, needs_escaping = false) { + return { type: 'expression', value, needs_escaping }; } /** @@ -94,7 +95,8 @@ function serialize_template(template, out = b.id('out')) { } else if (template_item.type === 'expression') { const value = template_item.value; if (value.type === 'TemplateLiteral') { - last.value.raw += sanitize_template_string(value.quasis[0].value.raw); + const raw = value.quasis[0].value.raw; + last.value.raw += template_item.needs_escaping ? sanitize_template_string(raw) : raw; quasis.push(...value.quasis.slice(1)); expressions.push(...value.expressions); continue; @@ -198,7 +200,7 @@ function process_children(nodes, parent, { visit, state }) { } } - state.template.push(t_expression(b.template(quasis, expressions))); + state.template.push(t_expression(b.template(quasis, expressions), true)); } for (let i = 0; i < nodes.length; i += 1) { diff --git a/packages/svelte/src/compiler/phases/3-transform/server/types.d.ts b/packages/svelte/src/compiler/phases/3-transform/server/types.d.ts index b982c1e0c095..7f38932807e0 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/types.d.ts +++ b/packages/svelte/src/compiler/phases/3-transform/server/types.d.ts @@ -12,6 +12,7 @@ import type { ComponentAnalysis } from '../../types.js'; export type TemplateExpression = { type: 'expression'; value: Expression; + needs_escaping: boolean; }; export type TemplateString = { diff --git a/packages/svelte/tests/runtime-runes/samples/html-tag-escaping/_config.js b/packages/svelte/tests/runtime-runes/samples/html-tag-escaping/_config.js new file mode 100644 index 000000000000..f28077cbfbff --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/html-tag-escaping/_config.js @@ -0,0 +1,5 @@ +import { test } from '../../test'; + +export default test({ + html: `s s s \\u73` +}); diff --git a/packages/svelte/tests/runtime-runes/samples/html-tag-escaping/main.svelte b/packages/svelte/tests/runtime-runes/samples/html-tag-escaping/main.svelte new file mode 100644 index 000000000000..52ad0d8d1e24 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/html-tag-escaping/main.svelte @@ -0,0 +1,5 @@ +{@html `\u{73}`} +{@html '\u{73}'} +{@html "\u{73}"} + +\u{73}