Skip to content

fix(demo): ship the highlighter's grammars so the docs site highlights - #134

Merged
tmccoy14 merged 1 commit into
mainfrom
fix/demo-grammars
Sep 11, 2026
Merged

fix(demo): ship the highlighter's grammars so the docs site highlights#134
tmccoy14 merged 1 commit into
mainfrom
fix/demo-grammars

Conversation

@tmccoy14

Copy link
Copy Markdown
Contributor

Every code block on the docs site renders plain. equality.eqtylab.io/components/code-block/ answers 404 for /_astro/grammars/json.js, bash.js, javascript.js and tsx.js.

Cause

The highlighter reaches a grammar through a computed dynamic import (microlighter/grammar-dependencies.js):

const getGrammar = language => import(`./grammars/${language}.js`)
  .then(module => module.default)
  .catch(() => null);

No bundler expands that specifier — it is inside node_modules, and Rollup emits no warning — so the 37 grammar modules are never written to the build. At runtime the browser resolves the path against the chunk's own URL, which Astro hashes into _astro/, giving /_astro/grammars/json.js. Nothing is there.

The .catch(() => null) then swallows it, and the highlighter reads null as "no grammar for this language", so the block silently loses its colour with nothing logged.

Confirmed locally before the fix: dist/_astro/code-block.Dhmj5oy2.js carries the unexpanded import, there is no dist/_astro/grammars/ directory, and no grammar module appears anywhere in dist/.

A dev server serves the modules from their real path in node_modules, which is why this only ever showed up on the deployed site.

Fix

A vite plugin emits the grammars beside whichever chunk carries the import, deriving the directory from that chunk's own fileName so it follows Astro's asset layout rather than hardcoding _astro.

It resolves the highlighter through the ui package, which is what declares it — packages/demo cannot resolve microlighter at all (MODULE_NOT_FOUND), since it only gets it transitively through the workspace.

Verification

Built locally and served, then checked in a real browser:

/_astro/grammars/json.js        -> 200 text/javascript
/_astro/grammars/bash.js        -> 200 text/javascript
/_astro/grammars/javascript.js  -> 200 text/javascript
/_astro/grammars/tsx.js         -> 200 text/javascript

code blocks on page:  8
grammar responses:    200 bash.js, 200 javascript.js, 200 json.js, 200 tsx.js, 200 typescript.js
CSS.highlights.size:  15
categories:           attribute-name, boolean, comment, constant, key, keyword, numeric,
                      operator, property, storage, string, support, tag, type, variable

37 grammars emitted to dist/_astro/grammars/. prettier and eslint clean.

Scope

This is the same defect already fixed in eqtylab/explorer#63 and Guardian's studio — the docs site is the third consumer hit by it. Each build has to place the files itself, because the specifier resolves against the importing chunk and bundling equality's dist relocates the path, so this package cannot fix it for consumers from the library side.

All three copies come out once the highlighter can be handed its grammars directly, which is worth raising upstream. If the plugin outlives that by long, it is worth exporting from this package as @eqtylab/equality/vite so there is one implementation instead of three.

No publish: this touches only packages/demo, and publish.yaml triggers on packages/ui/package.json. Merging does redeploy the docs, since docs.yaml watches packages/**.

🤖 Generated with Claude Code

Every code block on the docs site rendered plain, and
equality.eqtylab.io/components/code-block/ answered 404 for
/_astro/grammars/json.js and its siblings.

The highlighter reaches a grammar through import(`./grammars/${language}.js`),
a specifier no bundler expands, so the 37 grammar modules were never written
to the build. The loader catches the failed import and returns null, which
reads as "no grammar for this language" — so nothing is logged and the block
just loses its colour. A dev server serves the modules from their real path
in node_modules, which is why this only showed up on the deployed site.

A vite plugin now emits them beside whichever chunk carries that import,
which Astro hashes into _astro/. Resolved through the ui package, since that
is what declares the highlighter; the demo itself cannot resolve it.

Removable once the highlighter can be handed its grammars directly.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@tmccoy14 tmccoy14 self-assigned this Sep 11, 2026
@tmccoy14
tmccoy14 merged commit 7e7f393 into main Sep 11, 2026
1 check passed
@tmccoy14
tmccoy14 deleted the fix/demo-grammars branch September 11, 2026 13:53
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