astro-mermaid 2.0.3 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -75,6 +75,22 @@ npm install @mermaid-js/layout-elk
75
75
 
76
76
  Learn more about [Mermaid layouts](https://mermaid.js.org/config/layouts.html) or [The Eclipse Layout Kernel](https://eclipse.dev/elk/).
77
77
 
78
+ ## Astro Compatibility
79
+
80
+ `astro-mermaid` works across Astro 4, 5, 6, and 7 — no configuration needed. It
81
+ detects the active markdown engine at build time and registers its transform the
82
+ right way for each:
83
+
84
+ | Astro version | Markdown engine | How mermaid hooks in |
85
+ |---------------|-----------------|----------------------|
86
+ | 7+ | Sätteri (`@astrojs/markdown-satteri`, the new default) | a Sätteri **mdast plugin** |
87
+ | 6.4 – 6.x | `unified()` processor | remark + rehype plugins via `markdown.processor` |
88
+ | < 6.4 | legacy pipeline | `markdown.remarkPlugins` / `markdown.rehypePlugins` |
89
+
90
+ If you previously pinned `markdown.processor` to `unified()` purely to keep
91
+ mermaid working on Astro 7, you can now drop that workaround and let Astro use
92
+ its default Sätteri processor.
93
+
78
94
  ## Integration Order (Important!)
79
95
 
80
96
  When using with Starlight or other markdown-processing integrations, place mermaid **first**:
@@ -81,6 +81,40 @@ function remarkMermaidPlugin(options = {}) {
81
81
  };
82
82
  }
83
83
 
84
+ /**
85
+ * Sätteri mdast plugin to transform mermaid code blocks at the markdown level.
86
+ *
87
+ * Astro 7 ships `@astrojs/markdown-satteri` as the default markdown processor,
88
+ * which has its own mdast/hast plugin model instead of remark/rehype. This is
89
+ * the Sätteri equivalent of `remarkMermaidPlugin`: it visits `code` nodes and
90
+ * replaces mermaid blocks with a `<pre class="mermaid">` HTML node. Fixes #71.
91
+ *
92
+ * The visitor returns a plain `{ type: 'html' }` node — NOT Sätteri's
93
+ * `{ rawHtml }` escape hatch. `rawHtml` applies MDX-style brace escaping that
94
+ * corrupts mermaid syntax (e.g. a decision node `B{Decision}` becomes
95
+ * `B{'{'}Decision{'}'}`), whereas an `html` node is emitted verbatim.
96
+ *
97
+ * @returns {{ name: string, code: Function }} a Sätteri mdast plugin definition
98
+ */
99
+ function satteriMermaidPlugin(options = {}) {
100
+ return {
101
+ name: 'astro-mermaid',
102
+ code(node, context) {
103
+ if (node.lang !== 'mermaid') return;
104
+
105
+ if (options.logger) {
106
+ const file = context?.fileURL?.pathname || 'unknown file';
107
+ options.logger.info(`Sätteri transformed mermaid block in ${file}`);
108
+ }
109
+
110
+ return {
111
+ type: 'html',
112
+ value: `<pre class="mermaid">${escapeHtml(node.value)}</pre>`
113
+ };
114
+ }
115
+ };
116
+ }
117
+
84
118
  /**
85
119
  * Escape a string for safe use inside an HTML attribute value.
86
120
  */
@@ -255,24 +289,94 @@ export default function astroMermaid(options = {}) {
255
289
  viteOptimizeDepsInclude.push('@mermaid-js/layout-elk');
256
290
  }
257
291
 
