@vectojs/markdown 0.17.0 → 0.18.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.
- package/dist/Markdown.d.ts +32 -0
- package/dist/MarkdownWorkerSource.d.ts +1 -1
- package/dist/incrementalLex.d.ts +40 -19
- package/dist/index.js +148 -4
- package/dist/index.mjs +141 -3
- package/dist/markdown-abbr.d.ts +2 -2
- package/dist/markdown-container.d.ts +11 -5
- package/dist/markdown-fenced-registry.d.ts +159 -0
- package/dist/markdown-footnote.d.ts +6 -5
- package/package.json +1 -1
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import type { Entity } from '@vectojs/core';
|
|
2
|
+
import type { MarkdownTheme } from './theme';
|
|
3
|
+
/**
|
|
4
|
+
* Fenced block renderer registry: pluggable rendering for code fences keyed by
|
|
5
|
+
* info string.
|
|
6
|
+
*
|
|
7
|
+
* Each language (code, math, mermaid, graphviz, …) is a plugin rather than a
|
|
8
|
+
* branch in `Markdown.renderToken`. Renderers lazy-load on demand and cache
|
|
9
|
+
* conversions, reusing the pattern math already established.
|
|
10
|
+
*
|
|
11
|
+
* ## Lifecycle
|
|
12
|
+
*
|
|
13
|
+
* A renderer may be in one of three states:
|
|
14
|
+
* - **incomplete**: The renderer is registered but its module/assets are not
|
|
15
|
+
* loaded yet. The first call to `render()` triggers the load.
|
|
16
|
+
* - **ready**: The renderer is loaded and can render synchronously.
|
|
17
|
+
* - **error**: The renderer failed to load or encountered an unrecoverable error.
|
|
18
|
+
* Falls back to default code block rendering.
|
|
19
|
+
*
|
|
20
|
+
* ## Fallback
|
|
21
|
+
*
|
|
22
|
+
* When no renderer is registered for a language, or when a renderer returns
|
|
23
|
+
* `null`, the registry falls back to the default code block renderer. This
|
|
24
|
+
* preserves backward compatibility and degrades gracefully.
|
|
25
|
+
*
|
|
26
|
+
* ## Example
|
|
27
|
+
*
|
|
28
|
+
* ```typescript
|
|
29
|
+
* import { FencedBlockRegistry } from '@vectojs/markdown';
|
|
30
|
+
*
|
|
31
|
+
* // Register a custom renderer
|
|
32
|
+
* FencedBlockRegistry.register('mermaid', {
|
|
33
|
+
* async load() {
|
|
34
|
+
* const mermaid = await import('mermaid');
|
|
35
|
+
* return (source, lang, options) => {
|
|
36
|
+
* // ... render logic
|
|
37
|
+
* return entity;
|
|
38
|
+
* };
|
|
39
|
+
* }
|
|
40
|
+
* });
|
|
41
|
+
*
|
|
42
|
+
* // Unregister (for testing or cleanup)
|
|
43
|
+
* FencedBlockRegistry.unregister('mermaid');
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
/**
|
|
47
|
+
* Options passed to a fenced block renderer.
|
|
48
|
+
*
|
|
49
|
+
* Includes the theme, available width, and whether text should be selectable.
|
|
50
|
+
* Renderers may ignore options that don't apply to their output format.
|
|
51
|
+
*/
|
|
52
|
+
export interface FencedBlockRenderOptions {
|
|
53
|
+
/** The current Markdown theme (colors, fonts, sizes). */
|
|
54
|
+
theme: MarkdownTheme;
|
|
55
|
+
/** Available horizontal space in pixels. */
|
|
56
|
+
availableWidth: number;
|
|
57
|
+
/** Whether text content should be selectable. */
|
|
58
|
+
selectable: boolean;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* A fenced block renderer: converts source code in a specific language to an Entity.
|
|
62
|
+
*
|
|
63
|
+
* Returns `null` when rendering fails or the source is invalid. The caller falls
|
|
64
|
+
* back to a default code block.
|
|
65
|
+
*/
|
|
66
|
+
export type FencedBlockRenderer = (source: string, lang: string, options: FencedBlockRenderOptions) => Entity | null;
|
|
67
|
+
/**
|
|
68
|
+
* A lazy-loadable renderer specification.
|
|
69
|
+
*
|
|
70
|
+
* The `load()` method is called once, the first time a fence with this language
|
|
71
|
+
* appears. It should return a synchronous renderer function, or `null` if loading
|
|
72
|
+
* fails. Failures are logged but swallowed — the fence renders as a code block.
|
|
73
|
+
*/
|
|
74
|
+
export interface FencedBlockRendererSpec {
|
|
75
|
+
/**
|
|
76
|
+
* Load the renderer asynchronously.
|
|
77
|
+
*
|
|
78
|
+
* Called exactly once, the first time a fence with this language is encountered.
|
|
79
|
+
* Returns a synchronous renderer, or `null` on failure. The promise rejection
|
|
80
|
+
* is caught and logged; renderers must not leave unhandled rejections.
|
|
81
|
+
*/
|
|
82
|
+
load: () => Promise<FencedBlockRenderer | null>;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Register a lazy-loadable fenced block renderer for a language.
|
|
86
|
+
*
|
|
87
|
+
* @param lang - The language identifier (case-insensitive). Normalized to lowercase.
|
|
88
|
+
* @param spec - The renderer specification, with a `load()` method.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```typescript
|
|
92
|
+
* FencedBlockRegistry.register('mermaid', {
|
|
93
|
+
* async load() {
|
|
94
|
+
* const mermaid = await import('mermaid');
|
|
95
|
+
* return (source, lang, options) => {
|
|
96
|
+
* // ... render Mermaid diagram
|
|
97
|
+
* return entity;
|
|
98
|
+
* };
|
|
99
|
+
* }
|
|
100
|
+
* });
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
export declare function registerFencedBlockRenderer(lang: string, spec: FencedBlockRendererSpec): void;
|
|
104
|
+
/**
|
|
105
|
+
* Unregister a fenced block renderer.
|
|
106
|
+
*
|
|
107
|
+
* Used for testing (sabotage tests) and cleanup. After unregistering, fences with
|
|
108
|
+
* this language fall back to the default code block renderer.
|
|
109
|
+
*
|
|
110
|
+
* @param lang - The language identifier (case-insensitive).
|
|
111
|
+
*/
|
|
112
|
+
export declare function unregisterFencedBlockRenderer(lang: string): void;
|
|
113
|
+
/**
|
|
114
|
+
* Check if a renderer is registered for a language.
|
|
115
|
+
*
|
|
116
|
+
* Returns `true` if a renderer is registered, regardless of whether it has loaded yet.
|
|
117
|
+
*
|
|
118
|
+
* @param lang - The language identifier (case-insensitive).
|
|
119
|
+
*/
|
|
120
|
+
export declare function hasFencedBlockRenderer(lang: string): boolean;
|
|
121
|
+
/**
|
|
122
|
+
* Check if a renderer is ready (loaded and available for synchronous rendering).
|
|
123
|
+
*
|
|
124
|
+
* Returns `false` if the renderer is not registered, not loaded yet, or failed to load.
|
|
125
|
+
*
|
|
126
|
+
* @param lang - The language identifier (case-insensitive).
|
|
127
|
+
*/
|
|
128
|
+
export declare function isFencedBlockRendererReady(lang: string): boolean;
|
|
129
|
+
/**
|
|
130
|
+
* Begin (or join) loading a fenced block renderer.
|
|
131
|
+
*
|
|
132
|
+
* Idempotent: the load promise is cached, so multiple callers share one load.
|
|
133
|
+
* Failures are swallowed — the renderer simply stays unavailable.
|
|
134
|
+
*
|
|
135
|
+
* Call this when a fence with this language first appears, even while it is still
|
|
136
|
+
* open (incomplete). This prefetches the module so the closing fence can render
|
|
137
|
+
* synchronously, hiding the lazy load during a stream.
|
|
138
|
+
*
|
|
139
|
+
* @param lang - The language identifier (case-insensitive).
|
|
140
|
+
* @returns A promise that resolves when the renderer is ready, or immediately if
|
|
141
|
+
* already loaded.
|
|
142
|
+
*/
|
|
143
|
+
export declare function ensureFencedBlockRenderer(lang: string): Promise<void>;
|
|
144
|
+
/**
|
|
145
|
+
* Render a fenced code block using the registered renderer for its language.
|
|
146
|
+
*
|
|
147
|
+
* Returns `null` if:
|
|
148
|
+
* - No renderer is registered for this language
|
|
149
|
+
* - The renderer is not loaded yet
|
|
150
|
+
* - The renderer returned `null` (rendering failed)
|
|
151
|
+
*
|
|
152
|
+
* The caller falls back to the default code block renderer in all three cases.
|
|
153
|
+
*
|
|
154
|
+
* @param source - The source code inside the fence.
|
|
155
|
+
* @param lang - The language identifier (case-insensitive).
|
|
156
|
+
* @param options - Rendering options (theme, width, selectable).
|
|
157
|
+
* @returns The rendered entity, or `null` to fall back to default code block.
|
|
158
|
+
*/
|
|
159
|
+
export declare function renderFencedBlock(source: string, lang: string, options: FencedBlockRenderOptions): Entity | null;
|
|
@@ -59,14 +59,15 @@ export interface FootnoteDefToken {
|
|
|
59
59
|
* {@link consumeContinuation} can still be scanning forward (an open
|
|
60
60
|
* continuation) when more text arrives.
|
|
61
61
|
*
|
|
62
|
-
* Used by `incrementalLex.ts`'s degrade check, mirroring `
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
62
|
+
* Used by `incrementalLex.ts`'s degrade check, mirroring `hasContainerOpener`:
|
|
63
|
+
* a footnote definition's continuation-consuming tokenizer has the exact same
|
|
64
|
+
* forward-reach hazard a `:::` fence does, now that it can span a blank line.
|
|
65
|
+
* (`blockMath` used to be the third member of this set; its tokenizer now stops
|
|
66
|
+
* at a blank line, so it no longer degrades — see `paragraphPairCap`.) Deliberately does not try to determine
|
|
66
67
|
* whether a SPECIFIC header's continuation is still open — that would need to
|
|
67
68
|
* replicate the tokenizer's own scan — and instead degrades on the mere
|
|
68
69
|
* presence of any header, which is safe (if conservative) the same way
|
|
69
|
-
* `
|
|
70
|
+
* `hasContainerOpener` accepts matching inside a fenced code block it would
|
|
70
71
|
* never actually reach.
|
|
71
72
|
*/
|
|
72
73
|
export declare function hasFootnoteDefOpener(text: string): boolean;
|