@ai-markdown/core 3.3.1 → 3.4.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":"index.cjs","names":[],"sources":["../../src/components/nodes.ts","../../src/components/codeFrame.ts","../../src/components/formatJson.ts","../../src/components/jsonCompleteness.ts","../../src/components/renderQueue.ts","../../src/components/mermaid.ts","../../src/components/diagram.ts","../../src/components/scroll.ts","../../src/components/image.ts","../../src/components/imageTransform.ts"],"sourcesContent":["import type { Element, RootContent } from 'hast';\n\nexport interface CodeSource {\n code: string;\n language: string;\n}\n/** Enhance only ordinary fenced code; preserve all other pre overrides. */\nexport function extractCode(node?: Element): CodeSource | null {\n if (node?.tagName !== 'pre' || node.children.length !== 1 || Object.keys(node.properties).length) return null;\n const child = node.children[0];\n if (\n child.type !== 'element' ||\n child.tagName !== 'code' ||\n child.children.some((n) => n.type !== 'text') ||\n Object.keys(child.properties).some((k) => k !== 'className')\n )\n return null;\n const classes = child.properties.className ?? [];\n const names = (Array.isArray(classes) ? classes : String(classes).split(/\\s+/)).map(String).filter(Boolean);\n if (names.some((n) => !n.startsWith('language-'))) return null;\n const languages = [...new Set(names.map((n) => n.slice(9).trim().toLowerCase()))];\n if (languages.length > 1) return null;\n return { code: child.children.map((n) => (n.type === 'text' ? n.value : '')).join(''), language: languages[0] ?? '' };\n}\nexport function normalizeRenderers<T>(renderers: Readonly<Record<string, T>>): Readonly<Record<string, T>> {\n const result: Record<string, T> = Object.create(null);\n for (const [language, renderer] of Object.entries(renderers)) {\n const key = language.trim().toLowerCase();\n if (!key) throw new Error('Code renderer language must not be empty');\n if (Object.hasOwn(result, key)) throw new Error(`Duplicate code renderer: ${key}`);\n result[key] = renderer;\n }\n return Object.freeze(result);\n}\nfunction annotation(node: RootContent): Element | undefined {\n if (node.type !== 'element') return;\n if (node.tagName === 'annotation' && node.properties.encoding === 'application/x-tex') return node;\n for (const child of node.children) {\n const found = annotation(child);\n if (found) return found;\n }\n}\nfunction text(node: RootContent): string {\n if (node.type === 'text') return node.value;\n if (node.type !== 'element') return '';\n if (node.tagName === 'table') throw new Error('Nested tables cannot be exported');\n if (Array.isArray(node.properties.className) && node.properties.className.includes('katex')) {\n const tex = annotation(node);\n if (!tex) throw new Error('Math is missing its text annotation');\n return tex.children.map(text).join('');\n }\n if (node.tagName === 'br') return '\\n';\n if (node.tagName === 'img' || node.tagName === 'cross-chunk-image') return String(node.properties.alt ?? '');\n return node.children.map(text).join('');\n}\nexport type TableProjection = { rows: string[][]; reason?: undefined } | { rows?: undefined; reason: string };\n/** Project sanitized HAST semantics, never custom cell UI or raw Markdown. */\nexport function projectTable(node?: Element): TableProjection {\n try {\n if (node?.tagName !== 'table') throw new Error('Table source is unavailable');\n const rows: string[][] = [];\n const walk = (parent: Element) => {\n for (const child of parent.children) {\n if (child.type === 'text' && !child.value.trim()) continue;\n if (child.type !== 'element') throw new Error('Unsupported table content');\n if (child.tagName === 'tr') {\n const cells: string[] = [];\n for (const cell of child.children) {\n if (cell.type === 'text' && !cell.value.trim()) continue;\n if (\n cell.type !== 'element' ||\n !['th', 'td'].includes(cell.tagName) ||\n Number(cell.properties.colSpan ?? 1) !== 1 ||\n Number(cell.properties.rowSpan ?? 1) !== 1\n )\n throw new Error('Only tables without merged cells can be exported');\n cells.push(text(cell));\n }\n rows.push(cells);\n } else if (['thead', 'tbody', 'tfoot'].includes(child.tagName) && parent === node) walk(child);\n else throw new Error('Unsupported table structure');\n }\n };\n walk(node);\n if (!rows.length || !rows[0].length || rows.some((r) => r.length !== rows[0].length))\n throw new Error('Only rectangular tables can be exported');\n return { rows };\n } catch (error) {\n return { reason: error instanceof Error ? error.message : 'Table cannot be exported' };\n }\n}\n/** Spreadsheet text policy is independent of delimiter quoting. Negative\n * numbers stay numeric; formulas/control-prefixed text stay literal. */\n// Control-prefixed formulas must stay literal when pasted into a spreadsheet.\n// eslint-disable-next-line no-control-regex\nconst formulaPrefix = /^[\\s\\u0000-\\u001f]*[=+@-]/;\nexport function serializeTable(rows: readonly (readonly string[])[], delimiter: ',' | '\\t' = ','): string {\n return rows\n .map((row) =>\n row\n .map((value) => {\n if (\n (formulaPrefix.test(value) && !/^\\s*-?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:e[+-]?\\d+)?\\s*$/i.test(value)) ||\n /^[\\t\\r\\n]/.test(value)\n )\n value = `'${value}`;\n return /[\"\\r\\n\\t,]/.test(value) ? `\"${value.replaceAll('\"', '\"\"')}\"` : value;\n })\n .join(delimiter)\n )\n .join('\\r\\n');\n}\n","export interface CodeFrame {\n code: string;\n language: string;\n}\n\n/** A trailing throttle: append bursts replace one pending frame without\n * moving its deadline. Replacements and completion bypass the timer. */\nexport function createCodeFrame(initial: CodeFrame, publish: (frame: CodeFrame) => void) {\n let shown = initial;\n let latest = initial;\n let delay = 0;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const cancel = () => {\n if (timer !== undefined) clearTimeout(timer);\n timer = undefined;\n };\n const flush = () => {\n cancel();\n if (shown.code === latest.code && shown.language === latest.language) return;\n shown = latest;\n publish(shown);\n };\n return {\n update(next: CodeFrame, streaming: boolean, interval: number) {\n const replaced = next.language !== latest.language || !next.code.startsWith(latest.code);\n latest = next;\n if (delay !== interval) cancel();\n delay = interval;\n if (!streaming || interval === 0 || replaced) return flush();\n if (shown.code === next.code && shown.language === next.language) return cancel();\n timer ??= setTimeout(flush, interval);\n },\n // Cancellation is reversible: Strict Mode replays the update effect.\n dispose: cancel,\n };\n}\n","/** Validate with the native parser, but format lexical tokens so numbers,\n * duplicate keys and key order never pass through JavaScript's value model.\n * Nested JSON expansion is optional and only applies to string values. */\nexport function prettyPrintJson(text: string, expandNested = true): string {\n try {\n return format(text, expandNested, 0);\n } catch {\n return text;\n }\n}\n\nfunction format(text: string, expandNested: boolean, baseIndent: number): string {\n JSON.parse(text);\n const tokens =\n text.match(/\"(?:\\\\[\\s\\S]|[^\"\\\\])*\"|-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?|true|false|null|[{}[\\],:]/g) ?? [];\n const out: string[] = [];\n let indent = baseIndent;\n const newline = () => out.push('\\n', ' '.repeat(indent));\n for (let i = 0; i < tokens.length; i++) {\n const token = tokens[i];\n if (token === '{' || token === '[') {\n out.push(token);\n if (tokens[i + 1] !== (token === '{' ? '}' : ']')) {\n indent++;\n newline();\n }\n } else if (token === '}' || token === ']') {\n if (tokens[i - 1] !== (token === '}' ? '{' : '[')) {\n indent--;\n newline();\n }\n out.push(token);\n } else if (token === ',') {\n out.push(',');\n newline();\n } else if (token === ':') {\n out.push(': ');\n } else if (token.startsWith('\"')) {\n const value = JSON.parse(token) as string;\n const trimmed = value.trim();\n if (expandNested && tokens[i + 1] !== ':' && /^[{[]/.test(trimmed) && indent < 100) {\n try {\n out.push(format(trimmed, true, indent));\n continue;\n } catch {\n /* Keep non-JSON strings. */\n }\n }\n out.push(JSON.stringify(value));\n } else {\n out.push(token);\n }\n }\n return out.join('');\n}\n","/** Bracket-balance gate, not a JSON validator. Retain quote/escape state\n * across append seams so growing JSON does not rescan its whole body when\n * each nested object closes. Replacements start a fresh lineage. */\nexport function createJsonCompletenessScanner() {\n let previous = '';\n let depth = 0;\n let quoted = false;\n let escaped = false;\n let invalid = false;\n let last = '';\n return (text: string): boolean => {\n let from = previous.length;\n if (!text.startsWith(previous)) {\n from = 0;\n depth = 0;\n quoted = escaped = invalid = false;\n last = '';\n }\n previous = text;\n for (let i = from; i < text.length; i++) {\n const c = text[i];\n if (!/\\s/.test(c)) last = c;\n if (quoted) {\n if (escaped) escaped = false;\n else if (c === '\\\\') escaped = true;\n else if (c === '\"') quoted = false;\n } else if (c === '\"') quoted = true;\n else if (c === '{' || c === '[') depth++;\n else if (c === '}' || c === ']') {\n depth--;\n if (depth < 0) invalid = true;\n }\n }\n return !invalid && !quoted && depth === 0 && (last === '}' || last === ']');\n };\n}\n\nexport function jsonLooksComplete(text: string): boolean {\n return createJsonCompletenessScanner()(text);\n}\n","/** Mermaid owns global configuration and a global renderer. Keep initialize,\n * parse and render in one serialized task. Each mounted diagram retains at\n * most one pending task; superseded frames never enter Mermaid. */\nexport function createRenderQueue() {\n type Job = { run: () => Promise<void>; resolve: () => void; reject: (error: unknown) => void };\n const pending = new Map<object, Job>();\n let running = false;\n async function drain() {\n if (running) return;\n running = true;\n try {\n while (pending.size) {\n const [owner, job] = pending.entries().next().value!;\n pending.delete(owner);\n try {\n await job.run();\n job.resolve();\n } catch (error) {\n job.reject(error);\n }\n }\n } finally {\n running = false;\n }\n }\n return {\n enqueue(owner: object, run: () => Promise<void>): Promise<void> {\n pending.get(owner)?.resolve();\n const promise = new Promise<void>((resolve, reject) => pending.set(owner, { run, resolve, reject }));\n void drain();\n return promise;\n },\n cancel(owner: object) {\n pending.get(owner)?.resolve();\n pending.delete(owner);\n },\n };\n}\n\nexport const mermaidRenderQueue = createRenderQueue();\n","type MermaidConfig = {\n theme?: string;\n securityLevel?: string;\n darkMode?: boolean;\n suppressErrorRendering?: boolean;\n maxTextSize?: number;\n themeVariables?: unknown;\n};\n\n/** The part of the mermaid module this file touches. Structural so tests can\n * pass a stub; `mermaidAPI` is deprecated in mermaid's types but present at\n * runtime in mermaid 11, and it is the only place `getSiteConfig` /\n * `getConfig` live (the default export has neither). */\nexport type MermaidInitTarget = {\n initialize(config: MermaidConfig): void;\n mermaidAPI?: {\n getSiteConfig?: () => MermaidConfig;\n getConfig?: () => MermaidConfig;\n };\n};\n\n/**\n * `securityLevel` values under which mermaid still sanitizes what it emits.\n * `sandbox` is stricter than `strict` (the diagram renders inside a sandboxed\n * iframe), so a host that chose it must not be downgraded. `loose` and\n * `antiscript` skip DOMPurify and are upgraded to `strict`; so is an unset\n * value, which mermaid treats as `strict` but which we pin explicitly so the\n * guard below has something to compare against.\n */\nconst SAFE_SECURITY_LEVELS: ReadonlySet<string | undefined> = new Set(['strict', 'sandbox']);\n\n/** Theme we last wrote. mermaid's config is a module-level singleton, so this\n * is module-level too: instances under providers with DIFFERENT color\n * schemes each re-assert before their own render, and the check runs per\n * attempt (each streamed chunk re-runs the effect) rather than once per\n * instance. It also tells a theme WE wrote apart from one the host wrote —\n * the host's choice is left alone; ours follows the color scheme. */\nlet ownedThemes = new WeakMap<object, 'dark' | 'base'>();\n\n/** Test hook: forget the theme cache so each test starts from a cold module. */\nexport const resetMermaidInitializationForTests = () => {\n ownedThemes = new WeakMap();\n};\n\n/**\n * Read the config `mermaid.initialize` would replace. `getSiteConfig` is the\n * site config (what the host passed to `initialize`, merged over mermaid's\n * defaults); `getConfig` is the per-render config with `%%{init}%%`\n * directives merged in and is only a fallback for builds without the former.\n */\nconst readSiteConfig = (mermaid: MermaidInitTarget): MermaidConfig => {\n const api = mermaid.mermaidAPI;\n return api?.getSiteConfig?.() ?? api?.getConfig?.() ?? {};\n};\n\n/** mermaid's own default for `maxTextSize` (`MAX_TEXTLENGTH` in mermaidAPI). */\nexport const MERMAID_DEFAULT_MAX_TEXT_SIZE = 50_000;\n\n/**\n * The effective `maxTextSize`. `mermaid.render` does not reject oversized\n * input: it swaps in a placeholder diagram (\"Maximum text size in diagram\n * exceeded\") and resolves normally, and `mermaid.parse` has no size gate at\n * all, so the whole text is parsed first. The renderer checks this before\n * parsing and reports the size as an error instead. The key is in mermaid's\n * `secure` list, so a `%%{init}%%` directive cannot raise it and the site\n * config is the value that applies.\n */\nexport const getMermaidMaxTextSize = (mermaid: MermaidInitTarget): number => {\n const configured = readSiteConfig(mermaid).maxTextSize;\n return typeof configured === 'number' && Number.isFinite(configured) && configured >= 0\n ? configured\n : MERMAID_DEFAULT_MAX_TEXT_SIZE;\n};\n\n/**\n * mermaid's config is a module-level singleton shared with the host\n * application when the bundler dedupes the package, and a host that enables\n * `click` interactions calls `mermaid.initialize({ securityLevel: 'loose' })`\n * — the officially documented way. Under `loose` mermaid skips DOMPurify\n * and its output goes into this component's `innerHTML` verbatim: an\n * LLM-authored diagram string could then run script in the page origin.\n * So a theme cache alone is not enough of a guard: before every render the\n * current `securityLevel` is read back (a config copy, still far cheaper\n * than `initialize`'s merge + theme variables + diagram registration) and an\n * unsafe value forces a re-initialize\n * (2026-08-19 review r2 P2-11; the v2.4.2 \"documented premise\" made this\n * the host's problem — it is ours, the innerHTML is ours).\n *\n * In mermaid 11 `initialize` goes through `setSiteConfig`, which REPLACES\n * the site config with defaults + the keys passed in. Calling it with only\n * our keys wiped the host's `theme`, `fontFamily`, `flowchart` options and\n * so on, and turned a host `sandbox` into `strict` (3.0.2 review). So:\n * - the current site config is read back and passed through with our\n * overrides on top, so host keys survive;\n * - `sandbox` is accepted as is; only `loose` / `antiscript` / unset become\n * `strict`;\n * - a theme the host chose is kept (with its `themeVariables`); the color\n * scheme switch only applies to the theme when the host has not chosen\n * one, or when the current theme is one we wrote;\n * - when nothing needs to change, `initialize` is not called at all, so a\n * host on `strict`/`sandbox` and this component stop overwriting each\n * other on every render.\n */\nexport const ensureMermaidInitialized = (mermaid: MermaidInitTarget, isDark: boolean) => {\n const site = readSiteConfig(mermaid);\n const ownedTheme = ownedThemes.get(mermaid);\n const wantedTheme = isDark ? 'dark' : 'base';\n\n // `default` is mermaid's own initial value, so it does not count as a host\n // choice. A theme equal to the one we last wrote is ours to switch.\n const hostOwnsTheme = site.theme !== undefined && site.theme !== 'default' && site.theme !== ownedTheme;\n\n const levelOk = SAFE_SECURITY_LEVELS.has(site.securityLevel);\n const themeOk = hostOwnsTheme || (site.theme === wantedTheme && Boolean(site.darkMode) === isDark);\n const suppressOk = site.suppressErrorRendering === true;\n if (levelOk && themeOk && suppressOk) return;\n\n const next: MermaidConfig = {\n ...site,\n // Without this, a draw-phase throw (an error that got past\n // mermaid.parse) leaves mermaid's temp element orphaned in document.body\n // — its error path only cleans up when this flag is set. We render our\n // own error tab anyway, so mermaid's built-in error diagram is dead\n // weight here regardless.\n suppressErrorRendering: true,\n };\n if (!levelOk) {\n next.securityLevel = 'strict';\n }\n if (!hostOwnsTheme) {\n next.theme = wantedTheme;\n next.darkMode = isDark;\n // The site config carries the PREVIOUS theme's fully computed\n // `themeVariables`. `initialize` feeds `themeVariables` into the new\n // theme as overrides for every key present, so passing them back would\n // make the new theme look exactly like the old one. Drop them and keep\n // only `fontFamily`: `default`, `base` and `dark` share the same font\n // default, so a value that differs is the host's and survives the switch\n // (a top-level `fontFamily` survives through the spread above either way).\n // Mermaid's dark edge labels use #ccc text on #585858 (4.43:1).\n // Give our default palette enough contrast; host-owned themes stay intact.\n const fontFamily: unknown = (site.themeVariables as { fontFamily?: unknown } | undefined)?.fontFamily;\n if (typeof fontFamily === 'string') {\n next.themeVariables = { fontFamily, ...(isDark ? { edgeLabelBackground: '#444444' } : {}) };\n } else if (isDark) {\n next.themeVariables = { edgeLabelBackground: '#444444' };\n } else {\n delete next.themeVariables;\n }\n ownedThemes.set(mermaid, wantedTheme);\n }\n mermaid.initialize(next);\n};\n","import { mermaidRenderQueue } from './renderQueue';\nimport { ensureMermaidInitialized, getMermaidMaxTextSize, type MermaidInitTarget } from './mermaid';\n\nexport interface DiagramEngine extends MermaidInitTarget {\n parse(code: string, options: { suppressErrors: true }): Promise<unknown>;\n render(id: string, code: string): Promise<{ svg: string; bindFunctions?(element: object): void }>;\n}\nexport type DiagramState = {\n status: 'loading' | 'ready' | 'error';\n svg: string;\n error?: string;\n bind?: (element: object) => void;\n};\nexport interface DiagramRequest {\n code: string;\n dark: boolean;\n streaming: boolean;\n active: boolean;\n resetKey: string;\n interval: number;\n}\nlet nextId = 0;\n/** Owns cancellation and retries across both UI adapters. In-flight Mermaid\n * cannot be aborted, but obsolete work never publishes or starts a render. */\nexport function createDiagramController(load: () => Promise<DiagramEngine>, publish: (state: DiagramState) => void) {\n const owner = {};\n let epoch = 0;\n let previous: DiagramRequest | undefined;\n let svg = '';\n let bind: DiagramState['bind'];\n let timer: ReturnType<typeof setTimeout> | undefined;\n const cancel = () => {\n epoch++;\n if (timer !== undefined) clearTimeout(timer);\n timer = undefined;\n mermaidRenderQueue.cancel(owner);\n };\n return {\n update(request: DiagramRequest) {\n const replaced =\n !previous ||\n previous.resetKey !== request.resetKey ||\n previous.dark !== request.dark ||\n !request.code.startsWith(previous.code);\n const pending = timer !== undefined;\n // Append bursts retain their deadline; every request invalidates work\n // already running, including completion-only and active-only changes.\n epoch++;\n mermaidRenderQueue.cancel(owner);\n if (replaced) {\n svg = '';\n bind = undefined;\n if (timer !== undefined) clearTimeout(timer);\n timer = undefined;\n }\n previous = request;\n if (!request.active) {\n cancel();\n return;\n }\n publish({ status: 'loading', svg, bind });\n const attempt = () => {\n timer = undefined;\n const current = previous!;\n const generation = epoch;\n const valid = () => generation === epoch;\n let phase: 'load' | 'render' = 'load';\n void load()\n .then((engine) => {\n phase = 'render';\n if (!valid()) return;\n return mermaidRenderQueue.enqueue(owner, async () => {\n if (!valid()) return;\n ensureMermaidInitialized(engine, current.dark);\n if (current.code.length > getMermaidMaxTextSize(engine))\n throw new Error('Diagram exceeds Mermaid’s maximum text size');\n const parsed = await engine.parse(current.code, { suppressErrors: true });\n if (!valid()) return;\n if (parsed === false) throw new Error('Diagram syntax is incomplete or invalid');\n const result = await engine.render(`aimd-diagram-${++nextId}`, current.code);\n if (!valid()) return;\n svg = result.svg;\n bind = result.bindFunctions;\n publish({ status: 'ready', svg, bind });\n });\n })\n .catch((error) => {\n if (valid())\n publish({\n status: current.streaming && phase === 'render' ? 'loading' : 'error',\n svg,\n bind,\n error:\n (phase === 'load' ? 'Diagram engine could not load: ' : '') +\n (error instanceof Error ? error.message : String(error)).slice(0, 500),\n });\n });\n };\n if (!request.streaming || request.interval <= 0) {\n if (timer !== undefined) clearTimeout(timer);\n attempt();\n } else if (!pending || replaced) timer = setTimeout(attempt, request.interval);\n },\n dispose: cancel,\n };\n}\n","/** Structural browser target keeps the shared core independent of DOM libs.\n * Several React/Vue dialogs can coexist; the last owner restores scrolling. */\nconst locks = new WeakMap<object, { count: number; overflow: string }>();\nexport function lockImagePreviewScroll(target: { style: { overflow: string } }): () => void {\n let lock = locks.get(target);\n if (!lock) {\n lock = { count: 0, overflow: target.style.overflow };\n locks.set(target, lock);\n }\n lock.count++;\n target.style.overflow = 'hidden';\n let released = false;\n return () => {\n if (released) return;\n released = true;\n if (--lock.count === 0) {\n if (target.style.overflow === 'hidden') target.style.overflow = lock.overflow;\n locks.delete(target);\n }\n };\n}\n","/** Shared image semantics; no DOM or framework dependency. */\nexport type ImageActionIconName =\n 'rotateLeft' | 'rotateRight' | 'zoomIn' | 'zoomOut' | 'close' | 'prev' | 'next' | 'flipX' | 'flipY';\nexport type ImageIconName = 'placeholder' | 'error' | 'preview' | 'gallery' | ImageActionIconName;\nexport type ImageLoadStatus = 'loading' | 'ready' | 'error';\n/** Lucide paths supplied for the Markdown image skin (ISC license). */\nexport const imageIconPaths: Record<ImageIconName, readonly string[]> = {\n rotateLeft: ['M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8', 'M3 3v5h5'],\n rotateRight: ['M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8', 'M21 3v5h-5'],\n zoomIn: ['M19 11a8 8 0 1 1 -16 0a8 8 0 1 1 16 0', 'M21 21L16.65 16.65', 'M11 8L11 14', 'M8 11L14 11'],\n zoomOut: ['M19 11a8 8 0 1 1 -16 0a8 8 0 1 1 16 0', 'M21 21L16.65 16.65', 'M8 11L14 11'],\n close: ['M18 6 6 18', 'm6 6 12 12'],\n prev: ['m15 18-6-6 6-6'],\n next: ['m9 18 6-6-6-6'],\n flipX: [\n 'M8 3H5a2 2 0 0 0-2 2v14c0 1.1.9 2 2 2h3',\n 'M16 3h3a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-3',\n 'M12 20v2',\n 'M12 14v2',\n 'M12 8v2',\n 'M12 2v2',\n ],\n flipY: [\n 'M21 8V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v3',\n 'M21 16v3a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-3',\n 'M4 12H2',\n 'M10 12H8',\n 'M16 12h-2',\n 'M22 12h-2',\n ],\n placeholder: [\n 'M5 3h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2Z',\n 'M11 9a2 2 0 1 1-4 0 2 2 0 0 1 4 0',\n 'm21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21',\n ],\n error: [\n 'm2 2 20 20M10.41 10.41a2 2 0 1 1-2.83-2.83m5.92 5.92L6 21m12-9 3 3',\n 'M3.59 3.59A2 2 0 0 0 3 5v14a2 2 0 0 0 2 2h14c.55 0 1.052-.22 1.41-.59M21 15V5a2 2 0 0 0-2-2H9',\n ],\n gallery: ['M5 3h14a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2Z', 'M4 21h1m4 0h1m4 0h1m4 0h1'],\n preview: [\n 'M15 15.003a1 1 0 0 1 1.517-.859l4.997 2.997a1 1 0 0 1 0 1.718l-4.997 2.997a1 1 0 0 1-1.517-.86z',\n 'M21 12.17V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h6m-5 0 5-5',\n 'M11 9a2 2 0 1 1-4 0 2 2 0 0 1 4 0',\n ],\n};\nexport const imageGroupSelector = '[data-aimd-image-scope], .aim-typography-root, .aimd-vue, .mantine-Typography-root';\nexport interface ImageGalleryItem {\n id: object;\n src: string;\n alt: string;\n /** DOM adapters provide document ordering without leaking DOM types. */\n precedes: (other: object) => boolean;\n}\nexport interface ImageGallery {\n items: () => readonly ImageGalleryItem[];\n subscribe: (listener: () => void) => () => void;\n set: (item: ImageGalleryItem) => void;\n remove: (id: object) => void;\n}\nconst galleries = new WeakMap<object, ImageGallery>();\n/** Scope is an adapter-owned object, never a global document id. */\nexport function getImageGallery(scope: object): ImageGallery {\n const existing = galleries.get(scope);\n if (existing) return existing;\n const entries = new Map<object, ImageGalleryItem>();\n const listeners = new Set<() => void>();\n const notify = () => listeners.forEach((listener) => listener());\n const gallery: ImageGallery = {\n items: () => [...entries.values()].sort((a, b) => (a.precedes(b.id) ? -1 : b.precedes(a.id) ? 1 : 0)),\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n set(item) {\n const old = entries.get(item.id);\n if (old?.src === item.src && old?.alt === item.alt) return;\n entries.set(item.id, item);\n notify();\n },\n remove(id) {\n if (entries.delete(id)) notify();\n },\n };\n galleries.set(scope, gallery);\n return gallery;\n}\n\nexport const imageActionLabels: Record<ImageActionIconName, string> = {\n close: 'Close preview',\n prev: 'Previous image',\n next: 'Next image',\n rotateLeft: 'Rotate left',\n rotateRight: 'Rotate right',\n zoomIn: 'Zoom in',\n zoomOut: 'Zoom out',\n flipX: 'Flip horizontally',\n flipY: 'Flip vertically',\n};\n","/** Transform rules adapted from @rc-component/image 1.10.0 (MIT).\n * Keep the Vue adapter's gestures aligned with the upstream React engine. */\nexport interface ImageTransform {\n x: number;\n y: number;\n rotate: number;\n scale: number;\n flipX: boolean;\n flipY: boolean;\n}\nexport interface ImageGeometry {\n width: number;\n height: number;\n left: number;\n top: number;\n viewportWidth: number;\n viewportHeight: number;\n}\nexport const initialImageTransform = (): ImageTransform => ({\n x: 0,\n y: 0,\n rotate: 0,\n scale: 1,\n flipX: false,\n flipY: false,\n});\nexport function imageTransformStyle(transform: ImageTransform): string {\n const { x, y, scale, rotate, flipX, flipY } = transform;\n return `translate3d(${x}px, ${y}px, 0) scale3d(${flipX ? '-' : ''}${scale}, ${flipY ? '-' : ''}${scale}, 1) rotate(${rotate}deg)`;\n}\nexport function zoomImage(\n transform: ImageTransform,\n ratio: number,\n geometry: ImageGeometry,\n centerX = geometry.viewportWidth / 2,\n centerY = geometry.viewportHeight / 2,\n touch = false\n): ImageTransform {\n if (!Number.isFinite(ratio) || ratio <= 0) return transform;\n const scale = Math.min(50, touch ? Math.max(0.01, transform.scale * ratio) : Math.max(1, transform.scale * ratio));\n const difference = scale / transform.scale - 1;\n let x = transform.x - difference * (centerX - transform.x - geometry.left - geometry.width / 2);\n let y = transform.y - difference * (centerY - transform.y - geometry.top - geometry.height / 2);\n if (\n ratio < 1 &&\n scale === 1 &&\n geometry.width <= geometry.viewportWidth &&\n geometry.height <= geometry.viewportHeight\n )\n x = y = 0;\n return { ...transform, x, y, scale };\n}\nexport function imageWheelRatio(delta: number): number {\n const ratio = 1 + Math.min(Math.abs(delta / 100), 1) * 0.5;\n return delta > 0 ? 1 / ratio : ratio;\n}\n/** Snap a moved image back inside the viewport, taking quarter turns into account. */\nexport function reboundImage(\n transform: ImageTransform,\n geometry: ImageGeometry,\n bounds: { left: number; top: number }\n): ImageTransform {\n if (transform.scale < 1) return { ...transform, x: 0, y: 0, scale: 1 };\n const rotated = transform.rotate % 180 !== 0;\n const width = (rotated ? geometry.height : geometry.width) * transform.scale;\n const height = (rotated ? geometry.width : geometry.height) * transform.scale;\n if (width <= geometry.viewportWidth && height <= geometry.viewportHeight) return { ...transform, x: 0, y: 0 };\n const fix = (position: number, start: number, size: number, viewport: number) => {\n const offset = (size - viewport) / 2;\n if (size > viewport) {\n if (start > 0) return offset;\n if (start < 0 && start + size < viewport) return -offset;\n } else if (start < 0 || start + size > viewport) return start < 0 ? offset : -offset;\n return position;\n };\n return {\n ...transform,\n x: fix(transform.x, bounds.left, width, geometry.viewportWidth),\n y: fix(transform.y, bounds.top, height, geometry.viewportHeight),\n };\n}\n/** Upstream pinch center weights each finger by how far it moved. */\nexport function imagePinchCenter(\n oldA: { x: number; y: number },\n oldB: { x: number; y: number },\n a: { x: number; y: number },\n b: { x: number; y: number }\n): { x: number; y: number } {\n const distanceA = Math.hypot(a.x - oldA.x, a.y - oldA.y),\n distanceB = Math.hypot(b.x - oldB.x, b.y - oldB.y);\n const ratio = distanceA + distanceB ? distanceA / (distanceA + distanceB) : 0;\n return { x: oldA.x + ratio * (oldB.x - oldA.x), y: oldA.y + ratio * (oldB.y - oldA.y) };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["StreamingLanguageDetector"],"sources":["../../src/components/nodes.ts","../../src/components/codeText.ts","../../src/components/codeLanguage.ts","../../src/components/codeFrame.ts","../../src/components/formatJson.ts","../../src/components/jsonCompleteness.ts","../../src/components/codeBlock.ts","../../src/components/renderQueue.ts","../../src/components/mermaid.ts","../../src/components/diagram.ts","../../src/components/labels.ts","../../src/components/scroll.ts","../../src/components/imageTransform.ts","../../src/components/imagePreview.ts","../../src/components/image.ts"],"sourcesContent":["import type { Element, RootContent } from 'hast';\nimport type { TableExportReason } from './labels';\n\nexport interface CodeSource {\n code: string;\n language: string;\n}\n/** Enhance only ordinary fenced code; preserve all other pre overrides. */\nexport function extractCode(node?: Element): CodeSource | null {\n if (node?.tagName !== 'pre' || node.children.length !== 1 || Object.keys(node.properties).length) return null;\n const child = node.children[0];\n if (\n child.type !== 'element' ||\n child.tagName !== 'code' ||\n child.children.some((n) => n.type !== 'text') ||\n Object.keys(child.properties).some((k) => k !== 'className')\n )\n return null;\n const classes = child.properties.className ?? [];\n const names = (Array.isArray(classes) ? classes : String(classes).split(/\\s+/)).map(String).filter(Boolean);\n if (names.some((n) => !n.startsWith('language-'))) return null;\n const languages = [...new Set(names.map((n) => n.slice(9).trim().toLowerCase()))];\n if (languages.length > 1) return null;\n return { code: child.children.map((n) => (n.type === 'text' ? n.value : '')).join(''), language: languages[0] ?? '' };\n}\nexport function normalizeRenderers<T>(renderers: Readonly<Record<string, T>>): Readonly<Record<string, T>> {\n const result: Record<string, T> = Object.create(null);\n for (const [language, renderer] of Object.entries(renderers)) {\n const key = language.trim().toLowerCase();\n if (!key) throw new Error('Code renderer language must not be empty');\n if (Object.hasOwn(result, key)) throw new Error(`Duplicate code renderer: ${key}`);\n result[key] = renderer;\n }\n return Object.freeze(result);\n}\nfunction annotation(node: RootContent): Element | undefined {\n if (node.type !== 'element') return;\n if (node.tagName === 'annotation' && node.properties.encoding === 'application/x-tex') return node;\n for (const child of node.children) {\n const found = annotation(child);\n if (found) return found;\n }\n}\nfunction text(node: RootContent): string {\n if (node.type === 'text') return node.value;\n if (node.type !== 'element') return '';\n if (node.tagName === 'table') throw new Error('Nested tables cannot be exported');\n if (Array.isArray(node.properties.className) && node.properties.className.includes('katex')) {\n const tex = annotation(node);\n if (!tex) throw new Error('Math is missing its text annotation');\n return tex.children.map(text).join('');\n }\n if (node.tagName === 'br') return '\\n';\n if (node.tagName === 'img' || node.tagName === 'cross-chunk-image') return String(node.properties.alt ?? '');\n return node.children.map(text).join('');\n}\nexport type TableProjection =\n { rows: string[][]; reason?: undefined } | { rows?: undefined; reason: TableExportReason };\nclass ExportRefused extends Error {\n constructor(readonly reason: TableExportReason) {\n super(reason);\n }\n}\n/** Project sanitized HAST semantics, never custom cell UI or raw Markdown. A\n * table that cannot be exported reports why as a code; `TableLabels` has the text. */\nexport function projectTable(node?: Element): TableProjection {\n try {\n if (node?.tagName !== 'table') throw new ExportRefused('unavailable');\n const rows: string[][] = [];\n const walk = (parent: Element) => {\n for (const child of parent.children) {\n if (child.type === 'text' && !child.value.trim()) continue;\n if (child.type !== 'element') throw new ExportRefused('unsupportedContent');\n if (child.tagName === 'tr') {\n const cells: string[] = [];\n for (const cell of child.children) {\n if (cell.type === 'text' && !cell.value.trim()) continue;\n if (\n cell.type !== 'element' ||\n !['th', 'td'].includes(cell.tagName) ||\n Number(cell.properties.colSpan ?? 1) !== 1 ||\n Number(cell.properties.rowSpan ?? 1) !== 1\n )\n throw new ExportRefused('mergedCells');\n cells.push(text(cell));\n }\n rows.push(cells);\n } else if (['thead', 'tbody', 'tfoot'].includes(child.tagName) && parent === node) walk(child);\n else throw new ExportRefused('unsupportedStructure');\n }\n };\n walk(node);\n if (!rows.length || !rows[0].length || rows.some((r) => r.length !== rows[0].length))\n throw new ExportRefused('notRectangular');\n return { rows };\n } catch (error) {\n return { reason: error instanceof ExportRefused ? error.reason : 'unavailable' };\n }\n}\n/** Spreadsheet text policy is independent of delimiter quoting. Negative\n * numbers stay numeric; formulas/control-prefixed text stay literal. */\n// Control-prefixed formulas must stay literal when pasted into a spreadsheet.\n// eslint-disable-next-line no-control-regex\nconst formulaPrefix = /^[\\s\\u0000-\\u001f]*[=+@-]/;\nexport function serializeTable(rows: readonly (readonly string[])[], delimiter: ',' | '\\t' = ','): string {\n return rows\n .map((row) =>\n row\n .map((value) => {\n if (\n (formulaPrefix.test(value) && !/^\\s*-?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:e[+-]?\\d+)?\\s*$/i.test(value)) ||\n /^[\\t\\r\\n]/.test(value)\n )\n value = `'${value}`;\n return /[\"\\r\\n\\t,]/.test(value) ? `\"${value.replaceAll('\"', '\"\"')}\"` : value;\n })\n .join(delimiter)\n )\n .join('\\r\\n');\n}\n","/** hast code text ends with one newline that the Markdown source does not\n * have, so a mid-line append turns `ab\\n` into `abc\\n` and a plain prefix\n * test reports a replacement. These helpers work on the text without it. */\nexport function codeBody(code: string): string {\n return code.endsWith('\\n') ? code.slice(0, -1) : code;\n}\n\n/** While a document streams, an unlabelled block whose text has been still\n * this long is judged as complete. The streaming flag describes the document\n * and does not say when one fence has closed. */\nexport const CODE_LANGUAGE_SETTLE_MS = 300;\n\n/** Exact prefix test. On V8, string equality compares contiguous ranges much\n * faster than startsWith's character loop. It is still O(prefix): full-string\n * inputs cannot prove an arbitrary replacement in constant time. */\nexport function startsWithText(text: string, prefix: string): boolean {\n return text.length >= prefix.length && text.slice(0, prefix.length) === prefix;\n}\n\n/** Whether `next` is `previous` with nothing or more appended. */\nexport function extendsCode(next: string, previous: string): boolean {\n return startsWithText(next, codeBody(previous));\n}\n","import { StreamingLanguageDetector, type CodeLanguage } from '@ai-markdown/code-language-detector';\nimport { CODE_LANGUAGE_SETTLE_MS, codeBody, extendsCode } from './codeText';\n\n/**\n * Follows the language of one unlabelled code block.\n *\n * `read` answers during render, server rendering included, and changes\n * nothing: a render that is thrown away cannot move the verdict. `observe` is\n * called once the text is on screen, and only it feeds the detector that\n * follows the block. That detector keeps one verdict for as long as the text\n * only grows: it looks again only when the text has grown enough to change\n * the evidence, never lowers its confidence, and charges a margin for a\n * switch across language families. It is fed the text without hast's final\n * newline, which makes every append a continuation.\n *\n * What `read` answers for a text:\n * - the observed text, or one that extends it: the followed verdict as it\n * stands. `observe` then looks at the new text and returns true when the\n * verdict moved, so the host can read again;\n * - anything else (a first or server render, a rewrite, an older text): the\n * verdict a fresh detector gives it, which is also what `observe` will\n * arrive at after starting over.\n *\n * While the document streams the detector does not look again before 80 more\n * characters, and the streaming flag describes the document, not this fence.\n * `observe` therefore starts a timer after each change: a block whose text\n * has been still for `CODE_LANGUAGE_SETTLE_MS` is judged as complete, and\n * `onSettle` asks the host to read again.\n */\nexport function createCodeLanguageTracker(onSettle: () => void) {\n const detector = new StreamingLanguageDetector();\n /** The text the detector follows; undefined until the first `observe`. */\n let followed: string | undefined;\n let settled: string | null = null;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const cancel = () => {\n if (timer !== undefined) clearTimeout(timer);\n timer = undefined;\n };\n const judge = (from: StreamingLanguageDetector, text: string, streaming: boolean) =>\n (streaming && settled !== text ? from.update(text) : from.finalize(text)).language;\n return {\n /** The verdict for `code`. Changes nothing, so a repeated or abandoned render is harmless. */\n read(code: string, streaming: boolean): CodeLanguage | null {\n if (followed !== undefined && extendsCode(code, followed)) return detector.current.language;\n return judge(new StreamingLanguageDetector(), codeBody(code), streaming);\n },\n /** Call once the text is on screen. Each call replaces the pending timer. True when the verdict `read` gave for `code` has moved. */\n observe(code: string, streaming: boolean): boolean {\n cancel();\n const text = codeBody(code);\n const starting = followed === undefined || !extendsCode(code, followed);\n if (starting) detector.reset();\n const before = detector.current.language;\n followed = code;\n const after = judge(detector, text, streaming);\n if (streaming && settled !== text)\n timer = setTimeout(() => {\n timer = undefined;\n settled = text;\n detector.finalize(text);\n onSettle();\n }, CODE_LANGUAGE_SETTLE_MS);\n // A text that starts over was read with a fresh detector, which is what this one now is.\n return !starting && before !== after;\n },\n // Cancellation is reversible: a later observe starts a new timer.\n dispose: cancel,\n };\n}\n","import { extendsCode } from './codeText';\n\nexport interface CodeFrame {\n code: string;\n language: string;\n /** Shared only by append continuations (see `extendsCode`); never mutated. */\n generation: object;\n}\n\nexport function nextCodeFrame(previous: CodeFrame | undefined, code: string, language: string): CodeFrame {\n if (previous?.code === code && previous.language === language) return previous;\n const continues = previous && language === previous.language && extendsCode(code, previous.code);\n return { code, language, generation: continues ? previous.generation : {} };\n}\n\n/** A trailing throttle: append bursts replace one pending frame without\n * moving its deadline. Replacements and completion bypass the timer. */\nexport function createCodeFrame(initial: CodeFrame, publish: (frame: CodeFrame) => void) {\n let shown = initial;\n let latest = initial;\n let delay = 0;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const cancel = () => {\n if (timer !== undefined) clearTimeout(timer);\n timer = undefined;\n };\n const flush = () => {\n cancel();\n if (shown.code === latest.code && shown.language === latest.language) return;\n shown = latest;\n publish(shown);\n };\n return {\n update(next: CodeFrame, streaming: boolean, interval: number) {\n const replaced = next.generation !== latest.generation;\n latest = next;\n if (delay !== interval) cancel();\n delay = interval;\n if (!streaming || interval === 0 || replaced) return flush();\n if (shown.code === next.code && shown.language === next.language) return cancel();\n timer ??= setTimeout(flush, interval);\n },\n // Cancellation is reversible: Strict Mode replays the update effect.\n dispose: cancel,\n };\n}\n","/** Validate with the native parser, but format lexical tokens so numbers,\n * duplicate keys and key order never pass through JavaScript's value model.\n * Nested JSON expansion is optional and only applies to string values. */\nexport function prettyPrintJson(text: string, expandNested = true): string {\n try {\n return format(text, expandNested, 0);\n } catch {\n return text;\n }\n}\n\nfunction format(text: string, expandNested: boolean, baseIndent: number): string {\n JSON.parse(text);\n const tokens =\n text.match(/\"(?:\\\\[\\s\\S]|[^\"\\\\])*\"|-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?|true|false|null|[{}[\\],:]/g) ?? [];\n const out: string[] = [];\n let indent = baseIndent;\n const newline = () => out.push('\\n', ' '.repeat(indent));\n for (let i = 0; i < tokens.length; i++) {\n const token = tokens[i];\n if (token === '{' || token === '[') {\n out.push(token);\n if (tokens[i + 1] !== (token === '{' ? '}' : ']')) {\n indent++;\n newline();\n }\n } else if (token === '}' || token === ']') {\n if (tokens[i - 1] !== (token === '}' ? '{' : '[')) {\n indent--;\n newline();\n }\n out.push(token);\n } else if (token === ',') {\n out.push(',');\n newline();\n } else if (token === ':') {\n out.push(': ');\n } else if (token.startsWith('\"')) {\n const value = JSON.parse(token) as string;\n const trimmed = value.trim();\n if (expandNested && tokens[i + 1] !== ':' && /^[{[]/.test(trimmed) && indent < 100) {\n try {\n out.push(format(trimmed, true, indent));\n continue;\n } catch {\n /* Keep non-JSON strings. */\n }\n }\n out.push(JSON.stringify(value));\n } else {\n out.push(token);\n }\n }\n return out.join('');\n}\n","import { codeBody, startsWithText } from './codeText';\n\n/** Bracket-balance gate, not a JSON validator. Retain quote/escape state\n * across append seams so growing JSON does not rescan its whole body when\n * each nested object closes. Replacements start a fresh lineage. The final\n * newline of hast code text is left unscanned: it is whitespace, and it moves\n * on every append. */\nexport function createJsonCompletenessScanner() {\n let previous = '';\n let depth = 0;\n let quoted = false;\n let escaped = false;\n let invalid = false;\n let last = '';\n return (text: string): boolean => {\n const body = codeBody(text);\n let from = previous.length;\n if (!startsWithText(body, previous)) {\n from = 0;\n depth = 0;\n quoted = escaped = invalid = false;\n last = '';\n }\n previous = body;\n for (let i = from; i < body.length; i++) {\n const c = body[i];\n if (!/\\s/.test(c)) last = c;\n if (quoted) {\n if (escaped) escaped = false;\n else if (c === '\\\\') escaped = true;\n else if (c === '\"') quoted = false;\n } else if (c === '\"') quoted = true;\n else if (c === '{' || c === '[') depth++;\n else if (c === '}' || c === ']') {\n depth--;\n if (depth < 0) invalid = true;\n }\n }\n return !invalid && !quoted && depth === 0 && (last === '}' || last === ']');\n };\n}\n\nexport function jsonLooksComplete(text: string): boolean {\n return createJsonCompletenessScanner()(text);\n}\n","import { createCodeFrame, type CodeFrame } from './codeFrame';\nimport { createCodeLanguageTracker } from './codeLanguage';\nimport { extendsCode } from './codeText';\nimport { prettyPrintJson } from './formatJson';\nimport { createJsonCompletenessScanner } from './jsonCompleteness';\n\n/** The state of one code block at one update. Options arrive already resolved by the host. */\nexport interface CodeBlockInput {\n /** Raw accumulated source, including its trailing newline. */\n code: string;\n /** Explicit fence language, normalized. Empty when the fence has none. */\n language: string;\n /** Which block this is. A different value starts a new generation even when the text continues. */\n identity?: string;\n /** Document streaming state. */\n streaming: boolean;\n /** Detect the language of a block that has none. */\n autoDetect: boolean;\n /** Pretty-print a JSON block once it is complete. */\n formatJson: boolean;\n expandNestedJson: boolean;\n /** Minimum time between two displayed frames of a growing block. Zero shows every update. */\n highlightIntervalMs: number;\n}\n\nexport interface CodeBlockSnapshot {\n /** Text for the highlighter: throttled while the block grows, pretty-printed when it is complete JSON. */\n text: string;\n /** The fence language, else the detected one, else empty. */\n language: string;\n /** Grows by one when the block is rewritten or becomes another block. An append keeps it. */\n generation: number;\n}\n\ninterface Lineage {\n code: string;\n language: string;\n identity: string | undefined;\n generation: number;\n}\n\n/**\n * Everything a code block derives from its source, for one block.\n *\n * `read` answers during render, server rendering included. Equal input gives\n * an equal answer, and a render that is abandoned leaves the committed\n * generation and the language verdict alone. `commit` is called once the answer\n * is on screen: it records the lineage, lets the language detector look at the\n * text, and starts the display throttle and the language settle timer. When a\n * commit or a timer changes the answer, `onChange` asks the host to read again. A host that never commits, such as a server render, always reads the\n * current text.\n *\n * - An append keeps the generation; a rewrite, another fence language or\n * another `identity` advances it.\n * - While the document streams, appends inside `highlightIntervalMs` share one\n * displayed frame. A rewrite, a language change, a static update and the end\n * of the stream show the current text at once.\n * - A block with no fence language is detected as it grows and judged as\n * complete once its text has been still (see `createCodeLanguageTracker`).\n * - JSON is pretty-printed when the document is not streaming, or as soon as\n * the displayed text is a balanced value.\n */\nexport function createCodeBlockSession(onChange: () => void) {\n let committed: Lineage | undefined;\n /** The frame on screen: what the throttle last published. */\n let shown: { code: string; language: string; generation: number } | undefined;\n let frames: ReturnType<typeof createCodeFrame> | undefined;\n let token: { key: string; value: object } | undefined;\n let committing = false;\n const tracker = createCodeLanguageTracker(() => onChange());\n const scanJson = createJsonCompletenessScanner();\n let formatted: { source: string; nested: boolean; text: string } | undefined;\n\n const generationOf = (input: CodeBlockInput): number => {\n if (!committed) return 0;\n const continues =\n input.identity === committed.identity &&\n input.language === committed.language &&\n extendsCode(input.code, committed.code);\n return continues ? committed.generation : committed.generation + 1;\n };\n const languageOf = (input: CodeBlockInput): string =>\n input.language || (input.autoDetect ? (tracker.read(input.code, input.streaming) ?? '') : '');\n const pretty = (source: string, nested: boolean): string => {\n if (formatted?.source !== source || formatted.nested !== nested)\n formatted = { source, nested, text: prettyPrintJson(source, nested) };\n return formatted.text;\n };\n\n return {\n read(input: CodeBlockInput): CodeBlockSnapshot {\n const generation = generationOf(input);\n const language = languageOf(input);\n const current =\n !shown ||\n !input.streaming ||\n input.highlightIntervalMs === 0 ||\n shown.generation !== generation ||\n shown.language !== language;\n const displayed = current ? input.code : shown!.code;\n const text =\n input.formatJson && displayed && language === 'json' && (!input.streaming || scanJson(displayed))\n ? pretty(displayed, input.expandNestedJson)\n : displayed;\n return { text, language, generation };\n },\n commit(input: CodeBlockInput): void {\n const generation = generationOf(input);\n const detecting = input.autoDetect && !input.language;\n // Only a commit feeds the detector. It reports a verdict that differs from the one `read` gave.\n const moved = detecting ? tracker.observe(input.code, input.streaming) : (tracker.dispose(), false);\n const language = languageOf(input);\n committed = { code: input.code, language: input.language, identity: input.identity, generation };\n // The throttle treats a new token as a replacement: a rewrite, or another language to highlight in.\n const key = `${generation}:${language}`;\n if (token?.key !== key) token = { key, value: {} };\n const frame: CodeFrame = { code: input.code, language, generation: token.value };\n committing = true;\n try {\n if (!frames) {\n shown = { code: input.code, language, generation };\n frames = createCodeFrame(frame, (next) => {\n shown = { code: next.code, language: next.language, generation: committed!.generation };\n // A frame published inside commit is the text `read` already returned.\n if (!committing) onChange();\n });\n }\n frames.update(frame, input.streaming, input.highlightIntervalMs);\n // The throttle publishes nothing for unchanged text, so a new generation of it is adopted here.\n if (shown!.code === input.code && shown!.language === language) shown!.generation = generation;\n } finally {\n committing = false;\n }\n if (moved) onChange();\n },\n // Cancellation is reversible: a later commit starts the timers again.\n dispose(): void {\n frames?.dispose();\n tracker.dispose();\n },\n };\n}\n","/** Mermaid owns global configuration and a global renderer. Keep initialize,\n * parse and render in one serialized task. Each mounted diagram retains at\n * most one pending task; superseded frames never enter Mermaid. */\nexport function createRenderQueue() {\n type Job = { run: () => Promise<void>; resolve: () => void; reject: (error: unknown) => void };\n const pending = new Map<object, Job>();\n let running = false;\n async function drain() {\n if (running) return;\n running = true;\n try {\n while (pending.size) {\n const [owner, job] = pending.entries().next().value!;\n pending.delete(owner);\n try {\n await job.run();\n job.resolve();\n } catch (error) {\n job.reject(error);\n }\n }\n } finally {\n running = false;\n }\n }\n return {\n enqueue(owner: object, run: () => Promise<void>): Promise<void> {\n pending.get(owner)?.resolve();\n const promise = new Promise<void>((resolve, reject) => pending.set(owner, { run, resolve, reject }));\n void drain();\n return promise;\n },\n cancel(owner: object) {\n pending.get(owner)?.resolve();\n pending.delete(owner);\n },\n };\n}\n\nexport const mermaidRenderQueue = createRenderQueue();\n","type MermaidConfig = {\n theme?: string;\n securityLevel?: string;\n darkMode?: boolean;\n suppressErrorRendering?: boolean;\n maxTextSize?: number;\n themeVariables?: unknown;\n};\n\n/** The part of the mermaid module this file touches. Structural so tests can\n * pass a stub; `mermaidAPI` is deprecated in mermaid's types but present at\n * runtime in mermaid 11, and it is the only place `getSiteConfig` /\n * `getConfig` live (the default export has neither). */\nexport type MermaidInitTarget = {\n initialize(config: MermaidConfig): void;\n mermaidAPI?: {\n getSiteConfig?: () => MermaidConfig;\n getConfig?: () => MermaidConfig;\n };\n};\n\n/**\n * `securityLevel` values under which mermaid still sanitizes what it emits.\n * `sandbox` is stricter than `strict` (the diagram renders inside a sandboxed\n * iframe), so a host that chose it must not be downgraded. `loose` and\n * `antiscript` skip DOMPurify and are upgraded to `strict`; so is an unset\n * value, which mermaid treats as `strict` but which we pin explicitly so the\n * guard below has something to compare against.\n */\nconst SAFE_SECURITY_LEVELS: ReadonlySet<string | undefined> = new Set(['strict', 'sandbox']);\n\n/** Theme we last wrote. mermaid's config is a module-level singleton, so this\n * is module-level too: instances under providers with DIFFERENT color\n * schemes each re-assert before their own render, and the check runs per\n * attempt (each streamed chunk re-runs the effect) rather than once per\n * instance. It also tells a theme WE wrote apart from one the host wrote —\n * the host's choice is left alone; ours follows the color scheme. */\nlet ownedThemes = new WeakMap<object, 'dark' | 'base'>();\n\n/** Test hook: forget the theme cache so each test starts from a cold module. */\nexport const resetMermaidInitializationForTests = () => {\n ownedThemes = new WeakMap();\n};\n\n/**\n * Read the config `mermaid.initialize` would replace. `getSiteConfig` is the\n * site config (what the host passed to `initialize`, merged over mermaid's\n * defaults); `getConfig` is the per-render config with `%%{init}%%`\n * directives merged in and is only a fallback for builds without the former.\n */\nconst readSiteConfig = (mermaid: MermaidInitTarget): MermaidConfig => {\n const api = mermaid.mermaidAPI;\n return api?.getSiteConfig?.() ?? api?.getConfig?.() ?? {};\n};\n\n/** mermaid's own default for `maxTextSize` (`MAX_TEXTLENGTH` in mermaidAPI). */\nexport const MERMAID_DEFAULT_MAX_TEXT_SIZE = 50_000;\n\n/**\n * The effective `maxTextSize`. `mermaid.render` does not reject oversized\n * input: it swaps in a placeholder diagram (\"Maximum text size in diagram\n * exceeded\") and resolves normally, and `mermaid.parse` has no size gate at\n * all, so the whole text is parsed first. The renderer checks this before\n * parsing and reports the size as an error instead. The key is in mermaid's\n * `secure` list, so a `%%{init}%%` directive cannot raise it and the site\n * config is the value that applies.\n */\nexport const getMermaidMaxTextSize = (mermaid: MermaidInitTarget): number => {\n const configured = readSiteConfig(mermaid).maxTextSize;\n return typeof configured === 'number' && Number.isFinite(configured) && configured >= 0\n ? configured\n : MERMAID_DEFAULT_MAX_TEXT_SIZE;\n};\n\n/**\n * mermaid's config is a module-level singleton shared with the host\n * application when the bundler dedupes the package, and a host that enables\n * `click` interactions calls `mermaid.initialize({ securityLevel: 'loose' })`\n * — the officially documented way. Under `loose` mermaid skips DOMPurify\n * and its output goes into this component's `innerHTML` verbatim: an\n * LLM-authored diagram string could then run script in the page origin.\n * So a theme cache alone is not enough of a guard: before every render the\n * current `securityLevel` is read back (a config copy, still far cheaper\n * than `initialize`'s merge + theme variables + diagram registration) and an\n * unsafe value forces a re-initialize\n * (2026-08-19 review r2 P2-11; the v2.4.2 \"documented premise\" made this\n * the host's problem — it is ours, the innerHTML is ours).\n *\n * In mermaid 11 `initialize` goes through `setSiteConfig`, which REPLACES\n * the site config with defaults + the keys passed in. Calling it with only\n * our keys wiped the host's `theme`, `fontFamily`, `flowchart` options and\n * so on, and turned a host `sandbox` into `strict` (3.0.2 review). So:\n * - the current site config is read back and passed through with our\n * overrides on top, so host keys survive;\n * - `sandbox` is accepted as is; only `loose` / `antiscript` / unset become\n * `strict`;\n * - a theme the host chose is kept (with its `themeVariables`); the color\n * scheme switch only applies to the theme when the host has not chosen\n * one, or when the current theme is one we wrote;\n * - when nothing needs to change, `initialize` is not called at all, so a\n * host on `strict`/`sandbox` and this component stop overwriting each\n * other on every render.\n */\nexport const ensureMermaidInitialized = (mermaid: MermaidInitTarget, isDark: boolean) => {\n const site = readSiteConfig(mermaid);\n const ownedTheme = ownedThemes.get(mermaid);\n const wantedTheme = isDark ? 'dark' : 'base';\n\n // `default` is mermaid's own initial value, so it does not count as a host\n // choice. A theme equal to the one we last wrote is ours to switch.\n const hostOwnsTheme = site.theme !== undefined && site.theme !== 'default' && site.theme !== ownedTheme;\n\n const levelOk = SAFE_SECURITY_LEVELS.has(site.securityLevel);\n const themeOk = hostOwnsTheme || (site.theme === wantedTheme && Boolean(site.darkMode) === isDark);\n const suppressOk = site.suppressErrorRendering === true;\n if (levelOk && themeOk && suppressOk) return;\n\n const next: MermaidConfig = {\n ...site,\n // Without this, a draw-phase throw (an error that got past\n // mermaid.parse) leaves mermaid's temp element orphaned in document.body\n // — its error path only cleans up when this flag is set. We render our\n // own error tab anyway, so mermaid's built-in error diagram is dead\n // weight here regardless.\n suppressErrorRendering: true,\n };\n if (!levelOk) {\n next.securityLevel = 'strict';\n }\n if (!hostOwnsTheme) {\n next.theme = wantedTheme;\n next.darkMode = isDark;\n // The site config carries the PREVIOUS theme's fully computed\n // `themeVariables`. `initialize` feeds `themeVariables` into the new\n // theme as overrides for every key present, so passing them back would\n // make the new theme look exactly like the old one. Drop them and keep\n // only `fontFamily`: `default`, `base` and `dark` share the same font\n // default, so a value that differs is the host's and survives the switch\n // (a top-level `fontFamily` survives through the spread above either way).\n // Mermaid's dark edge labels use #ccc text on #585858 (4.43:1).\n // Give our default palette enough contrast; host-owned themes stay intact.\n const fontFamily: unknown = (site.themeVariables as { fontFamily?: unknown } | undefined)?.fontFamily;\n if (typeof fontFamily === 'string') {\n next.themeVariables = { fontFamily, ...(isDark ? { edgeLabelBackground: '#444444' } : {}) };\n } else if (isDark) {\n next.themeVariables = { edgeLabelBackground: '#444444' };\n } else {\n delete next.themeVariables;\n }\n ownedThemes.set(mermaid, wantedTheme);\n }\n mermaid.initialize(next);\n};\n","import { createCodeFrame, nextCodeFrame, type CodeFrame } from './codeFrame';\nimport { mermaidRenderQueue } from './renderQueue';\nimport { ensureMermaidInitialized, getMermaidMaxTextSize, type MermaidInitTarget } from './mermaid';\nimport type { DiagramLabels } from './labels';\n\nexport interface DiagramEngine extends MermaidInitTarget {\n /** Resolves truthy for a source that parses; rejects, or resolves falsy, for one that does not. */\n parse(code: string): Promise<unknown>;\n render(\n id: string,\n code: string\n ): Promise<{ svg: string; diagramType?: string; bindFunctions?(element: object): void }>;\n}\n\n/**\n * What the host shows. One value instead of separate flags whose combinations\n * had to be kept coherent by hand:\n * - `source`: nothing has rendered in this generation (warm-up, server render).\n * - `diagram`: the last successful render.\n * - `error`: only a failed corrective pass after a stream, or a static failure\n * with no diagram up, enters this state.\n */\nexport type DiagramView =\n | { kind: 'source' }\n | { kind: 'diagram'; svg: string; chartType: string; bind?: (element: object) => void }\n | DiagramError;\n\n/**\n * Why a diagram did not render, as data: the host owns the words.\n * - `tooLarge`: the source is longer than the engine's `maxTextSize`.\n * - `parse` and `render`: the engine refused the source or failed to draw it.\n * `message` is the engine's own text, which is diagnostic and not\n * translated, or empty when it gave none.\n */\nexport type DiagramError =\n | { kind: 'error'; reason: 'tooLarge'; length: number; limit: number }\n | { kind: 'error'; reason: 'parse' | 'render'; message: string };\n\n/** The text for an error view: the engine's own message when there is one, else the label for the reason. */\nexport function diagramErrorText(\n error: DiagramError,\n labels: Pick<DiagramLabels, 'tooLarge' | 'renderFailed'>\n): string {\n if (error.reason === 'tooLarge') return labels.tooLarge(error.length, error.limit);\n return error.message || labels.renderFailed;\n}\n\nexport interface DiagramState {\n view: DiagramView;\n /** The engine module could not be loaded and the automatic retries are spent. `retry()` starts over. */\n loadFailed: boolean;\n}\n\nexport interface DiagramRequest {\n code: string;\n dark: boolean;\n /** Document streaming state. Its edges mark the start and the end of a generation. */\n streaming: boolean;\n /** False while the host shows something else, such as the source. No attempt runs. */\n active: boolean;\n /** Minimum time between attempts while streaming. Zero attempts every update. */\n interval: number;\n}\n\n/** Longest error text published. A parse error is a few lines; anything longer is noise. */\nconst ERROR_MESSAGE_MAX_CHARS = 500;\n/** Bounded automatic retries of a failed engine download, per generation. */\nconst LOAD_RETRIES = 3;\nconst LOAD_RETRY_MS = 1500;\n\n/** The engine's own failure text, or empty. Hosts render it as a text node, never as HTML. */\nfunction engineMessage(error: unknown): string {\n const raw = error instanceof Error ? error.message : typeof error === 'string' ? error : '';\n const text = raw.replace(/\\r\\n?/g, '\\n').trim();\n return text.length > ERROR_MESSAGE_MAX_CHARS ? `${text.slice(0, ERROR_MESSAGE_MAX_CHARS)}…` : text;\n}\n/** Thrown inside an attempt to carry a finished error view to its handler. */\nclass DiagramFailure {\n constructor(readonly view: DiagramError) {}\n}\n\n/** A timestamp and a random suffix: unique across diagrams and across copies of this module. */\nconst diagramId = () => `mermaid-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;\n\n/**\n * The render state machine for one diagram. The host passes every change of\n * its inputs to `update` and draws what `publish` receives.\n *\n * ## While `streaming` is true\n *\n * The source is usually a truncated prefix, so a parse failure is expected:\n * - Before the first success the view stays `source`, never `error`.\n * - After a success the last diagram stays up; each attempt replaces it only\n * when it succeeds.\n * - Attempts are throttled by `interval` with the same trailing throttle as\n * code display: appends inside an interval replace one pending frame without\n * moving its deadline. A rewrite, a non-streaming update and the end of the\n * stream pass through at once.\n * - When streaming ends, one corrective pass runs on the final source. Its\n * failure is published even over a diagram, because that diagram no longer\n * matches the source. Only that one pass may do so.\n * - When streaming starts, a new generation begins on the same instance (a\n * regenerated answer keeps its block position). Everything from the previous\n * generation is dropped and the view returns to `source`.\n *\n * ## While `streaming` stays false\n *\n * A failure is published only while no diagram is up. Once one is, a later\n * failure (a theme change, an incomplete source from a host that does not pass\n * `streaming`) keeps it.\n *\n * ## Always\n *\n * - An attempt whose source and theme match the diagram on screen is skipped.\n * - A source above the engine's `maxTextSize` is an error, not a render.\n * - A failed engine download is not a diagram error. It keeps the view, keeps a\n * pending corrective pass, and is retried a bounded number of times.\n * - An attempt that has been superseded publishes nothing.\n */\nexport function createDiagramController(load: () => Promise<DiagramEngine>, publish: (state: DiagramState) => void) {\n const owner = {};\n let request: DiagramRequest | undefined;\n /** The latest source and its lineage, and the throttled frame attempts read. */\n let current: CodeFrame | undefined;\n let shown: CodeFrame | undefined;\n let frames: ReturnType<typeof createCodeFrame> | undefined;\n let updating = false;\n\n let view: DiagramView = { kind: 'source' };\n let loadFailed = false;\n let previousStreaming = false;\n /** Armed when streaming ends; consumed by the next attempt that completes. */\n let needsCorrective = false;\n /** Inputs of the diagram on screen. */\n let lastSuccess: { code: string; dark: boolean } | undefined;\n let loadFailures = 0;\n /** Bumped to run again on unchanged inputs: a load retry, or `retry()`. */\n let nonce = 0;\n /** Inputs of the last run. A run with the same inputs does nothing. */\n let ran: { code: string; dark: boolean; active: boolean; streaming: boolean; nonce: number } | undefined;\n let epoch = 0;\n let retryTimer: ReturnType<typeof setTimeout> | undefined;\n\n const sameError = (a: DiagramError, b: DiagramError) =>\n a.reason === 'tooLarge'\n ? b.reason === 'tooLarge' && a.length === b.length && a.limit === b.limit\n : b.reason === a.reason && a.message === b.message;\n const emit = () => publish({ view, loadFailed });\n /** Drops a view that repeats the one on screen. A diagram is always new: the host has to draw it. */\n const show = (next: DiagramView) => {\n if (next.kind === 'source' && view.kind === 'source') return;\n if (next.kind === 'error' && view.kind === 'error' && sameError(next, view)) return;\n view = next;\n emit();\n };\n const cancel = () => {\n epoch++;\n mermaidRenderQueue.cancel(owner);\n if (retryTimer !== undefined) clearTimeout(retryTimer);\n retryTimer = undefined;\n };\n\n const attempt = async (code: string, dark: boolean, streaming: boolean, generation: number) => {\n const stale = () => generation !== epoch;\n let engine: DiagramEngine;\n try {\n engine = await load();\n } catch {\n if (stale()) return;\n if (loadFailures < LOAD_RETRIES) {\n loadFailures += 1;\n retryTimer = setTimeout(() => {\n retryTimer = undefined;\n nonce++;\n run();\n }, LOAD_RETRY_MS);\n } else if (!loadFailed) {\n loadFailed = true;\n emit();\n }\n return;\n }\n loadFailures = 0;\n // Which step an exception came from. Everything but the parse itself counts as rendering.\n let reason: 'parse' | 'render' = 'render';\n try {\n if (stale()) return;\n // Initialization, parsing and rendering share one queued task, so another\n // diagram cannot change the theme in between.\n ensureMermaidInitialized(engine, dark);\n // The engine would resolve an oversized render with a placeholder diagram.\n // The raw length is compared; the engine measures the text after stripping\n // front matter and directives, so a source within a few bytes of the limit\n // can be refused here that it would still have rendered.\n const maxTextSize = getMermaidMaxTextSize(engine);\n if (code.length > maxTextSize) {\n throw new DiagramFailure({ kind: 'error', reason: 'tooLarge', length: code.length, limit: maxTextSize });\n }\n reason = 'parse';\n if (!(await engine.parse(code))) throw new DiagramFailure({ kind: 'error', reason: 'parse', message: '' });\n reason = 'render';\n if (stale()) return;\n const { svg, bindFunctions, diagramType } = await engine.render(diagramId(), code);\n if (stale()) return;\n needsCorrective = false;\n lastSuccess = { code, dark };\n loadFailed = false;\n show({ kind: 'diagram', svg, chartType: diagramType ?? '', bind: bindFunctions });\n } catch (error) {\n if (stale()) return;\n // Expected while the source is still arriving. The corrective pass reports real errors.\n if (streaming) return;\n const failure: DiagramError =\n error instanceof DiagramFailure ? error.view : { kind: 'error', reason, message: engineMessage(error) };\n if (needsCorrective) {\n needsCorrective = false;\n show(failure);\n return;\n }\n if (view.kind === 'diagram') return;\n show(failure);\n }\n };\n\n function run() {\n if (!request || !current || !shown) return;\n const { dark, active, streaming, interval } = request;\n const code = !streaming || interval === 0 || current.generation !== shown.generation ? request.code : shown.code;\n if (\n ran &&\n ran.code === code &&\n ran.dark === dark &&\n ran.active === active &&\n ran.streaming === streaming &&\n ran.nonce === nonce\n )\n return;\n ran = { code, dark, active, streaming, nonce };\n cancel();\n // Edges come before any early return: the first chunk of a new stream can arrive with an empty source.\n if (streaming && !previousStreaming) {\n needsCorrective = false;\n lastSuccess = undefined;\n loadFailures = 0;\n if (view.kind !== 'source' || loadFailed) {\n loadFailed = false;\n view = { kind: 'source' };\n emit();\n }\n } else if (!streaming && previousStreaming) {\n needsCorrective = true;\n }\n previousStreaming = streaming;\n if (!code || !active) return;\n // The diagram on screen came from exactly this source and theme. That render\n // is also the verdict a pending corrective pass was waiting for.\n if (lastSuccess?.code === code && lastSuccess.dark === dark) {\n needsCorrective = false;\n return;\n }\n const generation = epoch;\n void mermaidRenderQueue.enqueue(owner, () => attempt(code, dark, streaming, generation));\n }\n\n return {\n update(next: DiagramRequest) {\n request = next;\n updating = true;\n try {\n if (!frames || !current) {\n current = shown = nextCodeFrame(undefined, next.code, '');\n frames = createCodeFrame(current, (frame) => {\n shown = frame;\n if (!updating) run();\n });\n } else {\n current = nextCodeFrame(current, next.code, '');\n }\n frames.update(current, next.streaming, next.interval);\n } finally {\n updating = false;\n }\n run();\n },\n /** Attempts again on unchanged inputs, with a fresh download budget. */\n retry() {\n loadFailures = 0;\n if (loadFailed) {\n loadFailed = false;\n emit();\n }\n nonce++;\n run();\n },\n // Cancellation is reversible: the next update runs again, even on unchanged inputs.\n dispose() {\n cancel();\n frames?.dispose();\n ran = undefined;\n },\n };\n}\n","import type { ImageActionIconName } from './image';\n\n/**\n * The text of one component, as a partial override of its English defaults.\n * A function is read on every render, so it can follow an application's own\n * i18n state. This package ships no translations.\n */\nexport type LabelsOption<T> = Partial<T> | (() => Partial<T>);\n\n/** The defaults with the supplied entries on top. An entry set to `undefined` keeps its default. */\nexport function resolveLabels<T extends object>(defaults: T, option?: LabelsOption<T>): T {\n const overrides = typeof option === 'function' ? option() : option;\n if (!overrides) return defaults;\n const labels = { ...defaults };\n for (const key of Object.keys(overrides) as Array<keyof T>) {\n const value = overrides[key];\n if (value !== undefined) labels[key] = value as T[keyof T];\n }\n return labels;\n}\n\nexport interface CodeBlockLabels {\n /** Accessible name of the toolbar. */\n actions: string;\n /** Language shown for a block that has none. */\n plainText: string;\n copy: string;\n copied: string;\n copyFailed: string;\n showSource: string;\n showPreview: string;\n expand: string;\n collapse: string;\n /** Shown above the source when a language renderer throws. */\n previewFailed: string;\n}\nexport const defaultCodeBlockLabels: Readonly<CodeBlockLabels> = Object.freeze({\n actions: 'Code block actions',\n plainText: 'text',\n copy: 'Copy code',\n copied: 'Copied',\n copyFailed: 'Copy failed',\n showSource: 'Show source',\n showPreview: 'Show preview',\n expand: 'Expand',\n collapse: 'Collapse',\n previewFailed: 'Preview failed. Source is available below.',\n});\n\nexport interface DiagramLabels {\n /** Nothing has rendered yet and the document is still streaming. */\n waiting: string;\n /** Nothing has rendered yet and the source is complete. */\n rendering: string;\n /** The engine module could not be downloaded. */\n loadFailed: string;\n retry: string;\n /** The engine failed without a message of its own. */\n renderFailed: string;\n /** The source is longer than the engine's `maxTextSize`. */\n tooLarge: (length: number, limit: number) => string;\n}\nexport const defaultDiagramLabels: Readonly<DiagramLabels> = Object.freeze({\n waiting: 'Waiting for diagram…',\n rendering: 'Rendering diagram…',\n loadFailed: 'Diagram engine could not load.',\n retry: 'Retry diagram',\n renderFailed: 'Mermaid could not render this diagram.',\n tooLarge: (length: number, limit: number) =>\n `Diagram source is ${length} characters, above mermaid's maxTextSize of ${limit}.`,\n});\n\nexport interface ImageLabels extends Record<ImageActionIconName, string> {\n loading: string;\n loadFailed: string;\n /** Accessible name of the button that opens the preview. Receives the image's `alt`, which may be empty. */\n open: (alt: string) => string;\n /** Accessible name of a previewed image that has no `alt`. */\n preview: string;\n /** Accessible name of the preview toolbar. */\n actions: string;\n}\nexport const defaultImageLabels: Readonly<ImageLabels> = Object.freeze({\n close: 'Close preview',\n prev: 'Previous image',\n next: 'Next image',\n rotateLeft: 'Rotate left',\n rotateRight: 'Rotate right',\n zoomIn: 'Zoom in',\n zoomOut: 'Zoom out',\n flipX: 'Flip horizontally',\n flipY: 'Flip vertically',\n loading: 'Loading image…',\n loadFailed: 'Image could not be loaded.',\n open: (alt: string) => `Preview image${alt ? `: ${alt}` : ''}`,\n preview: 'Image preview',\n actions: 'Image preview actions',\n});\n\n/** Why a table has no export. `projectTable` reports one of these; `TableLabels` has the text for each. */\nexport type TableExportReason =\n 'mergedCells' | 'notRectangular' | 'unsupportedStructure' | 'unsupportedContent' | 'unavailable';\n\nexport interface TableLabels extends Record<TableExportReason, string> {\n /** Accessible name of the toolbar. */\n actions: string;\n copy: string;\n download: string;\n copied: string;\n copyFailed: string;\n /** Accessible name of the scrolling region. */\n scrollRegion: string;\n}\nexport const defaultTableLabels: Readonly<TableLabels> = Object.freeze({\n actions: 'Table actions',\n copy: 'Copy table',\n download: 'Download CSV',\n copied: 'Table copied',\n copyFailed: 'Copy failed',\n scrollRegion: 'Scrollable table',\n mergedCells: 'Only tables without merged cells can be exported',\n notRectangular: 'Only rectangular tables can be exported',\n unsupportedStructure: 'Unsupported table structure',\n unsupportedContent: 'Unsupported table content',\n unavailable: 'Table source is unavailable',\n});\n","/** Structural browser target keeps the shared core independent of DOM libs.\n * Several React/Vue dialogs can coexist; the last owner restores scrolling. */\nconst locks = new WeakMap<object, { count: number; overflow: string; paddingRight: string | undefined }>();\n/**\n * Stops the page behind a preview from scrolling. `scrollbarWidth` is the\n * width of the scrollbar that hiding the overflow removes\n * (`window.innerWidth - document.documentElement.clientWidth`); the same width\n * is added as padding so the page does not shift sideways. Pass zero, or\n * nothing, when the scrollbar takes no space.\n */\nexport function lockImagePreviewScroll(\n target: { style: { overflow: string; paddingRight?: string } },\n scrollbarWidth = 0\n): () => void {\n let lock = locks.get(target);\n if (!lock) {\n lock = { count: 0, overflow: target.style.overflow, paddingRight: target.style.paddingRight };\n locks.set(target, lock);\n if (scrollbarWidth > 0)\n target.style.paddingRight = lock.paddingRight\n ? `calc(${lock.paddingRight} + ${scrollbarWidth}px)`\n : `${scrollbarWidth}px`;\n }\n lock.count++;\n target.style.overflow = 'hidden';\n let released = false;\n return () => {\n if (released) return;\n released = true;\n if (--lock.count === 0) {\n if (target.style.overflow === 'hidden') target.style.overflow = lock.overflow;\n target.style.paddingRight = lock.paddingRight;\n locks.delete(target);\n }\n };\n}\n","/** Transform rules adapted from @rc-component/image 1.10.0 (MIT, Copyright (c) 2019-present react-component; see LICENSE).\n * Pure functions; `createImagePreviewController` applies them. */\nexport interface ImageTransform {\n x: number;\n y: number;\n rotate: number;\n scale: number;\n flipX: boolean;\n flipY: boolean;\n}\nexport interface ImageGeometry {\n width: number;\n height: number;\n left: number;\n top: number;\n viewportWidth: number;\n viewportHeight: number;\n}\nexport const initialImageTransform = (): ImageTransform => ({\n x: 0,\n y: 0,\n rotate: 0,\n scale: 1,\n flipX: false,\n flipY: false,\n});\nexport function imageTransformStyle(transform: ImageTransform): string {\n const { x, y, scale, rotate, flipX, flipY } = transform;\n return `translate3d(${x}px, ${y}px, 0) scale3d(${flipX ? '-' : ''}${scale}, ${flipY ? '-' : ''}${scale}, 1) rotate(${rotate}deg)`;\n}\nconst DEFAULT_SCALE_LIMITS = { min: 1, max: 50 };\n/** Scales by `ratio` about a viewport point, keeping the image point under it in place, within `limits`. */\nexport function zoomImage(\n transform: ImageTransform,\n ratio: number,\n geometry: ImageGeometry,\n centerX = geometry.viewportWidth / 2,\n centerY = geometry.viewportHeight / 2,\n touch = false,\n limits: { min: number; max: number } = DEFAULT_SCALE_LIMITS\n): ImageTransform {\n if (!Number.isFinite(ratio) || ratio <= 0) return transform;\n // A pinch may pass below the minimum while the fingers are down; `reboundImage` brings it back.\n const floor = touch ? 0.01 : limits.min;\n const scale = Math.min(limits.max, Math.max(floor, transform.scale * ratio));\n const difference = scale / transform.scale - 1;\n let x = transform.x - difference * (centerX - transform.x - geometry.left - geometry.width / 2);\n let y = transform.y - difference * (centerY - transform.y - geometry.top - geometry.height / 2);\n if (\n ratio < 1 &&\n scale === 1 &&\n geometry.width <= geometry.viewportWidth &&\n geometry.height <= geometry.viewportHeight\n )\n x = y = 0;\n return { ...transform, x, y, scale };\n}\n/**\n * The zoom factor for one wheel event. A full notch (100 pixels) is one 1.5x\n * step, and a smaller delta a proportional part of it.\n * - `mode` is `WheelEvent.deltaMode`. Some browsers and mice report lines or\n * pages, not pixels: three lines or one page count as a notch.\n * - `pinch` is a trackpad pinch, which arrives as a wheel event with the\n * control key set and small deltas. It scales continuously with the delta.\n * - `step` is what a full notch adds to the scale factor: 0.5 makes it 1.5x.\n */\nexport function imageWheelRatio(delta: number, mode = 0, pinch = false, step = 0.5): number {\n if (!Number.isFinite(delta) || delta === 0) return 1;\n if (pinch) return Math.min(1 + step, Math.max(1 / (1 + step), Math.exp(-delta / 100)));\n const pixels = mode === 1 ? (delta * 100) / 3 : mode === 2 ? delta * 100 : delta;\n const ratio = 1 + Math.min(Math.abs(pixels / 100), 1) * step;\n return pixels > 0 ? 1 / ratio : ratio;\n}\n/** Snap a moved image back inside the viewport, taking quarter turns into account. */\nexport function reboundImage(\n transform: ImageTransform,\n geometry: ImageGeometry,\n bounds: { left: number; top: number },\n minScale = 1\n): ImageTransform {\n if (transform.scale < minScale) return { ...transform, x: 0, y: 0, scale: minScale };\n const rotated = transform.rotate % 180 !== 0;\n const width = (rotated ? geometry.height : geometry.width) * transform.scale;\n const height = (rotated ? geometry.width : geometry.height) * transform.scale;\n if (width <= geometry.viewportWidth && height <= geometry.viewportHeight) return { ...transform, x: 0, y: 0 };\n const fix = (position: number, start: number, size: number, viewport: number) => {\n const offset = (size - viewport) / 2;\n if (size > viewport) {\n if (start > 0) return offset;\n if (start < 0 && start + size < viewport) return -offset;\n } else if (start < 0 || start + size > viewport) return start < 0 ? offset : -offset;\n return position;\n };\n return {\n ...transform,\n x: fix(transform.x, bounds.left, width, geometry.viewportWidth),\n y: fix(transform.y, bounds.top, height, geometry.viewportHeight),\n };\n}\n/** Upstream pinch center weights each finger by how far it moved. */\nexport function imagePinchCenter(\n oldA: { x: number; y: number },\n oldB: { x: number; y: number },\n a: { x: number; y: number },\n b: { x: number; y: number }\n): { x: number; y: number } {\n const distanceA = Math.hypot(a.x - oldA.x, a.y - oldA.y),\n distanceB = Math.hypot(b.x - oldB.x, b.y - oldB.y);\n const ratio = distanceA + distanceB ? distanceA / (distanceA + distanceB) : 0;\n return { x: oldA.x + ratio * (oldB.x - oldA.x), y: oldA.y + ratio * (oldB.y - oldA.y) };\n}\n","/** The image preview as state and rules, with no framework and no DOM.\n * Interaction rules adapted from @rc-component/image 1.10.0 (MIT, Copyright (c) 2019-present react-component; see LICENSE). */\nimport type { ImageActionIconName, ImageGallery, ImageGalleryItem, ImageLoadStatus } from './image';\nimport {\n imagePinchCenter,\n imageWheelRatio,\n initialImageTransform,\n reboundImage,\n zoomImage,\n type ImageGeometry,\n type ImageTransform,\n} from './imageTransform';\n\n/**\n * - `closed`: nothing to render.\n * - `opening`: rendered in its starting style, for the frames a transition needs to start from.\n * - `open`: the resting state.\n * - `closing`: still rendered, in its leaving style, until the close duration has passed.\n */\nexport type ImagePreviewPhase = 'closed' | 'opening' | 'open' | 'closing';\n\nexport interface ImagePreviewState {\n phase: ImagePreviewPhase;\n /** The gallery in document order. It follows the gallery while the preview is open. */\n items: readonly ImageGalleryItem[];\n /** Index of the image shown, or -1 while closed. */\n current: number;\n item: ImageGalleryItem | undefined;\n transform: ImageTransform;\n /** Load state of the image shown. */\n status: ImageLoadStatus;\n /** A drag or a pinch is in progress: the image follows the pointer without a transition. */\n moving: boolean;\n /** The image can be dragged and pinched (the `movable` option). */\n movable: boolean;\n /** Viewport point the preview grows out of and shrinks back into: the anchor of the image shown when it opened,\n * then of the image shown when it closes. Undefined means the centre of the viewport. */\n origin: { x: number; y: number } | undefined;\n canPrevious: boolean;\n canNext: boolean;\n canZoomIn: boolean;\n canZoomOut: boolean;\n}\n\n/** What the controller needs from the page. */\nexport interface ImagePreviewHost {\n /** Layout box of the image shown, before its transform, and the viewport. Undefined while there is no image. */\n geometry(): ImageGeometry | undefined;\n /** Runs the callback before the next paint and returns a cancel function. `requestAnimationFrame` in a browser. */\n frame(callback: () => void): () => void;\n /** Where the image registered under `id` sits on the page, as a viewport point: the centre of its thumbnail.\n * Undefined when it has none or it is out of view. Asked when the preview opens and again when it closes. */\n anchor?(id: object): { x: number; y: number } | undefined;\n}\n\nexport interface ImagePreviewOptions {\n /** How long the leaving style stays up, in milliseconds. Zero closes at once. A function is read at each close,\n * so a host can answer zero while the user prefers reduced motion. Default 300. */\n closeDuration?: number | (() => number);\n /** What one zoom step adds to the scale factor: the toolbar, a double click and a full wheel notch multiply or\n * divide by `1 + scaleStep`. Default 0.5. */\n scaleStep?: number;\n /** Smallest scale the toolbar and the wheel reach, and the one a pinch returns to. Default 1. */\n minScale?: number;\n /** Largest scale. Default 50. */\n maxScale?: number;\n /** Whether the image can be dragged and pinched. Default true. */\n movable?: boolean;\n /** Whether the wheel and a trackpad pinch zoom. Default true. */\n wheel?: boolean;\n /** The preview started to open (true) or to close (false). */\n onOpenChange?(open: boolean, info: { current: number; item: ImageGalleryItem | undefined }): void;\n /** An opening or a closing ran to its end. One that was interrupted, by reopening while it closed or by\n * `dispose`, reports nothing. */\n afterOpenChange?(open: boolean): void;\n /** The user moved to another image of the gallery. */\n onChange?(current: number, previous: number): void;\n /** The transform changed. A drag or a wheel burst reports once per frame, with the last action. */\n onTransform?(info: { transform: ImageTransform; action: ImagePreviewAction }): void;\n}\n\n/** What changed the transform, as reported to `onTransform`. */\nexport type ImagePreviewAction =\n | 'zoomIn'\n | 'zoomOut'\n | 'rotateLeft'\n | 'rotateRight'\n | 'flipX'\n | 'flipY'\n | 'wheel'\n | 'doubleClick'\n | 'move'\n | 'pinch'\n | 'rebound'\n | 'prev'\n | 'next';\n\nexport interface ImagePointer {\n /** Pointer id: one drag, or one finger of a pinch. */\n id: number;\n x: number;\n y: number;\n /** `PointerEvent.button`. Only the main button starts a gesture. */\n button?: number;\n}\n\nconst CLOSE_MS = 300;\nconst positive = (value: unknown, fallback: number) =>\n typeof value === 'number' && Number.isFinite(value) && value > 0 ? value : fallback;\n\nconst closedState: ImagePreviewState = Object.freeze({\n phase: 'closed',\n items: Object.freeze([]),\n current: -1,\n item: undefined,\n transform: initialImageTransform(),\n status: 'loading',\n moving: false,\n movable: true,\n origin: undefined,\n canPrevious: false,\n canNext: false,\n canZoomIn: false,\n canZoomOut: false,\n});\n\n/**\n * One image preview: which image of a gallery is shown, how it is transformed,\n * and where it is in opening and closing. The host forwards its events as plain\n * numbers and draws each state it is given.\n *\n * - `open(gallery, id)` shows the image registered under `id` and follows the\n * gallery from then on: images added or removed while the preview is open\n * update the list, and the preview closes when the image shown leaves it.\n * - Pointer input is one model for mouse, pen and touch. One pointer drags.\n * Two pointers pinch, around a centre weighted by how far each one moved. A\n * pinch may shrink the image below its natural size; when the last pointer\n * lifts the image snaps back inside the viewport. The host should capture\n * the pointer when `pointerDown` returns true, so a drag that leaves the\n * window or its frame still ends.\n * - Drag and wheel updates reach `publish` at most once per frame; everything\n * else is published at once. Each update is applied to the current state, so\n * several in one frame add up.\n * - Switching images resets the transform. Zoom is limited to 1x to 50x in\n * 1.5x steps unless the options say otherwise, about the pointer for the\n * wheel and a double click, about the viewport centre for the toolbar.\n * - The `on…` options report what the user did; they are called after the\n * state that reflects it has been published.\n */\nexport function createImagePreviewController(\n host: ImagePreviewHost,\n publish: (state: ImagePreviewState) => void,\n options: ImagePreviewOptions = {}\n) {\n const limits = { min: positive(options.minScale, 1), max: 0 };\n limits.max = Math.max(limits.min, positive(options.maxScale, 50));\n /** The natural size, or the nearest scale the limits allow: where an image starts and what a double click returns to. */\n const baseScale = Math.min(limits.max, Math.max(limits.min, 1));\n const scaleStep = positive(options.scaleStep, 0.5);\n const movable = options.movable ?? true;\n const wheelZoom = options.wheel ?? true;\n\n let phase: ImagePreviewPhase = 'closed';\n let items: readonly ImageGalleryItem[] = [];\n let selected: object | undefined;\n let current = -1;\n let transform = { ...initialImageTransform(), scale: baseScale };\n let status: ImageLoadStatus = 'loading';\n let moving = false;\n let origin: { x: number; y: number } | undefined;\n\n let unsubscribe: (() => void) | undefined;\n let cancelPublish: (() => void) | undefined;\n let cancelOpening: (() => void) | undefined;\n let closeTimer: ReturnType<typeof setTimeout> | undefined;\n\n /** Pointers that are down, in the order they arrived. */\n const pointers = new Map<number, { x: number; y: number }>();\n /** Offset between the dragging pointer and the image position. */\n let grip: { x: number; y: number } | undefined;\n /** The gesture moved or scaled the image, so it has to be put back in bounds when it ends. */\n let displaced = false;\n\n const snapshot = (): ImagePreviewState => {\n if (phase === 'closed') return closedState;\n const ready = status === 'ready';\n return {\n phase,\n items,\n current,\n item: items[current],\n transform,\n status,\n moving,\n movable,\n origin,\n canPrevious: current > 0,\n canNext: current < items.length - 1,\n canZoomIn: ready && transform.scale < limits.max,\n canZoomOut: ready && transform.scale > limits.min,\n };\n };\n /** The action behind a transform change that has not been reported yet. */\n let reported: ImagePreviewAction | undefined;\n /** Publishes, then tells the listener about a transform the state now shows. */\n const flush = () => {\n publish(snapshot());\n const action = reported;\n reported = undefined;\n if (action) options.onTransform?.({ transform, action });\n };\n const emit = () => {\n cancelPublish?.();\n cancelPublish = undefined;\n flush();\n };\n const emitNextFrame = () => {\n cancelPublish ??= host.frame(() => {\n cancelPublish = undefined;\n flush();\n });\n };\n /** Sets the transform for a user action. An equal transform is not a change and is not reported. */\n const apply = (next: ImageTransform, action: ImagePreviewAction) => {\n const same =\n next.x === transform.x &&\n next.y === transform.y &&\n next.scale === transform.scale &&\n next.rotate === transform.rotate &&\n next.flipX === transform.flipX &&\n next.flipY === transform.flipY;\n if (same) return;\n transform = next;\n reported = action;\n };\n const endGesture = () => {\n pointers.clear();\n grip = undefined;\n displaced = false;\n moving = false;\n };\n /** A new image, or the same image with another source: start from a clean view. */\n const startImage = () => {\n transform = { ...initialImageTransform(), scale: baseScale };\n // A change that was waiting for its frame belonged to the view that is gone.\n reported = undefined;\n status = 'loading';\n endGesture();\n };\n const zoom = (action: ImagePreviewAction, ratio: number, x?: number, y?: number, touch = false) => {\n const box = host.geometry();\n if (box && status === 'ready') apply(zoomImage(transform, ratio, box, x, y, touch, limits), action);\n };\n /** Where the transformed image sits, from the numbers alone: the page may not have drawn the latest transform yet. */\n const rebound = () => {\n // Below the smallest size the image goes back to it, measured or not.\n if (transform.scale < limits.min) {\n apply({ ...transform, x: 0, y: 0, scale: limits.min }, 'rebound');\n return;\n }\n const box = host.geometry();\n if (!box) return;\n const turned = transform.rotate % 180 !== 0;\n const width = (turned ? box.height : box.width) * transform.scale;\n const height = (turned ? box.width : box.height) * transform.scale;\n apply(\n reboundImage(\n transform,\n box,\n {\n left: box.left + box.width / 2 + transform.x - width / 2,\n top: box.top + box.height / 2 + transform.y - height / 2,\n },\n limits.min\n ),\n 'rebound'\n );\n };\n const anchorOf = (id: object) => {\n const point = host.anchor?.(id);\n return point && Number.isFinite(point.x) && Number.isFinite(point.y) ? { x: point.x, y: point.y } : undefined;\n };\n const finishClosing = () => {\n closeTimer = undefined;\n phase = 'closed';\n items = [];\n selected = undefined;\n origin = undefined;\n current = -1;\n reported = undefined;\n emit();\n options.afterOpenChange?.(false);\n };\n const close = () => {\n if (phase === 'closed' || phase === 'closing') return;\n cancelOpening?.();\n cancelOpening = undefined;\n unsubscribe?.();\n unsubscribe = undefined;\n endGesture();\n // A drag that was waiting for its frame is not reported once the preview is leaving.\n reported = undefined;\n // Back into the thumbnail of the image on screen now, which may not be the one that opened the preview.\n origin = selected ? anchorOf(selected) : undefined;\n phase = 'closing';\n const info = { current, item: items[current] };\n const duration =\n typeof options.closeDuration === 'function' ? options.closeDuration() : (options.closeDuration ?? CLOSE_MS);\n // The closing is fully under way before the listener hears of it: one that throws cannot leave it half done.\n if (duration > 0) {\n emit();\n closeTimer = setTimeout(finishClosing, duration);\n options.onOpenChange?.(false, info);\n } else {\n try {\n options.onOpenChange?.(false, info);\n } finally {\n if (phase === 'closing') finishClosing();\n }\n }\n };\n const go = (delta: number) => {\n const target = current + delta;\n if (phase === 'closed' || phase === 'closing' || target < 0 || target >= items.length || target === current) return;\n const previous = current;\n const { x, y, scale, rotate, flipX, flipY } = transform;\n const transformed = x !== 0 || y !== 0 || scale !== baseScale || rotate !== 0 || flipX || flipY;\n current = target;\n selected = items[target].id;\n startImage();\n // The new image starts from a clean view; that is a transform change when the old one was not clean.\n if (transformed) reported = delta < 0 ? 'prev' : 'next';\n emit();\n options.onChange?.(current, previous);\n };\n /** The gallery changed: keep showing the same image at its new index, or close when it is gone. */\n const follow = (gallery: ImageGallery) => {\n const next = gallery.items();\n const index = next.findIndex((item) => item.id === selected);\n if (index < 0) return close();\n if (next[index].src !== items[current]?.src) startImage();\n items = next;\n current = index;\n emit();\n };\n\n return {\n state: snapshot,\n /** Shows the image registered under `id`. False when the gallery has no such image. */\n open(gallery: ImageGallery, id: object): boolean {\n const list = gallery.items();\n const index = list.findIndex((item) => item.id === id);\n if (index < 0) return false;\n if (closeTimer !== undefined) clearTimeout(closeTimer);\n closeTimer = undefined;\n unsubscribe?.();\n cancelOpening?.();\n items = list;\n current = index;\n selected = id;\n origin = anchorOf(id);\n startImage();\n unsubscribe = gallery.subscribe(() => follow(gallery));\n // Already open on another image: nothing to open from. Any other phase starts, or restarts, the opening.\n if (phase === 'open') {\n emit();\n return true;\n }\n cancelOpening = undefined;\n // Restarting an opening that is under way is not a second opening.\n const starting = phase !== 'opening';\n phase = 'opening';\n emit();\n // Two frames: the first paints the starting style, the second may leave it.\n cancelOpening = host.frame(() => {\n // The host has drawn and locked the page by now, which can move the thumbnail by a scrollbar's width.\n // Nothing has scaled yet, so the point can still be corrected.\n const measured = selected ? anchorOf(selected) : undefined;\n if (measured?.x !== origin?.x || measured?.y !== origin?.y) {\n origin = measured;\n emit();\n }\n cancelOpening = host.frame(() => {\n cancelOpening = undefined;\n phase = 'open';\n emit();\n options.afterOpenChange?.(true);\n });\n });\n // Last, so a listener that closes or reopens finds the opening complete and can cancel it.\n if (starting) options.onOpenChange?.(true, { current, item: items[current] });\n return true;\n },\n close,\n /** Moves by `delta` images. Does nothing at either end of the gallery. */\n go,\n /** A toolbar action. */\n action(name: ImageActionIconName): void {\n if (phase === 'closed' || phase === 'closing') return;\n if (name === 'close') return close();\n if (name === 'prev') return go(-1);\n if (name === 'next') return go(1);\n if (status !== 'ready') return;\n if (name === 'zoomIn') zoom(name, 1 + scaleStep);\n else if (name === 'zoomOut') zoom(name, 1 / (1 + scaleStep));\n else if (name === 'rotateLeft') apply({ ...transform, rotate: transform.rotate - 90 }, name);\n else if (name === 'rotateRight') apply({ ...transform, rotate: transform.rotate + 90 }, name);\n else if (name === 'flipX') apply({ ...transform, flipX: !transform.flipX }, name);\n else if (name === 'flipY') apply({ ...transform, flipY: !transform.flipY }, name);\n emit();\n },\n /** The image shown finished loading, or failed to. */\n loaded(): void {\n if (phase === 'closed' || status === 'ready') return;\n status = 'ready';\n emit();\n },\n failed(): void {\n if (phase === 'closed' || status === 'error') return;\n status = 'error';\n endGesture();\n emit();\n },\n /** True when the pointer now takes part in a gesture: capture it and prevent the default action. */\n pointerDown(pointer: ImagePointer): boolean {\n if (!movable || (phase !== 'open' && phase !== 'opening') || status !== 'ready') return false;\n if (pointer.button !== undefined && pointer.button !== 0) return false;\n // A third finger is ignored: the pinch stays with the first two.\n if (pointers.size >= 2 && !pointers.has(pointer.id)) return false;\n pointers.set(pointer.id, { x: pointer.x, y: pointer.y });\n grip = pointers.size === 1 ? { x: pointer.x - transform.x, y: pointer.y - transform.y } : undefined;\n moving = true;\n emit();\n return true;\n },\n pointerMove(pointer: ImagePointer): void {\n const previous = pointers.get(pointer.id);\n if (!previous || (previous.x === pointer.x && previous.y === pointer.y)) return;\n const before = [...pointers.values()];\n pointers.set(pointer.id, { x: pointer.x, y: pointer.y });\n if (pointers.size === 2) {\n const [a, b] = [...pointers.values()];\n const span = Math.hypot(before[0].x - before[1].x, before[0].y - before[1].y);\n const center = imagePinchCenter(before[0], before[1], a, b);\n if (span > 0) zoom('pinch', Math.hypot(a.x - b.x, a.y - b.y) / span, center.x, center.y, true);\n } else if (grip) apply({ ...transform, x: pointer.x - grip.x, y: pointer.y - grip.y }, 'move');\n displaced = true;\n emitNextFrame();\n },\n /** A pointer lifted or was cancelled. */\n pointerUp(id: number): void {\n if (!pointers.delete(id)) return;\n const [remaining] = pointers.values();\n if (remaining) {\n // One finger of a pinch lifted: the other one carries on as a drag from where the image is.\n grip = { x: remaining.x - transform.x, y: remaining.y - transform.y };\n return;\n }\n const settle = displaced;\n endGesture();\n if (settle) rebound();\n emit();\n },\n /** True when the wheel zoomed: prevent the default action. `mode` is `WheelEvent.deltaMode`; `pinch` is a\n * trackpad pinch, which browsers report as a wheel event with the control key set. */\n wheel(input: { deltaY: number; x: number; y: number; mode?: number; pinch?: boolean }): boolean {\n if (!wheelZoom || phase !== 'open' || status !== 'ready' || !input.deltaY) return false;\n zoom('wheel', imageWheelRatio(input.deltaY, input.mode, input.pinch, scaleStep), input.x, input.y);\n emitNextFrame();\n return true;\n },\n /** Returns to the starting size, or zooms one step about the point when already there. */\n doubleClick(x: number, y: number): void {\n if (phase !== 'open' || status !== 'ready') return;\n if (transform.scale !== baseScale) apply({ ...transform, x: 0, y: 0, scale: baseScale }, 'doubleClick');\n else zoom('doubleClick', 1 + scaleStep, x, y);\n emit();\n },\n /** True when the key was used: prevent the default action. Left and right move through a gallery. */\n key(key: string): boolean {\n if ((phase !== 'open' && phase !== 'opening') || items.length < 2) return false;\n if (key !== 'ArrowLeft' && key !== 'ArrowRight') return false;\n go(key === 'ArrowLeft' ? -1 : 1);\n return true;\n },\n /** Stops every timer and subscription. The controller can be opened again afterwards. */\n dispose(): void {\n if (closeTimer !== undefined) clearTimeout(closeTimer);\n closeTimer = undefined;\n cancelPublish?.();\n cancelOpening?.();\n unsubscribe?.();\n cancelPublish = cancelOpening = unsubscribe = undefined;\n endGesture();\n phase = 'closed';\n items = [];\n selected = undefined;\n origin = undefined;\n current = -1;\n reported = undefined;\n },\n };\n}\n","/** Shared image semantics; no DOM or framework dependency. */\nexport type ImageActionIconName =\n 'rotateLeft' | 'rotateRight' | 'zoomIn' | 'zoomOut' | 'close' | 'prev' | 'next' | 'flipX' | 'flipY';\nexport type ImageIconName = 'placeholder' | 'error' | 'preview' | 'gallery' | ImageActionIconName;\nexport type ImageLoadStatus = 'loading' | 'ready' | 'error';\n/** Lucide paths supplied for the Markdown image skin (ISC license). */\nexport const imageIconPaths: Record<ImageIconName, readonly string[]> = {\n rotateLeft: ['M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8', 'M3 3v5h5'],\n rotateRight: ['M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8', 'M21 3v5h-5'],\n zoomIn: ['M19 11a8 8 0 1 1 -16 0a8 8 0 1 1 16 0', 'M21 21L16.65 16.65', 'M11 8L11 14', 'M8 11L14 11'],\n zoomOut: ['M19 11a8 8 0 1 1 -16 0a8 8 0 1 1 16 0', 'M21 21L16.65 16.65', 'M8 11L14 11'],\n close: ['M18 6 6 18', 'm6 6 12 12'],\n prev: ['m15 18-6-6 6-6'],\n next: ['m9 18 6-6-6-6'],\n flipX: [\n 'M8 3H5a2 2 0 0 0-2 2v14c0 1.1.9 2 2 2h3',\n 'M16 3h3a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-3',\n 'M12 20v2',\n 'M12 14v2',\n 'M12 8v2',\n 'M12 2v2',\n ],\n flipY: [\n 'M21 8V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v3',\n 'M21 16v3a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-3',\n 'M4 12H2',\n 'M10 12H8',\n 'M16 12h-2',\n 'M22 12h-2',\n ],\n placeholder: [\n 'M5 3h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2Z',\n 'M11 9a2 2 0 1 1-4 0 2 2 0 0 1 4 0',\n 'm21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21',\n ],\n error: [\n 'm2 2 20 20M10.41 10.41a2 2 0 1 1-2.83-2.83m5.92 5.92L6 21m12-9 3 3',\n 'M3.59 3.59A2 2 0 0 0 3 5v14a2 2 0 0 0 2 2h14c.55 0 1.052-.22 1.41-.59M21 15V5a2 2 0 0 0-2-2H9',\n ],\n gallery: ['M5 3h14a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2Z', 'M4 21h1m4 0h1m4 0h1m4 0h1'],\n preview: [\n 'M15 15.003a1 1 0 0 1 1.517-.859l4.997 2.997a1 1 0 0 1 0 1.718l-4.997 2.997a1 1 0 0 1-1.517-.86z',\n 'M21 12.17V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h6m-5 0 5-5',\n 'M11 9a2 2 0 1 1-4 0 2 2 0 0 1 4 0',\n ],\n};\nexport interface ImageGalleryItem {\n id: object;\n src: string;\n alt: string;\n /** DOM adapters provide document ordering without leaking DOM types. */\n precedes: (other: object) => boolean;\n}\nexport interface ImageGallery {\n /** Document-ordered entries. The same array is returned until the membership changes. */\n items: () => readonly ImageGalleryItem[];\n /** Number of registered entries; O(1), so listeners can test it without sorting. */\n size: () => number;\n subscribe: (listener: () => void) => () => void;\n set: (item: ImageGalleryItem) => void;\n remove: (id: object) => void;\n}\nconst galleries = new WeakMap<object, ImageGallery>();\n/** Scope is an adapter-owned object, never a global document id. */\nexport function getImageGallery(scope: object): ImageGallery {\n const existing = galleries.get(scope);\n if (existing) return existing;\n const entries = new Map<object, ImageGalleryItem>();\n const listeners = new Set<() => void>();\n // Sorted on read and cached: notifications do not sort, and readers that\n // share the array see the same reference until the next set or remove.\n let sorted: readonly ImageGalleryItem[] | undefined;\n const notify = () => {\n sorted = undefined;\n listeners.forEach((listener) => listener());\n };\n const gallery: ImageGallery = {\n items: () => (sorted ??= [...entries.values()].sort((a, b) => (a.precedes(b.id) ? -1 : b.precedes(a.id) ? 1 : 0))),\n size: () => entries.size,\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n set(item) {\n const old = entries.get(item.id);\n if (old?.src === item.src && old?.alt === item.alt) return;\n entries.set(item.id, item);\n notify();\n },\n remove(id) {\n if (entries.delete(id)) notify();\n },\n };\n galleries.set(scope, gallery);\n return gallery;\n}\n\n/** The preview toolbar actions, in toolbar order. */\nexport const imageActionNames: readonly ImageActionIconName[] = Object.freeze([\n 'close',\n 'prev',\n 'next',\n 'rotateLeft',\n 'rotateRight',\n 'zoomIn',\n 'zoomOut',\n 'flipX',\n 'flipY',\n]);\n"],"mappings":"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"}