Skip to content

Site.tsx export lost every quotation mark - #2

Merged
houko merged 1 commit into
mainfrom
fix/tsx-export-lost-quotes
Sep 20, 2026
Merged

houko merged 1 commit into
mainfrom
fix/tsx-export-lost-quotes

Conversation

@houko

@houko houko commented Sep 20, 2026

Copy link
Copy Markdown
Member

A regression from #1, found by exporting the thing rather than assuming it still worked.

Moving the testimonial quotes out of the markup and into content: open-quote fixed them on screen for eight languages, and silently broke the React export. That exporter reads the rendered DOM, so a mark that exists only in a stylesheet is invisible to it. What came out was a component with zero quotation marks and a quoted class pointing at a rule that does not ship with the file — while the file's own header promises no dependency beyond React.

before this PR:  <blockquote className="quoted text-[15px] leading-relaxed">
                   Endlich Zeit für Kreatives! …
                 </blockquote>          quote glyphs in the file: 0

What changed

The export resolves CSS generated content and writes it in as text:

  • open-quote / close-quote through the element's computed quotes pair, so German gets „…", French « … », Chinese 「…」
  • string literals as written
  • anything else — counters, attr(), images — left alone
  • quoted joins blk-in among the class names stripped on the way out, for the same reason: both name rules the file does not carry

The marks land on the same line as the text they wrap. JSX collapses the newline between two pieces of text into a single space, so the obvious implementation renders 「 like this 」. That is wrong in every language that does not ask for a space, and invisible unless you compare the strings — French wants the space and would have passed a casual look.

Verification

Not "it looks right". The exported file is compiled with esbuild and rendered with react-dom/server, then the <blockquote> is compared against what the live page shows, computed quotes included:

de  match  "„Endlich Zeit für Kreatives! Die Wochenendkurse sind"
fr  match  "« Le pain au levain d'Au Levain est incomparable. Cr"
zh  match  "「每次来都能感受到老板对咖啡的执着,那份用心真的能喝出来。」"
en  match  "“The instructor's patience and expertise made hand-t"

every exported component renders the page's own text

Seven new tests supply the pseudo-element styles jsdom will not compute. All six mutations of the new code turn them red, including the one that only breaks the spacing.

tsc --noEmit clean, 159 tests passing, npm run build clean.

Moving the testimonial quotes from the markup into `content: open-quote` fixed
them for eight languages on screen and silently broke the React export, which
reads the DOM and so cannot see a mark that only exists in a stylesheet. What
came out was a component with no quotes at all and a `quoted` class pointing at
a rule that does not ship with it — while the file's own header promises no
dependency beyond React.

The export now resolves generated content and writes it in as text: the quote
keywords through the element's computed `quotes` pair, string literals as
written, anything else (counters, attr, images) left alone. `quoted` joins
`blk-in` among the class names stripped on the way out, for the same reason —
both name rules the file does not carry.

The marks go on the same line as the text they wrap. JSX collapses the newline
between two pieces of text into a space, so the obvious version renders
`「 like this 」`, which is wrong in every language that does not ask for a
space and invisible unless you compare the strings.

Verified by compiling the exported file with esbuild and rendering it with
react-dom/server, then comparing the blockquote against what the page shows.
German, French, Chinese and English all round-trip exactly, spaces included.
The seven new tests supply pseudo-element styles jsdom will not compute, and
all six mutations of the new code turn them red.
@houko
houko merged commit 2c9b29b into main Sep 20, 2026
1 check passed
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.

1 participant