Skip to content

Reconcile whitespace where request-time instances meet - #150

Merged
collin-thomas merged 3 commits into
mainfrom
fix-request-render-seam-whitespace
Nov 12, 2026
Merged

collin-thomas merged 3 commits into
mainfrom
fix-request-render-seam-whitespace

Conversation

@collin-thomas

Copy link
Copy Markdown
Collaborator

Follow-up to the fidelity failure on #148. Independent of that PR; based on main.

What was wrong

With minify.html on, each component instance rendered from a server or stream script is minified on its own, while the build minifies the page once. Where two instances were written with nothing between them, the request-time bytes could differ from the build's:

  • In a table, a removed comment leaves an empty <!----> separator. The space between two inline instances landed before the separator (</a> <!----> <a>) where the build puts it after (</a><!----> <a>).
  • An instance that leaves nothing at its edge (empty, or only comments and whitespace) was treated as its neighbor's neighbor, so the instance beside it kept a space the build drops, or two spaces where the build keeps one.

These are byte differences. A browser renders both forms the same.

What it was not

A comment at the top of a component file does not reach this code in a real build: component files are minified as they are loaded, so the comment is already gone. The fidelity test hit it because it loaded each root's components once (with minify.html off for the first root) and reused that list for variants that build with it on.

Changes

  • request-render.ts: the usage finalizer resolves each instance's neighbors past instances that leave nothing, then merges the whitespace and separators at each seam the way the build treats that stretch. One pass over the pieces' edges.
  • component-manifest-fidelity.integration.test.ts: components are loaded per variant, under that variant's config.

Tests

  • A matrix of 16 instance shapes (comments before, after and around inline, block and text roots; empty and whitespace-only instances), every pair plus some triples, in six placements (table cell, formatting element, <pre>, paragraph), each compared with minifyHtml of the same bytes.
  • A fast-check property over random instance sequences and surrounding author text, 3,000 runs.
  • Five of these fail without the renderer change.

Verification

  • pkg unit: 8,776 pass
  • pkg integration: pass (809)
  • pkg linear-time: 475 pass
  • Cloudflare adapter unit: 563 pass; Netlify adapter unit: 77 pass
  • typecheck, format, spelling: clean

🤖 Generated with Claude Code

collin-thomas and others added 3 commits November 12, 2026 02:52
With minify.html on, each component instance rendered from a server or
stream script is minified on its own. Where two were written with nothing
between them, the space each kept at its own edge could differ from the
build, which minifies the page once:

- in a table, where a removed comment leaves an empty separator, the space
  landed before the separator instead of after it;
- an instance that leaves nothing at its edge (empty, or only comments and
  whitespace) was treated as a neighbor, so the instance beside it kept or
  doubled a space the build drops.

The finalizer now resolves each instance's neighbors past instances that
leave nothing, and merges the whitespace and separators at each seam the
way the build treats that stretch. The differences were in bytes, not in
what a browser renders.

The fidelity test loaded each root's components once and reused them for
every variant, so some variants paired files loaded with minify.html off
with pages built with it on. No build does that (component files are
minified as they load), and it is how a comment at the top of a component
file reached this code. Components are now loaded per variant.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
The shop-preview environment only deploys branches matching "*", which a
name with a slash does not.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Shop preview: https://bascik-shop-pr-150.collin-inbox.workers.dev

Stripe sandbox payments are enabled. Paid orders create unconfirmed Printful drafts only. Production confirmation and customer email are blocked in test mode. No live domain changes.

@github-actions

Copy link
Copy Markdown

Site Previews

Built from c9641bd on fix-request-render-seam-whitespace. Preview URLs stay the same for this pull request and show its newest successful build. Their hostname prefix is pr-<number> (or the branch name when there is no pull request), not the hosting provider. None of them is production.

Site Hosting resource Links
Bascik docs (Cloudflare branch preview) bascik / · /components · /deployment/cloudflare
Cloudflare adapter (branch preview) cloudflare-adapter / · /catalog · /catalog-stream
Netlify adapter (branch preview) Netlify: bascik-netlify-adapter / · /catalog · /catalog-stream

Deploy run

@collin-thomas
collin-thomas merged commit 6e2534e into main Nov 12, 2026
84 checks passed
@collin-thomas
collin-thomas deleted the fix-request-render-seam-whitespace branch November 12, 2026 16:30

This branch was successfully deployed

1 active deployment
shop-preview — c9641bdc Deployed Nov 12, 2026 by collin-thomas via deploy-preview #161
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