@scrider/formatter 1.0.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/LICENSE +21 -0
- package/NOTICE +52 -0
- package/README.md +123 -0
- package/dist/index.cjs +4946 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1658 -0
- package/dist/index.d.ts +1658 -0
- package/dist/index.js +4844 -0
- package/dist/index.js.map +1 -0
- package/package.json +109 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,1658 @@
|
|
|
1
|
+
import { AttributeMap, Op, Delta } from '@scrider/delta';
|
|
2
|
+
export * from '@scrider/delta';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* DOM Adapter Interface
|
|
6
|
+
*
|
|
7
|
+
* Provides a unified interface for DOM operations across different environments:
|
|
8
|
+
* - Browser: uses native DOM APIs
|
|
9
|
+
* - Node.js: uses jsdom
|
|
10
|
+
*
|
|
11
|
+
* This abstraction allows the same conversion code to work in both environments.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Minimal Document interface required for HTML parsing/rendering
|
|
15
|
+
*/
|
|
16
|
+
interface DOMDocument {
|
|
17
|
+
createElement(tagName: string): DOMElement;
|
|
18
|
+
createTextNode(text: string): DOMNode;
|
|
19
|
+
createDocumentFragment(): DOMDocumentFragment;
|
|
20
|
+
readonly body: DOMElement;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Minimal DocumentFragment interface
|
|
24
|
+
*/
|
|
25
|
+
interface DOMDocumentFragment {
|
|
26
|
+
appendChild(node: DOMNode): DOMNode;
|
|
27
|
+
readonly childNodes: DOMNodeList;
|
|
28
|
+
readonly firstChild: DOMNode | null;
|
|
29
|
+
readonly nodeType: number;
|
|
30
|
+
readonly textContent: string | null;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Minimal Node interface
|
|
34
|
+
*/
|
|
35
|
+
interface DOMNode {
|
|
36
|
+
readonly nodeType: number;
|
|
37
|
+
readonly nodeName: string;
|
|
38
|
+
readonly parentNode: DOMNode | null;
|
|
39
|
+
readonly childNodes: DOMNodeList;
|
|
40
|
+
readonly firstChild: DOMNode | null;
|
|
41
|
+
readonly nextSibling: DOMNode | null;
|
|
42
|
+
textContent: string | null;
|
|
43
|
+
appendChild(node: DOMNode): DOMNode;
|
|
44
|
+
cloneNode(deep?: boolean): DOMNode;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Minimal Element interface
|
|
48
|
+
*/
|
|
49
|
+
interface DOMElement extends DOMNode {
|
|
50
|
+
readonly tagName: string;
|
|
51
|
+
innerHTML: string;
|
|
52
|
+
outerHTML: string;
|
|
53
|
+
getAttribute(name: string): string | null;
|
|
54
|
+
setAttribute(name: string, value: string): void;
|
|
55
|
+
hasAttribute(name: string): boolean;
|
|
56
|
+
removeAttribute(name: string): void;
|
|
57
|
+
readonly style: DOMCSSStyleDeclaration;
|
|
58
|
+
readonly classList: DOMTokenList;
|
|
59
|
+
querySelector(selector: string): DOMElement | null;
|
|
60
|
+
querySelectorAll(selector: string): DOMNodeList;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Minimal CSSStyleDeclaration interface
|
|
64
|
+
*/
|
|
65
|
+
interface DOMCSSStyleDeclaration {
|
|
66
|
+
getPropertyValue(property: string): string;
|
|
67
|
+
setProperty(property: string, value: string): void;
|
|
68
|
+
color?: string;
|
|
69
|
+
backgroundColor?: string;
|
|
70
|
+
fontWeight?: string;
|
|
71
|
+
fontStyle?: string;
|
|
72
|
+
textDecoration?: string;
|
|
73
|
+
textAlign?: string;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Minimal DOMTokenList interface (for classList)
|
|
77
|
+
*/
|
|
78
|
+
interface DOMTokenList {
|
|
79
|
+
add(...tokens: string[]): void;
|
|
80
|
+
remove(...tokens: string[]): void;
|
|
81
|
+
contains(token: string): boolean;
|
|
82
|
+
readonly length: number;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Minimal NodeList interface
|
|
86
|
+
*/
|
|
87
|
+
interface DOMNodeList {
|
|
88
|
+
readonly length: number;
|
|
89
|
+
item(index: number): DOMNode | null;
|
|
90
|
+
[index: number]: DOMNode;
|
|
91
|
+
forEach(callback: (node: DOMNode, index: number) => void): void;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Node type constants
|
|
95
|
+
*/
|
|
96
|
+
declare const NODE_TYPE: {
|
|
97
|
+
readonly ELEMENT_NODE: 1;
|
|
98
|
+
readonly TEXT_NODE: 3;
|
|
99
|
+
readonly DOCUMENT_NODE: 9;
|
|
100
|
+
readonly DOCUMENT_FRAGMENT_NODE: 11;
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* DOM Adapter interface
|
|
104
|
+
*
|
|
105
|
+
* Provides methods for creating and manipulating DOM structures
|
|
106
|
+
* in a platform-agnostic way.
|
|
107
|
+
*/
|
|
108
|
+
interface DOMAdapter {
|
|
109
|
+
/**
|
|
110
|
+
* Parse HTML string into a document fragment
|
|
111
|
+
*/
|
|
112
|
+
parseHTML(html: string): DOMDocumentFragment;
|
|
113
|
+
/**
|
|
114
|
+
* Serialize a node to HTML string
|
|
115
|
+
*/
|
|
116
|
+
serializeHTML(node: DOMNode | DOMDocumentFragment): string;
|
|
117
|
+
/**
|
|
118
|
+
* Create a new document for building DOM structures
|
|
119
|
+
*/
|
|
120
|
+
createDocument(): DOMDocument;
|
|
121
|
+
/**
|
|
122
|
+
* Check if this adapter is available in the current environment
|
|
123
|
+
*/
|
|
124
|
+
isAvailable(): boolean;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Type guard: check if node is an Element
|
|
128
|
+
*/
|
|
129
|
+
declare function isElement(node: DOMNode): node is DOMElement;
|
|
130
|
+
/**
|
|
131
|
+
* Type guard: check if node is a Text node
|
|
132
|
+
*/
|
|
133
|
+
declare function isTextNode(node: DOMNode): boolean;
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Scope of a format
|
|
137
|
+
*
|
|
138
|
+
* - inline: applies to text runs (bold, italic, link, color...)
|
|
139
|
+
* - block: applies to lines (header, list, blockquote...)
|
|
140
|
+
* - embed: non-text content (image, video, formula...)
|
|
141
|
+
*/
|
|
142
|
+
type FormatScope = 'inline' | 'block' | 'embed';
|
|
143
|
+
/**
|
|
144
|
+
* Result returned by Format.match() when an HTML element is recognized.
|
|
145
|
+
*/
|
|
146
|
+
interface FormatMatchResult<T = unknown> {
|
|
147
|
+
/** The embed value for Delta (e.g. URL string, boolean, etc.) */
|
|
148
|
+
value: T;
|
|
149
|
+
/** Optional attributes to attach to the op (e.g. alt, width, height) */
|
|
150
|
+
attributes?: AttributeMap;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Format interface with optional conversion methods.
|
|
154
|
+
*
|
|
155
|
+
* Three-level extensibility:
|
|
156
|
+
* - Level 1 (validate/normalize): format works in Delta, no conversion
|
|
157
|
+
* - Level 2 (render/match): HTML roundtrip — Delta ↔ HTML
|
|
158
|
+
* - Level 3 (toMarkdown/fromMarkdown): Markdown roundtrip — Delta ↔ Markdown
|
|
159
|
+
*
|
|
160
|
+
* @template T - The type of the attribute value
|
|
161
|
+
*/
|
|
162
|
+
interface Format<T = unknown> {
|
|
163
|
+
/**
|
|
164
|
+
* Name of the attribute in Delta
|
|
165
|
+
* Must be unique within a Registry
|
|
166
|
+
*/
|
|
167
|
+
readonly name: string;
|
|
168
|
+
/**
|
|
169
|
+
* Scope of the format
|
|
170
|
+
*/
|
|
171
|
+
readonly scope: FormatScope;
|
|
172
|
+
/**
|
|
173
|
+
* Normalize value to canonical form
|
|
174
|
+
*
|
|
175
|
+
* Examples:
|
|
176
|
+
* - 'red' → '#ff0000'
|
|
177
|
+
* - 'RGB(255,0,0)' → '#ff0000'
|
|
178
|
+
* - 7 (header) → 6 (clamped)
|
|
179
|
+
*
|
|
180
|
+
* @param value - The value to normalize
|
|
181
|
+
* @returns Normalized value
|
|
182
|
+
*/
|
|
183
|
+
normalize?(value: T): T;
|
|
184
|
+
/**
|
|
185
|
+
* Validate that a value is acceptable
|
|
186
|
+
*
|
|
187
|
+
* @param value - The value to validate
|
|
188
|
+
* @returns true if value is valid
|
|
189
|
+
*/
|
|
190
|
+
validate?(value: T): boolean;
|
|
191
|
+
/**
|
|
192
|
+
* Render Delta value to HTML string.
|
|
193
|
+
*
|
|
194
|
+
* Used by deltaToHtml for embed formats. If not provided,
|
|
195
|
+
* the converter falls back to built-in EMBED_RENDERERS config.
|
|
196
|
+
*
|
|
197
|
+
* @param value - The embed value (e.g. URL string)
|
|
198
|
+
* @param attributes - Op-level attributes (alt, width, height, etc.)
|
|
199
|
+
* @returns HTML string
|
|
200
|
+
*/
|
|
201
|
+
render?(value: T, attributes?: AttributeMap): string;
|
|
202
|
+
/**
|
|
203
|
+
* Match an HTML element and extract Delta embed value.
|
|
204
|
+
*
|
|
205
|
+
* Used by htmlToDelta to recognize custom elements.
|
|
206
|
+
* Return null if this element is not a match for this format.
|
|
207
|
+
*
|
|
208
|
+
* @param element - The DOM element to inspect
|
|
209
|
+
* @returns Match result with value and optional attributes, or null
|
|
210
|
+
*/
|
|
211
|
+
match?(element: DOMElement): FormatMatchResult<T> | null;
|
|
212
|
+
/**
|
|
213
|
+
* Render Delta value to Markdown string.
|
|
214
|
+
*
|
|
215
|
+
* Return null to fall back to HTML-in-Markdown (current behavior
|
|
216
|
+
* for embeds without native Markdown representation).
|
|
217
|
+
*
|
|
218
|
+
* @param value - The embed value
|
|
219
|
+
* @param attributes - Op-level attributes
|
|
220
|
+
* @returns Markdown string, or null for HTML fallback
|
|
221
|
+
*/
|
|
222
|
+
toMarkdown?(value: T, attributes?: AttributeMap): string | null;
|
|
223
|
+
/**
|
|
224
|
+
* Parse a Markdown AST node into a Delta embed value.
|
|
225
|
+
*
|
|
226
|
+
* Used by markdownToDelta to recognize custom Markdown patterns
|
|
227
|
+
* (e.g. image-like URLs, fenced code blocks with custom language).
|
|
228
|
+
*
|
|
229
|
+
* @param node - Markdown AST node (MDAST)
|
|
230
|
+
* @returns Match result with value and optional attributes, or null
|
|
231
|
+
*/
|
|
232
|
+
fromMarkdown?(node: unknown): FormatMatchResult<T> | null;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Helper type for creating format objects
|
|
236
|
+
*/
|
|
237
|
+
type FormatDefinition<T = unknown> = Format<T>;
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Registry of formats
|
|
241
|
+
*
|
|
242
|
+
* Manages a collection of Format definitions for validation,
|
|
243
|
+
* normalization, and sanitization of Delta attributes.
|
|
244
|
+
*
|
|
245
|
+
* @example
|
|
246
|
+
* ```typescript
|
|
247
|
+
* const registry = new Registry()
|
|
248
|
+
* .register(boldFormat)
|
|
249
|
+
* .register(italicFormat)
|
|
250
|
+
* .register(colorFormat);
|
|
251
|
+
*
|
|
252
|
+
* // Normalize attributes
|
|
253
|
+
* registry.normalize({ color: 'red' });
|
|
254
|
+
* // { color: '#ff0000' }
|
|
255
|
+
*
|
|
256
|
+
* // Validate attributes
|
|
257
|
+
* registry.validate({ header: 3 }); // true
|
|
258
|
+
* registry.validate({ header: 10 }); // false
|
|
259
|
+
* ```
|
|
260
|
+
*/
|
|
261
|
+
declare class Registry {
|
|
262
|
+
private formats;
|
|
263
|
+
/**
|
|
264
|
+
* Register a format or array of formats
|
|
265
|
+
*
|
|
266
|
+
* @param format - Format or array of formats to register
|
|
267
|
+
* @returns this for chaining
|
|
268
|
+
*/
|
|
269
|
+
register(format: Format): this;
|
|
270
|
+
register(formats: Format[]): this;
|
|
271
|
+
/**
|
|
272
|
+
* Get a format by name
|
|
273
|
+
*
|
|
274
|
+
* @param name - Format name
|
|
275
|
+
* @returns Format or undefined if not found
|
|
276
|
+
*/
|
|
277
|
+
get(name: string): Format | undefined;
|
|
278
|
+
/**
|
|
279
|
+
* Check if a format is registered
|
|
280
|
+
*
|
|
281
|
+
* @param name - Format name
|
|
282
|
+
* @returns true if format exists
|
|
283
|
+
*/
|
|
284
|
+
has(name: string): boolean;
|
|
285
|
+
/**
|
|
286
|
+
* Get all formats with a specific scope
|
|
287
|
+
*
|
|
288
|
+
* @param scope - Format scope to filter by
|
|
289
|
+
* @returns Array of formats with the given scope
|
|
290
|
+
*/
|
|
291
|
+
getByScope(scope: FormatScope): Format[];
|
|
292
|
+
/**
|
|
293
|
+
* Get all registered format names
|
|
294
|
+
*
|
|
295
|
+
* @returns Array of format names
|
|
296
|
+
*/
|
|
297
|
+
getNames(): string[];
|
|
298
|
+
/**
|
|
299
|
+
* Normalize all attributes using registered formats
|
|
300
|
+
*
|
|
301
|
+
* Applies normalize() for each attribute that has a registered format.
|
|
302
|
+
* Unknown attributes are passed through unchanged.
|
|
303
|
+
*
|
|
304
|
+
* @param attributes - Attributes to normalize
|
|
305
|
+
* @returns New object with normalized attributes
|
|
306
|
+
*/
|
|
307
|
+
normalize(attributes: AttributeMap | undefined): AttributeMap | undefined;
|
|
308
|
+
/**
|
|
309
|
+
* Validate all attributes
|
|
310
|
+
*
|
|
311
|
+
* @param attributes - Attributes to validate
|
|
312
|
+
* @returns true if all known attributes are valid
|
|
313
|
+
*/
|
|
314
|
+
validate(attributes: AttributeMap | undefined): boolean;
|
|
315
|
+
/**
|
|
316
|
+
* Sanitize attributes by removing invalid values
|
|
317
|
+
*
|
|
318
|
+
* Removes attributes that:
|
|
319
|
+
* - Are not registered (unknown formats)
|
|
320
|
+
* - Fail validation
|
|
321
|
+
*
|
|
322
|
+
* @param attributes - Attributes to sanitize
|
|
323
|
+
* @param removeUnknown - If true, remove unregistered attributes (default: true)
|
|
324
|
+
* @returns New object with only valid attributes
|
|
325
|
+
*/
|
|
326
|
+
sanitize(attributes: AttributeMap | undefined, removeUnknown?: boolean): AttributeMap | undefined;
|
|
327
|
+
/**
|
|
328
|
+
* Get the number of registered formats
|
|
329
|
+
*/
|
|
330
|
+
get size(): number;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Options for block rendering
|
|
335
|
+
*/
|
|
336
|
+
interface BlockRenderOptions {
|
|
337
|
+
/** Pretty-print HTML output */
|
|
338
|
+
pretty?: boolean;
|
|
339
|
+
/** Indentation level for pretty-print */
|
|
340
|
+
indent?: number;
|
|
341
|
+
/** How to interpret colWidths: percent (default) or pixel */
|
|
342
|
+
tableWidthMode?: 'percent' | 'pixel';
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Context injected by converters into BlockHandler methods.
|
|
346
|
+
*
|
|
347
|
+
* Solves cyclic dependencies: handlers live in schema layer,
|
|
348
|
+
* converters live in conversion layer. Converters pass themselves
|
|
349
|
+
* as callbacks via context — no direct imports between layers.
|
|
350
|
+
*/
|
|
351
|
+
interface BlockContext {
|
|
352
|
+
/** Format registry for attribute validation/normalization */
|
|
353
|
+
registry: Registry;
|
|
354
|
+
/** Render options */
|
|
355
|
+
options?: BlockRenderOptions;
|
|
356
|
+
/** Render nested Delta ops → HTML (injected by deltaToHtml) */
|
|
357
|
+
renderDelta?: (ops: Op[]) => string;
|
|
358
|
+
/** Parse HTML element → Delta ops (injected by htmlToDelta) */
|
|
359
|
+
parseElement?: (element: DOMElement) => Op[];
|
|
360
|
+
/**
|
|
361
|
+
* Op-level attributes from the Delta operation containing this block embed.
|
|
362
|
+
* Used by handlers that store visual properties (float, width, height, overflow)
|
|
363
|
+
* in op attributes rather than in block data (e.g. Inline-Box).
|
|
364
|
+
*/
|
|
365
|
+
opAttributes?: Record<string, unknown>;
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Generic handler for complex block embeds with nested Delta content.
|
|
369
|
+
*
|
|
370
|
+
* Block embeds use a single `block` key in Delta:
|
|
371
|
+
* `{ insert: { block: { type: "table", ... } } }`
|
|
372
|
+
*
|
|
373
|
+
* The `type` field dispatches to the appropriate BlockHandler
|
|
374
|
+
* via BlockHandlerRegistry.
|
|
375
|
+
*
|
|
376
|
+
* T includes `type` — data is stored as `{ block: T }` where T
|
|
377
|
+
* is the full object including `type`. No destructuring needed.
|
|
378
|
+
*
|
|
379
|
+
* @template T - Block data type (e.g. TableBlockData)
|
|
380
|
+
*/
|
|
381
|
+
interface BlockHandler<T = unknown> {
|
|
382
|
+
/** Unique block type — value of `type` field in block embed */
|
|
383
|
+
readonly type: string;
|
|
384
|
+
/** Semantic validation of block data (cells, colWidths, etc.) */
|
|
385
|
+
validate(data: T): boolean;
|
|
386
|
+
/** Delta → HTML (context.renderDelta for nested Delta) */
|
|
387
|
+
toHtml(data: T, context: BlockContext): string;
|
|
388
|
+
/** HTML element → block data (context.parseElement for cells) */
|
|
389
|
+
fromHtml(element: DOMElement, context: BlockContext): T | null;
|
|
390
|
+
/** Delta → Markdown (null = fallback to toHtml) */
|
|
391
|
+
toMarkdown?(data: T, context: BlockContext): string | null;
|
|
392
|
+
/** Markdown AST node → block data */
|
|
393
|
+
fromMarkdown?(node: unknown, context: BlockContext): T | null;
|
|
394
|
+
/** Normalize block data + recursive normalization of nested Deltas */
|
|
395
|
+
normalize?(data: T, registry: Registry): T;
|
|
396
|
+
/** Extract all nested Deltas from block */
|
|
397
|
+
getNestedDeltas?(data: T): Op[][];
|
|
398
|
+
/** Replace nested Deltas (immutable, returns new T) */
|
|
399
|
+
setNestedDeltas?(data: T, deltas: Op[][]): T;
|
|
400
|
+
compose?(base: T, change: T): T;
|
|
401
|
+
transform?(a: T, b: T, priority: boolean): T;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Registry for BlockHandler implementations.
|
|
406
|
+
*
|
|
407
|
+
* Separate from Registry (FormatRegistry) — different responsibilities:
|
|
408
|
+
* - Registry: attribute validation/normalization (key-value pairs, primitives)
|
|
409
|
+
* - BlockHandlerRegistry: block rendering/parsing (complex structures with nested Delta)
|
|
410
|
+
*
|
|
411
|
+
* Connected to converters via options:
|
|
412
|
+
* ```typescript
|
|
413
|
+
* deltaToHtml(delta, { registry, blockHandlers });
|
|
414
|
+
* htmlToDelta(html, { registry, blockHandlers });
|
|
415
|
+
* ```
|
|
416
|
+
*
|
|
417
|
+
* @example
|
|
418
|
+
* ```typescript
|
|
419
|
+
* const blockHandlers = new BlockHandlerRegistry()
|
|
420
|
+
* .register(tableBlockHandler);
|
|
421
|
+
*
|
|
422
|
+
* deltaToHtml(delta, { registry, blockHandlers });
|
|
423
|
+
* ```
|
|
424
|
+
*/
|
|
425
|
+
declare class BlockHandlerRegistry {
|
|
426
|
+
private handlers;
|
|
427
|
+
/**
|
|
428
|
+
* Register a block handler
|
|
429
|
+
*
|
|
430
|
+
* @param handler - BlockHandler to register
|
|
431
|
+
* @returns this for chaining
|
|
432
|
+
* @throws Error if handler with same type is already registered
|
|
433
|
+
*/
|
|
434
|
+
register(handler: BlockHandler): this;
|
|
435
|
+
/**
|
|
436
|
+
* Get a handler by block type
|
|
437
|
+
*
|
|
438
|
+
* @param type - Block type (e.g. "table")
|
|
439
|
+
* @returns BlockHandler or undefined if not found
|
|
440
|
+
*/
|
|
441
|
+
get(type: string): BlockHandler | undefined;
|
|
442
|
+
/**
|
|
443
|
+
* Check if a handler is registered for a block type
|
|
444
|
+
*
|
|
445
|
+
* @param type - Block type
|
|
446
|
+
* @returns true if handler exists
|
|
447
|
+
*/
|
|
448
|
+
has(type: string): boolean;
|
|
449
|
+
/**
|
|
450
|
+
* Get the number of registered handlers
|
|
451
|
+
*/
|
|
452
|
+
get size(): number;
|
|
453
|
+
/**
|
|
454
|
+
* Get all registered block type names
|
|
455
|
+
*/
|
|
456
|
+
getTypes(): string[];
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Cell alignment options
|
|
461
|
+
*/
|
|
462
|
+
type CellAlign = 'left' | 'center' | 'right';
|
|
463
|
+
/**
|
|
464
|
+
* Data for a single cell in an Extended Table.
|
|
465
|
+
*
|
|
466
|
+
* Every non-merged cell must have `ops` — a nested Delta (Op[]).
|
|
467
|
+
* Empty cells use `{ ops: [{ insert: "\n" }] }`.
|
|
468
|
+
*/
|
|
469
|
+
interface CellData {
|
|
470
|
+
/** Nested Delta content (full rich-text) */
|
|
471
|
+
ops: Op[];
|
|
472
|
+
/** Number of columns this cell spans (default: 1) */
|
|
473
|
+
colspan?: number;
|
|
474
|
+
/** Number of rows this cell spans (default: 1) */
|
|
475
|
+
rowspan?: number;
|
|
476
|
+
}
|
|
477
|
+
/**
|
|
478
|
+
* Extended Table block data.
|
|
479
|
+
*
|
|
480
|
+
* Stored in Delta as: `{ insert: { block: <TableBlockData> } }`
|
|
481
|
+
*
|
|
482
|
+
* All coordinates "r:c" within the grid MUST be present in `cells`.
|
|
483
|
+
* - `CellData` — cell with content
|
|
484
|
+
* - `null` — cell absorbed by neighbor's colspan/rowspan
|
|
485
|
+
* - Missing key — INVALID (validate() rejects)
|
|
486
|
+
*/
|
|
487
|
+
interface TableBlockData {
|
|
488
|
+
/** Block type discriminator */
|
|
489
|
+
type: 'table';
|
|
490
|
+
/** Number of header rows (default: 0) */
|
|
491
|
+
headerRows?: number;
|
|
492
|
+
/** Column widths (percentages by default) */
|
|
493
|
+
colWidths?: number[];
|
|
494
|
+
/** Column alignments */
|
|
495
|
+
colAligns?: (CellAlign | null)[];
|
|
496
|
+
/** Cells indexed by "row:col" */
|
|
497
|
+
cells: Record<string, CellData | null>;
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* BlockHandler implementation for Extended Table.
|
|
501
|
+
*
|
|
502
|
+
* Handles validation, HTML conversion, and nested Delta access.
|
|
503
|
+
* toHtml/fromHtml are implemented in E.3/E.4 stages.
|
|
504
|
+
*/
|
|
505
|
+
declare const tableBlockHandler: BlockHandler<TableBlockData>;
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Footnotes block data — a collection of footnote definitions.
|
|
509
|
+
*
|
|
510
|
+
* Stored in Delta as: `{ insert: { block: <FootnotesBlockData> } }`
|
|
511
|
+
*
|
|
512
|
+
* Each note is keyed by its string identifier (e.g. "1", "note", "my-ref").
|
|
513
|
+
* Values contain nested Delta content (rich-text).
|
|
514
|
+
*
|
|
515
|
+
* Placed at the end of the document, after all content.
|
|
516
|
+
*/
|
|
517
|
+
interface FootnotesBlockData {
|
|
518
|
+
/** Block type discriminator */
|
|
519
|
+
type: 'footnotes';
|
|
520
|
+
/** Map of footnote id → content (nested Delta ops) */
|
|
521
|
+
notes: Record<string, {
|
|
522
|
+
ops: Op[];
|
|
523
|
+
}>;
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* BlockHandler implementation for Footnotes.
|
|
527
|
+
*
|
|
528
|
+
* Handles a single block embed containing all footnote definitions.
|
|
529
|
+
* Each footnote has an id and nested Delta content.
|
|
530
|
+
*
|
|
531
|
+
* HTML: <section class="footnotes"><ol><li id="fn-{id}">...</li></ol></section>
|
|
532
|
+
* Markdown: [^id]: content
|
|
533
|
+
*/
|
|
534
|
+
declare const footnotesBlockHandler: BlockHandler<FootnotesBlockData>;
|
|
535
|
+
|
|
536
|
+
/** The 5 standard GitHub alert types */
|
|
537
|
+
declare const ALERT_TYPES: readonly ["note", "tip", "important", "warning", "caution"];
|
|
538
|
+
/** Union of valid alert types */
|
|
539
|
+
type AlertType = (typeof ALERT_TYPES)[number];
|
|
540
|
+
/**
|
|
541
|
+
* Alert / Admonition block data.
|
|
542
|
+
*
|
|
543
|
+
* Stored in Delta as: `{ insert: { block: <AlertBlockData> } }`
|
|
544
|
+
*
|
|
545
|
+
* GitHub-style alerts:
|
|
546
|
+
* ```markdown
|
|
547
|
+
* > [!NOTE]
|
|
548
|
+
* > Useful information.
|
|
549
|
+
* ```
|
|
550
|
+
*
|
|
551
|
+
* HTML:
|
|
552
|
+
* ```html
|
|
553
|
+
* <div class="markdown-alert markdown-alert-note">
|
|
554
|
+
* <p class="markdown-alert-title">Note</p>
|
|
555
|
+
* <p>Useful information.</p>
|
|
556
|
+
* </div>
|
|
557
|
+
* ```
|
|
558
|
+
*/
|
|
559
|
+
interface AlertBlockData {
|
|
560
|
+
/** Block type discriminator */
|
|
561
|
+
type: 'alert';
|
|
562
|
+
/** Alert variant (note, tip, important, warning, caution) */
|
|
563
|
+
alertType: AlertType;
|
|
564
|
+
/** Nested Delta content (rich text) */
|
|
565
|
+
content: {
|
|
566
|
+
ops: Op[];
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* BlockHandler implementation for Alerts / Admonitions.
|
|
571
|
+
*
|
|
572
|
+
* Handles GitHub-style alerts (5 types: note, tip, important, warning, caution).
|
|
573
|
+
* Each alert contains nested Delta content (rich text).
|
|
574
|
+
*
|
|
575
|
+
* HTML: `<div class="markdown-alert markdown-alert-{type}"><p class="markdown-alert-title">{Type}</p>...</div>`
|
|
576
|
+
* Markdown: `> [!TYPE]\n> content`
|
|
577
|
+
*/
|
|
578
|
+
declare const alertBlockHandler: BlockHandler<AlertBlockData>;
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Columns Layout block data.
|
|
582
|
+
*
|
|
583
|
+
* Stored in Delta as: `{ insert: { block: <ColumnsBlockData> } }`
|
|
584
|
+
*
|
|
585
|
+
* Each column contains a full nested Delta (rich text, embeds, nested blocks).
|
|
586
|
+
*
|
|
587
|
+
* HTML:
|
|
588
|
+
* ```html
|
|
589
|
+
* <div class="columns columns-2">
|
|
590
|
+
* <div class="column"><p>Column 1</p></div>
|
|
591
|
+
* <div class="column"><p>Column 2</p></div>
|
|
592
|
+
* </div>
|
|
593
|
+
* ```
|
|
594
|
+
*
|
|
595
|
+
* With custom widths:
|
|
596
|
+
* ```html
|
|
597
|
+
* <div class="columns columns-2" style="grid-template-columns: 30% 70%">
|
|
598
|
+
* <div class="column"><p>Sidebar</p></div>
|
|
599
|
+
* <div class="column"><p>Main content</p></div>
|
|
600
|
+
* </div>
|
|
601
|
+
* ```
|
|
602
|
+
*
|
|
603
|
+
* Markdown: no native equivalent → toMarkdown returns null → HTML fallback.
|
|
604
|
+
*
|
|
605
|
+
* Resize-ready: `widths` for per-column resize (future scrider-editor),
|
|
606
|
+
* `width`/`height` in op attributes for overall dimensions.
|
|
607
|
+
*/
|
|
608
|
+
interface ColumnsBlockData {
|
|
609
|
+
/** Block type discriminator */
|
|
610
|
+
type: 'columns';
|
|
611
|
+
/** Column contents — array of nested Deltas */
|
|
612
|
+
columns: {
|
|
613
|
+
ops: Op[];
|
|
614
|
+
}[];
|
|
615
|
+
/** Optional: column widths in percent (sum ≈ 100). Default: equal (CSS 1fr each) */
|
|
616
|
+
widths?: number[];
|
|
617
|
+
}
|
|
618
|
+
/**
|
|
619
|
+
* BlockHandler implementation for Columns Layout.
|
|
620
|
+
*
|
|
621
|
+
* Multi-column layout with nested Delta content in each column.
|
|
622
|
+
* Analogous to Alert (nested Delta) but with an array of columns.
|
|
623
|
+
*
|
|
624
|
+
* HTML: `<div class="columns columns-N" [style="grid-template-columns: W1% W2%"]>
|
|
625
|
+
* <div class="column">...</div>...
|
|
626
|
+
* </div>`
|
|
627
|
+
* Markdown: no equivalent → toMarkdown returns null → HTML fallback
|
|
628
|
+
*/
|
|
629
|
+
declare const columnsBlockHandler: BlockHandler<ColumnsBlockData>;
|
|
630
|
+
|
|
631
|
+
/** Valid float positions for Inline-Box */
|
|
632
|
+
declare const BOX_FLOAT_VALUES: readonly ["left", "right", "center"];
|
|
633
|
+
/** Valid overflow modes for Inline-Box */
|
|
634
|
+
declare const BOX_OVERFLOW_VALUES: readonly ["auto", "hidden", "visible"];
|
|
635
|
+
/** Union of valid float positions */
|
|
636
|
+
type BoxFloat = (typeof BOX_FLOAT_VALUES)[number];
|
|
637
|
+
/** Union of valid overflow modes */
|
|
638
|
+
type BoxOverflow = (typeof BOX_OVERFLOW_VALUES)[number];
|
|
639
|
+
/**
|
|
640
|
+
* Inline-Box block data.
|
|
641
|
+
*
|
|
642
|
+
* Stored in Delta as: `{ insert: { block: <BoxBlockData> }, attributes: { float, width, height, overflow } }`
|
|
643
|
+
*
|
|
644
|
+
* A float container with nested Delta content and text wrapping.
|
|
645
|
+
* Visual properties (float, width, height, overflow) are stored in op attributes,
|
|
646
|
+
* not in block data — clean separation of semantics vs presentation.
|
|
647
|
+
*
|
|
648
|
+
* HTML (float left/right):
|
|
649
|
+
* ```html
|
|
650
|
+
* <div class="inline-box" data-float="left" data-overflow="auto"
|
|
651
|
+
* style="width: 200px; height: 300px;">
|
|
652
|
+
* <p>Rich content</p>
|
|
653
|
+
* </div>
|
|
654
|
+
* ```
|
|
655
|
+
*
|
|
656
|
+
* HTML (center — no wrapping):
|
|
657
|
+
* ```html
|
|
658
|
+
* <div class="inline-box" data-float="center" data-overflow="auto"
|
|
659
|
+
* style="width: 200px; height: 300px;">
|
|
660
|
+
* <p>Content</p>
|
|
661
|
+
* </div>
|
|
662
|
+
* ```
|
|
663
|
+
*
|
|
664
|
+
* Markdown: no native equivalent → toMarkdown returns null → HTML fallback.
|
|
665
|
+
*/
|
|
666
|
+
interface BoxBlockData {
|
|
667
|
+
/** Block type discriminator */
|
|
668
|
+
type: 'box';
|
|
669
|
+
/** Nested Delta content (rich text) */
|
|
670
|
+
content: {
|
|
671
|
+
ops: Op[];
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
* Op-level attributes for box block embed.
|
|
676
|
+
* Stored in `op.attributes`, not in block data.
|
|
677
|
+
*/
|
|
678
|
+
interface BoxOpAttributes {
|
|
679
|
+
/** Float position: left/right = text wrapping, center = no wrapping */
|
|
680
|
+
float?: BoxFloat;
|
|
681
|
+
/** Container width (e.g. "200px", "30%") */
|
|
682
|
+
width?: string;
|
|
683
|
+
/** Container height (e.g. "300px", "auto") */
|
|
684
|
+
height?: string;
|
|
685
|
+
/** Overflow behavior when content exceeds dimensions */
|
|
686
|
+
overflow?: BoxOverflow;
|
|
687
|
+
}
|
|
688
|
+
/**
|
|
689
|
+
* BlockHandler implementation for Inline-Box (Float Container).
|
|
690
|
+
*
|
|
691
|
+
* A container with nested Delta content that supports float positioning
|
|
692
|
+
* and text wrapping. Like Alert (single nested Delta), but visual
|
|
693
|
+
* properties are stored in op attributes, not in block data.
|
|
694
|
+
*
|
|
695
|
+
* HTML: `<div class="inline-box" data-float="F" data-overflow="O" style="width: W; height: H">...</div>`
|
|
696
|
+
* Markdown: no equivalent → toMarkdown returns null → HTML fallback
|
|
697
|
+
*/
|
|
698
|
+
declare const boxBlockHandler: BlockHandler<BoxBlockData>;
|
|
699
|
+
/**
|
|
700
|
+
* Extract op attributes for box from an HTML element.
|
|
701
|
+
*
|
|
702
|
+
* Used by html-to-delta intercept to reconstruct op attributes
|
|
703
|
+
* (float, width, height, overflow) from the HTML representation.
|
|
704
|
+
*/
|
|
705
|
+
declare function extractBoxOpAttributes(element: DOMElement): BoxOpAttributes;
|
|
706
|
+
|
|
707
|
+
/**
|
|
708
|
+
* All default inline formats
|
|
709
|
+
*/
|
|
710
|
+
declare const defaultInlineFormats: Format[];
|
|
711
|
+
/**
|
|
712
|
+
* All default block formats
|
|
713
|
+
*/
|
|
714
|
+
declare const defaultBlockFormats: Format[];
|
|
715
|
+
/**
|
|
716
|
+
* All default embed formats
|
|
717
|
+
*/
|
|
718
|
+
declare const defaultEmbedFormats: Format[];
|
|
719
|
+
/**
|
|
720
|
+
* All default formats combined
|
|
721
|
+
*/
|
|
722
|
+
declare const defaultFormats: Format[];
|
|
723
|
+
/**
|
|
724
|
+
* Create a Registry with all default formats registered
|
|
725
|
+
*
|
|
726
|
+
* @returns Registry with standard formats
|
|
727
|
+
*
|
|
728
|
+
* @example
|
|
729
|
+
* ```typescript
|
|
730
|
+
* const registry = createDefaultRegistry();
|
|
731
|
+
* registry.normalize({ color: 'red' }); // { color: '#ff0000' }
|
|
732
|
+
* ```
|
|
733
|
+
*/
|
|
734
|
+
declare function createDefaultRegistry(): Registry;
|
|
735
|
+
/**
|
|
736
|
+
* Create a BlockHandlerRegistry with default block handlers
|
|
737
|
+
*
|
|
738
|
+
* Includes:
|
|
739
|
+
* - tableBlockHandler (Extended Table)
|
|
740
|
+
* - footnotesBlockHandler (Footnotes)
|
|
741
|
+
* - alertBlockHandler (Alerts/Admonitions)
|
|
742
|
+
* - columnsBlockHandler (Columns Layout)
|
|
743
|
+
* - boxBlockHandler (Inline-Box / Float Container)
|
|
744
|
+
*
|
|
745
|
+
* @returns BlockHandlerRegistry with default handlers
|
|
746
|
+
*
|
|
747
|
+
* @example
|
|
748
|
+
* ```typescript
|
|
749
|
+
* const blockHandlers = createDefaultBlockHandlers();
|
|
750
|
+
* blockHandlers.has('table'); // true
|
|
751
|
+
* blockHandlers.has('footnotes'); // true
|
|
752
|
+
* blockHandlers.has('alert'); // true
|
|
753
|
+
* blockHandlers.has('columns'); // true
|
|
754
|
+
* blockHandlers.has('box'); // true
|
|
755
|
+
* ```
|
|
756
|
+
*/
|
|
757
|
+
declare function createDefaultBlockHandlers(): BlockHandlerRegistry;
|
|
758
|
+
|
|
759
|
+
/**
|
|
760
|
+
* Background color format
|
|
761
|
+
*
|
|
762
|
+
* Delta: { insert: "text", attributes: { background: "#ff0000" } }
|
|
763
|
+
*
|
|
764
|
+
* Normalizes all color formats (rgb, named, etc.) to lowercase hex (#rrggbb)
|
|
765
|
+
*/
|
|
766
|
+
declare const backgroundFormat: Format<string>;
|
|
767
|
+
|
|
768
|
+
/**
|
|
769
|
+
* Bold format
|
|
770
|
+
*
|
|
771
|
+
* Delta: { insert: "text", attributes: { bold: true } }
|
|
772
|
+
*/
|
|
773
|
+
declare const boldFormat: Format<boolean>;
|
|
774
|
+
|
|
775
|
+
/**
|
|
776
|
+
* Inline code format
|
|
777
|
+
*
|
|
778
|
+
* Delta: { insert: "text", attributes: { code: true } }
|
|
779
|
+
*/
|
|
780
|
+
declare const codeFormat: Format<boolean>;
|
|
781
|
+
|
|
782
|
+
/**
|
|
783
|
+
* Text color format
|
|
784
|
+
*
|
|
785
|
+
* Delta: { insert: "text", attributes: { color: "#ff0000" } }
|
|
786
|
+
*
|
|
787
|
+
* Normalizes all color formats (rgb, named, etc.) to lowercase hex (#rrggbb)
|
|
788
|
+
*/
|
|
789
|
+
declare const colorFormat: Format<string>;
|
|
790
|
+
|
|
791
|
+
/**
|
|
792
|
+
* Italic format
|
|
793
|
+
*
|
|
794
|
+
* Delta: { insert: "text", attributes: { italic: true } }
|
|
795
|
+
*/
|
|
796
|
+
declare const italicFormat: Format<boolean>;
|
|
797
|
+
|
|
798
|
+
/**
|
|
799
|
+
* Keyboard input format
|
|
800
|
+
*
|
|
801
|
+
* Delta: { insert: "text", attributes: { kbd: true } }
|
|
802
|
+
* HTML: <kbd>text</kbd>
|
|
803
|
+
* Markdown: <kbd>text</kbd> (inline HTML)
|
|
804
|
+
*/
|
|
805
|
+
declare const kbdFormat: Format<boolean>;
|
|
806
|
+
|
|
807
|
+
/**
|
|
808
|
+
* Link format
|
|
809
|
+
*
|
|
810
|
+
* Delta: { insert: "text", attributes: { link: "https://example.com" } }
|
|
811
|
+
*
|
|
812
|
+
* Supports:
|
|
813
|
+
* - Absolute URLs (http://, https://)
|
|
814
|
+
* - Relative URLs (/path, ./path, ../path)
|
|
815
|
+
* - Protocol-relative URLs (//example.com)
|
|
816
|
+
* - mailto: and tel: links
|
|
817
|
+
*/
|
|
818
|
+
declare const linkFormat: Format<string>;
|
|
819
|
+
|
|
820
|
+
/**
|
|
821
|
+
* Mark (highlight) format
|
|
822
|
+
*
|
|
823
|
+
* Delta: { insert: "text", attributes: { mark: true } }
|
|
824
|
+
* HTML: <mark>text</mark>
|
|
825
|
+
*/
|
|
826
|
+
declare const markFormat: Format<boolean>;
|
|
827
|
+
|
|
828
|
+
/**
|
|
829
|
+
* Strikethrough format
|
|
830
|
+
*
|
|
831
|
+
* Delta: { insert: "text", attributes: { strike: true } }
|
|
832
|
+
*/
|
|
833
|
+
declare const strikeFormat: Format<boolean>;
|
|
834
|
+
|
|
835
|
+
/**
|
|
836
|
+
* Subscript format
|
|
837
|
+
*
|
|
838
|
+
* Delta: { insert: "text", attributes: { subscript: true } }
|
|
839
|
+
* HTML: <sub>text</sub>
|
|
840
|
+
*/
|
|
841
|
+
declare const subscriptFormat: Format<boolean>;
|
|
842
|
+
|
|
843
|
+
/**
|
|
844
|
+
* Superscript format
|
|
845
|
+
*
|
|
846
|
+
* Delta: { insert: "text", attributes: { superscript: true } }
|
|
847
|
+
* HTML: <sup>text</sup>
|
|
848
|
+
*/
|
|
849
|
+
declare const superscriptFormat: Format<boolean>;
|
|
850
|
+
|
|
851
|
+
/**
|
|
852
|
+
* Underline format
|
|
853
|
+
*
|
|
854
|
+
* Delta: { insert: "text", attributes: { underline: true } }
|
|
855
|
+
*/
|
|
856
|
+
declare const underlineFormat: Format<boolean>;
|
|
857
|
+
|
|
858
|
+
/**
|
|
859
|
+
* Valid alignment values
|
|
860
|
+
*/
|
|
861
|
+
type AlignType = 'left' | 'center' | 'right' | 'justify';
|
|
862
|
+
/**
|
|
863
|
+
* Text alignment format
|
|
864
|
+
*
|
|
865
|
+
* Delta: { insert: "\n", attributes: { align: "center" } }
|
|
866
|
+
*/
|
|
867
|
+
declare const alignFormat: Format<AlignType>;
|
|
868
|
+
|
|
869
|
+
/**
|
|
870
|
+
* Blockquote format
|
|
871
|
+
*
|
|
872
|
+
* Delta: { insert: "\n", attributes: { blockquote: true } }
|
|
873
|
+
*/
|
|
874
|
+
declare const blockquoteFormat: Format<boolean>;
|
|
875
|
+
|
|
876
|
+
/**
|
|
877
|
+
* Code block format
|
|
878
|
+
*
|
|
879
|
+
* Delta: { insert: "\n", attributes: { "code-block": true } }
|
|
880
|
+
* Delta: { insert: "\n", attributes: { "code-block": "javascript" } }
|
|
881
|
+
*
|
|
882
|
+
* Value can be:
|
|
883
|
+
* - true: generic code block
|
|
884
|
+
* - string: language identifier for syntax highlighting
|
|
885
|
+
*/
|
|
886
|
+
declare const codeBlockFormat: Format<boolean | string>;
|
|
887
|
+
|
|
888
|
+
/**
|
|
889
|
+
* Header format (h1-h6)
|
|
890
|
+
*
|
|
891
|
+
* Delta: { insert: "\n", attributes: { header: 1 } }
|
|
892
|
+
*
|
|
893
|
+
* Values: 1-6 (corresponding to h1-h6)
|
|
894
|
+
*/
|
|
895
|
+
declare const headerFormat: Format<number>;
|
|
896
|
+
|
|
897
|
+
/**
|
|
898
|
+
* Header ID format — optional custom anchor id for headings
|
|
899
|
+
*
|
|
900
|
+
* Delta: { insert: "\n", attributes: { header: 2, "header-id": "getting-started" } }
|
|
901
|
+
*
|
|
902
|
+
* When present, the heading gets this exact id in HTML output.
|
|
903
|
+
* When absent, id is computed via slugify(text) at render time (if anchorLinks is enabled).
|
|
904
|
+
*
|
|
905
|
+
* Markdown: ## Title {#custom-id}
|
|
906
|
+
*/
|
|
907
|
+
declare const headerIdFormat: Format<string>;
|
|
908
|
+
|
|
909
|
+
/**
|
|
910
|
+
* Indent format
|
|
911
|
+
*
|
|
912
|
+
* Delta: { insert: "\n", attributes: { indent: 1 } }
|
|
913
|
+
*
|
|
914
|
+
* Values: 0-8 (0 = no indent)
|
|
915
|
+
*/
|
|
916
|
+
declare const indentFormat: Format<number>;
|
|
917
|
+
|
|
918
|
+
/**
|
|
919
|
+
* Valid list types
|
|
920
|
+
*/
|
|
921
|
+
type ListType = 'ordered' | 'bullet' | 'checked' | 'unchecked';
|
|
922
|
+
/**
|
|
923
|
+
* List format
|
|
924
|
+
*
|
|
925
|
+
* Delta: { insert: "\n", attributes: { list: "ordered" } }
|
|
926
|
+
* Delta: { insert: "\n", attributes: { list: "bullet" } }
|
|
927
|
+
* Delta: { insert: "\n", attributes: { list: "checked" } }
|
|
928
|
+
* Delta: { insert: "\n", attributes: { list: "unchecked" } }
|
|
929
|
+
*/
|
|
930
|
+
declare const listFormat: Format<ListType>;
|
|
931
|
+
|
|
932
|
+
/**
|
|
933
|
+
* Table row index format
|
|
934
|
+
*
|
|
935
|
+
* Delta: { insert: "\n", attributes: { "table-row": 0 } }
|
|
936
|
+
*/
|
|
937
|
+
declare const tableRowFormat: Format<number>;
|
|
938
|
+
|
|
939
|
+
/**
|
|
940
|
+
* Table column index format
|
|
941
|
+
*
|
|
942
|
+
* Delta: { insert: "\n", attributes: { "table-col": 0 } }
|
|
943
|
+
*/
|
|
944
|
+
declare const tableColFormat: Format<number>;
|
|
945
|
+
|
|
946
|
+
/**
|
|
947
|
+
* Table header cell format
|
|
948
|
+
*
|
|
949
|
+
* Delta: { insert: "\n", attributes: { "table-header": true } }
|
|
950
|
+
*
|
|
951
|
+
* When true, the cell is rendered as <th> inside <thead>.
|
|
952
|
+
*/
|
|
953
|
+
declare const tableHeaderFormat: Format<boolean>;
|
|
954
|
+
|
|
955
|
+
/**
|
|
956
|
+
* Valid table column alignment values
|
|
957
|
+
*/
|
|
958
|
+
type TableColAlignType = 'left' | 'center' | 'right';
|
|
959
|
+
/**
|
|
960
|
+
* Table column alignment format
|
|
961
|
+
*
|
|
962
|
+
* Delta: { insert: "\n", attributes: { "table-col-align": "center" } }
|
|
963
|
+
*
|
|
964
|
+
* Controls text-align of the column (rendered via style on <th>/<td>).
|
|
965
|
+
* Compatible with GFM alignment syntax (:---|:---:|---:).
|
|
966
|
+
*/
|
|
967
|
+
declare const tableColAlignFormat: Format<TableColAlignType>;
|
|
968
|
+
|
|
969
|
+
/**
|
|
970
|
+
* Block embed format — structural validation for complex block embeds.
|
|
971
|
+
*
|
|
972
|
+
* Delta: `{ insert: { block: { type: "table", ... } } }`
|
|
973
|
+
*
|
|
974
|
+
* This is the first level of two-level validation:
|
|
975
|
+
* 1. blockFormat.validate() — structural: is it an object with `type`?
|
|
976
|
+
* 2. BlockHandlerRegistry.get(type).validate() — semantic: is it a valid table?
|
|
977
|
+
*
|
|
978
|
+
* The `block` key is a **category**, not "just another embed".
|
|
979
|
+
* It signals to converters and OT layer: "nested structure, needs special handling".
|
|
980
|
+
*/
|
|
981
|
+
declare const blockFormat: Format<Record<string, unknown>>;
|
|
982
|
+
|
|
983
|
+
/**
|
|
984
|
+
* Divider (Horizontal Rule) embed format
|
|
985
|
+
*
|
|
986
|
+
* Delta: { insert: { divider: true } }
|
|
987
|
+
* HTML: <hr>
|
|
988
|
+
* Markdown: ---
|
|
989
|
+
*
|
|
990
|
+
* Value is always `true` (no additional data needed)
|
|
991
|
+
*/
|
|
992
|
+
declare const dividerFormat: Format<boolean>;
|
|
993
|
+
|
|
994
|
+
/**
|
|
995
|
+
* Footnote reference embed format
|
|
996
|
+
*
|
|
997
|
+
* Delta: { insert: { "footnote-ref": "1" } }
|
|
998
|
+
*
|
|
999
|
+
* Value is the footnote identifier string (e.g. "1", "note", "my-ref").
|
|
1000
|
+
* Rendered as superscript link in HTML: <sup class="footnote-ref"><a href="#fn-1">1</a></sup>
|
|
1001
|
+
* Markdown: [^1]
|
|
1002
|
+
*/
|
|
1003
|
+
declare const footnoteRefFormat: Format<string>;
|
|
1004
|
+
|
|
1005
|
+
/**
|
|
1006
|
+
* Formula (LaTeX) embed format
|
|
1007
|
+
*
|
|
1008
|
+
* Delta: { insert: { formula: "E = mc^2" } }
|
|
1009
|
+
*
|
|
1010
|
+
* Value is LaTeX string
|
|
1011
|
+
*/
|
|
1012
|
+
declare const formulaFormat: Format<string>;
|
|
1013
|
+
|
|
1014
|
+
/**
|
|
1015
|
+
* Image embed format
|
|
1016
|
+
*
|
|
1017
|
+
* Delta: { insert: { image: "https://example.com/image.png" } }
|
|
1018
|
+
*
|
|
1019
|
+
* Value is the image URL (http, https, data URI, or relative path)
|
|
1020
|
+
*/
|
|
1021
|
+
declare const imageFormat: Format<string>;
|
|
1022
|
+
|
|
1023
|
+
/**
|
|
1024
|
+
* Video embed format
|
|
1025
|
+
*
|
|
1026
|
+
* Delta: { insert: { video: "https://youtube.com/watch?v=..." } }
|
|
1027
|
+
*
|
|
1028
|
+
* Value is the video URL
|
|
1029
|
+
*/
|
|
1030
|
+
declare const videoFormat: Format<string>;
|
|
1031
|
+
|
|
1032
|
+
/**
|
|
1033
|
+
* Convert any color format to lowercase hex (#rrggbb)
|
|
1034
|
+
*
|
|
1035
|
+
* Supports:
|
|
1036
|
+
* - Hex: #rgb, #rrggbb, #rrggbbaa
|
|
1037
|
+
* - RGB: rgb(r, g, b), rgb(r g b)
|
|
1038
|
+
* - RGBA: rgba(r, g, b, a), rgba(r g b / a)
|
|
1039
|
+
* - Named colors: red, blue, etc.
|
|
1040
|
+
*
|
|
1041
|
+
* @param value - Color value to convert
|
|
1042
|
+
* @returns Lowercase hex color (#rrggbb) or original value if not recognized
|
|
1043
|
+
*/
|
|
1044
|
+
declare function toHexColor(value: string): string;
|
|
1045
|
+
/**
|
|
1046
|
+
* Check if a value is a valid hex color
|
|
1047
|
+
*
|
|
1048
|
+
* @param value - Value to check
|
|
1049
|
+
* @returns true if valid hex color (#rrggbb or #rgb)
|
|
1050
|
+
*/
|
|
1051
|
+
declare function isValidHexColor(value: string): boolean;
|
|
1052
|
+
/**
|
|
1053
|
+
* Check if a value is a valid color (hex, rgb, rgba, or named)
|
|
1054
|
+
*
|
|
1055
|
+
* @param value - Value to check
|
|
1056
|
+
* @returns true if valid color
|
|
1057
|
+
*/
|
|
1058
|
+
declare function isValidColor(value: string): boolean;
|
|
1059
|
+
/**
|
|
1060
|
+
* Get list of all named colors
|
|
1061
|
+
*/
|
|
1062
|
+
declare function getNamedColors(): string[];
|
|
1063
|
+
|
|
1064
|
+
/**
|
|
1065
|
+
* Browser DOM Adapter
|
|
1066
|
+
*
|
|
1067
|
+
* Uses native browser DOM APIs for HTML parsing and serialization.
|
|
1068
|
+
* Only available in browser environments.
|
|
1069
|
+
*/
|
|
1070
|
+
|
|
1071
|
+
/**
|
|
1072
|
+
* Browser DOM Adapter implementation
|
|
1073
|
+
*
|
|
1074
|
+
* Uses native browser APIs:
|
|
1075
|
+
* - DOMParser for parsing HTML
|
|
1076
|
+
* - Element.outerHTML for serialization
|
|
1077
|
+
*/
|
|
1078
|
+
declare class BrowserDOMAdapter implements DOMAdapter {
|
|
1079
|
+
/**
|
|
1080
|
+
* Parse HTML string into a document fragment
|
|
1081
|
+
*
|
|
1082
|
+
* Uses a template element to parse arbitrary HTML safely.
|
|
1083
|
+
*/
|
|
1084
|
+
parseHTML(html: string): DOMDocumentFragment;
|
|
1085
|
+
/**
|
|
1086
|
+
* Serialize a node to HTML string
|
|
1087
|
+
*/
|
|
1088
|
+
serializeHTML(node: DOMNode | DOMDocumentFragment): string;
|
|
1089
|
+
/**
|
|
1090
|
+
* Create a new document for building DOM structures
|
|
1091
|
+
*/
|
|
1092
|
+
createDocument(): DOMDocument;
|
|
1093
|
+
/**
|
|
1094
|
+
* Check if browser DOM APIs are available
|
|
1095
|
+
*/
|
|
1096
|
+
isAvailable(): boolean;
|
|
1097
|
+
}
|
|
1098
|
+
/**
|
|
1099
|
+
* Singleton instance of browser adapter
|
|
1100
|
+
*/
|
|
1101
|
+
declare const browserAdapter: BrowserDOMAdapter;
|
|
1102
|
+
|
|
1103
|
+
/**
|
|
1104
|
+
* Node.js DOM Adapter
|
|
1105
|
+
*
|
|
1106
|
+
* Uses jsdom for HTML parsing and serialization in Node.js environment.
|
|
1107
|
+
*/
|
|
1108
|
+
|
|
1109
|
+
/**
|
|
1110
|
+
* Node.js DOM Adapter implementation
|
|
1111
|
+
*
|
|
1112
|
+
* Uses jsdom for DOM operations in Node.js environment.
|
|
1113
|
+
* jsdom is loaded lazily to avoid issues in browser bundles.
|
|
1114
|
+
*/
|
|
1115
|
+
declare class NodeDOMAdapter implements DOMAdapter {
|
|
1116
|
+
private jsdom;
|
|
1117
|
+
/**
|
|
1118
|
+
* Parse HTML string into a document fragment
|
|
1119
|
+
*/
|
|
1120
|
+
parseHTML(html: string): DOMDocumentFragment;
|
|
1121
|
+
/**
|
|
1122
|
+
* Serialize a node to HTML string
|
|
1123
|
+
*/
|
|
1124
|
+
serializeHTML(node: DOMNode | DOMDocumentFragment): string;
|
|
1125
|
+
/**
|
|
1126
|
+
* Create a new document for building DOM structures
|
|
1127
|
+
*/
|
|
1128
|
+
createDocument(): DOMDocument;
|
|
1129
|
+
/**
|
|
1130
|
+
* Check if jsdom is available
|
|
1131
|
+
*/
|
|
1132
|
+
isAvailable(): boolean;
|
|
1133
|
+
/**
|
|
1134
|
+
* Initialize the adapter with jsdom (async)
|
|
1135
|
+
*
|
|
1136
|
+
* Call this before using the adapter if you want to handle
|
|
1137
|
+
* loading errors gracefully.
|
|
1138
|
+
*/
|
|
1139
|
+
initialize(): Promise<void>;
|
|
1140
|
+
/**
|
|
1141
|
+
* Get or create jsdom instance (sync, throws if not available)
|
|
1142
|
+
*/
|
|
1143
|
+
private getOrCreateJsdom;
|
|
1144
|
+
}
|
|
1145
|
+
/**
|
|
1146
|
+
* Singleton instance of Node adapter
|
|
1147
|
+
*/
|
|
1148
|
+
declare const nodeAdapter: NodeDOMAdapter;
|
|
1149
|
+
|
|
1150
|
+
/**
|
|
1151
|
+
* DOM Adapters
|
|
1152
|
+
*
|
|
1153
|
+
* Platform-agnostic DOM manipulation for HTML ↔ Delta conversion.
|
|
1154
|
+
*/
|
|
1155
|
+
|
|
1156
|
+
/**
|
|
1157
|
+
* Get the appropriate DOM adapter for the current environment
|
|
1158
|
+
*
|
|
1159
|
+
* - In browser: returns BrowserDOMAdapter (native DOM)
|
|
1160
|
+
* - In Node.js: returns NodeDOMAdapter (jsdom)
|
|
1161
|
+
*
|
|
1162
|
+
* @returns The appropriate DOM adapter
|
|
1163
|
+
* @throws Error if no adapter is available
|
|
1164
|
+
*/
|
|
1165
|
+
declare function getAdapter(): DOMAdapter;
|
|
1166
|
+
/**
|
|
1167
|
+
* Check if any DOM adapter is available
|
|
1168
|
+
*/
|
|
1169
|
+
declare function isAdapterAvailable(): boolean;
|
|
1170
|
+
|
|
1171
|
+
/**
|
|
1172
|
+
* Delta Sanitization
|
|
1173
|
+
*
|
|
1174
|
+
* Cleans Delta by removing unknown attributes, validating values,
|
|
1175
|
+
* and normalizing through Registry.
|
|
1176
|
+
*/
|
|
1177
|
+
|
|
1178
|
+
/**
|
|
1179
|
+
* Options for sanitizeDelta
|
|
1180
|
+
*/
|
|
1181
|
+
interface SanitizeOptions {
|
|
1182
|
+
/**
|
|
1183
|
+
* Remove attributes not registered in the registry
|
|
1184
|
+
* @default true
|
|
1185
|
+
*/
|
|
1186
|
+
removeUnknown?: boolean;
|
|
1187
|
+
/**
|
|
1188
|
+
* Normalize attribute values (e.g., color: 'red' → '#ff0000')
|
|
1189
|
+
* @default true
|
|
1190
|
+
*/
|
|
1191
|
+
normalize?: boolean;
|
|
1192
|
+
/**
|
|
1193
|
+
* Remove operations with invalid embed values
|
|
1194
|
+
* @default false
|
|
1195
|
+
*/
|
|
1196
|
+
removeInvalidEmbeds?: boolean;
|
|
1197
|
+
/**
|
|
1198
|
+
* List of embed types that are allowed (if not set, all registered are allowed)
|
|
1199
|
+
*/
|
|
1200
|
+
allowedEmbeds?: string[];
|
|
1201
|
+
}
|
|
1202
|
+
/**
|
|
1203
|
+
* Sanitize a Delta using a Registry
|
|
1204
|
+
*
|
|
1205
|
+
* Performs the following operations:
|
|
1206
|
+
* 1. Removes attributes not registered in the registry (if removeUnknown=true)
|
|
1207
|
+
* 2. Removes attributes with invalid values
|
|
1208
|
+
* 3. Normalizes attribute values (if normalize=true)
|
|
1209
|
+
* 4. Optionally removes invalid embed operations
|
|
1210
|
+
*
|
|
1211
|
+
* @param delta - The Delta to sanitize
|
|
1212
|
+
* @param registry - The Registry to use for validation/normalization
|
|
1213
|
+
* @param options - Sanitization options
|
|
1214
|
+
* @returns A new sanitized Delta
|
|
1215
|
+
*
|
|
1216
|
+
* @example
|
|
1217
|
+
* ```typescript
|
|
1218
|
+
* const registry = createDefaultRegistry();
|
|
1219
|
+
* const dirty = new Delta()
|
|
1220
|
+
* .insert('Hello', { bold: true, unknown: 'value', color: 'red' })
|
|
1221
|
+
* .insert('\n');
|
|
1222
|
+
*
|
|
1223
|
+
* const clean = sanitizeDelta(dirty, registry);
|
|
1224
|
+
* // { bold: true, color: '#ff0000' } - unknown removed, color normalized
|
|
1225
|
+
* ```
|
|
1226
|
+
*/
|
|
1227
|
+
declare function sanitizeDelta(delta: Delta, registry: Registry, options?: SanitizeOptions): Delta;
|
|
1228
|
+
/**
|
|
1229
|
+
* Normalize a Delta's attributes without removing anything
|
|
1230
|
+
*
|
|
1231
|
+
* This is a lighter operation that only normalizes values,
|
|
1232
|
+
* without removing unknown or invalid attributes.
|
|
1233
|
+
*
|
|
1234
|
+
* @param delta - The Delta to normalize
|
|
1235
|
+
* @param registry - The Registry to use for normalization
|
|
1236
|
+
* @returns A new Delta with normalized attributes
|
|
1237
|
+
*/
|
|
1238
|
+
declare function normalizeDelta(delta: Delta, registry: Registry): Delta;
|
|
1239
|
+
/**
|
|
1240
|
+
* Validate a Delta against a Registry
|
|
1241
|
+
*
|
|
1242
|
+
* @param delta - The Delta to validate
|
|
1243
|
+
* @param registry - The Registry to use for validation
|
|
1244
|
+
* @returns true if all attributes in the Delta are valid
|
|
1245
|
+
*/
|
|
1246
|
+
declare function validateDelta(delta: Delta, registry: Registry): boolean;
|
|
1247
|
+
/**
|
|
1248
|
+
* Deep clone a Delta
|
|
1249
|
+
*
|
|
1250
|
+
* @param delta - The Delta to clone
|
|
1251
|
+
* @returns A new Delta with cloned ops
|
|
1252
|
+
*/
|
|
1253
|
+
declare function cloneDelta(delta: Delta): Delta;
|
|
1254
|
+
|
|
1255
|
+
/**
|
|
1256
|
+
* Delta → HTML Conversion
|
|
1257
|
+
*
|
|
1258
|
+
* Converts a Delta document to an HTML string.
|
|
1259
|
+
*/
|
|
1260
|
+
|
|
1261
|
+
/**
|
|
1262
|
+
* Options for Delta → HTML conversion
|
|
1263
|
+
*/
|
|
1264
|
+
interface DeltaToHtmlOptions {
|
|
1265
|
+
/**
|
|
1266
|
+
* Pretty print output with indentation
|
|
1267
|
+
* @default false
|
|
1268
|
+
*/
|
|
1269
|
+
pretty?: boolean;
|
|
1270
|
+
/**
|
|
1271
|
+
* Custom embed renderers (merged with defaults)
|
|
1272
|
+
*/
|
|
1273
|
+
embedRenderers?: Record<string, (value: unknown, attrs?: Record<string, unknown>) => string>;
|
|
1274
|
+
/**
|
|
1275
|
+
* Wrap output in a container element
|
|
1276
|
+
* @default undefined (no wrapper)
|
|
1277
|
+
*/
|
|
1278
|
+
wrapper?: string;
|
|
1279
|
+
/**
|
|
1280
|
+
* Use semantic HTML5 elements
|
|
1281
|
+
* @default true
|
|
1282
|
+
*/
|
|
1283
|
+
semantic?: boolean;
|
|
1284
|
+
/**
|
|
1285
|
+
* Use hierarchical numbering for ordered lists (e.g., 1, 1.1, 1.1.1)
|
|
1286
|
+
* When enabled, list items get data-number attribute with calculated number
|
|
1287
|
+
* @default false
|
|
1288
|
+
*/
|
|
1289
|
+
hierarchicalNumbers?: boolean;
|
|
1290
|
+
/**
|
|
1291
|
+
* Block handler registry for complex block embeds (Extended Table, etc.)
|
|
1292
|
+
* When provided, `{ insert: { block: { type, ... } } }` ops are dispatched
|
|
1293
|
+
* to the matching BlockHandler.toHtml() for rendering.
|
|
1294
|
+
*/
|
|
1295
|
+
blockHandlers?: BlockHandlerRegistry;
|
|
1296
|
+
/**
|
|
1297
|
+
* Generate anchor link `id` attributes on heading elements (`<h1>`-`<h6>`).
|
|
1298
|
+
*
|
|
1299
|
+
* When enabled, headings get an `id` computed via slugify(text).
|
|
1300
|
+
* If a heading has an explicit `header-id` attribute in Delta, that id is used instead.
|
|
1301
|
+
* Duplicate slugs are deduplicated with `-1`, `-2` suffixes.
|
|
1302
|
+
*
|
|
1303
|
+
* @default false
|
|
1304
|
+
*/
|
|
1305
|
+
anchorLinks?: boolean;
|
|
1306
|
+
/**
|
|
1307
|
+
* Format registry for custom embed rendering.
|
|
1308
|
+
*
|
|
1309
|
+
* When provided, embed formats with a `render()` method are used
|
|
1310
|
+
* before falling back to built-in EMBED_RENDERERS.
|
|
1311
|
+
* This enables extensibility without modifying converter internals.
|
|
1312
|
+
*/
|
|
1313
|
+
registry?: Registry;
|
|
1314
|
+
}
|
|
1315
|
+
/**
|
|
1316
|
+
* Convert a Delta to an HTML string
|
|
1317
|
+
*
|
|
1318
|
+
* @param delta - The Delta to convert
|
|
1319
|
+
* @param options - Conversion options
|
|
1320
|
+
* @returns HTML string
|
|
1321
|
+
*
|
|
1322
|
+
* @example
|
|
1323
|
+
* ```typescript
|
|
1324
|
+
* const delta = new Delta()
|
|
1325
|
+
* .insert('Hello ', { bold: true })
|
|
1326
|
+
* .insert('World')
|
|
1327
|
+
* .insert('\n', { header: 1 });
|
|
1328
|
+
*
|
|
1329
|
+
* const html = deltaToHtml(delta);
|
|
1330
|
+
* // '<h1><strong>Hello </strong>World</h1>'
|
|
1331
|
+
* ```
|
|
1332
|
+
*/
|
|
1333
|
+
declare function deltaToHtml(delta: Delta, options?: DeltaToHtmlOptions): string;
|
|
1334
|
+
|
|
1335
|
+
/**
|
|
1336
|
+
* HTML → Delta Conversion
|
|
1337
|
+
*
|
|
1338
|
+
* Converts HTML string to a Delta document.
|
|
1339
|
+
*/
|
|
1340
|
+
|
|
1341
|
+
/**
|
|
1342
|
+
* Options for HTML → Delta conversion
|
|
1343
|
+
*/
|
|
1344
|
+
interface HtmlToDeltaOptions {
|
|
1345
|
+
/**
|
|
1346
|
+
* DOM adapter to use (defaults to auto-detected)
|
|
1347
|
+
*/
|
|
1348
|
+
adapter?: DOMAdapter;
|
|
1349
|
+
/**
|
|
1350
|
+
* Normalize whitespace (collapse multiple spaces, trim)
|
|
1351
|
+
* @default true
|
|
1352
|
+
*/
|
|
1353
|
+
normalizeWhitespace?: boolean;
|
|
1354
|
+
/**
|
|
1355
|
+
* Custom tag handlers for special elements
|
|
1356
|
+
*/
|
|
1357
|
+
tagHandlers?: Record<string, TagHandler>;
|
|
1358
|
+
/**
|
|
1359
|
+
* Block handler registry for Extended Table and other block embeds.
|
|
1360
|
+
* When provided and a handler for 'table' is registered,
|
|
1361
|
+
* `<table>` elements will be parsed as block embeds instead of Simple Table.
|
|
1362
|
+
*/
|
|
1363
|
+
blockHandlers?: BlockHandlerRegistry;
|
|
1364
|
+
/**
|
|
1365
|
+
* Format registry for custom embed matching.
|
|
1366
|
+
*
|
|
1367
|
+
* When provided, embed formats with a `match()` method are tried
|
|
1368
|
+
* before falling back to built-in tag handlers (img, video, iframe, etc.).
|
|
1369
|
+
* This enables extensibility without modifying converter internals.
|
|
1370
|
+
*/
|
|
1371
|
+
registry?: Registry;
|
|
1372
|
+
}
|
|
1373
|
+
/**
|
|
1374
|
+
* Custom tag handler function
|
|
1375
|
+
*/
|
|
1376
|
+
type TagHandler = (element: DOMElement, context: ParserContext$1) => void;
|
|
1377
|
+
/**
|
|
1378
|
+
* Parser context passed to tag handlers
|
|
1379
|
+
*/
|
|
1380
|
+
interface ParserContext$1 {
|
|
1381
|
+
delta: Delta;
|
|
1382
|
+
attributes: AttributeMap;
|
|
1383
|
+
blockAttributes: AttributeMap;
|
|
1384
|
+
pushText(text: string): void;
|
|
1385
|
+
pushEmbed(embed: Record<string, unknown>, attrs?: AttributeMap): void;
|
|
1386
|
+
pushNewline(): void;
|
|
1387
|
+
}
|
|
1388
|
+
/**
|
|
1389
|
+
* Convert HTML string to Delta
|
|
1390
|
+
*
|
|
1391
|
+
* @param html - The HTML string to convert
|
|
1392
|
+
* @param options - Conversion options
|
|
1393
|
+
* @returns Delta document
|
|
1394
|
+
*
|
|
1395
|
+
* @example
|
|
1396
|
+
* ```typescript
|
|
1397
|
+
* const html = '<p><strong>Hello</strong> World</p>';
|
|
1398
|
+
* const delta = htmlToDelta(html);
|
|
1399
|
+
* // { ops: [
|
|
1400
|
+
* // { insert: 'Hello', attributes: { bold: true } },
|
|
1401
|
+
* // { insert: ' World\n' }
|
|
1402
|
+
* // ]}
|
|
1403
|
+
* ```
|
|
1404
|
+
*/
|
|
1405
|
+
declare function htmlToDelta(html: string, options?: HtmlToDeltaOptions): Delta;
|
|
1406
|
+
|
|
1407
|
+
/**
|
|
1408
|
+
* Escape HTML special characters
|
|
1409
|
+
*/
|
|
1410
|
+
declare function escapeHtml(text: string): string;
|
|
1411
|
+
/**
|
|
1412
|
+
* Unescape HTML entities
|
|
1413
|
+
*/
|
|
1414
|
+
declare function unescapeHtml(text: string): string;
|
|
1415
|
+
|
|
1416
|
+
/**
|
|
1417
|
+
* GitHub-compatible slugify for heading anchor links.
|
|
1418
|
+
*
|
|
1419
|
+
* Algorithm matches GitHub's heading-to-id conversion:
|
|
1420
|
+
* 1. Trim leading/trailing whitespace
|
|
1421
|
+
* 2. Convert to lowercase
|
|
1422
|
+
* 3. Remove everything except word characters (letters, digits, underscore),
|
|
1423
|
+
* spaces, hyphens (preserves Unicode letters via \p{L})
|
|
1424
|
+
* 4. Replace spaces with hyphens
|
|
1425
|
+
* 5. Collapse consecutive hyphens
|
|
1426
|
+
* 6. Trim leading/trailing hyphens
|
|
1427
|
+
*
|
|
1428
|
+
* @param text - heading plain text content
|
|
1429
|
+
* @returns slugified string suitable for HTML id attribute
|
|
1430
|
+
*
|
|
1431
|
+
* @example
|
|
1432
|
+
* ```typescript
|
|
1433
|
+
* slugify('Getting Started'); // 'getting-started'
|
|
1434
|
+
* slugify('API Reference (v2)'); // 'api-reference-v2'
|
|
1435
|
+
* slugify('Что нового?'); // 'что-нового'
|
|
1436
|
+
* slugify(' Hello World '); // 'hello--world' → 'hello-world'
|
|
1437
|
+
* ```
|
|
1438
|
+
*/
|
|
1439
|
+
declare function slugify(text: string): string;
|
|
1440
|
+
/**
|
|
1441
|
+
* Slugify with deduplication: appends `-1`, `-2`, etc. on collision.
|
|
1442
|
+
*
|
|
1443
|
+
* Tracks used slugs via a Map. Call this for each heading in order during
|
|
1444
|
+
* a single document render pass.
|
|
1445
|
+
*
|
|
1446
|
+
* @param text - heading plain text content
|
|
1447
|
+
* @param usedSlugs - mutable map tracking slug usage counts
|
|
1448
|
+
* @returns unique slugified string
|
|
1449
|
+
*
|
|
1450
|
+
* @example
|
|
1451
|
+
* ```typescript
|
|
1452
|
+
* const used = new Map<string, number>();
|
|
1453
|
+
* slugifyWithDedup('FAQ', used); // 'faq'
|
|
1454
|
+
* slugifyWithDedup('FAQ', used); // 'faq-1'
|
|
1455
|
+
* slugifyWithDedup('FAQ', used); // 'faq-2'
|
|
1456
|
+
* ```
|
|
1457
|
+
*/
|
|
1458
|
+
declare function slugifyWithDedup(text: string, usedSlugs: Map<string, number>): string;
|
|
1459
|
+
|
|
1460
|
+
/**
|
|
1461
|
+
* Delta → Markdown Conversion
|
|
1462
|
+
*
|
|
1463
|
+
* Converts a Delta document to Markdown string.
|
|
1464
|
+
*/
|
|
1465
|
+
|
|
1466
|
+
/**
|
|
1467
|
+
* Options for Delta → Markdown conversion
|
|
1468
|
+
*/
|
|
1469
|
+
interface DeltaToMarkdownOptions {
|
|
1470
|
+
/**
|
|
1471
|
+
* Use strict Markdown (no GFM extensions)
|
|
1472
|
+
* @default false
|
|
1473
|
+
*/
|
|
1474
|
+
strict?: boolean;
|
|
1475
|
+
/**
|
|
1476
|
+
* Preserve empty lines using <br> tags
|
|
1477
|
+
* When false, multiple empty lines collapse to one paragraph break
|
|
1478
|
+
* @default false
|
|
1479
|
+
*/
|
|
1480
|
+
preserveEmptyLines?: boolean;
|
|
1481
|
+
/**
|
|
1482
|
+
* Math syntax for formula output
|
|
1483
|
+
* - 'dollar': $...$ for inline, $$...$$ for block (default, GFM-compatible)
|
|
1484
|
+
* - 'latex': \(...\) for inline, \[...\] for block (used by LLMs: DeepSeek, ChatGPT, Claude)
|
|
1485
|
+
* @default 'dollar'
|
|
1486
|
+
*/
|
|
1487
|
+
mathSyntax?: 'dollar' | 'latex';
|
|
1488
|
+
/**
|
|
1489
|
+
* Display math rendering mode
|
|
1490
|
+
* - true (default): code-block "math" → ```math ``` (GFM code block)
|
|
1491
|
+
* - false: code-block "math" → $...$ on its own line (inline syntax)
|
|
1492
|
+
*
|
|
1493
|
+
* Does NOT affect inline formulas ({ formula }) — they always render as $...$
|
|
1494
|
+
* @default true
|
|
1495
|
+
*/
|
|
1496
|
+
mathBlock?: boolean;
|
|
1497
|
+
/**
|
|
1498
|
+
* Mermaid diagram rendering mode
|
|
1499
|
+
* - true (default): code-block "mermaid" → ```mermaid ``` (fenced block)
|
|
1500
|
+
* - false: code-block "mermaid" → ```mermaid ``` (same output, but { diagram } embeds also → ```mermaid)
|
|
1501
|
+
*
|
|
1502
|
+
* Does NOT affect the Markdown output for code-block "mermaid" (always fenced).
|
|
1503
|
+
* Controls how { diagram } embeds are rendered.
|
|
1504
|
+
* @default true
|
|
1505
|
+
*/
|
|
1506
|
+
mermaidBlock?: boolean;
|
|
1507
|
+
/**
|
|
1508
|
+
* PlantUML diagram rendering mode
|
|
1509
|
+
* - true (default): code-block "plantuml" → ```plantuml ``` (fenced block)
|
|
1510
|
+
* - false: code-block "plantuml" → ```plantuml ``` (same output, but { diagram } embeds with @startuml → ```plantuml)
|
|
1511
|
+
*
|
|
1512
|
+
* Does NOT affect the Markdown output for code-block "plantuml" (always fenced).
|
|
1513
|
+
* Controls how { diagram } embeds containing PlantUML are rendered.
|
|
1514
|
+
* @default true
|
|
1515
|
+
*/
|
|
1516
|
+
plantumlBlock?: boolean;
|
|
1517
|
+
/**
|
|
1518
|
+
* Custom embed renderers
|
|
1519
|
+
*/
|
|
1520
|
+
embedRenderers?: Record<string, (value: unknown, attrs?: AttributeMap) => string>;
|
|
1521
|
+
/**
|
|
1522
|
+
* Block handler registry for Extended Table and other block embeds.
|
|
1523
|
+
* When provided, block embeds will be rendered via handler.toMarkdown() → fallback to handler.toHtml().
|
|
1524
|
+
*/
|
|
1525
|
+
blockHandlers?: BlockHandlerRegistry;
|
|
1526
|
+
/**
|
|
1527
|
+
* Pretty-print HTML output for block embeds (Extended Table, Columns, etc.)
|
|
1528
|
+
* When true, HTML fallback in Markdown is indented and line-broken for readability.
|
|
1529
|
+
* When false (default), HTML is compact single-line — safer for CommonMark.
|
|
1530
|
+
* @default false
|
|
1531
|
+
*/
|
|
1532
|
+
prettyHtml?: boolean;
|
|
1533
|
+
/**
|
|
1534
|
+
* Format registry for custom embed Markdown rendering.
|
|
1535
|
+
*
|
|
1536
|
+
* When provided, embed formats with a `toMarkdown()` method are used
|
|
1537
|
+
* before falling back to built-in handlers. If `toMarkdown()` returns null,
|
|
1538
|
+
* `render()` is used as HTML fallback in Markdown.
|
|
1539
|
+
*/
|
|
1540
|
+
registry?: Registry;
|
|
1541
|
+
}
|
|
1542
|
+
/**
|
|
1543
|
+
* Convert Delta to Markdown
|
|
1544
|
+
*
|
|
1545
|
+
* @param delta - The Delta document to convert
|
|
1546
|
+
* @param options - Conversion options
|
|
1547
|
+
* @returns Markdown string
|
|
1548
|
+
*
|
|
1549
|
+
* @example
|
|
1550
|
+
* ```typescript
|
|
1551
|
+
* const delta = new Delta()
|
|
1552
|
+
* .insert('Hello', { bold: true })
|
|
1553
|
+
* .insert(' World\n');
|
|
1554
|
+
*
|
|
1555
|
+
* const md = deltaToMarkdown(delta);
|
|
1556
|
+
* // '**Hello** World\n'
|
|
1557
|
+
* ```
|
|
1558
|
+
*/
|
|
1559
|
+
declare function deltaToMarkdown(delta: Delta, options?: DeltaToMarkdownOptions): string;
|
|
1560
|
+
|
|
1561
|
+
/**
|
|
1562
|
+
* Markdown → Delta Conversion
|
|
1563
|
+
*
|
|
1564
|
+
* Converts Markdown string to a Delta document using remark (unified).
|
|
1565
|
+
*/
|
|
1566
|
+
|
|
1567
|
+
/**
|
|
1568
|
+
* Options for Markdown → Delta conversion
|
|
1569
|
+
*/
|
|
1570
|
+
interface MarkdownToDeltaOptions {
|
|
1571
|
+
/**
|
|
1572
|
+
* Enable GFM (GitHub Flavored Markdown) extensions
|
|
1573
|
+
* Includes: tables, strikethrough, task lists, autolinks
|
|
1574
|
+
* @default true
|
|
1575
|
+
*/
|
|
1576
|
+
gfm?: boolean;
|
|
1577
|
+
/**
|
|
1578
|
+
* Display math rendering mode
|
|
1579
|
+
* - true (default): $$...$$ / ```math → code-block "math" in Delta
|
|
1580
|
+
* - false: $$...$$ / ```math → inline { formula } embed in Delta
|
|
1581
|
+
*
|
|
1582
|
+
* Does NOT affect inline math ($...$) — always becomes { formula } embed
|
|
1583
|
+
* @default true
|
|
1584
|
+
*/
|
|
1585
|
+
mathBlock?: boolean;
|
|
1586
|
+
/**
|
|
1587
|
+
* Mermaid diagram rendering mode
|
|
1588
|
+
* - true (default): ```mermaid → code-block "mermaid" in Delta
|
|
1589
|
+
* - false: ```mermaid → inline { diagram } embed in Delta
|
|
1590
|
+
* @default true
|
|
1591
|
+
*/
|
|
1592
|
+
mermaidBlock?: boolean;
|
|
1593
|
+
/**
|
|
1594
|
+
* PlantUML diagram rendering mode
|
|
1595
|
+
* - true (default): ```plantuml → code-block "plantuml" in Delta
|
|
1596
|
+
* - false: ```plantuml → inline { diagram } embed in Delta
|
|
1597
|
+
* @default true
|
|
1598
|
+
*/
|
|
1599
|
+
plantumlBlock?: boolean;
|
|
1600
|
+
/**
|
|
1601
|
+
* Custom node handlers for special elements
|
|
1602
|
+
*/
|
|
1603
|
+
nodeHandlers?: Record<string, NodeHandler>;
|
|
1604
|
+
/**
|
|
1605
|
+
* Block handler registry for Extended Table and other block embeds.
|
|
1606
|
+
* Reserved for future use — GFM tables don't support Extended Table features.
|
|
1607
|
+
* HTML tables in Markdown are parsed via htmlToDelta when blockHandlers is provided.
|
|
1608
|
+
*/
|
|
1609
|
+
blockHandlers?: BlockHandlerRegistry;
|
|
1610
|
+
}
|
|
1611
|
+
/**
|
|
1612
|
+
* MDAST node type (simplified)
|
|
1613
|
+
*/
|
|
1614
|
+
interface MdastNode {
|
|
1615
|
+
type: string;
|
|
1616
|
+
children?: MdastNode[];
|
|
1617
|
+
value?: string;
|
|
1618
|
+
url?: string;
|
|
1619
|
+
alt?: string;
|
|
1620
|
+
title?: string;
|
|
1621
|
+
lang?: string;
|
|
1622
|
+
meta?: string;
|
|
1623
|
+
depth?: number;
|
|
1624
|
+
ordered?: boolean;
|
|
1625
|
+
checked?: boolean | null;
|
|
1626
|
+
spread?: boolean;
|
|
1627
|
+
/** Footnote identifier (for footnoteReference / footnoteDefinition) */
|
|
1628
|
+
identifier?: string;
|
|
1629
|
+
/** Footnote label (for footnoteReference / footnoteDefinition) */
|
|
1630
|
+
label?: string;
|
|
1631
|
+
}
|
|
1632
|
+
/**
|
|
1633
|
+
* Custom node handler function
|
|
1634
|
+
*/
|
|
1635
|
+
type NodeHandler = (node: MdastNode, context: ParserContext) => void;
|
|
1636
|
+
/**
|
|
1637
|
+
* Parser context for building Delta
|
|
1638
|
+
*/
|
|
1639
|
+
interface ParserContext {
|
|
1640
|
+
delta: Delta;
|
|
1641
|
+
pushText(text: string, attrs?: AttributeMap): void;
|
|
1642
|
+
pushEmbed(embed: Record<string, unknown>, attrs?: AttributeMap): void;
|
|
1643
|
+
pushNewline(attrs?: AttributeMap): void;
|
|
1644
|
+
}
|
|
1645
|
+
/**
|
|
1646
|
+
* Check if remark is available
|
|
1647
|
+
*/
|
|
1648
|
+
declare function isRemarkAvailable(): boolean;
|
|
1649
|
+
/**
|
|
1650
|
+
* Convert Markdown to Delta (async)
|
|
1651
|
+
*/
|
|
1652
|
+
declare function markdownToDelta(markdown: string, options?: MarkdownToDeltaOptions): Promise<Delta>;
|
|
1653
|
+
/**
|
|
1654
|
+
* Synchronous version (requires remark to be pre-loaded or uses require)
|
|
1655
|
+
*/
|
|
1656
|
+
declare function markdownToDeltaSync(markdown: string, options?: MarkdownToDeltaOptions): Delta;
|
|
1657
|
+
|
|
1658
|
+
export { ALERT_TYPES, type AlertBlockData, type AlertType, type AlignType, BOX_FLOAT_VALUES, BOX_OVERFLOW_VALUES, type BlockContext, type BlockHandler, BlockHandlerRegistry, type BlockRenderOptions, type BoxBlockData, type BoxFloat, type BoxOpAttributes, type BoxOverflow, BrowserDOMAdapter, type CellAlign, type CellData, type ColumnsBlockData, type DOMAdapter, type DOMDocument, type DOMDocumentFragment, type DOMElement, type DOMNode, type DOMNodeList, type DeltaToHtmlOptions, type DeltaToMarkdownOptions, type FootnotesBlockData, type Format, type FormatDefinition, type FormatMatchResult, type FormatScope, type HtmlToDeltaOptions, type ListType, type MarkdownToDeltaOptions, NODE_TYPE, NodeDOMAdapter, Registry, type SanitizeOptions, type TableBlockData, type TableColAlignType, alertBlockHandler, alignFormat, backgroundFormat, blockFormat, blockquoteFormat, boldFormat, boxBlockHandler, browserAdapter, cloneDelta, codeBlockFormat, codeFormat, colorFormat, columnsBlockHandler, createDefaultBlockHandlers, createDefaultRegistry, defaultBlockFormats, defaultEmbedFormats, defaultFormats, defaultInlineFormats, deltaToHtml, deltaToMarkdown, dividerFormat, escapeHtml, extractBoxOpAttributes, footnoteRefFormat, footnotesBlockHandler, formulaFormat, getAdapter, getNamedColors, headerFormat, headerIdFormat, htmlToDelta, imageFormat, indentFormat, isAdapterAvailable, isElement, isRemarkAvailable, isTextNode, isValidColor, isValidHexColor, italicFormat, kbdFormat, linkFormat, listFormat, markFormat, markdownToDelta, markdownToDeltaSync, nodeAdapter, normalizeDelta, sanitizeDelta, slugify, slugifyWithDedup, strikeFormat, subscriptFormat, superscriptFormat, tableBlockHandler, tableColAlignFormat, tableColFormat, tableHeaderFormat, tableRowFormat, toHexColor, underlineFormat, unescapeHtml, validateDelta, videoFormat };
|