|
@@ -0,0 +1,126 @@
|
|
|
|
|
+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,
|
|
|
|
|
+ '<pre class="mermaid">flowchart LR\nA-->B</pre>',
|
|
|
|
|
+ );
|
|
|
|
|
+ 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"),
|
|
|
|
|
+ "<html><body>{{{content}}}</body></html>",
|
|
|
|
|
+ "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);
|
|
|
|
|
+});
|