258
- // Update markdown config to use both remark and rehype plugins
259
- updateConfig({
260
- markdown: {
261
- remarkPlugins: [
262
- ...(config.markdown?.remarkPlugins || []),
263
- [remarkMermaidPlugin, { logger }]
264
- ],
265
- rehypePlugins: [
266
- ...(config.markdown?.rehypePlugins || []),
267
- [rehypeMermaidPlugin, { logger }]
268
- ]
269
- },
270
- vite: {
271
- optimizeDeps: {
272
- include: viteOptimizeDepsInclude
292
+ const remarkEntry = [remarkMermaidPlugin, { logger }];
293
+ const rehypeEntry = [rehypeMermaidPlugin, { logger }];
294
+ const viteConfig = { optimizeDeps: { include: viteOptimizeDepsInclude } };
295
+
296
+ // Newer Astro versions expose the markdown engine on
297
+ // `config.markdown.processor`, and the deprecated top-level
298
+ // `markdown.remarkPlugins` / `markdown.rehypePlugins` arrays no longer
299
+ // run on it. We dispatch on the processor's `name`:
300
+ // - 'unified' (Astro 6.4+): pass plugins via `unified({...})`. Fixes #62.
301
+ // - 'satteri' (Astro 7+): register an mdast plugin via `satteri({...})`. Fixes #71.
302
+ // - no processor (Astro <6.4): fall back to the still-supported arrays.
303
+ // Branching on `name` (rather than importing both helper packages)
304
+ // matters because Astro 7 does not ship `@astrojs/markdown-remark`, so a
305
+ // blind import there would emit a misleading warning.
306
+ const existingProcessor = config.markdown?.processor;
307
+ let usedProcessor = false;
308
+
309
+ if (existingProcessor?.name === 'unified') {
310
+ try {
311
+ const { unified, isUnifiedProcessor } = await import('@astrojs/markdown-remark');
312
+ if (isUnifiedProcessor(existingProcessor)) {
313
+ const existingOptions = existingProcessor.options || {};
314
+ updateConfig({
315
+ markdown: {
316
+ processor: unified({
317
+ ...existingOptions,
318
+ remarkPlugins: [...(existingOptions.remarkPlugins || []), remarkEntry],
319
+ rehypePlugins: [...(existingOptions.rehypePlugins || []), rehypeEntry]
320
+ })
321
+ },
322
+ vite: viteConfig
323
+ });
324
+ usedProcessor = true;
273
325
  }
326
+ } catch (error) {
327
+ // Dynamic import failed, the unified processor helpers are not
328
+ // exported, or updateConfig rejected the processor — fall through
329
+ // to the legacy plugin arrays below.
330
+ logger.warn(
331
+ `Could not configure the unified markdown processor, falling back ` +
332
+ `to remark/rehype plugin arrays: ${error.message}`
333
+ );
274
334
  }
275
- });
335
+ } else if (existingProcessor?.name === 'satteri') {
336
+ try {
337
+ const { satteri, isSatteriProcessor } = await import('@astrojs/markdown-satteri');
338
+ if (isSatteriProcessor(existingProcessor)) {
339
+ const existingOptions = existingProcessor.options || {};
340
+ updateConfig({
341
+ markdown: {
342
+ processor: satteri({
343
+ ...existingOptions,
344
+ mdastPlugins: [
345
+ ...(existingOptions.mdastPlugins || []),
346
+ satteriMermaidPlugin({ logger })
347
+ ]
348
+ })
349
+ },
350
+ vite: viteConfig
351
+ });
352
+ usedProcessor = true;
353
+ }
354
+ } catch (error) {
355
+ // Dynamic import failed or updateConfig rejected the processor —
356
+ // fall through to the legacy plugin arrays below.
357
+ logger.warn(
358
+ `Could not configure the Sätteri markdown processor, falling back ` +
359
+ `to remark/rehype plugin arrays: ${error.message}`
360
+ );
361
+ }
362
+ }
363
+
364
+ if (!usedProcessor) {
365
+ // Update markdown config to use both remark and rehype plugins
366
+ updateConfig({
367
+ markdown: {
368
+ remarkPlugins: [
369
+ ...(config.markdown?.remarkPlugins || []),
370
+ remarkEntry
371
+ ],
372
+ rehypePlugins: [
373
+ ...(config.markdown?.rehypePlugins || []),
374
+ rehypeEntry
375
+ ]
376
+ },
377
+ vite: viteConfig
378
+ });
379
+ }
276
380
 
277
381
  // Validate and serialize icon packs for client-side use.
278
382
  // Only the pack name and either inline icon data or a JSON URL string
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro-mermaid",
3
- "version": "2.0.3",
3
+ "version": "2.1.0",
4
4
  "description": "An Astro integration for rendering Mermaid diagrams with automatic theme switching and client-side rendering",
5
5
  "type": "module",
6
6
  "main": "./astro-mermaid-integration.js",
@@ -43,6 +43,14 @@
43
43
  "mdast-util-to-string": "^4.0.0",
44
44
  "unist-util-visit": "^5.0.0"
45
45
  },
46
+ "overrides": {
47
+ "vite": "^7.3.5",
48
+ "esbuild": "^0.28.1",
49
+ "ip-address": "^10.1.1",
50
+ "js-yaml": "^4.2.0",
51
+ "picomatch": "^4.0.4",
52
+ "tar": "^7.5.16"
53
+ },
46
54
  "scripts": {
47
55
  "test": "vitest",
48
56
  "test:ui": "vitest --ui",
@@ -50,15 +58,17 @@
50
58
  "semantic-release": "semantic-release"
51
59
  },
52
60
  "devDependencies": {
61
+ "@astrojs/markdown-satteri": "^0.3.2",
53
62
  "@types/hast": "^3.0.4",
54
63
  "@vitest/ui": "^4.1.8",
55
- "astro": "^6.0.0",
64
+ "astro": "^6.4.6",
56
65
  "hast-util-from-html": "^2.0.3",
57
66
  "mermaid": "^11.0.0",
58
67
  "rehype-parse": "^9.0.1",
59
68
  "rehype-stringify": "^10.0.1",
60
69
  "remark-mermaid": "^0.2.0",
61
70
  "remark-parse": "^11.0.0",
71
+ "satteri": "^0.9.2",
62
72
  "semantic-release": "^25.0.3",
63
73
  "typescript": "^5.0.0",
64
74
  "unified": "^11.0.5",