@leadertechie/md2html 0.1.0-alpha.2 → 0.1.0-alpha.20

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/index.d.ts CHANGED
@@ -1,7 +1,746 @@
1
- export * from './types';
2
- export * from './parser';
3
- export * from './renderer';
4
- export * from './lit-renderer';
5
- export * from './pipeline';
6
- export { LitRenderer as HTMLRenderer } from './lit-renderer';
7
- //# sourceMappingURL=index.d.ts.map
1
+ import { LoggerInterface } from '@leadertechie/telemetry';
2
+
3
+ /**
4
+ * Handles 'blockquote' tokens.
5
+ */
6
+ export declare class BlockquoteHandler implements TokenHandler {
7
+ readonly type = "blockquote";
8
+ handle(token: Record<string, unknown>, ctx: ParseContext): {
9
+ type: "container";
10
+ attributes: {
11
+ tag: string;
12
+ };
13
+ children: ContentNode[];
14
+ };
15
+ }
16
+
17
+ /**
18
+ * Catch-all handler for any token type that doesn't have a dedicated handler.
19
+ * Wraps the raw token content in a container node so content is never silently lost.
20
+ * Reports the unhandled type via the context's reportUnhandled callback.
21
+ */
22
+ export declare class CatchAllHandler implements TokenHandler {
23
+ readonly type = "*";
24
+ handle(token: Record<string, unknown>, ctx: ParseContext): {
25
+ type: "container";
26
+ content: string;
27
+ attributes: {
28
+ 'data-unhandled': string;
29
+ tag: string;
30
+ };
31
+ };
32
+ }
33
+
34
+ /**
35
+ * Handles 'code' tokens (fenced code blocks).
36
+ */
37
+ export declare class CodeHandler implements TokenHandler {
38
+ readonly type = "code";
39
+ handle(token: Record<string, unknown>, _ctx: ParseContext): {
40
+ type: "code";
41
+ content: string;
42
+ attributes: {
43
+ lang: string;
44
+ };
45
+ };
46
+ }
47
+
48
+ /**
49
+ * Built-in visitor: collect all nodes of a specific type.
50
+ */
51
+ export declare function collectByType(root: ContentNode, type: string): ContentNode[];
52
+
53
+ /**
54
+ * Walk a ContentNode tree and collect results from the visitor.
55
+ * The collector function is called for each node and returns a value or null.
56
+ */
57
+ export declare function collectFromTree<T>(root: ContentNode, collector: (node: ContentNode, parent: ContentNode | null, depth: number) => T | null): T[];
58
+
59
+ /**
60
+ * Built-in visitor: collect all headings with their levels.
61
+ */
62
+ export declare function collectHeadings(root: ContentNode): Array<{
63
+ level: string;
64
+ text: string;
65
+ id?: string;
66
+ }>;
67
+
68
+ /**
69
+ * Built-in visitor: collect all images with their src/alt.
70
+ */
71
+ export declare function collectImages(root: ContentNode): Array<{
72
+ src: string;
73
+ alt: string;
74
+ }>;
75
+
76
+ /**
77
+ * Sequentially applies multiple preprocessors to the markdown.
78
+ * Each preprocessor's output becomes the next one's input.
79
+ *
80
+ * This follows the Chain of Responsibility pattern — you can add
81
+ * new preprocessors without modifying existing code.
82
+ */
83
+ export declare class CompositePreprocessor implements Preprocessor {
84
+ readonly name = "composite";
85
+ private processors;
86
+ constructor(processors?: Preprocessor[]);
87
+ /** Add a preprocessor to the chain. Returns `this` for fluent API. */
88
+ add(processor: Preprocessor): this;
89
+ /** Remove a preprocessor by name. */
90
+ remove(name: string): void;
91
+ /** Get the list of registered preprocessors. */
92
+ getProcessors(): ReadonlyArray<Preprocessor>;
93
+ process(markdown: string): string;
94
+ }
95
+
96
+ /**
97
+ * Sequentially applies multiple postprocessors to the token array.
98
+ */
99
+ export declare class CompositeTokenPostprocessor implements TokenPostprocessor {
100
+ readonly name = "composite";
101
+ private processors;
102
+ constructor(processors?: TokenPostprocessor[]);
103
+ /** Add a postprocessor to the chain. Returns `this` for fluent API. */
104
+ add(processor: TokenPostprocessor): this;
105
+ /** Remove a postprocessor by name. */
106
+ remove(name: string): void;
107
+ /** Get the list of registered postprocessors. */
108
+ getProcessors(): ReadonlyArray<TokenPostprocessor>;
109
+ process(tokens: unknown[]): unknown[];
110
+ }
111
+
112
+ /**
113
+ * ContainerBlockHandler — handles custom :::tag#id.class container blocks.
114
+ *
115
+ * These are produced by the MarkdownParser's preprocessor which converts
116
+ * the ::: syntax into marked tokens before lexing, then reconstructs
117
+ * containerBlock tokens after lexing.
118
+ *
119
+ * The handler parses the specifier (e.g. "section#header.content") into
120
+ * tag name, id, and class(es), then recursively parses the inner tokens
121
+ * as normal markdown content, producing a container node with the
122
+ * specified HTML wrapper.
123
+ */
124
+ export declare class ContainerBlockHandler implements TokenHandler {
125
+ readonly type = "containerBlock";
126
+ handle(token: Record<string, unknown>, ctx: ParseContext): ContentNode | null;
127
+ }
128
+
129
+ /**
130
+ * Collapses `<!-- md-container:... -->` and `<!-- /md-container -->` comment
131
+ * markers into nested `containerBlock` tokens with proper parent-child structure.
132
+ *
133
+ * Handles nesting depth up to any reasonable limit (depends on stack memory).
134
+ */
135
+ export declare class ContainerBlockPostprocessor implements TokenPostprocessor {
136
+ readonly name = "container-blocks";
137
+ process(tokens: unknown[]): unknown[];
138
+ }
139
+
140
+ /**
141
+ * Converts `:::tag#id.class` container syntax into HTML comment markers
142
+ * that marked will preserve as HTML tokens, without affecting markdown parsing
143
+ * of the inner content.
144
+ *
145
+ * Example:
146
+ * :::section#header
147
+ * # Heading inside container
148
+ * Some text
149
+ * :::
150
+ *
151
+ * Becomes:
152
+ * <!-- md-container:section#header -->
153
+ * # Heading inside container
154
+ * Some text
155
+ * <!-- /md-container -->
156
+ */
157
+ export declare class ContainerBlockPreprocessor implements Preprocessor {
158
+ readonly name = "container-blocks";
159
+ process(markdown: string): string;
160
+ }
161
+
162
+ export declare interface ContentNode {
163
+ type: ContentNodeType;
164
+ content?: string;
165
+ children?: ContentNode[];
166
+ attributes?: Record<string, unknown>;
167
+ className?: string;
168
+ src?: string;
169
+ alt?: string;
170
+ ordered?: boolean;
171
+ /** Raw HTML content for passthrough mode */
172
+ rawHTML?: string;
173
+ /** Scope anchor value for data-md-scope */
174
+ scope?: string;
175
+ }
176
+
177
+ export declare type ContentNodeType = 'text' | 'heading' | 'paragraph' | 'list' | 'list-item' | 'image' | 'code' | 'container' | 'strong' | 'emphasis' | 'link';
178
+
179
+ /** Default postprocessor chain with the built-in container block support. */
180
+ export declare function createDefaultPostprocessor(): CompositeTokenPostprocessor;
181
+
182
+ /** Default preprocessor chain with the built-in container block support. */
183
+ export declare function createDefaultPreprocessor(): CompositePreprocessor;
184
+
185
+ /**
186
+ * Create a ParseContext from parser services.
187
+ *
188
+ * Each call creates a fresh context with its own metadata store,
189
+ * allowing for clean separation between recursive parse calls.
190
+ *
191
+ * The getters use closures to lazily access the parser's current state,
192
+ * so the context always reflects the latest configuration.
193
+ */
194
+ export declare function createParseContext(services: ParserServices): ParseContext;
195
+
196
+ /** Default allowed HTML tags for preserveRawHTML mode */
197
+ export declare const defaultAllowedHTMLTags: string[];
198
+
199
+ /**
200
+ * FrontmatterHandler — consumes YAML-ish frontmatter tokens produced by marked.lexer().
201
+ * Parses the raw YAML and stores key-value pairs onto ctx.metadata.
202
+ * Returns null so no HTML is emitted for frontmatter blocks.
203
+ *
204
+ * Handles both formats:
205
+ * key: value
206
+ * key:
207
+ * - item1
208
+ * - item2
209
+ */
210
+ export declare class FrontmatterHandler implements TokenHandler {
211
+ readonly type = "frontmatter";
212
+ handle(token: Record<string, unknown>, ctx: ParseContext): null;
213
+ }
214
+
215
+ /**
216
+ * Handles 'heading' tokens (h1-h6).
217
+ */
218
+ export declare class HeadingHandler implements TokenHandler {
219
+ readonly type = "heading";
220
+ handle(token: Record<string, unknown>, ctx: ParseContext): {
221
+ type: "heading";
222
+ content: string;
223
+ attributes: {
224
+ level: string;
225
+ };
226
+ };
227
+ }
228
+
229
+ /**
230
+ * Handles 'hr' tokens (horizontal rules).
231
+ */
232
+ export declare class HrHandler implements TokenHandler {
233
+ readonly type = "hr";
234
+ handle(_token: Record<string, unknown>, _ctx: ParseContext): {
235
+ type: "container";
236
+ attributes: {
237
+ tag: string;
238
+ };
239
+ };
240
+ }
241
+
242
+ /**
243
+ * Handles 'html' tokens (inline or block-level raw HTML).
244
+ * In preserveRawHTML mode, passes through allowed HTML tags.
245
+ * Otherwise, stores the raw content as a container node.
246
+ */
247
+ export declare class HtmlHandler implements TokenHandler {
248
+ readonly type = "html";
249
+ handle(token: Record<string, unknown>, ctx: ParseContext): {
250
+ type: "container";
251
+ rawHTML: string;
252
+ content?: undefined;
253
+ } | {
254
+ type: "container";
255
+ content: string;
256
+ rawHTML?: undefined;
257
+ } | null;
258
+ }
259
+
260
+ export declare class HTMLRenderer {
261
+ private config;
262
+ private strategyRegistry;
263
+ constructor(config?: StyleConfigV2);
264
+ /** Access the strategy registry for customization. */
265
+ get strategies(): RendererStrategyRegistry;
266
+ private hasClassConfig;
267
+ private getClass;
268
+ private generateHeadingId;
269
+ /**
270
+ * Get the scope attribute string for a node type.
271
+ * Returns empty string if emitScopeAnchors is disabled.
272
+ */
273
+ private getScopeAttr;
274
+ /**
275
+ * Get the CSS class for a container's tag-based rendering.
276
+ * Returns just the tag name since renderWithClass applies the prefix.
277
+ */
278
+ private getContainerClass;
279
+ private buildRenderContext;
280
+ renderNode(node: ContentNode): string;
281
+ renderNodes(nodes: ContentNode[]): string;
282
+ renderToHTMLString(nodes: ContentNode[]): string;
283
+ render(markdown: string): string;
284
+ getCustomCSS(): string;
285
+ }
286
+
287
+ /**
288
+ * Handles standalone 'image' tokens.
289
+ */
290
+ export declare class ImageHandler implements TokenHandler {
291
+ readonly type = "image";
292
+ handle(token: Record<string, unknown>, ctx: ParseContext): {
293
+ type: "image";
294
+ src: string;
295
+ alt: string;
296
+ };
297
+ }
298
+
299
+ /**
300
+ * Handles standalone 'link' tokens (e.g., reference-style links, or links
301
+ * that appear outside paragraphs in certain edge cases).
302
+ */
303
+ export declare class LinkHandler implements TokenHandler {
304
+ readonly type = "link";
305
+ handle(token: Record<string, unknown>, ctx: ParseContext): {
306
+ type: "link";
307
+ content: string;
308
+ attributes: {
309
+ title?: string | undefined;
310
+ href: string;
311
+ };
312
+ };
313
+ }
314
+
315
+ /**
316
+ * Handles 'list' tokens (ordered and unordered).
317
+ */
318
+ export declare class ListHandler implements TokenHandler {
319
+ readonly type = "list";
320
+ handle(token: Record<string, unknown>, ctx: ParseContext): {
321
+ type: "list";
322
+ ordered: boolean;
323
+ children: {
324
+ type: "list-item";
325
+ content: string;
326
+ }[];
327
+ };
328
+ }
329
+
330
+ export declare interface MarkdownContent {
331
+ title: string;
332
+ metadata?: Record<string, unknown>;
333
+ content: ContentNode[];
334
+ }
335
+
336
+ export declare class MarkdownParser {
337
+ private imagePathPrefix;
338
+ private imageBaseUrl;
339
+ private preserveRawHTML;
340
+ private slotPattern;
341
+ private onSlot;
342
+ private errorRecovery;
343
+ private maxRecursionDepth;
344
+ private allowedHTMLTags;
345
+ private allowedAttributes;
346
+ private handlerRegistry;
347
+ private onUnhandledToken?;
348
+ private log;
349
+ private preprocessor;
350
+ private postprocessor;
351
+ constructor(options?: ParserOptions);
352
+ /** Access the handler registry for customization. */
353
+ get handlers(): TokenHandlerRegistry;
354
+ /** Access the preprocessor chain for customization. */
355
+ get preprocessors(): CompositePreprocessor;
356
+ /** Access the token postprocessor chain for customization. */
357
+ get postprocessors(): CompositeTokenPostprocessor;
358
+ private processImagePath;
359
+ private processInlineFormatting;
360
+ private processSlots;
361
+ /**
362
+ * Check if an attribute name is allowed for a given tag.
363
+ * Supports "data-*" wildcard prefix matching.
364
+ */
365
+ private isAttributeAllowed;
366
+ /**
367
+ * Check if an attribute name matches a list of allowed patterns.
368
+ * Supports "data-*" wildcard prefix matching.
369
+ */
370
+ private matchesAttributeList;
371
+ /**
372
+ * Filter attributes on an HTML tag, keeping only allowed ones.
373
+ */
374
+ private filterTagAttributes;
375
+ private processRawHTML;
376
+ /**
377
+ * Build a ParserServices object that bridges the parser's private methods
378
+ * to the ParseContext factory. This keeps context creation decoupled.
379
+ */
380
+ private buildServices;
381
+ /**
382
+ * Process an array of marked tokens into ContentNodes.
383
+ * When depth === 0 (root), creates a shared context that accumulates metadata.
384
+ * For recursive calls (depth > 0), creates a fresh context for each level.
385
+ */
386
+ private parseTokens;
387
+ parse(markdown: string, options?: ParseOptions): MarkdownContent;
388
+ parseToNodes(markdown: string, options?: ParseOptions): ContentNode[];
389
+ }
390
+
391
+ export declare class MarkdownPipeline {
392
+ private parser;
393
+ private renderer;
394
+ private config;
395
+ private log;
396
+ constructor(config?: PipelineConfigV2);
397
+ parse(markdown: string): ContentNode[];
398
+ parseWithMetadata(markdown: string): MarkdownContent;
399
+ render(nodes: ContentNode[]): string;
400
+ renderMarkdown(markdown: string): string;
401
+ renderPage(title: string, nodes: ContentNode[], options?: {
402
+ lang?: string;
403
+ charset?: string;
404
+ }): string;
405
+ getConfig(): Readonly<PipelineConfigV2>;
406
+ getCustomCSS(): string;
407
+ }
408
+
409
+ /**
410
+ * ContentNode factory — a builder API for creating ContentNode instances
411
+ * consistently across the codebase. Eliminates scattered object literals
412
+ * and provides type-safe construction with sensible defaults.
413
+ *
414
+ * Usage:
415
+ * NodeFactory.heading('Hello', { level: '1' })
416
+ * NodeFactory.paragraph('Some text')
417
+ * NodeFactory.container({ tag: 'section', id: 'main' }, [children...])
418
+ */
419
+ export declare class NodeFactory {
420
+ static heading(content: string, attributes?: Record<string, unknown>): ContentNode;
421
+ static paragraph(contentOrChildren: string | ContentNode[], children?: ContentNode[]): ContentNode;
422
+ static list(items: ContentNode[], ordered?: boolean, attributes?: Record<string, unknown>): ContentNode;
423
+ static listItem(content: string): ContentNode;
424
+ static image(src: string, alt?: string, className?: string): ContentNode;
425
+ static code(content: string, lang?: string): ContentNode;
426
+ static container(children?: ContentNode[], config?: {
427
+ tag?: string;
428
+ id?: string;
429
+ className?: string;
430
+ rawHTML?: string;
431
+ scope?: string;
432
+ }): ContentNode;
433
+ static text(content: string): ContentNode;
434
+ static strong(content: string): ContentNode;
435
+ static emphasis(content: string): ContentNode;
436
+ static link(href: string, content: string): ContentNode;
437
+ }
438
+
439
+ /**
440
+ * Strategy interface for rendering a specific ContentNode type to HTML.
441
+ * This is the renderer-side equivalent of TokenHandler — each node type
442
+ * gets its own strategy, eliminating the large switch statement.
443
+ *
444
+ * To add support for a new node type:
445
+ * 1. Create a class implementing NodeRendererStrategy
446
+ * 2. Register it with the RendererStrategyRegistry
447
+ */
448
+ export declare interface NodeRendererStrategy {
449
+ /** The node type this strategy handles */
450
+ readonly type: string;
451
+ /** Render a node of this type to an HTML string */
452
+ render(node: ContentNode, renderChild: (child: ContentNode) => string, ctx: RenderContext): string;
453
+ }
454
+
455
+ /** Maps ContentNodeType to ScopeValue */
456
+ export declare const nodeTypeToScope: Record<ContentNodeType, ScopeValue>;
457
+
458
+ /**
459
+ * Visitor interface for traversing/walking a ContentNode AST.
460
+ *
461
+ * Implement this interface to inspect, collect, or transform nodes.
462
+ * Each method returns a ContentNode or null — returning null removes the node.
463
+ *
464
+ * Use cases:
465
+ * - Collect all images for preloading
466
+ * - Transform link URLs
467
+ * - Validate AST structure
468
+ * - Extract headings for ToC
469
+ * - Inject attributes
470
+ */
471
+ export declare interface NodeVisitor {
472
+ /** Called when entering a node, before visiting its children. */
473
+ enter?(node: ContentNode, parent: ContentNode | null, depth: number): ContentNode | null;
474
+ /** Called after visiting all children of the node. */
475
+ exit?(node: ContentNode, parent: ContentNode | null, depth: number): ContentNode | null;
476
+ }
477
+
478
+ /**
479
+ * Handles 'paragraph' tokens, including inline images, links, and raw HTML.
480
+ */
481
+ export declare class ParagraphHandler implements TokenHandler {
482
+ readonly type = "paragraph";
483
+ handle(token: Record<string, unknown>, ctx: ParseContext): {
484
+ type: "paragraph";
485
+ children: ContentNode[];
486
+ content?: undefined;
487
+ } | {
488
+ type: "paragraph";
489
+ content: string;
490
+ children?: undefined;
491
+ } | null;
492
+ }
493
+
494
+ /**
495
+ * Context passed to every token handler, giving access to parser services.
496
+ */
497
+ export declare interface ParseContext {
498
+ processImagePath(src: string): string;
499
+ processInlineFormatting(text: string): string;
500
+ processSlots(text: string): string;
501
+ processRawHTML(html: string): string;
502
+ parseTokens(tokens: unknown[], depth: number): ContentNode[];
503
+ preserveRawHTML: boolean;
504
+ errorRecovery: 'throw' | 'warn' | 'silent';
505
+ maxRecursionDepth: number;
506
+ /** Report an unhandled token type so callers can be notified */
507
+ reportUnhandled(type: string, token: Record<string, unknown>): void;
508
+ /**
509
+ * Shared metadata store populated by token handlers (e.g. FrontmatterHandler).
510
+ * After parsing, this object contains all frontmatter key-value pairs.
511
+ */
512
+ metadata: Record<string, unknown>;
513
+ }
514
+
515
+ export declare interface ParseOptions {
516
+ gfm?: boolean;
517
+ breaks?: boolean;
518
+ pedantic?: boolean;
519
+ }
520
+
521
+ export declare interface ParserOptions {
522
+ /** Optional telemetry logger */
523
+ logger?: LoggerInterface;
524
+ imagePathPrefix?: string;
525
+ imageBaseUrl?: string;
526
+ preserveRawHTML?: boolean;
527
+ slotPattern?: RegExp;
528
+ onSlot?: (name: string) => string;
529
+ errorRecovery?: 'throw' | 'warn' | 'silent';
530
+ maxRecursionDepth?: number;
531
+ allowedHTMLTags?: string[];
532
+ /**
533
+ * Allowed HTML attributes per tag for preserveRawHTML mode.
534
+ * Key "*" applies to all tags. Key "tag" applies to specific tags.
535
+ * Supports "data-*" wildcard prefix matching.
536
+ */
537
+ allowedAttributes?: Record<string, string[]>;
538
+ /**
539
+ * Callback invoked when a token type has no dedicated handler.
540
+
541
+ * The catch-all handler will still produce a container node for the content,
542
+ * but this callback allows callers to log, warn, or track unhandled types.
543
+ *
544
+ * @param type - The unhandled token type name (e.g. 'table', 'def')
545
+ * @param token - The raw marked token
546
+ */
547
+ onUnhandledToken?: (type: string, token: Record<string, unknown>) => void;
548
+ }
549
+
550
+ /**
551
+ * Services needed by the ParseContext factory.
552
+ * This is the interface the parser exposes to context creation.
553
+ */
554
+ export declare interface ParserServices {
555
+ preserveRawHTML: boolean;
556
+ errorRecovery: 'throw' | 'warn' | 'silent';
557
+ maxRecursionDepth: number;
558
+ processImagePath(src: string): string;
559
+ processInlineFormatting(text: string): string;
560
+ processSlots(text: string): string;
561
+ processRawHTML(html: string): string;
562
+ parseTokens(tokens: unknown[], depth: number): ContentNode[];
563
+ onUnhandledToken?: (type: string, token: Record<string, unknown>) => void;
564
+ }
565
+
566
+ export declare interface PipelineConfig {
567
+ imagePathPrefix?: string;
568
+ imageBaseUrl?: string;
569
+ parseOptions?: ParseOptions;
570
+ styleOptions?: StyleConfig | StyleConfigV2;
571
+ }
572
+
573
+ /**
574
+ * v2: Extended PipelineConfig with raw HTML passthrough, slot hooks, and error recovery.
575
+ */
576
+ export declare interface PipelineConfigV2 extends PipelineConfig {
577
+ /** Optional telemetry logger for observability. Pass your own or a default console logger is used. */
578
+ logger?: LoggerInterface;
579
+ styleOptions?: StyleConfigV2;
580
+ /** Preserve raw HTML tags in markdown (img, style, div, span, etc.) (default: false) */
581
+ preserveRawHTML?: boolean;
582
+ /** Regex pattern for slot placeholders like [[SLOT_NAME]] (default: /\[\[(.*?)\]\]/g) */
583
+ slotPattern?: RegExp;
584
+ /** Callback to resolve slot values. Called with the slot name, returns replacement string. */
585
+ onSlot?: (name: string) => string;
586
+ /** Error recovery mode (default: 'throw' — backward compatible) */
587
+ errorRecovery?: 'throw' | 'warn' | 'silent';
588
+ /** Max recursion depth to prevent stack overflow (default: 100) */
589
+ maxRecursionDepth?: number;
590
+ /** Additional allowed HTML tags for preserveRawHTML mode */
591
+ allowedHTMLTags?: string[];
592
+ /**
593
+ * Allowed HTML attributes per tag for preserveRawHTML mode.
594
+ * Key "*" applies to all tags. Key "tag" applies to specific tags.
595
+ * Supports "data-*" wildcard prefix matching.
596
+ * Example: { "*": ["id", "class"], "script": ["type", "src"] }
597
+ */
598
+ allowedAttributes?: Record<string, string[]>;
599
+ }
600
+
601
+ /**
602
+ * Markdown Preprocessor
603
+ *
604
+ * Single responsibility: Transform markdown text before it reaches the lexer.
605
+ * Currently handles `:::` container block syntax conversion to HTML comments.
606
+ *
607
+ * This is the first stage in the parsing pipeline.
608
+ *
609
+ * Extensibility: Additional preprocessors can be composed via the
610
+ * CompositePipeline pattern (see composite-pipeline.ts).
611
+ */
612
+ export declare interface Preprocessor {
613
+ /** Name identifier for logging/debugging */
614
+ readonly name: string;
615
+ /** Transform the markdown before lexing */
616
+ process(markdown: string): string;
617
+ }
618
+
619
+ /**
620
+ * Context passed to every render strategy, providing access to
621
+ * shared rendering services and configuration.
622
+ */
623
+ export declare interface RenderContext {
624
+ classPrefix: string;
625
+ addHeadingIds: boolean;
626
+ emitScopeAnchors: boolean;
627
+ customCSS: string;
628
+ getClass(baseClass: string, nodeClass?: string): string;
629
+ getScopeAttr(node: ContentNode): string;
630
+ generateHeadingId(content?: string): string;
631
+ getContainerClass(tag: string): string;
632
+ hasClassConfig(): boolean;
633
+ }
634
+
635
+ /**
636
+ * Registry of renderer strategies. Maps ContentNode types to their
637
+ * rendering strategy. This is the renderer-side equivalent of
638
+ * TokenHandlerRegistry.
639
+ *
640
+ * The registry uses a two-tier lookup:
641
+ * 1. Check for a dedicated strategy by node type
642
+ * 2. Fall back to the catch-all strategy (registered as '*')
643
+ */
644
+ export declare class RendererStrategyRegistry {
645
+ private strategies;
646
+ private fallback;
647
+ constructor();
648
+ /** Register a strategy for a node type. Overrides any existing strategy. */
649
+ register(strategy: NodeRendererStrategy): void;
650
+ /** Unregister a strategy by node type. */
651
+ unregister(type: string): void;
652
+ /** Get a strategy for the given node type, falling back to catch-all. */
653
+ get(type: string): NodeRendererStrategy;
654
+ /** Check if a dedicated strategy exists for the given node type. */
655
+ has(type: string): boolean;
656
+ /** Get all registered dedicated strategy types. */
657
+ get types(): string[];
658
+ /** Replace the fallback strategy. */
659
+ setFallback(strategy: NodeRendererStrategy): void;
660
+ }
661
+
662
+ /** Scope hierarchy values for data-md-scope */
663
+ export declare type ScopeValue = 'root' | 'heading' | 'paragraph' | 'list' | 'list-item' | 'image' | 'code' | 'strong' | 'emphasis' | 'link' | 'container';
664
+
665
+ export declare interface StyleConfig {
666
+ classPrefix?: string;
667
+ customCSS?: string;
668
+ addHeadingIds?: boolean;
669
+ }
670
+
671
+ /**
672
+ * v2: Extended StyleConfig with scope anchor support.
673
+ */
674
+ export declare interface StyleConfigV2 extends StyleConfig {
675
+ /** Emit data-md-scope attributes for CSS @scope anchoring (default: false) */
676
+ emitScopeAnchors?: boolean;
677
+ }
678
+
679
+ /**
680
+ * A token handler knows how to convert a single marked token into a ContentNode.
681
+ * Handlers are registered by token type name in the handler registry.
682
+ */
683
+ export declare interface TokenHandler {
684
+ /** The marked token type this handler processes (e.g. 'heading', 'paragraph') */
685
+ readonly type: string;
686
+ /** Convert a marked token to a ContentNode (or null to skip) */
687
+ handle(token: Record<string, unknown>, ctx: ParseContext): ContentNode | null;
688
+ }
689
+
690
+ /**
691
+ * Registry of token handlers. Handlers can be added/overridden externally
692
+ * to extend the parser without modifying its internals.
693
+ *
694
+ * The registry uses a two-tier lookup:
695
+ * 1. First, check for a dedicated handler by token type name
696
+ * 2. If none found, fall back to the catch-all handler (registered as '*')
697
+ *
698
+ * The catch-all handler ensures no content is silently lost — unhandled
699
+ * token types are wrapped in a container node with `data-unhandled` attribute.
700
+ */
701
+ export declare class TokenHandlerRegistry {
702
+ private handlers;
703
+ private catchAll;
704
+ constructor();
705
+ /** Register a handler. Overrides any existing handler for the same token type. */
706
+ register(handler: TokenHandler): void;
707
+ /** Unregister a handler by token type. */
708
+ unregister(type: string): void;
709
+ /**
710
+ * Get a handler for the given token type.
711
+ * Falls back to the catch-all handler if no dedicated handler is registered.
712
+ */
713
+ get(type: string): TokenHandler;
714
+ /** Check if a dedicated handler exists for the given token type (excludes catch-all). */
715
+ has(type: string): boolean;
716
+ /** Get all registered dedicated handler types. */
717
+ get types(): string[];
718
+ /** Replace the catch-all handler with a custom implementation. */
719
+ setCatchAll(handler: TokenHandler): void;
720
+ /** Get the current catch-all handler. */
721
+ getCatchAll(): TokenHandler;
722
+ }
723
+
724
+ /**
725
+ * Token Postprocessor
726
+ *
727
+ * Single responsibility: Transform the flat array of marked tokens into
728
+ * a structured tree. Currently handles collapsing HTML comment markers
729
+ * (from container block preprocessing) into structured `containerBlock` tokens.
730
+ *
731
+ * This is the third stage in the parsing pipeline (after lexing).
732
+ */
733
+ export declare interface TokenPostprocessor {
734
+ /** Name identifier for logging/debugging */
735
+ readonly name: string;
736
+ /** Transform an array of tokens into an array of (possibly restructured) tokens */
737
+ process(tokens: unknown[]): unknown[];
738
+ }
739
+
740
+ /**
741
+ * Walk a ContentNode tree, applying a visitor at each node.
742
+ * Returns a new tree (immutable) — does not mutate the original.
743
+ */
744
+ export declare function walkTree(root: ContentNode, visitor: NodeVisitor): ContentNode;
745
+
746
+ export { }