Skip to content

fix: preserve line feed character references in attribute values - #18691

Open
giaBaoJS wants to merge 1 commit into
sveltejs:mainfrom
giaBaoJS:fix/attribute-line-feed-entity
Open

fix: preserve line feed character references in attribute values#18691
giaBaoJS wants to merge 1 commit into
sveltejs:mainfrom
giaBaoJS:fix/attribute-line-feed-entity

Conversation

@giaBaoJS

Copy link
Copy Markdown

Fixes #15555

<span title="A&#x0A;B"> currently renders with a space instead of a line break, so there is no way to get a newline into an attribute value using a character reference. &#x0D; works, and title={'A\nB'} works, but the LF entity silently loses the newline.

Why it happens

decode_character_references() already knows whether it is decoding an attribute value — is_attribute_value is threaded in from element.js (true) and text.js (false) — but the flag stops at the call to validate_code() on line 63. validate_code() unconditionally maps code point 10 to 32:

// line feed becomes generic whitespace
if (code === 10) {
	return 32;
}

That is correct for text content, where the line feed would be collapsed along with the surrounding whitespace anyway, but an attribute value is not whitespace-normalized, so the collapse is simply lossy there.

The fix

Pass is_attribute_value down to validate_code() and skip the collapse when it is set. Nothing else changes: every other code point takes the same path it did before, and text content still collapses.

Changes

  • 1-parse/utils/html.js: thread is_attribute_value into validate_code() and guard the LF collapse with it
  • tests/parser-legacy/samples/convert-entities-line-feed: AST snapshot pinning both halves — <p title="A&#x0A;B">A&#x0A;B</p> parses to data: "A\nB" for the attribute and data: "A B" for the text
  • tests/runtime-runes/samples/html-entity-line-feed: the reported case end to end — hex and decimal LF entities on title, an LF entity in a prop passed to a component, and a &copy; control to show ordinary entities still decode

Test plan

pnpm test
#  Test Files  34 passed (34)
#  Tests  7756 passed | 69 skipped (7825)
#  (7753 on main, +3 from the new fixtures)

pnpm lint                    # clean
pnpm --filter svelte check   # clean

Reverting just the html.js change turns both fixtures red:

FAIL packages/svelte/tests/runtime-runes/test.ts > html-entity-line-feed (dom)
FAIL packages/svelte/tests/runtime-runes/test.ts > html-entity-line-feed (hydrate)
AssertionError: expected 'A B' to equal 'A\nB'

FAIL packages/svelte/tests/parser-legacy/test.ts > convert-entities-line-feed
-  "data": "A\nB",
+  "data": "A B",

The parser snapshot is deliberately the one that guards against over-fixing: in that diff only the attribute data moves, the text data stays "A B". Replacing the guard with a wholesale removal of the LF rule flips the other half red instead, on the text node, so the fixture pins the behaviour in both directions.

One thing I noticed while writing the runtime test but did not touch, since it is unrelated and predates this change: for text content the client backend inlines the raw source into the template ($.from_html(\A B`)) and lets the browser decode it, so the DOM ends up with a real newline, while SSR emits the collapsed A B`. That client/SSR divergence is identical before and after this PR. Happy to open a separate issue for it if it is worth tracking.

@pkg-svelte-dev

Copy link
Copy Markdown

Install the latest version of svelte from 5a40c98:

pnpm add https://pkg.svelte.dev/svelte/c/5a40c98d5d5e70e3134d5afa892a565bf17cd2e0

Open in pkg.svelte.dev: https://pkg.svelte.dev/repos/svelte/pr/18691

Note

This PR is from a fork. A maintainer must approve approve each commit before it can be built and installed.

@changeset-bot

changeset-bot Bot commented Aug 23, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 5a40c98

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
svelte Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Svelte disrespects line break entities, regardless of preserveWhitespace option

1 participant