import assert from "node:assert/strict"; import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; import test from "node:test"; import { buildMermaidRuntimeHtml, createMarkdownRenderer, } from "../src/actions/_shared/markdown.js"; import { clearTemplateCache } from "../src/actions/_shared/template-cache.js"; import { renderMarkdownWithTemplate } from "../src/actions/renderMarkdownWithTemplate/index.js"; test("mermaid fences render as mermaid blocks and track render state", () => { const renderer = createMarkdownRenderer({ resources: {} }); const html = renderer("```mermaid\nflowchart LR\nA-->B\n```"); assert.equal( html, '
flowchart LR\nA-->B
', ); assert.deepEqual(renderer.getLastRenderState(), { hasMermaid: true }); renderer("Regular paragraph"); assert.deepEqual(renderer.getLastRenderState(), { hasMermaid: false }); }); test("mermaid runtime html uses defaults and respects overrides", () => { const defaultRuntime = buildMermaidRuntimeHtml({ opts: { markdown: {} } }); assert.equal( defaultRuntime.includes( 'src="https://cdn.jsdelivr.net/npm/mermaid@11.13.0/dist/mermaid.min.js"', ), true, ); assert.equal(defaultRuntime.includes('"startOnLoad":false'), true); const customRuntime = buildMermaidRuntimeHtml({ opts: { markdown: { mermaid: { initialize: { theme: "forest" }, scriptSrc: "/static/vendor/mermaid.min.js", }, }, }, }); assert.equal( customRuntime.includes('src="/static/vendor/mermaid.min.js"'), true, ); assert.equal(customRuntime.includes('"theme":"forest"'), true); }); test("renderMarkdownWithTemplate injects mermaid runtime only when needed", async t => { const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "rhedyn-mermaid-")); const templateDir = path.join(tempDir, "templates"); const outDir = path.join(tempDir, "dist"); const partialDir = path.join(tempDir, "partials"); const mermaidMarkdownPath = path.join(tempDir, "diagram.md"); const plainMarkdownPath = path.join(tempDir, "plain.md"); const mermaidOutputPath = path.join(outDir, "diagram.html"); const plainOutputPath = path.join(outDir, "plain.html"); t.after(async () => { await fs.rm(tempDir, { force: true, recursive: true }); }); await fs.mkdir(templateDir, { recursive: true }); await fs.mkdir(partialDir, { recursive: true }); await fs.writeFile( path.join(templateDir, "page.hbs"), "{{{content}}}", "utf8", ); await fs.writeFile( mermaidMarkdownPath, "```mermaid\nflowchart LR\nA-->B\n```", "utf8", ); await fs.writeFile(plainMarkdownPath, "Plain paragraph.", "utf8"); clearTemplateCache(); const meta = { opts: { markdown: {}, outDir: outDir, runDir: tempDir, }, resources: {}, }; await renderMarkdownWithTemplate({ config: { defaultTemplate: "page", fileOutputPath: mermaidOutputPath, filePath: mermaidMarkdownPath, partialDirs: [partialDir], templateDirs: [templateDir], }, meta, }); await renderMarkdownWithTemplate({ config: { defaultTemplate: "page", fileOutputPath: plainOutputPath, filePath: plainMarkdownPath, partialDirs: [partialDir], templateDirs: [templateDir], }, meta, }); const mermaidHtml = await fs.readFile(mermaidOutputPath, "utf8"); const plainHtml = await fs.readFile(plainOutputPath, "utf8"); assert.equal(/class=(?:"mermaid"|mermaid)/.test(mermaidHtml), true); assert.equal(mermaidHtml.includes("mermaid.initialize"), true); assert.equal(mermaidHtml.includes("cdn.jsdelivr.net/npm/mermaid@11.13.0"), true); assert.equal(plainHtml.includes("mermaid.initialize"), false); assert.equal(plainHtml.includes("cdn.jsdelivr.net/npm/mermaid@11.13.0"), false); });