fix: follow-up formatting in `print()` for block-level elements (#17699)

Follow-up to #17319.

The `Fragment` visitor in `print()` only flushed sequences on
`RegularElement`, causing block-level elements (`Component`,
`SvelteHead`, `SvelteBoundary`, etc.) to be lumped into the same
sequence as adjacent nodes. This broke tools that programmatically
manipulate the AST (e.g.
[sveltejs/cli#915](https://github.com/sveltejs/cli/pull/915)).

The fix flushes before and after all block-level element types, ensuring
they get their own sequence and proper line separation.

### Before

```svelte
<svelte:head><title>Page Title</title></svelte:head><div>no space</div>
<Component /><Component />
<Component><span>child</span></Component><div>after component</div>
<svelte:boundary><div>boundary content</div></svelte:boundary><div>after boundary</div>
<!--comment--><div>after comment</div>
<div>before comment</div>
<!--comment-->

{#each items as item}
	<div>{item}</div>
{/each}<div>after each</div>

{@render children()}<div>after render</div>
<div>before render</div>
{@render children()}
```

### After

```svelte
<svelte:head><title>Page Title</title></svelte:head>
<div>no space</div>
<Component />
<Component />
<Component><span>child</span></Component>
<div>after component</div>
<svelte:boundary><div>boundary content</div></svelte:boundary>
<div>after boundary</div>
<!--comment-->
<div>after comment</div>
<div>before comment</div>
<!--comment-->

{#each items as item}
	<div>{item}</div>
{/each}

<div>after each</div>
{@render children()}
<div>after render</div>
<div>before render</div>
{@render children()}
```
pull/17693/head
jyc.dev 7 months ago committed by GitHub
parent 0565dca1f7
commit 86d5522096
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
"svelte": patch
---
fix: follow-up formatting in `print()` — flush block-level elements into separate sequences

@ -371,9 +371,23 @@ const svelte_visitors = {
}
}
} else {
const is_block_element =
child_node.type === 'RegularElement' ||
child_node.type === 'Component' ||
child_node.type === 'SvelteHead' ||
child_node.type === 'SvelteFragment' ||
child_node.type === 'SvelteBoundary' ||
child_node.type === 'SvelteDocument' ||
child_node.type === 'SvelteSelf' ||
child_node.type === 'SvelteWindow' ||
child_node.type === 'SvelteComponent' ||
child_node.type === 'SvelteElement' ||
child_node.type === 'SlotElement' ||
child_node.type === 'TitleElement';
if (is_block_element && sequence.length > 0) flush();
sequence.push(child_node);
if (child_node.type === 'RegularElement') flush();
if (is_block_element) flush();
}
}

@ -0,0 +1,25 @@
<svelte:head><title>Page Title</title></svelte:head><div>no space</div>
<Component /><Component />
<Component><span>child</span></Component><div>after component</div>
<svelte:boundary><div>boundary content</div></svelte:boundary><div>after boundary</div>
<!--comment--><div>after comment</div>
<div>before comment</div><!--comment-->
{#each items as item}<div>{item}</div>{/each}<div>after each</div>
{@render children()}<div>after render</div>
<div>before render</div>{@render children()}
<Component /> <div>with spaces</div>
<Component><span>child</span></Component> <div>spaces after component</div>
<!--comment--> <div>spaces after comment</div>
{@render children()} <div>spaces after render</div>
<Component />
<div>newline between</div>
<!--comment-->
<div>newline after comment</div>
{#each items as item}
<div>{item}</div>
{/each}
<div>newline after each</div>
{@render children()}
<div>after render</div>

@ -0,0 +1,42 @@
<svelte:head><title>Page Title</title></svelte:head>
<div>no space</div>
<Component />
<Component />
<Component><span>child</span></Component>
<div>after component</div>
<svelte:boundary><div>boundary content</div></svelte:boundary>
<div>after boundary</div>
<!--comment-->
<div>after comment</div>
<div>before comment</div>
<!--comment-->
{#each items as item}
<div>{item}</div>
{/each}
<div>after each</div>
{@render children()}
<div>after render</div>
<div>before render</div>
{@render children()}
<Component />
<div>with spaces</div>
<Component><span>child</span></Component>
<div>spaces after component</div>
<!--comment-->
<div>spaces after comment</div>
{@render children()}
<div>spaces after render</div>
<Component />
<div>newline between</div>
<!--comment-->
<div>newline after comment</div>
{#each items as item}
<div>{item}</div>
{/each}
<div>newline after each</div>
{@render children()}
<div>after render</div>
Loading…
Cancel
Save