Skip to content

Fix silently-disabled syntax highlighting; add copyable CodeEditor - #7

Merged
StanBarrows merged 1 commit into
mainfrom
fix/codemirror-language-duplication
Aug 3, 2026
Merged

Fix silently-disabled syntax highlighting; add copyable CodeEditor#7
StanBarrows merged 1 commit into
mainfrom
fix/codemirror-language-duplication

Conversation

@StanBarrows

Copy link
Copy Markdown
Contributor

The bug

rollupOptions.external listed @codemirror/state, view, lang-json and lang-markdown — but not @codemirror/language or @codemirror/commands. Rollup inlined those two into extra chunks (dist/index-CCl_-Asu.js, dist/index-3Q3F9MC4.js), so every consumer loaded two copies of @codemirror/language:

  • lang-json / lang-markdown resolve the app's node_modules copy and register their syntax tree against its facets;
  • syntaxHighlighting(defaultHighlightStyle) came from the bundled copy and read its facets.

It found nothing. Every CodeEditor in every consuming app rendered as flat monochrome text, with no error in the console. Storybook never showed it because it compiles from src against a single copy.

Changes

  • vite.config.ts — externalise every @codemirror/* package.
  • package.json — declare the optional peers in peerDependencies, not only in peerDependenciesMeta (which alone pins no version range).
  • scripts/verify-externals.mjs (new, wired into npm run build) — fails the build on any unexpected chunk in dist/ or any relative import out of flows.js. This is the only place the regression is observable; neither Storybook nor Playwright can see it. Verified it fails when the two externals are removed again.
  • CodePreview — never applied syntaxHighlighting at all. Now it does.
  • CodeEditor — new opt-in copyable prop (plus copyLabel / copiedMessage) pinning a CopyButton top-right. sticky, not absolute, so it stays put while a long document scrolls in autoHeight mode; copies the pretty-printed document rather than the raw modelValue.

Tests

  • CodeEditor.stories.tsJson and Markdown play functions assert some token is painted a colour other than the body text's. (Deliberately not "more than one token colour": a short JSON document may contain only one styled tag kind, since defaultHighlightStyle leaves plain propertyName uncoloured.)
  • interactions.spec.ts — a copyable editor writes its pretty-printed document to the clipboard.
  • Full suite: 198 passed. Lint and typecheck clean.

🤖 Generated with Claude Code

`rollupOptions.external` listed `@codemirror/state`, `view`, `lang-json` and
`lang-markdown`, but not `@codemirror/language` or `@codemirror/commands`, so
the library build inlined those two into extra chunks. Consumers therefore
loaded TWO copies of `@codemirror/language`: the language extensions
registered their syntax tree against the facets of the copy in the app's
node_modules, while `syntaxHighlighting(defaultHighlightStyle)` read the
facets of the bundled copy. It found nothing, and every CodeEditor in every
consuming app rendered as flat monochrome text — with no error, and with
Storybook unaffected because it compiles from `src` against a single copy.

- vite.config.ts: externalise every @codemirror/* package.
- package.json: declare the optional peers in `peerDependencies` too, not
  only in `peerDependenciesMeta` (the latter alone pins no version range).
- scripts/verify-externals.mjs: fail `npm run build` on any unexpected chunk
  or relative import in dist — the only place this class of bug is visible.
- CodePreview: it never applied `syntaxHighlighting` at all. Now it does.
- CodeEditor: new opt-in `copyable` prop (with `copyLabel` /`copiedMessage`)
  pinning a CopyButton over the top-right. Sticky, not absolute, so it stays
  put while a long document scrolls in `autoHeight` mode. It copies the
  pretty-printed document rather than the raw `modelValue`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@StanBarrows
StanBarrows merged commit 4e1f88f into main Aug 3, 2026
2 checks 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