restore compact Mermaid presentation

This commit is contained in:
tianma-if committed 2026-08-03 19:33:25 +08:00
1 parent e5169b27e1
commit 5708fb472b
7 files changed
+98 -23

No files matched your search

+3 -16
View File
@@ -6,6 +6,7 @@ import { MERMAID_THEME_PALETTES, useTheme } from "./ThemeProvider";
import { MermaidViewer } from "./MermaidViewer";
import { copyTextToClipboard } from "@/lib/clipboard";
import { renderMermaidWithFallback } from "@/lib/mermaid-renderer";
import { getOfficialMermaidThemeVariables } from "@/lib/mermaid-theme";
type MermaidModule = typeof import("mermaid")["default"];
type BeautifulMermaidModule = typeof import("beautiful-mermaid");
@@ -79,22 +80,7 @@ export const MermaidCodeBlock = ({ editor, node }: NodeViewProps) => {
securityLevel: "strict",
suppressErrorRendering: true,
theme: "base",
themeVariables: {
background: palette.bg,
primaryColor: palette.surface ?? palette.bg,
primaryTextColor: palette.fg,
primaryBorderColor: palette.border ?? palette.fg,
lineColor: palette.line ?? palette.fg,
textColor: palette.fg,
mainBkg: palette.bg,
nodeBorder: palette.border ?? palette.fg,
edgeLabelBackground: palette.bg,
actorBkg: palette.surface ?? palette.bg,
actorBorder: palette.border ?? palette.fg,
actorTextColor: palette.fg,
signalColor: palette.line ?? palette.fg,
signalTextColor: palette.fg,
},
themeVariables: getOfficialMermaidThemeVariables(palette),
});
const valid = await mermaid.parse(source, { suppressErrors: true });
if (!valid) throw new Error("Invalid Mermaid diagram");
@@ -237,6 +223,7 @@ export const MermaidCodeBlock = ({ editor, node }: NodeViewProps) => {
className="edgeever-mermaid-preview"
contentEditable={false}
aria-label={t("editorToolbar.mermaidPreview")}
style={{ backgroundColor: MERMAID_THEME_PALETTES[mermaidTheme].bg }}
>
{!source && <p className="edgeever-mermaid-message">{t("editorToolbar.mermaidEmpty")}</p>}
{source && renderState === "loading" && !svg && (
+3 -3
View File
@@ -21,7 +21,7 @@ export const MERMAID_THEME_NAMES = [
] as const;
export type MermaidThemeName = (typeof MERMAID_THEME_NAMES)[number];
interface MermaidThemePalette {
export interface MermaidThemePalette {
bg: string;
fg: string;
line?: string;
@@ -157,9 +157,9 @@ export const getStoredMermaidTheme = (): MermaidThemeName => {
};
export const getStoredMermaidRenderer = (): MermaidRenderer => {
if (typeof window === "undefined") return "mermaid";
if (typeof window === "undefined") return "beautiful";
const stored = window.localStorage.getItem(MERMAID_RENDERER_STORAGE_KEY);
return MERMAID_RENDERERS.includes(stored as MermaidRenderer) ? stored as MermaidRenderer : "mermaid";
return MERMAID_RENDERERS.includes(stored as MermaidRenderer) ? stored as MermaidRenderer : "beautiful";
};
export const getStoredEditorTheme = (): string => {
@@ -1,6 +1,7 @@
import { describe, expect, test } from "bun:test";
import { renderMermaidSVG } from "beautiful-mermaid";
import mermaid from "mermaid";
import { getStoredMermaidRenderer } from "../components/ThemeProvider";
import { renderMermaidWithFallback } from "./mermaid-renderer";
const GANTT_SOURCE = `gantt
@@ -9,6 +10,10 @@ const GANTT_SOURCE = `gantt
Compatibility fallback :fallback, 2026-07-30, 1d`;
describe("Mermaid renderer fallback", () => {
test("defaults to the compact renderer when no browser preference exists", () => {
expect(getStoredMermaidRenderer()).toBe("beautiful");
});
test("uses the official renderer for a valid Gantt diagram unsupported by beautiful-mermaid", async () => {
expect(await mermaid.parse(GANTT_SOURCE, { suppressErrors: true })).toBeTruthy();
+32
View File
@@ -0,0 +1,32 @@
import { describe, expect, test } from "bun:test";
import { MERMAID_THEME_PALETTES } from "../components/ThemeProvider";
import { getOfficialMermaidThemeVariables } from "./mermaid-theme";
describe("official Mermaid theme variables", () => {
test("maps every built-in theme across flowchart, sequence, and state diagrams", () => {
for (const palette of Object.values(MERMAID_THEME_PALETTES)) {
const variables = getOfficialMermaidThemeVariables(palette);
const expectedAccent = palette.accent ?? palette.line ?? palette.fg;
const expectedLine = palette.line ?? palette.muted ?? palette.fg;
const expectedBorder = palette.border ?? palette.muted ?? expectedAccent;
expect(variables.background).toBe(palette.bg);
expect(variables.primaryTextColor).toBe(palette.fg);
expect(variables.clusterBorder).toBe(expectedBorder);
expect(variables.actorBorder).toBe(expectedBorder);
expect(variables.signalColor).toBe(expectedAccent);
expect(variables.stateBorder).toBe(expectedBorder);
expect(variables.transitionColor).toBe(expectedLine);
}
});
test("keeps minimal two-color themes coherent", () => {
const palette = MERMAID_THEME_PALETTES["zinc-light"];
const variables = getOfficialMermaidThemeVariables(palette);
expect(variables.background).toBe(palette.bg);
expect(variables.primaryColor).toBe(palette.bg);
expect(variables.primaryBorderColor).toBe(palette.fg);
expect(variables.signalColor).toBe(palette.fg);
});
});
+51
View File
@@ -0,0 +1,51 @@
import type { MermaidThemePalette } from "@/components/ThemeProvider";
export const getOfficialMermaidThemeVariables = (palette: MermaidThemePalette) => {
const surface = palette.surface ?? palette.bg;
const accent = palette.accent ?? palette.line ?? palette.fg;
const line = palette.line ?? palette.muted ?? palette.fg;
const border = palette.border ?? palette.muted ?? accent;
return {
background: palette.bg,
primaryColor: surface,
primaryTextColor: palette.fg,
primaryBorderColor: border,
secondaryColor: surface,
secondaryTextColor: palette.fg,
secondaryBorderColor: border,
tertiaryColor: surface,
tertiaryTextColor: palette.fg,
tertiaryBorderColor: border,
textColor: palette.fg,
lineColor: line,
mainBkg: surface,
nodeBorder: border,
nodeTextColor: palette.fg,
edgeLabelBackground: palette.bg,
clusterBkg: palette.bg,
clusterBorder: border,
titleColor: palette.fg,
actorBkg: surface,
actorBorder: border,
actorTextColor: palette.fg,
actorLineColor: line,
signalColor: accent,
signalTextColor: palette.fg,
labelBoxBkgColor: surface,
labelBoxBorderColor: border,
labelTextColor: palette.fg,
loopTextColor: palette.fg,
noteBkgColor: surface,
noteBorderColor: border,
noteTextColor: palette.fg,
activationBkgColor: surface,
activationBorderColor: accent,
sequenceNumberColor: accent,
stateBkg: surface,
stateBorder: border,
stateLabelColor: palette.fg,
transitionColor: line,
labelBackgroundColor: palette.bg,
};
};
+2 -2
View File
@@ -576,10 +576,10 @@ textarea {
.ProseMirror .edgeever-mermaid-svg svg {
display: block;
width: 100%;
width: auto;
max-width: 100%;
height: auto;
max-height: none;
max-height: 30rem;
}
.ProseMirror .edgeever-mermaid-source {
@@ -537,10 +537,10 @@ input {
.edgeever-mobile-tiptap-content .edgeever-mermaid-svg svg {
display: block;
width: 100%;
width: auto;
max-width: 100%;
height: auto;
max-height: none;
max-height: 440px;
}
.edgeever-mobile-tiptap-content .edgeever-mermaid-source {