feat(mermaid): start implementing a basic linter

This commit is contained in:
Elian Doran 2025-03-22 00:38:05 +02:00
parent c416fca88a
commit 44db1545a1
No known key found for this signature in database
3 changed files with 60 additions and 5 deletions

View File

@ -207,6 +207,8 @@ declare global {
modeInfo: ModeInfo[];
findModeByMIME(mime: string): ModeInfo;
autoLoadMode(instance: CodeMirrorInstance, mode: string)
registerHelper(type: string, filter: string | null, callback: (text: string, options: object) => unknown);
Pos(line: number, col: number);
}
interface ModeInfo {

View File

@ -0,0 +1,43 @@
import mermaid from "mermaid";
interface MermaidParseError extends Error {
hash: {
text: string;
token: string;
line: number;
loc: {
first_line: number;
first_column: number;
last_line: number;
last_column: number;
};
expected: string[]
}
}
export default function registerErrorReporter() {
CodeMirror.registerHelper("lint", null, (async (text, options) => {
if (!text.trim()) {
return [];
}
try {
await mermaid.parse(text);
} catch (e: unknown) {
console.warn("Got validation error", JSON.stringify(e));
const mermaidError = (e as MermaidParseError);
const loc = mermaidError.hash.loc;
return [
{
message: mermaidError.message,
severity: "error",
from: CodeMirror.Pos(loc.first_line - 1, loc.first_column - 1),
to: CodeMirror.Pos(loc.last_line - 1, loc.last_column - 1)
}
];
}
return [];
}));
}

View File

@ -1,9 +1,9 @@
import type { MermaidConfig } from "mermaid";
import library_loader from "../../services/library_loader.js";
import { loadElkIfNeeded, postprocessMermaidSvg } from "../../services/mermaid.js";
import AbstractSvgSplitTypeWidget from "./abstract_svg_split_type_widget.js";
let idCounter = 1;
let registeredErrorReporter = false;
export class MermaidTypeWidget extends AbstractSvgSplitTypeWidget {
@ -14,19 +14,29 @@ export class MermaidTypeWidget extends AbstractSvgSplitTypeWidget {
async renderSvg(content: string) {
const mermaid = (await import("mermaid")).default;
await loadElkIfNeeded(mermaid, content);
if (!registeredErrorReporter) {
(await import("./linters/mermaid.js")).default();
registeredErrorReporter = true;
}
mermaid.mermaidAPI.initialize({
mermaid.initialize({
startOnLoad: false,
...(getMermaidConfig() as any)
...(getMermaidConfig() as any),
});
idCounter++;
const { svg } = await mermaid.mermaidAPI.render(`mermaid-graph-${idCounter}`, content);
return postprocessMermaidSvg(svg);
try {
const { svg } = await mermaid.render(`mermaid-graph-${idCounter}`, content);
return postprocessMermaidSvg(svg);
} catch (e) {
console.warn(JSON.stringify(e));
return "";
}
}
}
export function getMermaidConfig(): MermaidConfig {
const documentStyle = window.getComputedStyle(document.documentElement);
const mermaidTheme = documentStyle.getPropertyValue("--mermaid-theme") as "default";