Skip to content

fix: trim surrounding whitespace in <title> same as <desc> - #2287

Open
si-kui-a wants to merge 1 commit into
svg:mainfrom
si-kui-a:fix/title-whitespace-trim
Open

fix: trim surrounding whitespace in <title> same as <desc>#2287
si-kui-a wants to merge 1 commit into
svg:mainfrom
si-kui-a:fix/title-whitespace-trim

Conversation

@si-kui-a

@si-kui-a si-kui-a commented Sep 3, 2026

Copy link
Copy Markdown

Fixes #2052.

Problem

textElems in plugins/_collections.js explicitly included 'title' alongside 'pre' and the genuinely-rendered text-content elements (text, tspan, etc.) — the elements where surrounding whitespace is semantically meaningful and must be preserved verbatim. <title> is a non-rendered accessibility/metadata element — like its sibling <desc> and <metadata> in elemsGroups.descriptive — where whitespace has no such significance, but it was the only member of that group also present in textElems.

lib/parser.js's sax.ontext handler branches on textElems membership: members keep raw (untrimmed) text, non-members get text.trim(). Since title was in textElems, <title> My Title </title> kept its leading/trailing whitespace while the structurally identical <desc> My Desc </desc> got trimmed to "My Desc" — the exact asymmetry reported in #2052.

Fix

Remove 'title' from the textElems Set literal (one line). Confirmed via repo-wide code search that only lib/parser.js and lib/stringifier.js reference textElems besides the definition itself, so the change is fully self-contained.

lib/stringifier.js also branches on the same textElems set to decide whether an element's children get pretty-mode indentation/newlines, so this also makes <title> format consistently with <desc> when js2svg pretty output is used — same underlying membership change, not a separate behavior. This surfaced as one existing fixture test failure (inlineStyles.16), whose expected output I've updated to match: <title>button</title> now gets the same indented multi-line layout <desc> already receives in pretty mode.

Testing

Added a regression test in lib/parser.test.js reproducing the exact before/after asymmetry from #2052 (title now trims identically to desc).

Ran the actual suite locally (not just hand-traced):

  • pnpm install --frozen-lockfile
  • pnpm vitest run — 521 passed, 3 skipped. Confirmed the new test genuinely catches the bug by temporarily reverting the fix and re-running (it fails as expected), then restored the fix and re-ran (passes).
  • pnpm lint (eslint + prettier) — clean.
  • pnpm typecheck (tsc) — clean.

Did not run test:bundles / test:regression (the full qa script's remaining steps) — those build the rollup bundle and pixel-diff a large external SVG corpus, which felt disproportionate to verify for a one-line Set membership change already covered by the unit/fixture suite above; happy to run them too if maintainers want that before merge.

🤖 Generated with Claude Code

https://claude.ai/code/session_01HG5wiw3Z8QdjNWb5bFDLiA

textElems in plugins/_collections.js explicitly included 'title' alongside
'pre' and the genuinely-rendered text-content elements (text, tspan, etc.),
which are the elements where surrounding whitespace is semantically
meaningful and must be preserved verbatim. <title> is a non-rendered
accessibility/metadata element -- like its sibling <desc> and <metadata> in
elemsGroups.descriptive -- where whitespace has no such significance, but it
was the only member of that group also present in textElems.

lib/parser.js's sax.ontext handler branches on textElems membership: members
keep raw (untrimmed) text, non-members get text.trim(). Since 'title' was in
textElems, <title>  My Title  </title> kept its leading/trailing whitespace
while the structurally identical <desc>  My Desc  </desc> got trimmed to
"My Desc" -- the exact asymmetry reported in svg#2052.

lib/stringifier.js also branches on the same textElems set to decide whether
an element's children get pretty-mode indentation/newlines, so this fix also
makes <title> format consistently with <desc> when js2svg pretty output is
used (see the updated inlineStyles.16 fixture below).

Fix: remove 'title' from the textElems Set literal (one line). No other file
references textElems besides parser.js/stringifier.js and the definition
itself (confirmed via repo-wide code search), so the change is fully
self-contained.

Added a regression test in lib/parser.test.js reproducing the exact
before/after asymmetry from svg#2052 (title now trims identically to desc).
Updated test/plugins/inlineStyles.16.svg.txt's expected output: with pretty
formatting, <title>button</title> now gets the same indented multi-line
layout <desc> already receives, which is the same underlying textElems
membership change, not a separate behavior.

Fixes svg#2052.

Verified for real, not just hand-traced: installed deps via
`pnpm install --frozen-lockfile` and ran `pnpm vitest run` (521 passed, 3
skipped -- confirmed the new test fails without the fix and passes with it
by temporarily reverting and re-running), `pnpm lint` (eslint + prettier,
clean). This is possible because Node/pnpm are available in the environment
this PR was prepared in, unlike the PHP-based WordPress plugin fixes from
the same session, which had to be hand-traced and disclosed as such.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HG5wiw3Z8QdjNWb5bFDLiA
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.

Contents of "title" tag should be trimmed

1 participant