Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@ All notable changes to this project are documented here. The format follows
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.0.0-prerelease.7] - 2026-11-09

### Fixed

- **`.md` fences render in `astro dev`.** On a `.md` page with no React island,
the fence script failed with `@vitejs/plugin-react can't detect preamble`,
because @astrojs/react installs React's fast-refresh preamble only on pages
with an island. The script now imports `@vitejs/plugin-react/preamble` before
the diagram code when no preamble is installed. Builds were unaffected; the
module is empty outside dev.

## [1.0.0-prerelease.6] - 2026-11-09

### Added
Expand Down
4 changes: 4 additions & 0 deletions docs/wiki/Troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ component). If it never mounts:
and a page script containing `[data-astroc4-fence]`.
3. A page rendered outside Astro's pipeline (raw HTML, a custom renderer) does not
get the injected script.
4. In `astro dev` on `1.0.0-prerelease.6`, the console shows
`@vitejs/plugin-react can't detect preamble`: @astrojs/react installs React's
fast-refresh preamble only on pages with an island. Upgrade to
`1.0.0-prerelease.7`, whose script installs it first. Builds are unaffected.


## Build fails: `Several LikeC4 projects exist (…); pass project="…"`
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@purview-dev/astroc4",
"version": "1.0.0-prerelease.6",
"version": "1.0.0-prerelease.7",
"description": "Interactive LikeC4 architecture diagrams for Astro and Starlight: <LikeC4View>, ```likec4 fences, and LikeC4 syntax highlighting derived from the live Langium grammar.",
"license": "MIT",
"author": {
Expand Down
20 changes: 20 additions & 0 deletions src/__tests__/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,26 @@ describe('likec4Integration', () => {
expect(injectScript).toHaveBeenCalledWith('page', expect.stringContaining(`import('${PACKAGE_NAME}/components/md-fences')`));
});

// In dev, @astrojs/react installs the fast-refresh preamble only on pages with an
// island, and a .md page has none: React components then throw "can't detect preamble".
it('installs the React preamble before it loads the .md fence components', async () => {
const injectScript = vi.fn();

await likec4Integration().hooks['astro:config:setup']!({
command: 'dev',
config: { root: pathToFileURL(process.cwd()), vite: {}, integrations: [] },
updateConfig: vi.fn(),
injectScript,
logger: stubLogger(),
} as never);

const script: string = injectScript.mock.calls.find(([stage]) => stage === 'page')![1];
const preamble = script.indexOf(`import('@vitejs/plugin-react/preamble')`);

expect(preamble).toBeGreaterThan(-1);
expect(preamble).toBeLessThan(script.indexOf(`import('${PACKAGE_NAME}/components/md-fences')`));
});

it('registers the fence transform with the site Markdown processor', async () => {
const { updateConfig } = await setup();

Expand Down
9 changes: 8 additions & 1 deletion src/integration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,18 @@ const OPTIMIZED_DEPENDENCIES = ['react/compiler-runtime'];
/**
* Mounts the fences of .md pages. Injected into every page, so React and LikeC4
* are only `import()`ed on a page that has a placeholder.
*
* In dev, @astrojs/react installs React's fast-refresh preamble only on pages with
* an island, and a .md page has none, so the script installs it first. Outside dev,
* @vitejs/plugin-react serves the preamble module empty.
*/
const MD_FENCES_SCRIPT = [
`const mountLikeC4Fences = () => {`,
` if (!document.querySelector('[data-astroc4-fence]:not([data-astroc4-mounted])')) return;`,
` import('${PACKAGE_NAME}/components/md-fences').then((module) => module.mountFences());`,
` const preamble = window.$RefreshReg$ ? Promise.resolve() : import('@vitejs/plugin-react/preamble');`,
` preamble`,
` .then(() => import('${PACKAGE_NAME}/components/md-fences'))`,
` .then((module) => module.mountFences());`,
`};`,
`if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', mountLikeC4Fences);`,
`else mountLikeC4Fences();`,
Expand Down
Loading