mirror of
https://github.com/alexmickelson/canvasManagement.git
synced 2026-03-25 15:18:32 -06:00
mermaid diagrams are rendered as image tags with link to mermaid server rendering; uses pako for compression as expected
This commit is contained in:
@@ -32,6 +32,7 @@
|
|||||||
"marked-katex-extension": "^5.1.5",
|
"marked-katex-extension": "^5.1.5",
|
||||||
"mcp-handler": "^1.0.0",
|
"mcp-handler": "^1.0.0",
|
||||||
"next": "^15.3.5",
|
"next": "^15.3.5",
|
||||||
|
"pako": "^2.1.0",
|
||||||
"react": "^19.1.0",
|
"react": "^19.1.0",
|
||||||
"react-dom": "^19.1.0",
|
"react-dom": "^19.1.0",
|
||||||
"socket.io": "^4.8.1",
|
"socket.io": "^4.8.1",
|
||||||
|
|||||||
8
pnpm-lock.yaml
generated
8
pnpm-lock.yaml
generated
@@ -65,6 +65,9 @@ importers:
|
|||||||
next:
|
next:
|
||||||
specifier: ^15.3.5
|
specifier: ^15.3.5
|
||||||
version: 15.3.5(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
version: 15.3.5(@babel/core@7.28.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||||
|
pako:
|
||||||
|
specifier: ^2.1.0
|
||||||
|
version: 2.1.0
|
||||||
react:
|
react:
|
||||||
specifier: ^19.1.0
|
specifier: ^19.1.0
|
||||||
version: 19.1.0
|
version: 19.1.0
|
||||||
@@ -2628,6 +2631,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
|
resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
|
pako@2.1.0:
|
||||||
|
resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==}
|
||||||
|
|
||||||
parent-module@1.0.1:
|
parent-module@1.0.1:
|
||||||
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
|
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
@@ -5853,6 +5859,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
p-limit: 3.1.0
|
p-limit: 3.1.0
|
||||||
|
|
||||||
|
pako@2.1.0: {}
|
||||||
|
|
||||||
parent-module@1.0.1:
|
parent-module@1.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
callsites: 3.1.0
|
callsites: 3.1.0
|
||||||
|
|||||||
22
src/services/htmlMarkdownUtils.mermaid.test.ts
Normal file
22
src/services/htmlMarkdownUtils.mermaid.test.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { describe, it, expect } from 'vitest';
|
||||||
|
import { markdownToHtmlNoImages } from './htmlMarkdownUtils';
|
||||||
|
|
||||||
|
describe('markdownToHtmlNoImages', () => {
|
||||||
|
it('renders mermaid diagrams correctly using pako compression', () => {
|
||||||
|
const markdown = `
|
||||||
|
\`\`\`mermaid
|
||||||
|
graph TD;
|
||||||
|
A-->B;
|
||||||
|
A-->C;
|
||||||
|
B-->D;
|
||||||
|
C-->D;
|
||||||
|
\`\`\`
|
||||||
|
`;
|
||||||
|
const html = markdownToHtmlNoImages(markdown);
|
||||||
|
|
||||||
|
// The expected URL part for the graph above when compressed with pako
|
||||||
|
const expectedUrlPart = "pako:eNqrVkrOT0lVslJKL0osyFAIcbGOyVMAAkddXTsnJLYzlO0EZMPUOIPZSjpKualFuYmZKUpW1UolGam5IONSUtMSS3NKlGprAQJ0Gx4";
|
||||||
|
|
||||||
|
expect(html).toContain(`https://mermaid.ink/img/${expectedUrlPart}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
import { marked } from "marked";
|
import { marked } from "marked";
|
||||||
import DOMPurify from "isomorphic-dompurify";
|
import DOMPurify from "isomorphic-dompurify";
|
||||||
import markedKatex from "marked-katex-extension";
|
import markedKatex from "marked-katex-extension";
|
||||||
|
import pako from "pako";
|
||||||
import { LocalCourseSettings } from "@/features/local/course/localCourseSettings";
|
import { LocalCourseSettings } from "@/features/local/course/localCourseSettings";
|
||||||
|
|
||||||
const mermaidExtension = {
|
const mermaidExtension = {
|
||||||
@@ -22,9 +23,17 @@ const mermaidExtension = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
renderer(token: { text: string }) {
|
renderer(token: { text: string }) {
|
||||||
const base64 = btoa(token.text);
|
const data = JSON.stringify({
|
||||||
const url = `https://mermaid.ink/img/${base64}?type=svg`;
|
code: token.text,
|
||||||
console.log(token.text, url);
|
mermaid: { theme: "default" },
|
||||||
|
});
|
||||||
|
const compressed = pako.deflate(data, { level: 9 });
|
||||||
|
const binaryString = Array.from(compressed, (byte) =>
|
||||||
|
String.fromCharCode(byte)
|
||||||
|
).join("");
|
||||||
|
const base64 = btoa(binaryString).replace(/\+/g, "-").replace(/\//g, "_");
|
||||||
|
const url = `https://mermaid.ink/img/pako:${base64}?type=svg`;
|
||||||
|
// console.log(token.text, url);
|
||||||
return `<img src="${url}" alt="Mermaid diagram" />`;
|
return `<img src="${url}" alt="Mermaid diagram" />`;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -63,6 +72,8 @@ export function convertImagesToCanvasImages(
|
|||||||
}, {} as { [key: string]: string });
|
}, {} as { [key: string]: string });
|
||||||
|
|
||||||
for (const imageSrc of imageSources) {
|
for (const imageSrc of imageSources) {
|
||||||
|
if (imageSrc.startsWith("http://") || imageSrc.startsWith("https://"))
|
||||||
|
continue;
|
||||||
const destinationUrl = imageLookup[imageSrc];
|
const destinationUrl = imageLookup[imageSrc];
|
||||||
if (typeof destinationUrl === "undefined") {
|
if (typeof destinationUrl === "undefined") {
|
||||||
console.log(
|
console.log(
|
||||||
|
|||||||
Reference in New Issue
Block a user