@ai-markdown/core 3.4.2 → 3.5.0
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.
- package/dist/components/index.cjs +515 -30
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.d.cts +369 -170
- package/dist/components/index.d.ts +369 -170
- package/dist/components/index.js +504 -32
- package/dist/components/index.js.map +1 -1
- package/package.json +3 -3
|
@@ -1,5 +1,134 @@
|
|
|
1
1
|
import { CodeLanguage } from "@ai-markdown/code-language-detector";
|
|
2
2
|
import { Element } from "hast";
|
|
3
|
+
/** Engine spellings, independent of the UI package. */
|
|
4
|
+
export declare enum CodeLanguageFormat {
|
|
5
|
+
HighlightJs = "highlight-js",
|
|
6
|
+
Shiki = "shiki",
|
|
7
|
+
Pierre = "pierre"
|
|
8
|
+
}
|
|
9
|
+
type CodeLanguageResolver = CodeLanguageFormat | ((language: string) => string);
|
|
10
|
+
export declare function resolveCodeHighlightLanguage(language: string, format?: CodeLanguageResolver): string;
|
|
11
|
+
export declare function resolveCodeHighlightInterval(value: number | undefined, fallback?: number): number;
|
|
12
|
+
interface CodeHighlightToken {
|
|
13
|
+
text: string;
|
|
14
|
+
color?: string;
|
|
15
|
+
backgroundColor?: string;
|
|
16
|
+
/** Shiki-compatible bit flags: italic=1, bold=2, underline=4. */
|
|
17
|
+
fontStyle?: number;
|
|
18
|
+
}
|
|
19
|
+
/** HTML must come from a trusted highlighter which escapes source text. Never return raw source as HTML. */
|
|
20
|
+
type CodeHighlightResult = {
|
|
21
|
+
html: string;
|
|
22
|
+
} | {
|
|
23
|
+
tokens: readonly CodeHighlightToken[];
|
|
24
|
+
};
|
|
25
|
+
interface CodeHighlightRequest {
|
|
26
|
+
code: string;
|
|
27
|
+
language: string;
|
|
28
|
+
colorScheme: 'light' | 'dark';
|
|
29
|
+
/** Enable incremental work while the document is streaming. */
|
|
30
|
+
streaming?: boolean;
|
|
31
|
+
}
|
|
32
|
+
/** Mutable engine state owned by one mounted code block, updated only on commit. */
|
|
33
|
+
interface CodeHighlightBackend {
|
|
34
|
+
highlight(request: CodeHighlightRequest): CodeHighlightResult | undefined;
|
|
35
|
+
dispose(): void;
|
|
36
|
+
}
|
|
37
|
+
/** Inject engines from the application; core imports no highlighting runtime. */
|
|
38
|
+
interface CodeHighlightAdapter {
|
|
39
|
+
languageFormat: CodeLanguageResolver;
|
|
40
|
+
/** Optional incremental backend. Never created during rendering or SSR. */
|
|
41
|
+
createSession?(): CodeHighlightBackend;
|
|
42
|
+
supports?(language: string): boolean;
|
|
43
|
+
isReady?(request: CodeHighlightRequest): boolean;
|
|
44
|
+
/** Called only after the framework commits. May load an engine, theme or language. */
|
|
45
|
+
prepare?(request: CodeHighlightRequest): void | Promise<void>;
|
|
46
|
+
/** Synchronous after preparation. Return undefined to display plain source. */
|
|
47
|
+
highlight(request: CodeHighlightRequest): CodeHighlightResult | undefined;
|
|
48
|
+
}
|
|
49
|
+
interface CodeHighlightInput {
|
|
50
|
+
adapter?: CodeHighlightAdapter;
|
|
51
|
+
code: string;
|
|
52
|
+
/** Unconverted fence language or detector result. */
|
|
53
|
+
language: string;
|
|
54
|
+
colorScheme: 'light' | 'dark';
|
|
55
|
+
/** Enable incremental work while the document is streaming. */
|
|
56
|
+
streaming?: boolean;
|
|
57
|
+
generation: number;
|
|
58
|
+
active?: boolean;
|
|
59
|
+
}
|
|
60
|
+
interface CodeHighlightSnapshot {
|
|
61
|
+
language: string;
|
|
62
|
+
status: 'plain' | 'loading' | 'ready' | 'error';
|
|
63
|
+
result?: CodeHighlightResult;
|
|
64
|
+
error?: unknown;
|
|
65
|
+
}
|
|
66
|
+
/** Per-block cache and async preparation. A late preparation never publishes an old code result. */
|
|
67
|
+
export declare function createCodeHighlightSession(onChange: () => void): {
|
|
68
|
+
read(input: CodeHighlightInput): CodeHighlightSnapshot;
|
|
69
|
+
commit(input: CodeHighlightInput): void;
|
|
70
|
+
retry(): void;
|
|
71
|
+
dispose(): void;
|
|
72
|
+
};
|
|
73
|
+
type MermaidConfig = {
|
|
74
|
+
theme?: string;
|
|
75
|
+
securityLevel?: string;
|
|
76
|
+
darkMode?: boolean;
|
|
77
|
+
suppressErrorRendering?: boolean;
|
|
78
|
+
maxTextSize?: number;
|
|
79
|
+
themeVariables?: unknown;
|
|
80
|
+
};
|
|
81
|
+
/** The part of the mermaid module this file touches. Structural so tests can
|
|
82
|
+
* pass a stub; `mermaidAPI` is deprecated in mermaid's types but present at
|
|
83
|
+
* runtime in mermaid 11, and it is the only place `getSiteConfig` /
|
|
84
|
+
* `getConfig` live (the default export has neither). */
|
|
85
|
+
type MermaidInitTarget = {
|
|
86
|
+
initialize(config: MermaidConfig): void;
|
|
87
|
+
mermaidAPI?: {
|
|
88
|
+
getSiteConfig?: () => MermaidConfig;
|
|
89
|
+
getConfig?: () => MermaidConfig;
|
|
90
|
+
};
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* The effective `maxTextSize`. `mermaid.render` does not reject oversized
|
|
94
|
+
* input: it swaps in a placeholder diagram ("Maximum text size in diagram
|
|
95
|
+
* exceeded") and resolves normally, and `mermaid.parse` has no size gate at
|
|
96
|
+
* all, so the whole text is parsed first. The renderer checks this before
|
|
97
|
+
* parsing and reports the size as an error instead. The key is in mermaid's
|
|
98
|
+
* `secure` list, so a `%%{init}%%` directive cannot raise it and the site
|
|
99
|
+
* config is the value that applies.
|
|
100
|
+
*/
|
|
101
|
+
export declare const getMermaidMaxTextSize: (mermaid: MermaidInitTarget) => number;
|
|
102
|
+
/**
|
|
103
|
+
* mermaid's config is a module-level singleton shared with the host
|
|
104
|
+
* application when the bundler dedupes the package, and a host that enables
|
|
105
|
+
* `click` interactions calls `mermaid.initialize({ securityLevel: 'loose' })`
|
|
106
|
+
* — the officially documented way. Under `loose` mermaid skips DOMPurify
|
|
107
|
+
* and its output goes into this component's `innerHTML` verbatim: an
|
|
108
|
+
* LLM-authored diagram string could then run script in the page origin.
|
|
109
|
+
* So a theme cache alone is not enough of a guard: before every render the
|
|
110
|
+
* current `securityLevel` is read back (a config copy, still far cheaper
|
|
111
|
+
* than `initialize`'s merge + theme variables + diagram registration) and an
|
|
112
|
+
* unsafe value forces a re-initialize
|
|
113
|
+
* (2026-08-19 review r2 P2-11; the v2.4.2 "documented premise" made this
|
|
114
|
+
* the host's problem — it is ours, the innerHTML is ours).
|
|
115
|
+
*
|
|
116
|
+
* In mermaid 11 `initialize` goes through `setSiteConfig`, which REPLACES
|
|
117
|
+
* the site config with defaults + the keys passed in. Calling it with only
|
|
118
|
+
* our keys wiped the host's `theme`, `fontFamily`, `flowchart` options and
|
|
119
|
+
* so on, and turned a host `sandbox` into `strict` (3.0.2 review). So:
|
|
120
|
+
* - the current site config is read back and passed through with our
|
|
121
|
+
* overrides on top, so host keys survive;
|
|
122
|
+
* - `sandbox` is accepted as is; only `loose` / `antiscript` / unset become
|
|
123
|
+
* `strict`;
|
|
124
|
+
* - a theme the host chose is kept (with its `themeVariables`); the color
|
|
125
|
+
* scheme switch only applies to the theme when the host has not chosen
|
|
126
|
+
* one, or when the current theme is one we wrote;
|
|
127
|
+
* - when nothing needs to change, `initialize` is not called at all, so a
|
|
128
|
+
* host on `strict`/`sandbox` and this component stop overwriting each
|
|
129
|
+
* other on every render.
|
|
130
|
+
*/
|
|
131
|
+
export declare const ensureMermaidInitialized: (mermaid: MermaidInitTarget, isDark: boolean) => void;
|
|
3
132
|
/** Shared image semantics; no DOM or framework dependency. */
|
|
4
133
|
type ImageActionIconName = 'rotateLeft' | 'rotateRight' | 'zoomIn' | 'zoomOut' | 'close' | 'prev' | 'next' | 'flipX' | 'flipY';
|
|
5
134
|
type ImageIconName = 'placeholder' | 'error' | 'preview' | 'gallery' | ImageActionIconName;
|
|
@@ -88,6 +217,145 @@ interface TableLabels extends Record<TableExportReason, string> {
|
|
|
88
217
|
scrollRegion: string;
|
|
89
218
|
}
|
|
90
219
|
export declare const defaultTableLabels: Readonly<TableLabels>;
|
|
220
|
+
interface DiagramEngine extends MermaidInitTarget {
|
|
221
|
+
kind?: 'mermaid';
|
|
222
|
+
/** Resolves truthy for a source that parses; rejects, or resolves falsy, for one that does not. */
|
|
223
|
+
parse(code: string): Promise<unknown>;
|
|
224
|
+
render(id: string, code: string): Promise<{
|
|
225
|
+
svg: string;
|
|
226
|
+
diagramType?: string;
|
|
227
|
+
bindFunctions?(element: object): void;
|
|
228
|
+
}>;
|
|
229
|
+
}
|
|
230
|
+
/** A stateless SVG renderer. Output must be safe to insert into the document. */
|
|
231
|
+
interface SvgDiagramEngine {
|
|
232
|
+
/** Identifies the built-in CSS palette, not a capability registry. */
|
|
233
|
+
palette?: 'pele' | 'ondine';
|
|
234
|
+
kind: 'svg';
|
|
235
|
+
maxTextSize?: number;
|
|
236
|
+
render(id: string, code: string, dark: boolean): Promise<{
|
|
237
|
+
svg: string;
|
|
238
|
+
diagramType?: string;
|
|
239
|
+
bindFunctions?(element: object): void | (() => void);
|
|
240
|
+
}>;
|
|
241
|
+
}
|
|
242
|
+
type DiagramEngineLoader = () => Promise<DiagramEngine | SvgDiagramEngine>;
|
|
243
|
+
/**
|
|
244
|
+
* What the host shows. One value instead of separate flags whose combinations
|
|
245
|
+
* had to be kept coherent by hand:
|
|
246
|
+
* - `source`: nothing has rendered in this generation (warm-up, server render).
|
|
247
|
+
* - `diagram`: the last successful render.
|
|
248
|
+
* - `error`: only a failed corrective pass after a stream, or a static failure
|
|
249
|
+
* with no diagram up, enters this state.
|
|
250
|
+
*/
|
|
251
|
+
type DiagramView = {
|
|
252
|
+
kind: 'source';
|
|
253
|
+
} | {
|
|
254
|
+
kind: 'diagram';
|
|
255
|
+
svg: string;
|
|
256
|
+
chartType: string;
|
|
257
|
+
palette?: 'pele' | 'ondine';
|
|
258
|
+
dark?: boolean;
|
|
259
|
+
onBindError?: (error: unknown) => void;
|
|
260
|
+
bind?: (element: object) => void | (() => void);
|
|
261
|
+
} | DiagramError;
|
|
262
|
+
/**
|
|
263
|
+
* Why a diagram did not render, as data: the host owns the words.
|
|
264
|
+
* - `tooLarge`: the source is longer than the engine's `maxTextSize`.
|
|
265
|
+
* - `parse` and `render`: the engine refused the source or failed to draw it.
|
|
266
|
+
* `message` is the engine's own text, which is diagnostic and not
|
|
267
|
+
* translated, or empty when it gave none.
|
|
268
|
+
*/
|
|
269
|
+
type DiagramError = {
|
|
270
|
+
kind: 'error';
|
|
271
|
+
reason: 'tooLarge';
|
|
272
|
+
length: number;
|
|
273
|
+
limit: number;
|
|
274
|
+
} | {
|
|
275
|
+
kind: 'error';
|
|
276
|
+
reason: 'parse' | 'render';
|
|
277
|
+
message: string;
|
|
278
|
+
};
|
|
279
|
+
/** The text for an error view: the engine's own message when there is one, else the label for the reason. */
|
|
280
|
+
export declare function diagramErrorText(error: DiagramError, labels: Pick<DiagramLabels, 'tooLarge' | 'renderFailed'>): string;
|
|
281
|
+
interface DiagramState {
|
|
282
|
+
view: DiagramView;
|
|
283
|
+
/** The engine module could not be loaded and the automatic retries are spent. `retry()` starts over. */
|
|
284
|
+
loadFailed: boolean;
|
|
285
|
+
}
|
|
286
|
+
interface DiagramRequest {
|
|
287
|
+
code: string;
|
|
288
|
+
dark: boolean;
|
|
289
|
+
/** Document streaming state. Its edges mark the start and the end of a generation. */
|
|
290
|
+
streaming: boolean;
|
|
291
|
+
/** False while the host shows something else, such as the source. No attempt runs. */
|
|
292
|
+
active: boolean;
|
|
293
|
+
/** Minimum time between attempts while streaming. Zero attempts every update. */
|
|
294
|
+
interval: number;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* The render state machine for one diagram. The host passes every change of
|
|
298
|
+
* its inputs to `update` and draws what `publish` receives.
|
|
299
|
+
*
|
|
300
|
+
* ## While `streaming` is true
|
|
301
|
+
*
|
|
302
|
+
* The source is usually a truncated prefix, so a parse failure is expected:
|
|
303
|
+
* - Before the first success the view stays `source`, never `error`.
|
|
304
|
+
* - After a success the last diagram stays up; each attempt replaces it only
|
|
305
|
+
* when it succeeds.
|
|
306
|
+
* - Attempts are throttled by `interval` with the same trailing throttle as
|
|
307
|
+
* code display: appends inside an interval replace one pending frame without
|
|
308
|
+
* moving its deadline. A rewrite, a non-streaming update and the end of the
|
|
309
|
+
* stream pass through at once.
|
|
310
|
+
* - When streaming ends, one corrective pass runs on the final source. Its
|
|
311
|
+
* failure is published even over a diagram, because that diagram no longer
|
|
312
|
+
* matches the source. Only that one pass may do so.
|
|
313
|
+
* - When streaming starts, a new generation begins on the same instance (a
|
|
314
|
+
* regenerated answer keeps its block position). Everything from the previous
|
|
315
|
+
* generation is dropped and the view returns to `source`.
|
|
316
|
+
*
|
|
317
|
+
* ## While `streaming` stays false
|
|
318
|
+
*
|
|
319
|
+
* A failure is published only while no diagram is up. Once one is, a later
|
|
320
|
+
* failure (a theme change, an incomplete source from a host that does not pass
|
|
321
|
+
* `streaming`) keeps it.
|
|
322
|
+
*
|
|
323
|
+
* ## Always
|
|
324
|
+
*
|
|
325
|
+
* - An attempt whose source and theme match the diagram on screen is skipped.
|
|
326
|
+
* - A source above the engine's `maxTextSize` is an error, not a render.
|
|
327
|
+
* - A failed engine download is not a diagram error. It keeps the view, keeps a
|
|
328
|
+
* pending corrective pass, and is retried a bounded number of times.
|
|
329
|
+
* - An attempt that has been superseded publishes nothing.
|
|
330
|
+
*/
|
|
331
|
+
export declare function createDiagramController(load: DiagramEngineLoader, publish: (state: DiagramState) => void, fallback?: DiagramEngineLoader): {
|
|
332
|
+
update(next: DiagramRequest): void;
|
|
333
|
+
/** Attempts again on unchanged inputs, with a fresh download budget. */
|
|
334
|
+
retry(): void;
|
|
335
|
+
dispose(): void;
|
|
336
|
+
};
|
|
337
|
+
interface CodeBlockOptions {
|
|
338
|
+
/** Legacy callbacks default to highlight.js names. Adapters own their language format. */
|
|
339
|
+
languageFormat?: CodeLanguageResolver;
|
|
340
|
+
/** Takes precedence over the legacy framework highlight callback. Keep adapter identity stable. */
|
|
341
|
+
highlighter?: CodeHighlightAdapter;
|
|
342
|
+
defaultExpanded?: boolean;
|
|
343
|
+
autoDetectUnknownLanguage?: boolean;
|
|
344
|
+
formatJson?: boolean;
|
|
345
|
+
expandNestedJson?: boolean;
|
|
346
|
+
highlightIntervalMs?: number;
|
|
347
|
+
mermaidIntervalMs?: number;
|
|
348
|
+
/** Optional renderer loader. Omit to use Mermaid. Keep its identity stable. */
|
|
349
|
+
mermaidEngine?: DiagramEngineLoader | false;
|
|
350
|
+
/** Standard entry only: fall back to Mermaid for a known unavailable type. Default true. */
|
|
351
|
+
mermaidFallback?: boolean;
|
|
352
|
+
/** Text of the code block, as overrides of the English defaults. A function is called on every render. */
|
|
353
|
+
labels?: LabelsOption<CodeBlockLabels>;
|
|
354
|
+
}
|
|
355
|
+
/** Common behavior defaults. UI integrations may override these defaults, not their resolution rules. */
|
|
356
|
+
type CodeBlockPolicy = Required<Pick<CodeBlockOptions, 'defaultExpanded' | 'autoDetectUnknownLanguage' | 'formatJson' | 'expandNestedJson' | 'highlightIntervalMs'>>;
|
|
357
|
+
export declare const defaultCodeBlockPolicy: Readonly<CodeBlockPolicy>;
|
|
358
|
+
export declare function resolveCodeBlockPolicy(overrides?: Partial<CodeBlockPolicy>, inherited?: Partial<CodeBlockPolicy>, defaults?: Partial<CodeBlockPolicy>): CodeBlockPolicy;
|
|
91
359
|
interface CodeSource {
|
|
92
360
|
code: string;
|
|
93
361
|
language: string;
|
|
@@ -221,165 +489,6 @@ export declare const mermaidRenderQueue: {
|
|
|
221
489
|
enqueue(owner: object, run: () => Promise<void>): Promise<void>;
|
|
222
490
|
cancel(owner: object): void;
|
|
223
491
|
};
|
|
224
|
-
type MermaidConfig = {
|
|
225
|
-
theme?: string;
|
|
226
|
-
securityLevel?: string;
|
|
227
|
-
darkMode?: boolean;
|
|
228
|
-
suppressErrorRendering?: boolean;
|
|
229
|
-
maxTextSize?: number;
|
|
230
|
-
themeVariables?: unknown;
|
|
231
|
-
};
|
|
232
|
-
/** The part of the mermaid module this file touches. Structural so tests can
|
|
233
|
-
* pass a stub; `mermaidAPI` is deprecated in mermaid's types but present at
|
|
234
|
-
* runtime in mermaid 11, and it is the only place `getSiteConfig` /
|
|
235
|
-
* `getConfig` live (the default export has neither). */
|
|
236
|
-
type MermaidInitTarget = {
|
|
237
|
-
initialize(config: MermaidConfig): void;
|
|
238
|
-
mermaidAPI?: {
|
|
239
|
-
getSiteConfig?: () => MermaidConfig;
|
|
240
|
-
getConfig?: () => MermaidConfig;
|
|
241
|
-
};
|
|
242
|
-
};
|
|
243
|
-
/**
|
|
244
|
-
* The effective `maxTextSize`. `mermaid.render` does not reject oversized
|
|
245
|
-
* input: it swaps in a placeholder diagram ("Maximum text size in diagram
|
|
246
|
-
* exceeded") and resolves normally, and `mermaid.parse` has no size gate at
|
|
247
|
-
* all, so the whole text is parsed first. The renderer checks this before
|
|
248
|
-
* parsing and reports the size as an error instead. The key is in mermaid's
|
|
249
|
-
* `secure` list, so a `%%{init}%%` directive cannot raise it and the site
|
|
250
|
-
* config is the value that applies.
|
|
251
|
-
*/
|
|
252
|
-
export declare const getMermaidMaxTextSize: (mermaid: MermaidInitTarget) => number;
|
|
253
|
-
/**
|
|
254
|
-
* mermaid's config is a module-level singleton shared with the host
|
|
255
|
-
* application when the bundler dedupes the package, and a host that enables
|
|
256
|
-
* `click` interactions calls `mermaid.initialize({ securityLevel: 'loose' })`
|
|
257
|
-
* — the officially documented way. Under `loose` mermaid skips DOMPurify
|
|
258
|
-
* and its output goes into this component's `innerHTML` verbatim: an
|
|
259
|
-
* LLM-authored diagram string could then run script in the page origin.
|
|
260
|
-
* So a theme cache alone is not enough of a guard: before every render the
|
|
261
|
-
* current `securityLevel` is read back (a config copy, still far cheaper
|
|
262
|
-
* than `initialize`'s merge + theme variables + diagram registration) and an
|
|
263
|
-
* unsafe value forces a re-initialize
|
|
264
|
-
* (2026-08-19 review r2 P2-11; the v2.4.2 "documented premise" made this
|
|
265
|
-
* the host's problem — it is ours, the innerHTML is ours).
|
|
266
|
-
*
|
|
267
|
-
* In mermaid 11 `initialize` goes through `setSiteConfig`, which REPLACES
|
|
268
|
-
* the site config with defaults + the keys passed in. Calling it with only
|
|
269
|
-
* our keys wiped the host's `theme`, `fontFamily`, `flowchart` options and
|
|
270
|
-
* so on, and turned a host `sandbox` into `strict` (3.0.2 review). So:
|
|
271
|
-
* - the current site config is read back and passed through with our
|
|
272
|
-
* overrides on top, so host keys survive;
|
|
273
|
-
* - `sandbox` is accepted as is; only `loose` / `antiscript` / unset become
|
|
274
|
-
* `strict`;
|
|
275
|
-
* - a theme the host chose is kept (with its `themeVariables`); the color
|
|
276
|
-
* scheme switch only applies to the theme when the host has not chosen
|
|
277
|
-
* one, or when the current theme is one we wrote;
|
|
278
|
-
* - when nothing needs to change, `initialize` is not called at all, so a
|
|
279
|
-
* host on `strict`/`sandbox` and this component stop overwriting each
|
|
280
|
-
* other on every render.
|
|
281
|
-
*/
|
|
282
|
-
export declare const ensureMermaidInitialized: (mermaid: MermaidInitTarget, isDark: boolean) => void;
|
|
283
|
-
interface DiagramEngine extends MermaidInitTarget {
|
|
284
|
-
/** Resolves truthy for a source that parses; rejects, or resolves falsy, for one that does not. */
|
|
285
|
-
parse(code: string): Promise<unknown>;
|
|
286
|
-
render(id: string, code: string): Promise<{
|
|
287
|
-
svg: string;
|
|
288
|
-
diagramType?: string;
|
|
289
|
-
bindFunctions?(element: object): void;
|
|
290
|
-
}>;
|
|
291
|
-
}
|
|
292
|
-
/**
|
|
293
|
-
* What the host shows. One value instead of separate flags whose combinations
|
|
294
|
-
* had to be kept coherent by hand:
|
|
295
|
-
* - `source`: nothing has rendered in this generation (warm-up, server render).
|
|
296
|
-
* - `diagram`: the last successful render.
|
|
297
|
-
* - `error`: only a failed corrective pass after a stream, or a static failure
|
|
298
|
-
* with no diagram up, enters this state.
|
|
299
|
-
*/
|
|
300
|
-
type DiagramView = {
|
|
301
|
-
kind: 'source';
|
|
302
|
-
} | {
|
|
303
|
-
kind: 'diagram';
|
|
304
|
-
svg: string;
|
|
305
|
-
chartType: string;
|
|
306
|
-
bind?: (element: object) => void;
|
|
307
|
-
} | DiagramError;
|
|
308
|
-
/**
|
|
309
|
-
* Why a diagram did not render, as data: the host owns the words.
|
|
310
|
-
* - `tooLarge`: the source is longer than the engine's `maxTextSize`.
|
|
311
|
-
* - `parse` and `render`: the engine refused the source or failed to draw it.
|
|
312
|
-
* `message` is the engine's own text, which is diagnostic and not
|
|
313
|
-
* translated, or empty when it gave none.
|
|
314
|
-
*/
|
|
315
|
-
type DiagramError = {
|
|
316
|
-
kind: 'error';
|
|
317
|
-
reason: 'tooLarge';
|
|
318
|
-
length: number;
|
|
319
|
-
limit: number;
|
|
320
|
-
} | {
|
|
321
|
-
kind: 'error';
|
|
322
|
-
reason: 'parse' | 'render';
|
|
323
|
-
message: string;
|
|
324
|
-
};
|
|
325
|
-
/** The text for an error view: the engine's own message when there is one, else the label for the reason. */
|
|
326
|
-
export declare function diagramErrorText(error: DiagramError, labels: Pick<DiagramLabels, 'tooLarge' | 'renderFailed'>): string;
|
|
327
|
-
interface DiagramState {
|
|
328
|
-
view: DiagramView;
|
|
329
|
-
/** The engine module could not be loaded and the automatic retries are spent. `retry()` starts over. */
|
|
330
|
-
loadFailed: boolean;
|
|
331
|
-
}
|
|
332
|
-
interface DiagramRequest {
|
|
333
|
-
code: string;
|
|
334
|
-
dark: boolean;
|
|
335
|
-
/** Document streaming state. Its edges mark the start and the end of a generation. */
|
|
336
|
-
streaming: boolean;
|
|
337
|
-
/** False while the host shows something else, such as the source. No attempt runs. */
|
|
338
|
-
active: boolean;
|
|
339
|
-
/** Minimum time between attempts while streaming. Zero attempts every update. */
|
|
340
|
-
interval: number;
|
|
341
|
-
}
|
|
342
|
-
/**
|
|
343
|
-
* The render state machine for one diagram. The host passes every change of
|
|
344
|
-
* its inputs to `update` and draws what `publish` receives.
|
|
345
|
-
*
|
|
346
|
-
* ## While `streaming` is true
|
|
347
|
-
*
|
|
348
|
-
* The source is usually a truncated prefix, so a parse failure is expected:
|
|
349
|
-
* - Before the first success the view stays `source`, never `error`.
|
|
350
|
-
* - After a success the last diagram stays up; each attempt replaces it only
|
|
351
|
-
* when it succeeds.
|
|
352
|
-
* - Attempts are throttled by `interval` with the same trailing throttle as
|
|
353
|
-
* code display: appends inside an interval replace one pending frame without
|
|
354
|
-
* moving its deadline. A rewrite, a non-streaming update and the end of the
|
|
355
|
-
* stream pass through at once.
|
|
356
|
-
* - When streaming ends, one corrective pass runs on the final source. Its
|
|
357
|
-
* failure is published even over a diagram, because that diagram no longer
|
|
358
|
-
* matches the source. Only that one pass may do so.
|
|
359
|
-
* - When streaming starts, a new generation begins on the same instance (a
|
|
360
|
-
* regenerated answer keeps its block position). Everything from the previous
|
|
361
|
-
* generation is dropped and the view returns to `source`.
|
|
362
|
-
*
|
|
363
|
-
* ## While `streaming` stays false
|
|
364
|
-
*
|
|
365
|
-
* A failure is published only while no diagram is up. Once one is, a later
|
|
366
|
-
* failure (a theme change, an incomplete source from a host that does not pass
|
|
367
|
-
* `streaming`) keeps it.
|
|
368
|
-
*
|
|
369
|
-
* ## Always
|
|
370
|
-
*
|
|
371
|
-
* - An attempt whose source and theme match the diagram on screen is skipped.
|
|
372
|
-
* - A source above the engine's `maxTextSize` is an error, not a render.
|
|
373
|
-
* - A failed engine download is not a diagram error. It keeps the view, keeps a
|
|
374
|
-
* pending corrective pass, and is retried a bounded number of times.
|
|
375
|
-
* - An attempt that has been superseded publishes nothing.
|
|
376
|
-
*/
|
|
377
|
-
export declare function createDiagramController(load: () => Promise<DiagramEngine>, publish: (state: DiagramState) => void): {
|
|
378
|
-
update(next: DiagramRequest): void;
|
|
379
|
-
/** Attempts again on unchanged inputs, with a fresh download budget. */
|
|
380
|
-
retry(): void;
|
|
381
|
-
dispose(): void;
|
|
382
|
-
};
|
|
383
492
|
/**
|
|
384
493
|
* Stops the page behind a preview from scrolling. `scrollbarWidth` is the
|
|
385
494
|
* width of the scrollbar that hiding the overflow removes
|
|
@@ -592,6 +701,106 @@ export declare function createImagePreviewController(host: ImagePreviewHost, pub
|
|
|
592
701
|
/** Stops every timer and subscription. The controller can be opened again afterwards. */
|
|
593
702
|
dispose(): void;
|
|
594
703
|
};
|
|
704
|
+
/** Structural subset; generic options preserve the installed engine's own parameter types. */
|
|
705
|
+
interface SvgRendererModule<Options extends object = {
|
|
706
|
+
idPrefix?: string;
|
|
707
|
+
limit?: number;
|
|
708
|
+
}> {
|
|
709
|
+
render(source: string, options?: Options): {
|
|
710
|
+
svg: string;
|
|
711
|
+
type?: string;
|
|
712
|
+
} | Promise<{
|
|
713
|
+
svg: string;
|
|
714
|
+
type?: string;
|
|
715
|
+
}>;
|
|
716
|
+
}
|
|
717
|
+
interface DiagramAdapterOptions<Options extends object> {
|
|
718
|
+
renderOptions?: Omit<Options, 'idPrefix'>;
|
|
719
|
+
}
|
|
720
|
+
export declare function createPeleLoader<Options extends object>(load: () => Promise<SvgRendererModule<Options>>, options?: DiagramAdapterOptions<Options>): DiagramEngineLoader;
|
|
721
|
+
export declare function createOndineLoader<Options extends object>(load: () => Promise<SvgRendererModule<Options>>, options?: DiagramAdapterOptions<Options>): DiagramEngineLoader;
|
|
722
|
+
interface PierreHighlightToken {
|
|
723
|
+
content: string;
|
|
724
|
+
offset: number;
|
|
725
|
+
color?: string;
|
|
726
|
+
bgColor?: string;
|
|
727
|
+
fontStyle?: number;
|
|
728
|
+
}
|
|
729
|
+
/** Only the synchronous, editable-document API is needed; core imports no WASM runtime. */
|
|
730
|
+
interface PierreLiveTokenizer {
|
|
731
|
+
readonly lineCount: number;
|
|
732
|
+
getLineLength(line: number): number;
|
|
733
|
+
getLineTokens(line: number): {
|
|
734
|
+
tokens: readonly PierreHighlightToken[];
|
|
735
|
+
};
|
|
736
|
+
applyEdits(edits: readonly {
|
|
737
|
+
range: {
|
|
738
|
+
start: {
|
|
739
|
+
line: number;
|
|
740
|
+
character: number;
|
|
741
|
+
};
|
|
742
|
+
end: {
|
|
743
|
+
line: number;
|
|
744
|
+
character: number;
|
|
745
|
+
};
|
|
746
|
+
};
|
|
747
|
+
newText: string;
|
|
748
|
+
}[]): {
|
|
749
|
+
lineChanges: readonly {
|
|
750
|
+
oldStartLine: number;
|
|
751
|
+
oldEndLine: number;
|
|
752
|
+
newStartLine: number;
|
|
753
|
+
newEndLine: number;
|
|
754
|
+
}[];
|
|
755
|
+
};
|
|
756
|
+
dispose(): void;
|
|
757
|
+
}
|
|
758
|
+
/** Structural interface: applications own the optional WASM engine and theme imports. */
|
|
759
|
+
interface PierreHighlightRuntime<Language extends string, Theme> {
|
|
760
|
+
isSupportedLanguage(language: string): boolean;
|
|
761
|
+
codeToTokens(code: string, options: {
|
|
762
|
+
lang: Language;
|
|
763
|
+
theme: NoInfer<Theme>;
|
|
764
|
+
}): {
|
|
765
|
+
tokens: readonly (readonly PierreHighlightToken[])[];
|
|
766
|
+
fg?: string;
|
|
767
|
+
};
|
|
768
|
+
LiveTokenizer?: new (options: {
|
|
769
|
+
code: string;
|
|
770
|
+
lang: Language;
|
|
771
|
+
theme: NoInfer<Theme>;
|
|
772
|
+
}) => PierreLiveTokenizer;
|
|
773
|
+
themes: {
|
|
774
|
+
light: Theme;
|
|
775
|
+
dark: Theme;
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
/** Lazy initialization is shared; mutable tokenizers belong to individual mounted blocks. */
|
|
779
|
+
export declare function createPierreHighlightAdapter<Language extends string, Theme>(options: {
|
|
780
|
+
load: () => Promise<PierreHighlightRuntime<Language, Theme>>;
|
|
781
|
+
/** Defaults to true. Disable to compare with full-frame tokenization. */
|
|
782
|
+
incremental?: boolean;
|
|
783
|
+
}): CodeHighlightAdapter;
|
|
784
|
+
/** Raised only for an identified diagram type unavailable in the selected engine. */
|
|
785
|
+
export declare class UnsupportedDiagramError extends Error {
|
|
786
|
+
readonly diagramType: string;
|
|
787
|
+
constructor(diagramType: string);
|
|
788
|
+
}
|
|
789
|
+
export declare const resolveDiagramInterval: (value: number | undefined) => number;
|
|
790
|
+
/** Shared per loader, not per component. Rejected imports are never retained. */
|
|
791
|
+
export declare function createCachedDiagramLoader(load: DiagramEngineLoader): DiagramEngineLoader;
|
|
792
|
+
export declare function preloadDiagramEngine(load: DiagramEngineLoader): Promise<void>;
|
|
793
|
+
interface DiagramInput {
|
|
794
|
+
code: string;
|
|
795
|
+
colorScheme: 'light' | 'dark';
|
|
796
|
+
streaming: boolean;
|
|
797
|
+
active: boolean;
|
|
798
|
+
resetKey: string;
|
|
799
|
+
intervalMs?: number;
|
|
800
|
+
load: DiagramEngineLoader;
|
|
801
|
+
/** Absent in engine-independent entry points. Only a classified unsupported type can use this. */
|
|
802
|
+
fallback?: DiagramEngineLoader;
|
|
803
|
+
}
|
|
595
804
|
export interface CodeRendererInput {
|
|
596
805
|
/** Raw accumulated source, including its trailing newline. */
|
|
597
806
|
code: string;
|
|
@@ -604,14 +813,4 @@ export interface CodeRendererInput {
|
|
|
604
813
|
/** Changes on source replacement or identity change; append preserves it. */
|
|
605
814
|
resetKey: string;
|
|
606
815
|
}
|
|
607
|
-
export
|
|
608
|
-
defaultExpanded?: boolean;
|
|
609
|
-
autoDetectUnknownLanguage?: boolean;
|
|
610
|
-
formatJson?: boolean;
|
|
611
|
-
expandNestedJson?: boolean;
|
|
612
|
-
highlightIntervalMs?: number;
|
|
613
|
-
mermaidIntervalMs?: number;
|
|
614
|
-
/** Text of the code block, as overrides of the English defaults. A function is called on every render. */
|
|
615
|
-
labels?: LabelsOption<CodeBlockLabels>;
|
|
616
|
-
}
|
|
617
|
-
export type { CodeBlockInput, CodeBlockLabels, CodeBlockSnapshot, CodeFrame, CodeSource, DiagramEngine, DiagramError, DiagramLabels, DiagramRequest, DiagramState, DiagramView, ImageActionIconName, ImageGallery, ImageGalleryItem, ImageGeometry, ImageIconName, ImageLabels, ImageLoadStatus, ImagePointer, ImagePreviewAction, ImagePreviewHost, ImagePreviewOptions, ImagePreviewPhase, ImagePreviewState, ImageTransform, LabelsOption, MermaidInitTarget, TableExportReason, TableLabels, TableProjection };
|
|
816
|
+
export type { CodeBlockInput, CodeBlockLabels, CodeBlockOptions, CodeBlockPolicy, CodeBlockSnapshot, CodeFrame, CodeHighlightAdapter, CodeHighlightBackend, CodeHighlightInput, CodeHighlightRequest, CodeHighlightResult, CodeHighlightSnapshot, CodeHighlightToken, CodeLanguageResolver, CodeSource, DiagramAdapterOptions, DiagramEngine, DiagramEngineLoader, DiagramError, DiagramInput, DiagramLabels, DiagramRequest, DiagramState, DiagramView, ImageActionIconName, ImageGallery, ImageGalleryItem, ImageGeometry, ImageIconName, ImageLabels, ImageLoadStatus, ImagePointer, ImagePreviewAction, ImagePreviewHost, ImagePreviewOptions, ImagePreviewPhase, ImagePreviewState, ImageTransform, LabelsOption, MermaidInitTarget, PierreHighlightRuntime, PierreHighlightToken, PierreLiveTokenizer, SvgDiagramEngine, SvgRendererModule, TableExportReason, TableLabels, TableProjection };
|