diff --git a/crates/tsv_svelte/src/printer/nodes/fragment_text_doc.rs b/crates/tsv_svelte/src/printer/nodes/fragment_text_doc.rs
index 1bb1c20d3..2834bf81a 100644
--- a/crates/tsv_svelte/src/printer/nodes/fragment_text_doc.rs
+++ b/crates/tsv_svelte/src/printer/nodes/fragment_text_doc.rs
@@ -613,6 +613,11 @@ impl<'a> Printer<'a> {
// of `break_before_wide_flow` below (never folded into `next_is_flow_or_tag`, whose
// other readers key the leading-side arms and the inline-sibling wrap on the flow set).
let next_is_rendering_block = next_node.is_some_and(is_control_flow_block);
+ // Whether the next sibling is a BLOCK element. Its own `handle_block_child` supplies the
+ // break in front of it, so a trailing space before it is spent on that break at EVERY
+ // position of this text — the deferred-trim arm below — never kept as the fill's own
+ // `line`. See that arm.
+ let next_is_block_el = next_node.is_some_and(|n| self.is_block_element_node(n));
// Whether the next sibling is a flowing inline element OR component (the
// Fill-idempotency boundary). Text before such a node ends its fill with a trailing
// `line` so the boundary breaks per width inside the fill (keeping the run idempotent),
@@ -994,7 +999,23 @@ impl<'a> Printer<'a> {
trim_right = true;
trailing_hardlines = if trailing_ws_newlines >= 2 { 2 } else { 1 };
} else if has_trailing_ws && !is_last && position.next_is_inline() {
- if is_first || next_is_flow_or_tag {
+ if next_is_block_el {
+ // BLOCK element follower: a block sibling takes its own line, so the space is
+ // spent on the break its `handle_block_child` emits (`break_before` reads the
+ // deferred trim), at every position of this text alike. A FIRST child used to
+ // fall through to the `trailing_line` arm below instead, keeping the block hugged
+ // on the text line (`text1 text2
block1
`) where the same text one
+ // sibling later broke before it — prettier-plugin-svelte's `handleTextChild`
+ // returns early for its first child before its block-follower trim, and tsv had
+ // mirrored the artifact. Of that boundary's three spellings only the first-child
+ // space hugged (the glued and newline spellings already break), so a spelling
+ // and a position were selecting the layout; and a block that renders multiline
+ // dangled its head on the text line, the one unit kind without the whole-unit
+ // drop. Cataloged: conformance_prettier_svelte.md §Svelte: Inline content
+ // block-style, `elements/block_after_spaced_text_prettier_divergence`.
+ trim_right = true;
+ *handle_whitespace_of_prev_text = true;
+ } else if is_first || next_is_flow_or_tag {
// One boundary, one answer: a first child, and a middle child before a tag or
// before a flowing inline element / component, all end the fill with a trailing
// `line`, so the boundary breaks per width INSIDE the fill — which is what keeps
@@ -1020,11 +1041,11 @@ impl<'a> Printer<'a> {
trailing_line = true;
// A first child's leading boundary is the parent's, already trimmed.
trim_right = !is_first;
- } else if !is_first {
- // Remaining inline callers: the follower is `is_inline_content` but neither
- // `is_inline_el_or_comp` nor a tag, which leaves exactly a BLOCK element. Wrap it
- // with `group([line, element])`. (Not a comment — see the arm below, which is
- // where a comment follower actually lands.)
+ } else {
+ // Remaining inline callers: the follower is `is_inline_content` but neither a
+ // block element, `is_inline_el_or_comp`, nor a tag. Wrap it with
+ // `group([line, element])`. (Not a comment — see the arm below, which is where a
+ // comment follower actually lands.)
trim_right = true;
*handle_whitespace_of_prev_text = true;
}
diff --git a/docs/conformance_prettier.md b/docs/conformance_prettier.md
index 50a73f973..4a4a56085 100644
--- a/docs/conformance_prettier.md
+++ b/docs/conformance_prettier.md
@@ -44,6 +44,7 @@ The fixture-pinned `◆prettier_bug` cases — where Prettier produces output th
- `` — ignores `singleQuote` and skips escaping → invalid output (`this={"a"b"}`) — [svelte_element_this_string](../tests/fixtures/svelte/special_elements/svelte_element_this_string_prettier_divergence/)
- `` — fails to collapse repeated whitespace — [svelte_element_class_whitespace](../tests/fixtures/svelte/special_elements/svelte_element_class_whitespace_prettier_divergence/)
- Space after block element — strands a leading space, non-idempotent — [space_after_block](../tests/fixtures/svelte/elements/space_after_block_prettier_divergence/)
+- Space before an inline element after block-then-text — deletes the rendered space (`text1 text2 x` → `text1 text2x`), a content change; idempotent on its own output, so nothing reveals it — [block_text_inline_space](../tests/fixtures/svelte/elements/block_text_inline_space_prettier_divergence/)
- `//` comment in a `
` / `
// c`, ``), so it renders as page text or is dropped on the next pass; non-idempotent either way — [ws_sensitive_attr_comment_line](../tests/fixtures/svelte/elements/ws_sensitive_attr_comment_line_prettier_divergence/)
- Constrained `infer … extends` operand parens — strips required parens → output fails to re-parse — [constrained_extends_parens](../tests/fixtures/typescript/types/infer/constrained_extends_parens_prettier_divergence/)
- Negative literal type sign comment (`-/* c */ 1`) — *adds* parens to hold the comment (`-(/* c */ 1)`), but no such type exists: `-` is a negative literal type only when the next token is a numeric/bigint literal → output fails to re-parse — [negative_literal_sign_comment](../tests/fixtures/typescript/types/negative_literal_sign_comment_prettier_divergence/)
diff --git a/docs/conformance_prettier_svelte.md b/docs/conformance_prettier_svelte.md
index 5e4fb52b4..31e503f36 100644
--- a/docs/conformance_prettier_svelte.md
+++ b/docs/conformance_prettier_svelte.md
@@ -64,6 +64,7 @@ the parser keeps the wider set deliberately. See
- svelte:element `this` — ◆prettier_bug — [svelte_element_this_string](../tests/fixtures/svelte/special_elements/svelte_element_this_string_prettier_divergence/). Anything between the `{` and a string literal (a paren, or a leading comment) fails prettier's `{`-precedes-literal check and collapses the binding to the plain attribute `this="x"` — which for a comment is also ◆content_preservation, since the collapsed form has nowhere to put it and prettier drops it.
- svelte:element class ws — ◆prettier_bug — [svelte_element_class_whitespace](../tests/fixtures/svelte/special_elements/svelte_element_class_whitespace_prettier_divergence/)
- Space after block element — ◆prettier_bug — [space_after_block](../tests/fixtures/svelte/elements/space_after_block_prettier_divergence/)
+- Space before an inline element after block-then-text — ◆prettier_bug ◆content_preservation — [block_text_inline_space](../tests/fixtures/svelte/elements/block_text_inline_space_prettier_divergence/) (`
b
⏎text1 text2 x` → prettier's `text1 text2x`, which renders `text1 text2x`: its `handleTextChild` trims the text's trailing space before an inline element but, with a block-element predecessor, sets the flag that would re-emit it to false, so nothing prints it — from either authoring, for a one-word text, and whether or not the run is the fragment's first; a tag or a component follower keeps the space under both. tsv keeps it as the element's per-width wrap, as everywhere else)
- Nested foreign `` body columns — ◆prettier_bug — [template_foreign_lang_nested](../tests/fixtures/svelte/elements/template_foreign_lang_nested_prettier_divergence/)
**Fill after inline**: Prettier's fill algorithm allows lines to exceed print width when text follows an inline element closing tag. Prettier produces 111 char lines, tsv breaks at exactly 100 chars.
@@ -286,11 +287,11 @@ Note this is **orthogonal to whether the element lays out multiline at all**, wh
### What the rule does not reshape, and where convergence stops
-Five things are **not** reshaped, because none is a mere spelling difference. A **comment** keeps its authored line (its position is authorship — folding one into a fill would relocate it across a semantic boundary, see [§Comment Position Philosophy](./conformance_prettier.md#comment-position-philosophy)); a **` `** keeps its authored line too — it *is* a rendered line break, so the source newline beside it mirrors the render rather than spelling a space, which is the one licence the flow rule runs on; it is line-owning exactly as a comment is (it bounds the run without sterilizing it, and its space spelling `text text` is never forced open), and prettier holds it as well, so this is agreement rather than divergence — [void_br_newline](../tests/fixtures/svelte/elements/void_br_newline/) pins every authoring and [inline_sibling_newline_flow](../tests/fixtures/svelte/elements/inline_sibling_newline_flow_prettier_divergence/)'s ` ` control carries the bounding-not-sterilizing half beside the comment's; a **blank line** still breaks (a Tier-2 authoring signal independent of render); a **block sibling** still takes its own line (blocks merely partition a fragment into inline runs, each of which flows on its own); and a **control-flow block** (`{#if}` / `{#each}` / `{#key}` / `{#await}` / `{#snippet}`) keeps its own line too — for `{#snippet}` that is unconditional (it is a declaration and takes its own line, [see below](#svelte-inline-content-block-style)), so only the four rendering heads remain in question here. The reason for that last one is neither "a block's width is not fixed" (a breaking `{expr}` tag expands mid-run too — `{f(⏎…⏎)}text4` — so width separates nothing) nor a bare appeal to a fixture. It is that **a flowed block has no way to pay an overflow except by tearing itself open.** An inline element that cannot fit drops to its own line *whole*, tags intact — that is what `break_before_wide_flow` buys, and it is what makes flowing safe for elements. A **spaced** block follower has that escape too (the spaced half of `break_before_wide_flow` admits control-flow blocks — [§Svelte: Blocks, "Multiline block head after spaced text"](#svelte-blocks)), but a **glued** one still does not: a glued block detaches by its own layout, so its weld survives only in the source (measuring it as a welded unit is a two-pass hazard), and the only break available there is the block's own head↔body seam — the body node lands on its own line and the flowed sibling text welds to the tail (`{#key key}⏎text6⏎{/key}text7`). The visible cost is that identical constructs then render differently by horizontal accident — in a run of five blocks, the two that happen to straddle the width boundary expand while their siblings stay inline. So the exclusion is a **consequence of a missing mechanism, not a property of blocks**: admitting them to the flow is gated on the remaining glued half of that whole-unit drop, not on re-litigating this predicate. Measured against the fixture suite, admitting blocks as-is converges ~39 more `authoring_audit` sites — the yield is real, which is exactly why the bar is the layout, not the count. A breaking `{expr}` tag, by contrast, expands *inside its own expression* (the call's argument list) and leaves both of its outer adjacencies untouched, so it flows without this hazard — a settled choice rather than a rough edge.
+Five things are **not** reshaped, because none is a mere spelling difference. A **comment** keeps its authored line (its position is authorship — folding one into a fill would relocate it across a semantic boundary, see [§Comment Position Philosophy](./conformance_prettier.md#comment-position-philosophy)); a **` `** keeps its authored line too — it *is* a rendered line break, so the source newline beside it mirrors the render rather than spelling a space, which is the one licence the flow rule runs on; it is line-owning exactly as a comment is (it bounds the run without sterilizing it, and its space spelling `text text` is never forced open), and prettier holds it as well, so this is agreement rather than divergence — [void_br_newline](../tests/fixtures/svelte/elements/void_br_newline/) pins every authoring and [inline_sibling_newline_flow](../tests/fixtures/svelte/elements/inline_sibling_newline_flow_prettier_divergence/)'s ` ` control carries the bounding-not-sterilizing half beside the comment's; a **blank line** still breaks (a Tier-2 authoring signal independent of render); a **block sibling** still takes its own line (blocks merely partition a fragment into inline runs, each of which flows on its own — after a spaced text as much as after any other sibling, at every position of that text, [see below](#svelte-inline-content-block-style)); and a **control-flow block** (`{#if}` / `{#each}` / `{#key}` / `{#await}` / `{#snippet}`) keeps its own line too — for `{#snippet}` that is unconditional (it is a declaration and takes its own line, [see below](#svelte-inline-content-block-style)), so only the four rendering heads remain in question here. The reason for that last one is neither "a block's width is not fixed" (a breaking `{expr}` tag expands mid-run too — `{f(⏎…⏎)}text4` — so width separates nothing) nor a bare appeal to a fixture. It is that **a flowed block has no way to pay an overflow except by tearing itself open.** An inline element that cannot fit drops to its own line *whole*, tags intact — that is what `break_before_wide_flow` buys, and it is what makes flowing safe for elements. A **spaced** block follower has that escape too (the spaced half of `break_before_wide_flow` admits control-flow blocks — [§Svelte: Blocks, "Multiline block head after spaced text"](#svelte-blocks)), but a **glued** one still does not: a glued block detaches by its own layout, so its weld survives only in the source (measuring it as a welded unit is a two-pass hazard), and the only break available there is the block's own head↔body seam — the body node lands on its own line and the flowed sibling text welds to the tail (`{#key key}⏎text6⏎{/key}text7`). The visible cost is that identical constructs then render differently by horizontal accident — in a run of five blocks, the two that happen to straddle the width boundary expand while their siblings stay inline. So the exclusion is a **consequence of a missing mechanism, not a property of blocks**: admitting them to the flow is gated on the remaining glued half of that whole-unit drop, not on re-litigating this predicate. Measured against the fixture suite, admitting blocks as-is converges ~39 more `authoring_audit` sites — the yield is real, which is exactly why the bar is the layout, not the count. A breaking `{expr}` tag, by contrast, expands *inside its own expression* (the call's argument list) and leaves both of its outer adjacencies untouched, so it flows without this hazard — a settled choice rather than a rough edge.
**The comment exclusion is held on each SIDE independently, and it is where this section's convergence deliberately stops rather than a divergence from prettier.** "Keeps its authored line" is the symmetric reading, and it is the weaker one: the newline *after* a comment holds the following run off the comment's line exactly as the newline *before* it holds the comment off the preceding run's, so a one-sided authoring is a fixed point on that side alone — `text1 ⏎text2` and `text1⏎ text2` both stay, at any width, beside the both-sided form — and beside the form with a newline on neither side, which stays hugged, because the rule HOLDS an authored line rather than FORCING one around a comment (that fourth authoring is the pair's null control: it varies the same dimension, so without it an implementation that always broke both sides would satisfy the other three). Prettier holds all four too, so there is nothing to catalog against it here; the exclusion's whole cost is that these authorings do not converge with each other, which is the price [§Comment Position Philosophy](./conformance_prettier.md#comment-position-philosophy) is already paid for. ⚠️ **It is comment-specific, and the discriminating control has to hold the SITE fixed** — an element or a tag in the identical position flows (`text1 a⏎text2` collapses). Two *other* gates in this rule suppress flow for every sibling kind at once (the prose gate below, and the reflowable-fill suppression the paragraph after it, which closes this rule by making the element multiline for a reason it does not read), so an element control run in a shape either one already catches keeps its lines regardless of what sits there, and reads back as "the newline rule is not about comments" when it is. — [inline_separator_comment_newline](../tests/fixtures/svelte/elements/inline_separator_comment_newline/) pins all four comment authorings, and is deliberately **not** a divergence fixture: prettier holds each one too, so there is nothing for an `output_prettier` to claim. The element twins of the one-sided pair are [inline_sibling_newline_flow](../tests/fixtures/svelte/elements/inline_sibling_newline_flow_prettier_divergence/)'s `prettier_variant_newline_after` / `prettier_variant_newline_before`, which converge on its input — that pair beside these four is the whole control. ⚠️ **The exclusion is scoped to the comment's OWN two boundaries: it BOUNDS the run, it does not STERILIZE one.** The runs a comment separates keep flowing on their own — `text1 a text2⏎⏎text3 b text4` converges from every isolated authoring of those spans, with only the comment's two newlines held. Nothing distinguishes that from the wider reading ("a run holding a comment keeps every line") unless a control puts a flowing run *beside* the comment and re-authors it: a control whose run is already hugged in every file is a fixed point under either rule and cannot separate them, which is why [inline_sibling_newline_flow](../tests/fixtures/svelte/elements/inline_sibling_newline_flow_prettier_divergence/)'s comment-boundary control is re-authored in all three `prettier_variant_*` files rather than held. The same is true of every other run-bounding sibling (that fixture's block-sibling control carries the parallel pin), so the property belongs to run boundaries in general and not to comments — what is comment-specific is only the *holding*. The practical consequence is that a comment tsv has broken onto its own line for **width** ([fill_break_before_comment_spaced_long](../tests/fixtures/svelte/elements/fill_break_before_comment_spaced_long_prettier_divergence/)) reaches a second fixed point when the run after it was authored on the next line — the same document, differing only in whether that run shares the comment's line.
-**The rule's boundary is the presence of a `fill` to reflow into, not the shape of the separator node.** Flowing means reflowing a run per width, and a run reflows only where there is prose for a `fill` to pack. So the rule reaches a whitespace-only separator standing *between two non-text siblings* — `text1⏎a` and `a⏎b` converge alike — **when that separator's inline run holds prose, which is at least two words**, and not otherwise. A run of pure elements or tags (`⏎`) keeps its authored lines: with no prose its newlines are the only structure the author has, collapsing them packs independent siblings onto one line, and on a short run the collapse cascades into the parent element's own hug decision — an outright idempotency break (`` re-hugs on the second pass once its children fold). **A run holding a single word is a label, not prose, and keeps its lines the same way** — `⏎Delete⏎{n}`, `hue:⏎`, `⏎private`, `chars⏎{n}`, `{@render icon()}⏎text1` are a caption beside its icon, a field beside its unit, a label beside its value, and a fill needs a phrase to reflow into; prettier holds every such shape too, so the hold is agreement. Only the run's TEXT counts: an expression tag renders as a value, and a word beside one is a label like any other. The count is **run-level and never node-local**: at a content text's edge run the node beside the sibling is often the one-word tail a previous wrap left behind (`…x⏎prop.`), which a node-local test would hold alone on its line — the accretion the flow rule exists to heal, run in reverse — where the run's total sees the sentence it belongs to, so a one-word node ending a real sentence flows with it. The cliff is two words (`Remember me` still packs), where label and prose genuinely blur, and the count is the most words any **one** text node carries, never a sum over the run: words in two different text nodes are separated by a sibling, and that separation is the author's, so two one-word captions in one run (`text1⏎⏎text2⏎`, an icon-and-caption list) are two labels and hold — a sum packs every such list the moment it holds two entries. The cost is a sentence spelled entirely as one-word fragments between siblings (`text1⏎inline1⏎text2`), which holds; real prose has a two-word node somewhere in its run. The cliff's own cost is the mirror: one two-word caption in a list of one-word captions is prose, and packs its neighbours with it (`⏎text1⏎⏎text2 text3` → one line) — pinned as a control so it is recorded, not discovered. The gate is asked identically at all three of the rule's sites — the whitespace-only separator and a content text's leading and trailing runs — and **it is a hold, never a forced break**: it decides whether an authored newline may reflow, and says nothing about an authored space. So a run's space spelling stays inline everywhere, whatever the run holds and whatever precedes it — beside an element, a void element, a component, a render/html tag, inside a content text, and between two **tags**, where the whitespace-only separator defers to the tag's per-width group as a prose run's does: the space-spelled tag separator reads **no run gate and no neighbour gate at all**, so a wordless `{a} {b}` packs exactly as `text1 {a} {b}` does, in every container, and a tag after a comment, a ` ` or a control-flow block keeps its authored space exactly as an inline element or component does there (` x` and ` {x}` hug alike; the comment's own line is what the NEWLINE spelling holds). Prettier's `line` between a tag and its neighbour breaks with the container whatever the run holds, so a space-spelled tag after any sibling but text in a multiline container is a divergence of the same family as the prose tag pair below — tsv packs where prettier splits. **And the follower never turns a space into a newline either**: a space before a **comment**, a `{@debug}` or a control-flow block that renders inline is that follower's own per-width wrap after any sibling — an element, a component, a tag, another comment — exactly as it already was after text, so `a ` keeps its space as `text1 ` does, where prettier breaks the former with the container; the NEWLINE spelling is what holds a comment's line, on both of its sides. Only a **block element** on either side of a space still breaks it (its own break already separates them, and a wrap would strand a space after it), and a unit that **renders multiline** drops to a fresh line whole — the wrap's group breaks on its own hardlines — so a space is decided by the follower's kind alone, for every predecessor but a block. — [inline_sibling_space_before_bounding](../tests/fixtures/svelte/elements/inline_sibling_space_before_bounding_prettier_divergence/) (comment, `{@debug}` and inline-block followers after an element, a component and a tag, in a block and at the root, a comment spaced on both sides, a two-comment run; `variant_newline` the held control, with the multiline block, the block predecessor and the comment's own 100/101 as the parity controls), [inline_adjacent_comment_space_long](../tests/fixtures/svelte/elements/inline_adjacent_comment_space_long_prettier_divergence/) (the same follower at the ELEMENT's width boundary: the 101-char `
` goes block-style and the comment stays on its 97-wide content line). — [inline_sibling_newline_label_hold](../tests/fixtures/svelte/elements/inline_sibling_newline_label_hold_prettier_divergence/) (every label shape held, the caption list and the fragmented sentence among them; the two-word cliff, the one-word sentence tail, the phrase's reach across a whole run and the cliff in a list flowing as `prettier_variant_newline`; `variant_space` the null control), [inline_tag_pair_space](../tests/fixtures/svelte/elements/inline_tag_pair_space_prettier_divergence/) (the space-spelled pair — wordless, before and after a word, at the root, and led by an inline element or a component — with the newline spelling as the held control), [inline_tag_pair_space_container](../tests/fixtures/svelte/elements/inline_tag_pair_space_container_prettier_divergence/) (the same pair in every container kind), [inline_tag_pair_space_bounded](../tests/fixtures/svelte/elements/inline_tag_pair_space_bounded_prettier_divergence/) (the pair after a comment, a ` `, a multiline control-flow block and a multiline element — the space hugs the neighbour's line as an element's would and the newline spelling is held — with a block-element predecessor and a line-owning follower as the controls that still break), [inline_tag_pair_space_welded](../tests/fixtures/svelte/elements/inline_tag_pair_space_welded_prettier_divergence/) (a welded unit — a glued pair, an ` `, a word glued to both tags — beside a spaced boundary: the weld holds and the space packs), [inline_tag_pair_space_expr_break](../tests/fixtures/svelte/elements/inline_tag_pair_space_expr_break_prettier_divergence/) (a first tag whose expression breaks — the second hugs its closing `)}` line per width, as an element or a word does after a broken tag; the newline spelling held and a breaking second tag travelling whole are the controls), and [inline_sibling_newline_label_hold_long](../tests/fixtures/svelte/elements/inline_sibling_newline_label_hold_long_prettier_divergence/) (the hold at the print-width boundary: the space spelling stays at 100 and wraps at 101 onto the newline spelling, which is then held — the one-way ratchet the hold accepts, prettier's too, though prettier tolerates the 101-char line itself; the wrap is the Elements catalog's fill-boundary divergence). What counts as a word is the fill's own item split over the SOURCE BYTES — an NBSP-joined pair is one word, and so is an entity-encoded space (`text1 text2` is one unbreakable fill item under both formatters, so the count must not promise a seam the fill has not got; the render-side question, whether a node is a separator in content's clothing, reads the decoded text, and the two axes are deliberately distinct), punctuation alone is a word, a hyphenated pair is one, a word glued to a tag is one — and the cliff is the same at a void element (` text1 text2`, the checkbox-and-caption shape): [inline_sibling_newline_prose_words](../tests/fixtures/svelte/elements/inline_sibling_newline_prose_words_prettier_divergence/). The container is not an axis on the holding side either — the root, an inline element, a list item, a table cell, a control-flow block body and a snippet body hold a one-word run alike: [inline_sibling_newline_label_hold_container](../tests/fixtures/svelte/elements/inline_sibling_newline_label_hold_container_prettier_divergence/). A run is bounded by whatever owns its own line — a block element, a control-flow block, a comment, a ` ` — and by an authored blank line **wherever the parser put it**: in a whitespace-only node between two siblings, or folded into the edge whitespace of the content text beside it, so that one document does not count two ways by that accident. The count is per run, so a fragment's prose does not license flow in a neighbouring run that has none — a two-word run on one side of a boundary flows right up to it, and the one-word run on the other holds: [inline_sibling_newline_run_bounded](../tests/fixtures/svelte/elements/inline_sibling_newline_run_bounded_prettier_divergence/) (every boundary kind, the blank in both spellings, prose on one side and a label on the other in each, the prose half flowing as `prettier_variant_newline`; and the unbounded twin, where the label flows with the prose). An authored blank INSIDE one text node is not a boundary — a run is a partition of nodes — and the fill collapses it under both formatters, so the sibling newlines beside such a node flow with its prose where prettier holds them: [inline_sibling_newline_interior_blank](../tests/fixtures/svelte/elements/inline_sibling_newline_interior_blank_prettier_divergence/). Bounding is not sterilizing, though: a run that *does* hold prose still flows right up against the bounding sibling, and the two spellings of that ("its own boundaries are held" vs "every line near it is held") are only separated by a control that re-authors the neighbouring run — see the comment-boundary note above. Two mechanics keep this sound and are load-bearing. First, a flowing single newline takes the **space arm verbatim** rather than a parallel one: emitting a different collapsible form for the newline than for the space it claims to equal makes the formatter write a newline that its next pass re-reads as flowable and collapses. Second, the boundary must defer to the next sibling for every follower kind — a tag, a comment, a `{@debug}`, a control-flow block — as it always did for an element: a bare `line` in the child list resolves all-or-nothing with the parent group, and a multiline fragment's parent group is always broken, so without that the one boundary owned by a content text's `fill` would flow while the rest of the same run hard-broke. The deferral is unconditional (a block-element predecessor excepted, whose own break already separates them; a declaration takes its own line): a space asks nothing about what precedes it — a comment's line is authorship, and it is the NEWLINE spelling that holds it. Note `authoring_audit` is blind to the tag half: both spellings agree there whichever form the rule picks — on the flowed form now, on the hard-broken one under a narrower gate — so it scores them as converging either way. — [inline_sibling_newline_flow](../tests/fixtures/svelte/elements/inline_sibling_newline_flow_prettier_divergence/) (an inline element, a component and all three tag kinds — expression, render and `{@html}`, one predicate arm each — plus all five controls) and [expressions/angle_escaped](../tests/fixtures/svelte/expressions/angle_escaped_prettier_divergence/) (the tag-separator case, where prettier's plain `line` holds each tag on its authored line), and the shapes the rule reaches across the suite: [fill_text_inline_collapse](../tests/fixtures/svelte/elements/fill_text_inline_collapse_prettier_divergence/), [root_text_newline_inline](../tests/fixtures/svelte/elements/root_text_newline_inline_prettier_divergence/), [block_text_multiline_collapse](../tests/fixtures/svelte/elements/block_text_multiline_collapse_prettier_divergence/), [inline_attrs_multiline_content](../tests/fixtures/svelte/elements/inline_attrs_multiline_content_prettier_divergence/), [components/root_with_text](../tests/fixtures/svelte/components/root_with_text_prettier_divergence/). **The CONTAINER holding the run is not an axis either**, and no fixture above varies it to say so — nearly all put the flowing run in a block container, and the one inline container that carries one ([inline_attrs_multiline_content](../tests/fixtures/svelte/elements/inline_attrs_multiline_content_prettier_divergence/)) reaches multiline past a 99-char attribute line, confounding the kind with the attribute wrap that fixture exists to test. An inline element reaches the multiline form by a *different boundary rule* — both-or-neither, rather than the block's leading boundary alone — so it is the kind where a container-keyed rule would show, and the run lays out identically once there: [container_kind_newline_flow](../tests/fixtures/svelte/elements/container_kind_newline_flow_prettier_divergence/) holds one run fixed and varies the container across all four kinds — `