From a6153f1d2a9168f8371149fbd775fa428c718a9b Mon Sep 17 00:00:00 2001 From: "svelte-triage-bot[bot]" <316883489+svelte-triage-bot[bot]@users.noreply.github.com> Date: Fri, 21 Aug 2026 22:16:30 +0200 Subject: [PATCH] fix: preserve whitespace after inline elements when printing (#18685) Fixes #18683. The printer previously trimmed leading whitespace after an inline element and failed to replace it when the fragment stayed on one line. Track that whitespace while grouping fragment nodes and emit a space for inline output, while retaining newline-based separation for multiline output. Adds regression coverage for whitespace following an inline element and updates existing print snapshots that exposed the same behavior. --- .changeset/gentle-spaces-print.md | 5 +++ packages/svelte/src/compiler/print/index.js | 37 +++++++++++-------- .../tests/print/samples/comment/output.svelte | 2 +- .../samples/expression-tag/output.svelte | 2 +- .../inline-element-whitespace/input.svelte | 1 + .../inline-element-whitespace/output.svelte | 1 + .../samples/regular-element/output.svelte | 2 +- 7 files changed, 31 insertions(+), 19 deletions(-) create mode 100644 .changeset/gentle-spaces-print.md create mode 100644 packages/svelte/tests/print/samples/inline-element-whitespace/input.svelte create mode 100644 packages/svelte/tests/print/samples/inline-element-whitespace/output.svelte diff --git a/.changeset/gentle-spaces-print.md b/.changeset/gentle-spaces-print.md new file mode 100644 index 0000000000..70b337fcd7 --- /dev/null +++ b/.changeset/gentle-spaces-print.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: preserve whitespace after inline elements when printing diff --git a/packages/svelte/src/compiler/print/index.js b/packages/svelte/src/compiler/print/index.js index 4a78854e1e..554e788654 100644 --- a/packages/svelte/src/compiler/print/index.js +++ b/packages/svelte/src/compiler/print/index.js @@ -587,15 +587,19 @@ const svelte_visitors = (comments, state) => ({ last?.type === 'Text' && /\s$/.test(last.data); - /** @type {AST.SvelteNode[][]} */ + /** @type {{ nodes: AST.SvelteNode[]; leading_whitespace: boolean }[]} */ const items = []; /** @type {AST.SvelteNode[]} */ let sequence = []; + let leading_whitespace = false; const flush = () => { - items.push(sequence); - sequence = []; + if (sequence.length > 0) { + items.push({ nodes: sequence, leading_whitespace }); + sequence = []; + leading_whitespace = false; + } }; for (let i = 0; i < node.nodes.length; i += 1) { @@ -624,6 +628,7 @@ const svelte_visitors = (comments, state) => ({ if (child_node.data.startsWith(' ') && prev && prev.type !== 'ExpressionTag') { flush(); + leading_whitespace = true; child_node.data = child_node.data.trimStart(); } @@ -662,20 +667,18 @@ const svelte_visitors = (comments, state) => ({ let multiline = false; let width = 0; - const child_contexts = items - .filter((x) => x.length > 0) - .map((sequence) => { - const child_context = context.new(); + const child_contexts = items.map(({ nodes, leading_whitespace }) => { + const child_context = context.new(); - for (const node of sequence) { - child_context.visit(node); - multiline ||= child_context.multiline; - } + for (const node of nodes) { + child_context.visit(node); + multiline ||= child_context.multiline; + } - width += child_context.measure(); + width += child_context.measure() + (leading_whitespace ? 1 : 0); - return child_context; - }); + return { context: child_context, leading_whitespace }; + }); multiline ||= width > LINE_BREAK_THRESHOLD; // Normally context.newline() also makes context.multiline true, but the below loop only @@ -687,14 +690,16 @@ const svelte_visitors = (comments, state) => ({ const prev = child_contexts[i]; const next = child_contexts[i + 1]; - context.append(prev); + context.append(prev.context); if (next) { - if (prev.multiline || next.multiline) { + if (prev.context.multiline || next.context.multiline) { context.margin(); context.newline(); } else if (multiline) { context.newline(); + } else if (next.leading_whitespace) { + context.write(' '); } } } diff --git a/packages/svelte/tests/print/samples/comment/output.svelte b/packages/svelte/tests/print/samples/comment/output.svelte index f2f97b65be..2cac5f4048 100644 --- a/packages/svelte/tests/print/samples/comment/output.svelte +++ b/packages/svelte/tests/print/samples/comment/output.svelte @@ -1,3 +1,3 @@ - diff --git a/packages/svelte/tests/print/samples/expression-tag/output.svelte b/packages/svelte/tests/print/samples/expression-tag/output.svelte index 9142a59631..5af5746d87 100644 --- a/packages/svelte/tests/print/samples/expression-tag/output.svelte +++ b/packages/svelte/tests/print/samples/expression-tag/output.svelte @@ -1 +1 @@ -{name}{count + 1} +{name} {count + 1} diff --git a/packages/svelte/tests/print/samples/inline-element-whitespace/input.svelte b/packages/svelte/tests/print/samples/inline-element-whitespace/input.svelte new file mode 100644 index 0000000000..e442ae954c --- /dev/null +++ b/packages/svelte/tests/print/samples/inline-element-whitespace/input.svelte @@ -0,0 +1 @@ +

Hello bold world

diff --git a/packages/svelte/tests/print/samples/inline-element-whitespace/output.svelte b/packages/svelte/tests/print/samples/inline-element-whitespace/output.svelte new file mode 100644 index 0000000000..e442ae954c --- /dev/null +++ b/packages/svelte/tests/print/samples/inline-element-whitespace/output.svelte @@ -0,0 +1 @@ +

Hello bold world

diff --git a/packages/svelte/tests/print/samples/regular-element/output.svelte b/packages/svelte/tests/print/samples/regular-element/output.svelte index 0cf7c2472f..f5fd3c8f42 100644 --- a/packages/svelte/tests/print/samples/regular-element/output.svelte +++ b/packages/svelte/tests/print/samples/regular-element/output.svelte @@ -1 +1 @@ -
bar

+
bar