import assert from 'node:assert/strict'; import test from 'node:test'; import { createMarkdownProcessor } from '@astrojs/markdown-remark'; import remarkMermaid from '../src/plugins/remark-mermaid.mjs'; import rehypeStaticMermaid from '../src/plugins/rehype-mermaid.mjs'; const renderer = await createMarkdownProcessor({ remarkPlugins: [remarkMermaid], rehypePlugins: [rehypeStaticMermaid], }); const fence = (diagram) => `\`\`\`mermaid\n${diagram}\n\`\`\``; test('multiple diagrams and both themes have distinct IDs and working arrow references', async () => { const sequence = fence('sequenceDiagram\nAlice->>Bob: Hello'); const source = [fence('flowchart LR\nA[中文标签] --> B[完成]'), sequence, sequence].join('\n\n'); const { code } = await renderer.render(source); assert.equal([...code.matchAll(/data-rendered="static"/g)].length, 3); assert.equal([...code.matchAll(/ match[1]); assert.equal(ids.length, new Set(ids).size); const markers = [...code.matchAll(/marker-(?:start|end)="url\(#([^)]*)\)"/g)]; assert(markers.length > 0); for (const match of markers) assert(ids.includes(match[1]), `Missing arrow marker: ${match[1]}`); }); test('invalid diagram rejects compilation with source position', async (t) => { // Astro logs the expected parse failure before throwing it. t.mock.method(console, 'error', () => {}); await assert.rejects( renderer.render(fence('flowchart LR\nA[Unclosed'), { fileURL: new URL('./invalid-mermaid.md', import.meta.url), }), (error) => error.fatal === true && error.ruleId === 'rehype-mermaid' && error.line === 1 && error.file.endsWith('invalid-mermaid.md'), ); });