@aparte/plugin-mermaid 0.28.0 → 0.28.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmE,KAAK,YAAY,EAAkC,MAAM,cAAc,CAAC;AAElJ;;;GAGG;AACH,MAAM,WAAW,WAAW;IACxB,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAClD,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,cAAc,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9E,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpF;AAED,MAAM,WAAW,cAAc;IAC3B;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AA4BD;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAC5B,OAAO,EAAE,WAAW,GAAG,CAAC,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,EACnD,OAAO,GAAE,cAAmB,EAC5B,MAAM,GAAE,YAAiC,GAC1C,MAAM,IAAI,CA2BZ"}
1
+ {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmE,KAAK,YAAY,EAAkC,MAAM,cAAc,CAAC;AAElJ;;;GAGG;AACH,MAAM,WAAW,WAAW;IACxB,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAClD,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,cAAc,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9E,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpF;AAED,MAAM,WAAW,cAAc;IAC3B;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAiCD;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAC5B,OAAO,EAAE,WAAW,GAAG,CAAC,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,EACnD,OAAO,GAAE,cAAmB,EAC5B,MAAM,GAAE,YAAiC,GAC1C,MAAM,IAAI,CA2BZ"}
package/dist/core.js CHANGED
@@ -2,6 +2,7 @@ import { aparteGlobalConfig, renderCodeLanguages, escapeHtml, escapeAttr } from
2
2
  const SVG_NS = "http://www.w3.org/2000/svg";
3
3
  const SYSTEM_FONTS = 'system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif';
4
4
  const PROGRESSIVE_MS = 300;
5
+ const PENDING = '<span class="aparte-skeleton aparte-skeleton--rect" aria-hidden="true"></span>';
5
6
  let queue = Promise.resolve();
6
7
  let ids = 0;
7
8
  const ID_PREFIX = `aparte-mermaid-${Math.random().toString(36).slice(2, 8)}`;
@@ -49,7 +50,7 @@ function createMermaidRenderer(load, options, seen) {
49
50
  const part = host.closest("[data-segment-id]") ?? host.closest("pre")?.parentElement ?? host.parentElement ?? host;
50
51
  let state = arriving.get(part);
51
52
  if (!state) {
52
- state = { waiting: null, running: false, timer: void 0, at: 0, took: 0 };
53
+ state = { waiting: null, running: false, timer: void 0, at: 0, took: 0, started: null };
53
54
  arriving.set(part, state);
54
55
  }
55
56
  return state;
@@ -80,13 +81,15 @@ function createMermaidRenderer(load, options, seen) {
80
81
  return instance;
81
82
  };
82
83
  const draw = (ctx) => serial(async () => {
84
+ const source = ctx.open ? ctx.source.slice(0, ctx.source.lastIndexOf("\n") + 1) : ctx.source;
85
+ if (!source.trim()) return null;
83
86
  const m = await mermaidOf();
84
87
  m.initialize(mermaidConfig(user, ctx.host));
85
- if (!await m.parse(ctx.source, { suppressErrors: true })) return null;
88
+ if (!await m.parse(source, { suppressErrors: true })) return null;
86
89
  const id = `${ID_PREFIX}-${++ids}`;
87
90
  try {
88
- const { svg, diagramType } = await m.render(id, ctx.source);
89
- return image(svg, diagramType);
91
+ const { svg, diagramType } = await m.render(id, source);
92
+ return image(svg, diagramType, ctx.open);
90
93
  } finally {
91
94
  document.getElementById(id)?.remove();
92
95
  document.getElementById(`d${id}`)?.remove();
@@ -110,6 +113,7 @@ function createMermaidRenderer(load, options, seen) {
110
113
  if (waiting && ctx.source.startsWith(waiting.ctx.source)) {
111
114
  waiting.answer(null);
112
115
  state.waiting = null;
116
+ state.started = null;
113
117
  }
114
118
  return draw(ctx).then(
115
119
  (html) => html ?? failed(ctx),
@@ -119,6 +123,10 @@ function createMermaidRenderer(load, options, seen) {
119
123
  waiting?.answer(null);
120
124
  state.waiting = null;
121
125
  if (!progressive) return null;
126
+ if (state.started === null || !ctx.source.startsWith(state.started)) {
127
+ state.started = ctx.source;
128
+ return PENDING;
129
+ }
122
130
  return new Promise((answer) => {
123
131
  state.waiting = { ctx, answer };
124
132
  schedule(state);
@@ -159,7 +167,7 @@ function mermaidConfig(user, host) {
159
167
  secure: ["secure", "securityLevel", "startOnLoad", "maxTextSize", "maxEdges", "suppressErrorRendering", "htmlLabels", "flowchart", "themeCSS", "fontFamily"]
160
168
  };
161
169
  }
162
- function image(svg, diagramType) {
170
+ function image(svg, diagramType, arriving = false) {
163
171
  const template = document.createElement("template");
164
172
  template.innerHTML = svg.trim();
165
173
  const root = template.content.firstElementChild;
@@ -168,6 +176,7 @@ function image(svg, diagramType) {
168
176
  const width = Math.ceil(box[2] ?? 0);
169
177
  const height = Math.ceil(box[3] ?? 0);
170
178
  if (!(width > 0 && height > 0)) return null;
179
+ if (arriving && !drawsSomething(root)) return null;
171
180
  root.setAttribute("width", String(width));
172
181
  root.setAttribute("height", String(height));
173
182
  root.removeAttribute("style");
@@ -175,6 +184,12 @@ function image(svg, diagramType) {
175
184
  const type = diagramType ? ` data-diagram-type="${escapeHtml(diagramType)}"` : "";
176
185
  return `<img class="aparte-diagram" src="${escapeAttr(src)}" width="${escapeAttr(String(width))}" height="${escapeAttr(String(height))}" alt=""${type} decoding="async" draggable="false">`;
177
186
  }
187
+ function drawsSomething(root) {
188
+ for (const el of Array.from(root.querySelectorAll("path, rect, circle, ellipse, polygon, polyline, line, text, image, use"))) {
189
+ if (!el.closest("defs, marker, symbol, clipPath, mask, pattern")) return true;
190
+ }
191
+ return false;
192
+ }
178
193
  function failed(ctx) {
179
194
  return `<span class="aparte-code-error" role="note" data-aparte-diagram-error></span><pre class="aparte-code-error">${escapeHtml(ctx.source)}</pre>`;
180
195
  }
package/dist/core.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"core.js","sources":["../src/core.ts"],"sourcesContent":["import { aparteGlobalConfig, escapeAttr, escapeHtml, renderCodeLanguages, type AparteConfig, type AparteCodeLanguageContext } from '@aparte/core';\n\n/**\n * The part of Mermaid this plugin calls. Structural, so this module imports nothing\n * from `mermaid` — a bundle that hands over its own instance carries one copy.\n */\nexport interface MermaidLike {\n initialize(config: Record<string, unknown>): void;\n parse(text: string, options?: { suppressErrors?: boolean }): Promise<unknown>;\n render(id: string, text: string): Promise<{ svg: string; diagramType?: string }>;\n}\n\nexport interface MermaidOptions {\n /**\n * Redraw a diagram while its fence arrives, keeping the last version that parsed\n * (default `true`). `false` draws it once the fence has closed.\n */\n progressive?: boolean;\n /**\n * Mermaid configuration — a `flowchart` curve, `sequence` spacing, `themeVariables`\n * over the ones read from the chat's theme. The plugin keeps the keys that make\n * model-written diagrams safe to draw: `securityLevel` is `'strict'`, HTML labels\n * are off, and a diagram's own `%%{init}%%` cannot change either.\n */\n mermaid?: Record<string, unknown>;\n}\n\n/**\n * The fonts a diagram is measured and drawn in. An `<img>` cannot load the page's web\n * fonts, so Mermaid must measure its labels in the fonts the image will actually use,\n * or every box comes out the wrong size.\n */\nconst SVG_NS = 'http://www.w3.org/2000/svg';\nconst SYSTEM_FONTS = 'system-ui, -apple-system, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif';\n/** The least time between two drawings of a diagram still arriving. */\nconst PROGRESSIVE_MS = 300;\n\n/*\n * One render at a time on the whole page, whichever chat asks: Mermaid is one object,\n * `initialize` replaces its whole configuration, and a render reads it. A queue per chat\n * let one chat's diagram be drawn with another chat's options and colours.\n */\nlet queue: Promise<unknown> = Promise.resolve();\nlet ids = 0;\n/** Unique to this copy of the plugin, so two bundles on one page never remove each other's nodes. */\nconst ID_PREFIX = `aparte-mermaid-${Math.random().toString(36).slice(2, 8)}`;\n\nconst serial = <T>(job: () => Promise<T>): Promise<T> => {\n const run = queue.then(job, job);\n queue = run.catch(() => undefined);\n return run;\n};\n\n/**\n * Draw diagrams with a Mermaid you provide — the instance, or a function that loads it\n * on the first diagram. The entry point for a bundle that controls what it ships:\n * `@aparte/plugin-mermaid` itself is this, with `() => import('mermaid')`.\n *\n * @returns a disposer that unregisters the renderer and stops watching the theme.\n * @example\n * import mermaid from 'mermaid';\n * import { setupMermaidWith } from '@aparte/plugin-mermaid/core';\n * setupMermaidWith(mermaid);\n */\nexport function setupMermaidWith(\n mermaid: MermaidLike | (() => Promise<MermaidLike>),\n options: MermaidOptions = {},\n config: AparteConfig = aparteGlobalConfig,\n): () => void {\n const load = typeof mermaid === 'function' ? mermaid : () => Promise.resolve(mermaid);\n /*\n * The shadow roots diagrams were drawn in. Neither the page's observer nor a redraw\n * from <body> reaches inside one, so each is watched, and redrawn, on its own.\n */\n const shadows = new Set<ShadowRoot>();\n const redraw = (): void => {\n renderer.epoch++;\n renderCodeLanguages(document.body, { refresh: true, language: 'mermaid' });\n for (const root of shadows) {\n // A widget taken off the page is let go, not drawn again: if it comes back,\n // its next drawing hands its root over once more.\n if (!root.host.isConnected) { shadows.delete(root); continue; }\n for (const child of Array.from(root.children)) renderCodeLanguages(child, { refresh: true, language: 'mermaid' });\n }\n };\n const watch = watchTheme(redraw);\n const renderer = createMermaidRenderer(load, options, (host) => {\n const root = host.getRootNode();\n if (typeof ShadowRoot === 'undefined' || !(root instanceof ShadowRoot) || shadows.has(root)) return;\n for (const old of shadows) if (!old.host.isConnected) shadows.delete(old);\n shadows.add(root);\n watch.add(root);\n });\n const unregister = config.registerCodeLanguageRenderer(renderer);\n return () => { watch.stop(); shadows.clear(); unregister(); };\n}\n\nfunction createMermaidRenderer(load: () => Promise<MermaidLike>, options: MermaidOptions, seen: (host: HTMLElement) => void) {\n const progressive = options.progressive !== false;\n const user = options.mermaid ?? {};\n let instance: Promise<MermaidLike> | undefined;\n /**\n * A diagram still arriving, by the part of the reply it is in — a rebuild replaces its\n * placeholder, never its part: the latest source waiting to be drawn, whether a\n * drawing is running, and the pace of the last one — the next waits as long as it\n * took, and at least `PROGRESSIVE_MS`.\n */\n interface Arriving {\n waiting: { ctx: AparteCodeLanguageContext; answer: (html: string | null) => void } | null;\n running: boolean;\n timer: ReturnType<typeof setTimeout> | undefined;\n at: number;\n took: number;\n }\n const arriving = new WeakMap<Element, Arriving>();\n const watched = new WeakSet<HTMLImageElement>();\n\n const stateOf = (host: HTMLElement): Arriving => {\n const part = host.closest('[data-segment-id]') ?? host.closest('pre')?.parentElement ?? host.parentElement ?? host;\n let state = arriving.get(part);\n if (!state) {\n state = { waiting: null, running: false, timer: undefined, at: 0, took: 0 };\n arriving.set(part, state);\n }\n return state;\n };\n\n const schedule = (state: Arriving): void => {\n if (state.running || state.timer !== undefined || !state.waiting) return;\n const wait = Math.max(0, state.at + Math.max(PROGRESSIVE_MS, state.took) - performance.now());\n state.timer = setTimeout(() => {\n state.timer = undefined;\n const job = state.waiting;\n state.waiting = null;\n if (!job) return;\n state.running = true;\n const started = performance.now();\n void draw(job.ctx).then(job.answer, () => job.answer(null)).finally(() => {\n state.running = false;\n state.at = performance.now();\n state.took = state.at - started;\n schedule(state);\n });\n }, wait);\n };\n\n const mermaidOf = (): Promise<MermaidLike> => {\n // Not poisoned: a failed load is tried again on the next diagram.\n instance ??= load().catch((error: unknown) => { instance = undefined; throw error; });\n return instance;\n };\n\n /** Draw `ctx.source` as an image; `null` when it does not parse. */\n const draw = (ctx: AparteCodeLanguageContext): Promise<string | null> => serial(async () => {\n const m = await mermaidOf();\n m.initialize(mermaidConfig(user, ctx.host));\n if (!(await m.parse(ctx.source, { suppressErrors: true }))) return null;\n const id = `${ID_PREFIX}-${++ids}`;\n try {\n const { svg, diagramType } = await m.render(id, ctx.source);\n return image(svg, diagramType);\n } finally {\n // Mermaid leaves its scratch and error nodes in <body> when a render fails.\n document.getElementById(id)?.remove();\n document.getElementById(`d${id}`)?.remove();\n }\n });\n\n const renderer = {\n languages: ['mermaid'] as const,\n lazy: true,\n epoch: 0,\n /** The colours themselves, not the theme's name: two skins may share one name. */\n cacheKey(ctx: AparteCodeLanguageContext): string {\n seen(ctx.host);\n return `${renderer.epoch}|${colourKey(ctx.host)}`;\n },\n render(ctx: AparteCodeLanguageContext): string | null | Promise<string | null> {\n if (!ctx.display) return null;\n seen(ctx.host);\n const state = stateOf(ctx.host);\n const waiting = state.waiting;\n if (!ctx.open) {\n // The end of the diagram that was arriving: its waiting frame is not drawn.\n // Another diagram of the same part, drawn again, leaves it waiting.\n if (waiting && ctx.source.startsWith(waiting.ctx.source)) {\n waiting.answer(null);\n state.waiting = null;\n }\n return draw(ctx).then(\n (html) => html ?? failed(ctx),\n () => failed(ctx),\n );\n }\n // A newer source supersedes the one still waiting.\n waiting?.answer(null);\n state.waiting = null;\n if (!progressive) return null;\n return new Promise<string | null>((answer) => {\n state.waiting = { ctx, answer };\n schedule(state);\n });\n },\n relabel(drawing: HTMLElement, ctx: AparteCodeLanguageContext): void {\n const locale = ctx.config.getLocale() as Record<string, unknown>;\n const img = drawing.querySelector<HTMLImageElement>('img.aparte-diagram');\n if (img) {\n img.alt = describe(ctx.source) ?? String(locale['diagramAlt'] ?? 'Diagram');\n // A page whose CSP refuses `data:` images shows the source instead. Once per\n // image, and holding the source only: a relabel runs on every locale change.\n if (!watched.has(img)) {\n watched.add(img);\n const source = ctx.source;\n img.addEventListener('error', () => img.replaceWith(errorNode(source)), { once: true });\n }\n }\n const note = drawing.querySelector<HTMLElement>('[data-aparte-diagram-error]');\n if (note) note.textContent = String(locale['diagramError'] ?? 'This diagram could not be drawn.');\n },\n };\n return renderer;\n}\n\n/** The configuration every render runs with: the caller's, under the keys the plugin keeps. */\nfunction mermaidConfig(user: Record<string, unknown>, host: HTMLElement): Record<string, unknown> {\n const palette = paletteOf(host);\n return {\n ...user,\n startOnLoad: false,\n securityLevel: 'strict',\n htmlLabels: false,\n suppressErrorRendering: true,\n theme: 'base',\n fontFamily: SYSTEM_FONTS,\n flowchart: { ...(user['flowchart'] as Record<string, unknown> | undefined), htmlLabels: false },\n themeVariables: { ...palette, ...(user['themeVariables'] as Record<string, unknown> | undefined), fontFamily: SYSTEM_FONTS },\n maxTextSize: 50_000,\n maxEdges: 500,\n // What a diagram's own `%%{init}%%` may not change.\n secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize', 'maxEdges', 'suppressErrorRendering', 'htmlLabels', 'flowchart', 'themeCSS', 'fontFamily'],\n };\n}\n\n/**\n * The SVG as an image: no script and no style of it can reach the page.\n *\n * Read by the HTML parser, as Mermaid wrote it: it serialises its SVG as HTML (a no-break\n * space comes out as `&nbsp;`, and its `#hearts;` codes as `&hearts;`), which an XML\n * parser refuses — and a French label, `Étape 1 : début`, then never drew. Anything\n * the parser had to put beside the `<svg>` means it was not one clean SVG.\n */\nfunction image(svg: string, diagramType?: string): string | null {\n const template = document.createElement('template');\n template.innerHTML = svg.trim();\n const root = template.content.firstElementChild;\n if (!root || template.content.children.length !== 1 || root.localName !== 'svg' || root.namespaceURI !== SVG_NS\n || root.getElementsByTagName('foreignObject').length > 0) return null;\n const box = (root.getAttribute('viewBox') ?? '').split(/[\\s,]+/).map(Number);\n const width = Math.ceil(box[2] ?? 0);\n const height = Math.ceil(box[3] ?? 0);\n if (!(width > 0 && height > 0)) return null;\n root.setAttribute('width', String(width));\n root.setAttribute('height', String(height));\n root.removeAttribute('style');\n const src = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(new XMLSerializer().serializeToString(root))}`;\n const type = diagramType ? ` data-diagram-type=\"${escapeHtml(diagramType)}\"` : '';\n return `<img class=\"aparte-diagram\" src=\"${escapeAttr(src)}\" width=\"${escapeAttr(String(width))}\" height=\"${escapeAttr(String(height))}\" alt=\"\"${type} decoding=\"async\" draggable=\"false\">`;\n}\n\n/** The note and the source, for a diagram that does not parse. Its text is set by `relabel`. */\nfunction failed(ctx: AparteCodeLanguageContext): string {\n return `<span class=\"aparte-code-error\" role=\"note\" data-aparte-diagram-error></span><pre class=\"aparte-code-error\">${escapeHtml(ctx.source)}</pre>`;\n}\n\nfunction errorNode(source: string): Node {\n const pre = document.createElement('pre');\n pre.className = 'aparte-code-error';\n pre.textContent = source;\n return pre;\n}\n\n/** The title or description a diagram gives itself for assistive technology, if any. */\nfunction describe(source: string): string | undefined {\n return /^\\s*accTitle\\s*:\\s*(.+)$/m.exec(source)?.[1]?.trim()\n ?? /^\\s*accDescr\\s*:\\s*(.+)$/m.exec(source)?.[1]?.trim();\n}\n\n/** Which theme the chat around `host` is in: its own attribute, else the system's. */\nfunction themeOf(host: HTMLElement): string {\n const attr = host.closest('[data-aparte-theme]')?.getAttribute('data-aparte-theme');\n if (attr) return attr;\n return typeof matchMedia === 'function' && matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n}\n\n/** The tokens a diagram is coloured from, with the colour each falls back to. */\nconst TOKENS = {\n bg: ['--aparte-bg', '#ffffff'],\n text: ['--aparte-text', '#1a1a1a'],\n muted: ['--aparte-text-muted', '#666666'],\n border: ['--aparte-border', '#d0d0d0'],\n surface: ['--aparte-surface-2', '#f4f4f4'],\n surfaceLow: ['--aparte-surface-1', '#fafafa'],\n primary: ['--aparte-primary', '#3b5bdb'],\n} as const;\n\n/**\n * What a diagram's colours depend on at `host`: the theme, the colour scheme, and the\n * tokens as declared there. Cheap — one style read, no probe — since the engine asks it\n * on every pass; two skins with the same theme name still differ in their tokens.\n */\nfunction colourKey(host: HTMLElement): string {\n const theme = themeOf(host);\n if (typeof getComputedStyle !== 'function') return theme;\n const style = getComputedStyle(host);\n return [theme, style.colorScheme, ...Object.values(TOKENS).map(([token]) => style.getPropertyValue(token).trim())].join('|');\n}\n\n/**\n * The chat's colours as Mermaid can read them. A token may be `color-mix()` or `oklch()`,\n * which Mermaid's colour library cannot parse, so each is resolved by the browser — a\n * probe's computed colour — and normalised to hex by a canvas.\n */\nfunction paletteOf(host: HTMLElement): Record<string, unknown> {\n if (typeof getComputedStyle !== 'function') return {};\n const probe = document.createElement('span');\n probe.style.display = 'none';\n // Beside the source, never in it: an incremental provider may still be writing there.\n (host.parentElement ?? document.body).appendChild(probe);\n const canvas = document.createElement('canvas').getContext?.('2d') ?? null;\n const read = (token: string, fallback: string): string => {\n probe.style.color = `var(${token}, ${fallback})`;\n const computed = getComputedStyle(probe).color || fallback;\n if (!canvas) return computed;\n canvas.fillStyle = '#000';\n canvas.fillStyle = computed;\n return String(canvas.fillStyle);\n };\n try {\n const bg = read(...TOKENS.bg);\n const text = read(...TOKENS.text);\n const muted = read(...TOKENS.muted);\n const border = read(...TOKENS.border);\n const surface = read(...TOKENS.surface);\n const surfaceLow = read(...TOKENS.surfaceLow);\n const primary = read(...TOKENS.primary);\n return {\n darkMode: luminance(bg) < 0.5,\n background: bg,\n primaryColor: surface,\n primaryTextColor: text,\n primaryBorderColor: primary,\n secondaryColor: surfaceLow,\n tertiaryColor: surfaceLow,\n mainBkg: surface,\n nodeBorder: border,\n clusterBkg: surfaceLow,\n clusterBorder: border,\n lineColor: muted,\n textColor: text,\n titleColor: text,\n edgeLabelBackground: bg,\n noteBkgColor: surfaceLow,\n noteTextColor: text,\n noteBorderColor: border,\n actorBkg: surface,\n actorBorder: primary,\n actorTextColor: text,\n signalColor: muted,\n signalTextColor: text,\n };\n } finally {\n probe.remove();\n }\n}\n\nfunction luminance(color: string): number {\n const hex = /^#([0-9a-f]{6})$/i.exec(color)?.[1];\n if (!hex) return 1;\n const [r, g, b] = [0, 2, 4].map((i) => parseInt(hex.slice(i, i + 2), 16) / 255);\n return 0.2126 * r! + 0.7152 * g! + 0.0722 * b!;\n}\n\n/**\n * Call `changed` when the chat's theme or the system's colour scheme changes — on the\n * page, and in each shadow root handed to `add`.\n */\nfunction watchTheme(changed: () => void): { add: (root: ShadowRoot) => void; stop: () => void } {\n if (typeof MutationObserver === 'undefined' || typeof document === 'undefined') return { add: () => {}, stop: () => {} };\n const observer = new MutationObserver(changed);\n const options: MutationObserverInit = { attributes: true, subtree: true, attributeFilter: ['data-aparte-theme'] };\n observer.observe(document.documentElement, options);\n const media = typeof matchMedia === 'function' ? matchMedia('(prefers-color-scheme: dark)') : null;\n media?.addEventListener('change', changed);\n return {\n add: (root) => observer.observe(root, options),\n stop: () => { observer.disconnect(); media?.removeEventListener('change', changed); },\n };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"core.js","sources":["../src/core.ts"],"sourcesContent":["import { aparteGlobalConfig, escapeAttr, escapeHtml, renderCodeLanguages, type AparteConfig, type AparteCodeLanguageContext } from '@aparte/core';\n\n/**\n * The part of Mermaid this plugin calls. Structural, so this module imports nothing\n * from `mermaid` — a bundle that hands over its own instance carries one copy.\n */\nexport interface MermaidLike {\n initialize(config: Record<string, unknown>): void;\n parse(text: string, options?: { suppressErrors?: boolean }): Promise<unknown>;\n render(id: string, text: string): Promise<{ svg: string; diagramType?: string }>;\n}\n\nexport interface MermaidOptions {\n /**\n * Redraw a diagram while its fence arrives, keeping the last version that parsed\n * (default `true`). `false` draws it once the fence has closed.\n */\n progressive?: boolean;\n /**\n * Mermaid configuration — a `flowchart` curve, `sequence` spacing, `themeVariables`\n * over the ones read from the chat's theme. The plugin keeps the keys that make\n * model-written diagrams safe to draw: `securityLevel` is `'strict'`, HTML labels\n * are off, and a diagram's own `%%{init}%%` cannot change either.\n */\n mermaid?: Record<string, unknown>;\n}\n\n/**\n * The fonts a diagram is measured and drawn in. An `<img>` cannot load the page's web\n * fonts, so Mermaid must measure its labels in the fonts the image will actually use,\n * or every box comes out the wrong size.\n */\nconst SVG_NS = 'http://www.w3.org/2000/svg';\nconst SYSTEM_FONTS = 'system-ui, -apple-system, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif';\n/** The least time between two drawings of a diagram still arriving. */\nconst PROGRESSIVE_MS = 300;\n/**\n * What a diagram still arriving shows before it has a node to draw: a quiet box, not its\n * source scrolling by, and not the empty image Mermaid draws for a header alone.\n */\nconst PENDING = '<span class=\"aparte-skeleton aparte-skeleton--rect\" aria-hidden=\"true\"></span>';\n\n/*\n * One render at a time on the whole page, whichever chat asks: Mermaid is one object,\n * `initialize` replaces its whole configuration, and a render reads it. A queue per chat\n * let one chat's diagram be drawn with another chat's options and colours.\n */\nlet queue: Promise<unknown> = Promise.resolve();\nlet ids = 0;\n/** Unique to this copy of the plugin, so two bundles on one page never remove each other's nodes. */\nconst ID_PREFIX = `aparte-mermaid-${Math.random().toString(36).slice(2, 8)}`;\n\nconst serial = <T>(job: () => Promise<T>): Promise<T> => {\n const run = queue.then(job, job);\n queue = run.catch(() => undefined);\n return run;\n};\n\n/**\n * Draw diagrams with a Mermaid you provide — the instance, or a function that loads it\n * on the first diagram. The entry point for a bundle that controls what it ships:\n * `@aparte/plugin-mermaid` itself is this, with `() => import('mermaid')`.\n *\n * @returns a disposer that unregisters the renderer and stops watching the theme.\n * @example\n * import mermaid from 'mermaid';\n * import { setupMermaidWith } from '@aparte/plugin-mermaid/core';\n * setupMermaidWith(mermaid);\n */\nexport function setupMermaidWith(\n mermaid: MermaidLike | (() => Promise<MermaidLike>),\n options: MermaidOptions = {},\n config: AparteConfig = aparteGlobalConfig,\n): () => void {\n const load = typeof mermaid === 'function' ? mermaid : () => Promise.resolve(mermaid);\n /*\n * The shadow roots diagrams were drawn in. Neither the page's observer nor a redraw\n * from <body> reaches inside one, so each is watched, and redrawn, on its own.\n */\n const shadows = new Set<ShadowRoot>();\n const redraw = (): void => {\n renderer.epoch++;\n renderCodeLanguages(document.body, { refresh: true, language: 'mermaid' });\n for (const root of shadows) {\n // A widget taken off the page is let go, not drawn again: if it comes back,\n // its next drawing hands its root over once more.\n if (!root.host.isConnected) { shadows.delete(root); continue; }\n for (const child of Array.from(root.children)) renderCodeLanguages(child, { refresh: true, language: 'mermaid' });\n }\n };\n const watch = watchTheme(redraw);\n const renderer = createMermaidRenderer(load, options, (host) => {\n const root = host.getRootNode();\n if (typeof ShadowRoot === 'undefined' || !(root instanceof ShadowRoot) || shadows.has(root)) return;\n for (const old of shadows) if (!old.host.isConnected) shadows.delete(old);\n shadows.add(root);\n watch.add(root);\n });\n const unregister = config.registerCodeLanguageRenderer(renderer);\n return () => { watch.stop(); shadows.clear(); unregister(); };\n}\n\nfunction createMermaidRenderer(load: () => Promise<MermaidLike>, options: MermaidOptions, seen: (host: HTMLElement) => void) {\n const progressive = options.progressive !== false;\n const user = options.mermaid ?? {};\n let instance: Promise<MermaidLike> | undefined;\n /**\n * A diagram still arriving, by the part of the reply it is in — a rebuild replaces its\n * placeholder, never its part: the latest source waiting to be drawn, whether a\n * drawing is running, and the pace of the last one — the next waits as long as it\n * took, and at least `PROGRESSIVE_MS`.\n */\n interface Arriving {\n waiting: { ctx: AparteCodeLanguageContext; answer: (html: string | null) => void } | null;\n running: boolean;\n timer: ReturnType<typeof setTimeout> | undefined;\n at: number;\n took: number;\n /** The source of the diagram this part has started showing, or `null` before its first frame. */\n started: string | null;\n }\n const arriving = new WeakMap<Element, Arriving>();\n const watched = new WeakSet<HTMLImageElement>();\n\n const stateOf = (host: HTMLElement): Arriving => {\n const part = host.closest('[data-segment-id]') ?? host.closest('pre')?.parentElement ?? host.parentElement ?? host;\n let state = arriving.get(part);\n if (!state) {\n state = { waiting: null, running: false, timer: undefined, at: 0, took: 0, started: null };\n arriving.set(part, state);\n }\n return state;\n };\n\n const schedule = (state: Arriving): void => {\n if (state.running || state.timer !== undefined || !state.waiting) return;\n const wait = Math.max(0, state.at + Math.max(PROGRESSIVE_MS, state.took) - performance.now());\n state.timer = setTimeout(() => {\n state.timer = undefined;\n const job = state.waiting;\n state.waiting = null;\n if (!job) return;\n state.running = true;\n const started = performance.now();\n void draw(job.ctx).then(job.answer, () => job.answer(null)).finally(() => {\n state.running = false;\n state.at = performance.now();\n state.took = state.at - started;\n schedule(state);\n });\n }, wait);\n };\n\n const mermaidOf = (): Promise<MermaidLike> => {\n // Not poisoned: a failed load is tried again on the next diagram.\n instance ??= load().catch((error: unknown) => { instance = undefined; throw error; });\n return instance;\n };\n\n /**\n * Draw `ctx.source` as an image; `null` when it does not parse. A diagram still arriving\n * is drawn up to its last complete line: a line half written (`A[Mod`) does not parse, and\n * drawing only whole statements is what makes each node appear as its line ends.\n */\n const draw = (ctx: AparteCodeLanguageContext): Promise<string | null> => serial(async () => {\n const source = ctx.open ? ctx.source.slice(0, ctx.source.lastIndexOf('\\n') + 1) : ctx.source;\n if (!source.trim()) return null;\n const m = await mermaidOf();\n m.initialize(mermaidConfig(user, ctx.host));\n if (!(await m.parse(source, { suppressErrors: true }))) return null;\n const id = `${ID_PREFIX}-${++ids}`;\n try {\n const { svg, diagramType } = await m.render(id, source);\n return image(svg, diagramType, ctx.open);\n } finally {\n // Mermaid leaves its scratch and error nodes in <body> when a render fails.\n document.getElementById(id)?.remove();\n document.getElementById(`d${id}`)?.remove();\n }\n });\n\n const renderer = {\n languages: ['mermaid'] as const,\n lazy: true,\n epoch: 0,\n /** The colours themselves, not the theme's name: two skins may share one name. */\n cacheKey(ctx: AparteCodeLanguageContext): string {\n seen(ctx.host);\n return `${renderer.epoch}|${colourKey(ctx.host)}`;\n },\n render(ctx: AparteCodeLanguageContext): string | null | Promise<string | null> {\n if (!ctx.display) return null;\n seen(ctx.host);\n const state = stateOf(ctx.host);\n const waiting = state.waiting;\n if (!ctx.open) {\n // The end of the diagram that was arriving: its waiting frame is not drawn.\n // Another diagram of the same part, drawn again, leaves it waiting.\n if (waiting && ctx.source.startsWith(waiting.ctx.source)) {\n waiting.answer(null);\n state.waiting = null;\n state.started = null;\n }\n return draw(ctx).then(\n (html) => html ?? failed(ctx),\n () => failed(ctx),\n );\n }\n // A newer source supersedes the one still waiting.\n waiting?.answer(null);\n state.waiting = null;\n if (!progressive) return null;\n // A diagram's first frame: the box it will be drawn in, at once, in place of\n // its source. The frames after it draw what has arrived, and a frame that\n // draws nothing keeps what is shown.\n if (state.started === null || !ctx.source.startsWith(state.started)) {\n state.started = ctx.source;\n return PENDING;\n }\n return new Promise<string | null>((answer) => {\n state.waiting = { ctx, answer };\n schedule(state);\n });\n },\n relabel(drawing: HTMLElement, ctx: AparteCodeLanguageContext): void {\n const locale = ctx.config.getLocale() as Record<string, unknown>;\n const img = drawing.querySelector<HTMLImageElement>('img.aparte-diagram');\n if (img) {\n img.alt = describe(ctx.source) ?? String(locale['diagramAlt'] ?? 'Diagram');\n // A page whose CSP refuses `data:` images shows the source instead. Once per\n // image, and holding the source only: a relabel runs on every locale change.\n if (!watched.has(img)) {\n watched.add(img);\n const source = ctx.source;\n img.addEventListener('error', () => img.replaceWith(errorNode(source)), { once: true });\n }\n }\n const note = drawing.querySelector<HTMLElement>('[data-aparte-diagram-error]');\n if (note) note.textContent = String(locale['diagramError'] ?? 'This diagram could not be drawn.');\n },\n };\n return renderer;\n}\n\n/** The configuration every render runs with: the caller's, under the keys the plugin keeps. */\nfunction mermaidConfig(user: Record<string, unknown>, host: HTMLElement): Record<string, unknown> {\n const palette = paletteOf(host);\n return {\n ...user,\n startOnLoad: false,\n securityLevel: 'strict',\n htmlLabels: false,\n suppressErrorRendering: true,\n theme: 'base',\n fontFamily: SYSTEM_FONTS,\n flowchart: { ...(user['flowchart'] as Record<string, unknown> | undefined), htmlLabels: false },\n themeVariables: { ...palette, ...(user['themeVariables'] as Record<string, unknown> | undefined), fontFamily: SYSTEM_FONTS },\n maxTextSize: 50_000,\n maxEdges: 500,\n // What a diagram's own `%%{init}%%` may not change.\n secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize', 'maxEdges', 'suppressErrorRendering', 'htmlLabels', 'flowchart', 'themeCSS', 'fontFamily'],\n };\n}\n\n/**\n * The SVG as an image: no script and no style of it can reach the page.\n *\n * Read by the HTML parser, as Mermaid wrote it: it serialises its SVG as HTML (a no-break\n * space comes out as `&nbsp;`, and its `#hearts;` codes as `&hearts;`), which an XML\n * parser refuses — and a French label, `Étape 1 : début`, then never drew. Anything\n * the parser had to put beside the `<svg>` means it was not one clean SVG.\n */\nfunction image(svg: string, diagramType?: string, arriving = false): string | null {\n const template = document.createElement('template');\n template.innerHTML = svg.trim();\n const root = template.content.firstElementChild;\n if (!root || template.content.children.length !== 1 || root.localName !== 'svg' || root.namespaceURI !== SVG_NS\n || root.getElementsByTagName('foreignObject').length > 0) return null;\n const box = (root.getAttribute('viewBox') ?? '').split(/[\\s,]+/).map(Number);\n const width = Math.ceil(box[2] ?? 0);\n const height = Math.ceil(box[3] ?? 0);\n if (!(width > 0 && height > 0)) return null;\n // A diagram still arriving with nothing to draw yet — a header, a title — comes out as\n // an empty box: shown, it would replace what is on screen with nothing.\n if (arriving && !drawsSomething(root)) return null;\n root.setAttribute('width', String(width));\n root.setAttribute('height', String(height));\n root.removeAttribute('style');\n const src = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(new XMLSerializer().serializeToString(root))}`;\n const type = diagramType ? ` data-diagram-type=\"${escapeHtml(diagramType)}\"` : '';\n return `<img class=\"aparte-diagram\" src=\"${escapeAttr(src)}\" width=\"${escapeAttr(String(width))}\" height=\"${escapeAttr(String(height))}\" alt=\"\"${type} decoding=\"async\" draggable=\"false\">`;\n}\n\n/** Whether an SVG paints anything beyond its definitions: a header alone draws no shape. */\nfunction drawsSomething(root: Element): boolean {\n for (const el of Array.from(root.querySelectorAll('path, rect, circle, ellipse, polygon, polyline, line, text, image, use'))) {\n if (!el.closest('defs, marker, symbol, clipPath, mask, pattern')) return true;\n }\n return false;\n}\n\n/** The note and the source, for a diagram that does not parse. Its text is set by `relabel`. */\nfunction failed(ctx: AparteCodeLanguageContext): string {\n return `<span class=\"aparte-code-error\" role=\"note\" data-aparte-diagram-error></span><pre class=\"aparte-code-error\">${escapeHtml(ctx.source)}</pre>`;\n}\n\nfunction errorNode(source: string): Node {\n const pre = document.createElement('pre');\n pre.className = 'aparte-code-error';\n pre.textContent = source;\n return pre;\n}\n\n/** The title or description a diagram gives itself for assistive technology, if any. */\nfunction describe(source: string): string | undefined {\n return /^\\s*accTitle\\s*:\\s*(.+)$/m.exec(source)?.[1]?.trim()\n ?? /^\\s*accDescr\\s*:\\s*(.+)$/m.exec(source)?.[1]?.trim();\n}\n\n/** Which theme the chat around `host` is in: its own attribute, else the system's. */\nfunction themeOf(host: HTMLElement): string {\n const attr = host.closest('[data-aparte-theme]')?.getAttribute('data-aparte-theme');\n if (attr) return attr;\n return typeof matchMedia === 'function' && matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n}\n\n/** The tokens a diagram is coloured from, with the colour each falls back to. */\nconst TOKENS = {\n bg: ['--aparte-bg', '#ffffff'],\n text: ['--aparte-text', '#1a1a1a'],\n muted: ['--aparte-text-muted', '#666666'],\n border: ['--aparte-border', '#d0d0d0'],\n surface: ['--aparte-surface-2', '#f4f4f4'],\n surfaceLow: ['--aparte-surface-1', '#fafafa'],\n primary: ['--aparte-primary', '#3b5bdb'],\n} as const;\n\n/**\n * What a diagram's colours depend on at `host`: the theme, the colour scheme, and the\n * tokens as declared there. Cheap — one style read, no probe — since the engine asks it\n * on every pass; two skins with the same theme name still differ in their tokens.\n */\nfunction colourKey(host: HTMLElement): string {\n const theme = themeOf(host);\n if (typeof getComputedStyle !== 'function') return theme;\n const style = getComputedStyle(host);\n return [theme, style.colorScheme, ...Object.values(TOKENS).map(([token]) => style.getPropertyValue(token).trim())].join('|');\n}\n\n/**\n * The chat's colours as Mermaid can read them. A token may be `color-mix()` or `oklch()`,\n * which Mermaid's colour library cannot parse, so each is resolved by the browser — a\n * probe's computed colour — and normalised to hex by a canvas.\n */\nfunction paletteOf(host: HTMLElement): Record<string, unknown> {\n if (typeof getComputedStyle !== 'function') return {};\n const probe = document.createElement('span');\n probe.style.display = 'none';\n // Beside the source, never in it: an incremental provider may still be writing there.\n (host.parentElement ?? document.body).appendChild(probe);\n const canvas = document.createElement('canvas').getContext?.('2d') ?? null;\n const read = (token: string, fallback: string): string => {\n probe.style.color = `var(${token}, ${fallback})`;\n const computed = getComputedStyle(probe).color || fallback;\n if (!canvas) return computed;\n canvas.fillStyle = '#000';\n canvas.fillStyle = computed;\n return String(canvas.fillStyle);\n };\n try {\n const bg = read(...TOKENS.bg);\n const text = read(...TOKENS.text);\n const muted = read(...TOKENS.muted);\n const border = read(...TOKENS.border);\n const surface = read(...TOKENS.surface);\n const surfaceLow = read(...TOKENS.surfaceLow);\n const primary = read(...TOKENS.primary);\n return {\n darkMode: luminance(bg) < 0.5,\n background: bg,\n primaryColor: surface,\n primaryTextColor: text,\n primaryBorderColor: primary,\n secondaryColor: surfaceLow,\n tertiaryColor: surfaceLow,\n mainBkg: surface,\n nodeBorder: border,\n clusterBkg: surfaceLow,\n clusterBorder: border,\n lineColor: muted,\n textColor: text,\n titleColor: text,\n edgeLabelBackground: bg,\n noteBkgColor: surfaceLow,\n noteTextColor: text,\n noteBorderColor: border,\n actorBkg: surface,\n actorBorder: primary,\n actorTextColor: text,\n signalColor: muted,\n signalTextColor: text,\n };\n } finally {\n probe.remove();\n }\n}\n\nfunction luminance(color: string): number {\n const hex = /^#([0-9a-f]{6})$/i.exec(color)?.[1];\n if (!hex) return 1;\n const [r, g, b] = [0, 2, 4].map((i) => parseInt(hex.slice(i, i + 2), 16) / 255);\n return 0.2126 * r! + 0.7152 * g! + 0.0722 * b!;\n}\n\n/**\n * Call `changed` when the chat's theme or the system's colour scheme changes — on the\n * page, and in each shadow root handed to `add`.\n */\nfunction watchTheme(changed: () => void): { add: (root: ShadowRoot) => void; stop: () => void } {\n if (typeof MutationObserver === 'undefined' || typeof document === 'undefined') return { add: () => {}, stop: () => {} };\n const observer = new MutationObserver(changed);\n const options: MutationObserverInit = { attributes: true, subtree: true, attributeFilter: ['data-aparte-theme'] };\n observer.observe(document.documentElement, options);\n const media = typeof matchMedia === 'function' ? matchMedia('(prefers-color-scheme: dark)') : null;\n media?.addEventListener('change', changed);\n return {\n add: (root) => observer.observe(root, options),\n stop: () => { observer.disconnect(); media?.removeEventListener('change', changed); },\n };\n}\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aparte/plugin-mermaid",
3
- "version": "0.28.0",
3
+ "version": "0.28.1",
4
4
  "homepage": "https://apartejs.dev/guides/diagrams/",
5
5
  "description": "Diagrams for aparté via Mermaid — drawn as the fence streams, in a sandboxed image.",
6
6
  "type": "module",
@@ -31,14 +31,14 @@
31
31
  "node": ">=18"
32
32
  },
33
33
  "peerDependencies": {
34
- "@aparte/core": ">=0.28.0 <1.0.0",
34
+ "@aparte/core": ">=0.28.1 <1.0.0",
35
35
  "mermaid": "^11.16.1"
36
36
  },
37
37
  "devDependencies": {
38
38
  "mermaid": "^11.17.2",
39
39
  "typescript": "~5.7.0",
40
40
  "vite": "^6.0.0",
41
- "@aparte/core": "0.28.0"
41
+ "@aparte/core": "0.28.1"
42
42
  },
43
43
  "keywords": [
44
44
  "aparte",