@leadertechie/md2html 0.1.0-alpha.18 → 0.1.0-alpha.19
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/README.md +152 -2
- package/dist/index.d.ts +266 -28
- package/dist/index.js +452 -435
- package/dist/index.js.map +1 -1
- package/dist/index2.js +4 -325
- package/dist/index2.js.map +1 -1
- package/dist/lit-renderer-Bp1Q6wYL.js +790 -0
- package/dist/lit-renderer-Bp1Q6wYL.js.map +1 -0
- package/dist/lit-renderer.d.ts +46 -2
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -189,9 +189,94 @@ Additional safety with `maxRecursionDepth` (default: 100) to prevent stack overf
|
|
|
189
189
|
|
|
190
190
|
## Architecture (v2)
|
|
191
191
|
|
|
192
|
-
|
|
192
|
+
The pipeline is built from modular stages, each with a clear design pattern and single responsibility:
|
|
193
193
|
|
|
194
|
-
|
|
194
|
+
```
|
|
195
|
+
Markdown String
|
|
196
|
+
│
|
|
197
|
+
▼
|
|
198
|
+
┌──────────────────────────┐
|
|
199
|
+
│ 1. Preprocessor Chain │ Chain of Responsibility
|
|
200
|
+
│ (preprocessor.ts) │ Transforms raw markdown before lexing
|
|
201
|
+
│ • ContainerBlock │ (e.g., ::: containers → HTML comments)
|
|
202
|
+
└──────────┬───────────────┘
|
|
203
|
+
│
|
|
204
|
+
▼
|
|
205
|
+
┌──────────────────────────┐
|
|
206
|
+
│ 2. marked.lexer() │ Third-party lexer
|
|
207
|
+
└──────────┬───────────────┘
|
|
208
|
+
│
|
|
209
|
+
▼
|
|
210
|
+
┌──────────────────────────┐
|
|
211
|
+
│ 3. Token Postprocessor │ Chain of Responsibility
|
|
212
|
+
│ (token-postprocessor │ Restructures flat tokens → nested tree
|
|
213
|
+
│ .ts) │ (e.g., comments → containerBlock)
|
|
214
|
+
│ • ContainerBlock │
|
|
215
|
+
└──────────┬───────────────┘
|
|
216
|
+
│
|
|
217
|
+
▼
|
|
218
|
+
┌──────────────────────────┐
|
|
219
|
+
│ 4. Token Handlers │ Strategy Pattern
|
|
220
|
+
│ (handlers/) │ Each marked token type has a dedicated
|
|
221
|
+
│ • TokenHandlerRegistry│ handler, registered by type name.
|
|
222
|
+
│ • CatchAllHandler │ Extensible at runtime via registry.
|
|
223
|
+
└──────────┬───────────────┘
|
|
224
|
+
│
|
|
225
|
+
▼
|
|
226
|
+
ContentNode[]
|
|
227
|
+
(AST)
|
|
228
|
+
│
|
|
229
|
+
▼
|
|
230
|
+
┌──────────────────────────┐
|
|
231
|
+
│ 5. Renderer │ Strategy Pattern
|
|
232
|
+
│ (renderer-strategies │ Each ContentNode type has its own
|
|
233
|
+
│ .ts / lit-strategies │ render strategy — choose between:
|
|
234
|
+
│ .ts) │ • HTMLRenderer (plain HTML strings)
|
|
235
|
+
│ • NodeRendererStrategy│ • LitRenderer (Lit TemplateResult)
|
|
236
|
+
│ • LitNodeRendererStrat│
|
|
237
|
+
└──────────────────────────┘
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### 1. Preprocessing (`preprocessor.ts`)
|
|
241
|
+
|
|
242
|
+
The `CompositePreprocessor` chains `Preprocessor` transforms that run on raw markdown **before** lexing. Built-in:
|
|
243
|
+
|
|
244
|
+
- **`ContainerBlockPreprocessor`** — converts `:::tag#id.class` fences to `<!-- md-container:... -->` HTML comment markers, so `marked` preserves them without affecting inner markdown parsing
|
|
245
|
+
|
|
246
|
+
The chain is extensible:
|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
import { MarkdownParser, Preprocessor } from '@leadertechie/md2html';
|
|
250
|
+
|
|
251
|
+
class EmojiPreprocessor implements Preprocessor {
|
|
252
|
+
readonly name = 'emoji';
|
|
253
|
+
process(markdown: string): string {
|
|
254
|
+
return markdown.replace(':smile:', '😊');
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const parser = new MarkdownParser();
|
|
259
|
+
parser.preprocessors.add(new EmojiPreprocessor());
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### 2. Token Postprocessing (`token-postprocessor.ts`)
|
|
263
|
+
|
|
264
|
+
The `CompositeTokenPostprocessor` chains `TokenPostprocessor` transforms that run on the flat token array **after** lexing. Built-in:
|
|
265
|
+
|
|
266
|
+
- **`ContainerBlockPostprocessor`** — collapses `<!-- md-container:... -->` / `<!-- /md-container -->` markers into nested `containerBlock` tokens with proper parent-child structure (handles arbitrary nesting depth)
|
|
267
|
+
|
|
268
|
+
Custom postprocessors:
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
parser.postprocessors.add({
|
|
272
|
+
name: 'filter-unwanted',
|
|
273
|
+
process: (tokens) => tokens.filter(t => (t as any).type !== 'html')
|
|
274
|
+
});
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### 3. Token Handling — Strategy Pattern (`handlers/`)
|
|
278
|
+
|
|
279
|
+
Each marked token type has its own `TokenHandler` class, registered in the `TokenHandlerRegistry`:
|
|
195
280
|
|
|
196
281
|
```
|
|
197
282
|
src/handlers/
|
|
@@ -205,6 +290,10 @@ src/handlers/
|
|
|
205
290
|
├── hr-handler.ts # <hr>
|
|
206
291
|
├── blockquote-handler.ts # <blockquote>
|
|
207
292
|
├── html-handler.ts # raw HTML passthrough
|
|
293
|
+
├── link-handler.ts # <a>
|
|
294
|
+
├── frontmatter-handler.ts# YAML frontmatter metadata
|
|
295
|
+
├── container-block- # ::: container blocks
|
|
296
|
+
│ handler.ts
|
|
208
297
|
└── catchall-handler.ts # fallback for unregistered types
|
|
209
298
|
```
|
|
210
299
|
|
|
@@ -253,6 +342,67 @@ const parser = new MarkdownParser({
|
|
|
253
342
|
});
|
|
254
343
|
```
|
|
255
344
|
|
|
345
|
+
### 4. Rendering — Strategy Pattern (`renderer-strategies.ts`, `lit-strategies.ts`)
|
|
346
|
+
|
|
347
|
+
The AST renderers use the same Strategy + Registry pattern as the token handlers:
|
|
348
|
+
|
|
349
|
+
- **`HTMLRenderer`** — produces plain HTML strings. Uses `NodeRendererStrategy` / `RendererStrategyRegistry` for each node type. Supports `classPrefix`, `addHeadingIds`, and `emitScopeAnchors` styling.
|
|
350
|
+
- **`LitRenderer`** — produces Lit `TemplateResult` objects. Uses `LitNodeRendererStrategy` / `LitStrategyRegistry`. Perfect for Lit web components.
|
|
351
|
+
|
|
352
|
+
Both registries are publicly accessible for customization:
|
|
353
|
+
|
|
354
|
+
```typescript
|
|
355
|
+
import { HTMLRenderer, NodeRendererStrategy } from '@leadertechie/md2html';
|
|
356
|
+
|
|
357
|
+
const renderer = new HTMLRenderer({ classPrefix: 'my-' });
|
|
358
|
+
|
|
359
|
+
// Register a custom strategy
|
|
360
|
+
renderer.strategies.register({
|
|
361
|
+
type: 'custom',
|
|
362
|
+
render: (node, renderChild, ctx) => `<my-el>${node.content}</my-el>`
|
|
363
|
+
});
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
The `LitRenderer.renderToHTMLString()` delegates to `HTMLRenderer` to avoid duplicating string rendering logic.
|
|
367
|
+
|
|
368
|
+
### 5. Context Factory (`context-factory.ts`)
|
|
369
|
+
|
|
370
|
+
The `createParseContext()` pure function separates context construction from the parser class. It bridges parser services (image processing, slot resolution, HTML sanitization) to token handlers via the `ParserServices` interface. This makes the context testable in isolation and decouples handler logic from parser internals.
|
|
371
|
+
|
|
372
|
+
### Source Map
|
|
373
|
+
|
|
374
|
+
```
|
|
375
|
+
src/
|
|
376
|
+
├── parser.ts # Orchestrator: coordinates pre/post-processing + token handling
|
|
377
|
+
├── preprocessor.ts # Chain of Responsibility: markdown transforms before lexing
|
|
378
|
+
├── token-postprocessor.ts # Chain of Responsibility: token transforms after lexing
|
|
379
|
+
├── context-factory.ts # Factory: creates ParseContext for token handlers
|
|
380
|
+
├── handlers/ # Strategy: per-token-type ContentNode producers
|
|
381
|
+
│ ├── types.ts
|
|
382
|
+
│ ├── registry.ts
|
|
383
|
+
│ ├── heading-handler.ts
|
|
384
|
+
│ ├── paragraph-handler.ts
|
|
385
|
+
│ ├── list-handler.ts
|
|
386
|
+
│ ├── image-handler.ts
|
|
387
|
+
│ ├── code-handler.ts
|
|
388
|
+
│ ├── hr-handler.ts
|
|
389
|
+
│ ├── blockquote-handler.ts
|
|
390
|
+
│ ├── html-handler.ts
|
|
391
|
+
│ ├── link-handler.ts
|
|
392
|
+
│ ├── frontmatter-handler.ts
|
|
393
|
+
│ ├── container-block-handler.ts
|
|
394
|
+
│ └── catchall-handler.ts
|
|
395
|
+
├── renderer.ts # HTMLRenderer: transforms ContentNodes to plain HTML
|
|
396
|
+
├── renderer-strategies.ts # Strategy: per-node-type HTML string renderers
|
|
397
|
+
├── lit-renderer.ts # LitRenderer: transforms ContentNodes to Lit TemplateResult
|
|
398
|
+
├── lit-strategies.ts # Strategy: per-node-type Lit TemplateResult renderers
|
|
399
|
+
├── visitor.ts # Visitor: tree traversal utilities
|
|
400
|
+
├── factory.ts # NodeFactory: ContentNode builder API
|
|
401
|
+
├── pipeline.ts # Facade: high-level MarkdownPipeline API
|
|
402
|
+
├── types.ts # Core types: ContentNode, MarkdownContent, configs
|
|
403
|
+
└── telemetry-init.ts # Shared logger initialization
|
|
404
|
+
```
|
|
405
|
+
|
|
256
406
|
## License
|
|
257
407
|
|
|
258
408
|
MIT
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { LoggerInterface } from '@leadertechie/telemetry';
|
|
2
|
+
import { TemplateResult } from 'lit';
|
|
3
|
+
|
|
1
4
|
/**
|
|
2
5
|
* Handles 'blockquote' tokens.
|
|
3
6
|
*/
|
|
@@ -71,6 +74,42 @@ export declare function collectImages(root: ContentNode): Array<{
|
|
|
71
74
|
alt: string;
|
|
72
75
|
}>;
|
|
73
76
|
|
|
77
|
+
/**
|
|
78
|
+
* Sequentially applies multiple preprocessors to the markdown.
|
|
79
|
+
* Each preprocessor's output becomes the next one's input.
|
|
80
|
+
*
|
|
81
|
+
* This follows the Chain of Responsibility pattern — you can add
|
|
82
|
+
* new preprocessors without modifying existing code.
|
|
83
|
+
*/
|
|
84
|
+
export declare class CompositePreprocessor implements Preprocessor {
|
|
85
|
+
readonly name = "composite";
|
|
86
|
+
private processors;
|
|
87
|
+
constructor(processors?: Preprocessor[]);
|
|
88
|
+
/** Add a preprocessor to the chain. Returns `this` for fluent API. */
|
|
89
|
+
add(processor: Preprocessor): this;
|
|
90
|
+
/** Remove a preprocessor by name. */
|
|
91
|
+
remove(name: string): void;
|
|
92
|
+
/** Get the list of registered preprocessors. */
|
|
93
|
+
getProcessors(): ReadonlyArray<Preprocessor>;
|
|
94
|
+
process(markdown: string): string;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Sequentially applies multiple postprocessors to the token array.
|
|
99
|
+
*/
|
|
100
|
+
export declare class CompositeTokenPostprocessor implements TokenPostprocessor {
|
|
101
|
+
readonly name = "composite";
|
|
102
|
+
private processors;
|
|
103
|
+
constructor(processors?: TokenPostprocessor[]);
|
|
104
|
+
/** Add a postprocessor to the chain. Returns `this` for fluent API. */
|
|
105
|
+
add(processor: TokenPostprocessor): this;
|
|
106
|
+
/** Remove a postprocessor by name. */
|
|
107
|
+
remove(name: string): void;
|
|
108
|
+
/** Get the list of registered postprocessors. */
|
|
109
|
+
getProcessors(): ReadonlyArray<TokenPostprocessor>;
|
|
110
|
+
process(tokens: unknown[]): unknown[];
|
|
111
|
+
}
|
|
112
|
+
|
|
74
113
|
/**
|
|
75
114
|
* ContainerBlockHandler — handles custom :::tag#id.class container blocks.
|
|
76
115
|
*
|
|
@@ -88,6 +127,39 @@ export declare class ContainerBlockHandler implements TokenHandler {
|
|
|
88
127
|
handle(token: Record<string, unknown>, ctx: ParseContext): ContentNode | null;
|
|
89
128
|
}
|
|
90
129
|
|
|
130
|
+
/**
|
|
131
|
+
* Collapses `<!-- md-container:... -->` and `<!-- /md-container -->` comment
|
|
132
|
+
* markers into nested `containerBlock` tokens with proper parent-child structure.
|
|
133
|
+
*
|
|
134
|
+
* Handles nesting depth up to any reasonable limit (depends on stack memory).
|
|
135
|
+
*/
|
|
136
|
+
export declare class ContainerBlockPostprocessor implements TokenPostprocessor {
|
|
137
|
+
readonly name = "container-blocks";
|
|
138
|
+
process(tokens: unknown[]): unknown[];
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Converts `:::tag#id.class` container syntax into HTML comment markers
|
|
143
|
+
* that marked will preserve as HTML tokens, without affecting markdown parsing
|
|
144
|
+
* of the inner content.
|
|
145
|
+
*
|
|
146
|
+
* Example:
|
|
147
|
+
* :::section#header
|
|
148
|
+
* # Heading inside container
|
|
149
|
+
* Some text
|
|
150
|
+
* :::
|
|
151
|
+
*
|
|
152
|
+
* Becomes:
|
|
153
|
+
* <!-- md-container:section#header -->
|
|
154
|
+
* # Heading inside container
|
|
155
|
+
* Some text
|
|
156
|
+
* <!-- /md-container -->
|
|
157
|
+
*/
|
|
158
|
+
export declare class ContainerBlockPreprocessor implements Preprocessor {
|
|
159
|
+
readonly name = "container-blocks";
|
|
160
|
+
process(markdown: string): string;
|
|
161
|
+
}
|
|
162
|
+
|
|
91
163
|
export declare interface ContentNode {
|
|
92
164
|
type: ContentNodeType;
|
|
93
165
|
content?: string;
|
|
@@ -105,6 +177,23 @@ export declare interface ContentNode {
|
|
|
105
177
|
|
|
106
178
|
export declare type ContentNodeType = 'text' | 'heading' | 'paragraph' | 'list' | 'list-item' | 'image' | 'code' | 'container' | 'strong' | 'emphasis' | 'link';
|
|
107
179
|
|
|
180
|
+
/** Default postprocessor chain with the built-in container block support. */
|
|
181
|
+
export declare function createDefaultPostprocessor(): CompositeTokenPostprocessor;
|
|
182
|
+
|
|
183
|
+
/** Default preprocessor chain with the built-in container block support. */
|
|
184
|
+
export declare function createDefaultPreprocessor(): CompositePreprocessor;
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Create a ParseContext from parser services.
|
|
188
|
+
*
|
|
189
|
+
* Each call creates a fresh context with its own metadata store,
|
|
190
|
+
* allowing for clean separation between recursive parse calls.
|
|
191
|
+
*
|
|
192
|
+
* The getters use closures to lazily access the parser's current state,
|
|
193
|
+
* so the context always reflects the latest configuration.
|
|
194
|
+
*/
|
|
195
|
+
export declare function createParseContext(services: ParserServices): ParseContext;
|
|
196
|
+
|
|
108
197
|
/** Default allowed HTML tags for preserveRawHTML mode */
|
|
109
198
|
export declare const defaultAllowedHTMLTags: string[];
|
|
110
199
|
|
|
@@ -239,6 +328,118 @@ export declare class ListHandler implements TokenHandler {
|
|
|
239
328
|
};
|
|
240
329
|
}
|
|
241
330
|
|
|
331
|
+
export declare class LitCodeStrategy implements LitNodeRendererStrategy {
|
|
332
|
+
readonly type = "code";
|
|
333
|
+
render(node: ContentNode, _renderChild: (child: ContentNode) => TemplateResult): TemplateResult;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
export declare class LitContainerStrategy implements LitNodeRendererStrategy {
|
|
337
|
+
readonly type = "container";
|
|
338
|
+
render(node: ContentNode, renderChild: (child: ContentNode) => TemplateResult): TemplateResult;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
export declare class LitEmphasisStrategy implements LitNodeRendererStrategy {
|
|
342
|
+
readonly type = "emphasis";
|
|
343
|
+
render(node: ContentNode, _renderChild: (child: ContentNode) => TemplateResult): TemplateResult;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
export declare class LitFallbackStrategy implements LitNodeRendererStrategy {
|
|
347
|
+
readonly type = "*";
|
|
348
|
+
render(_node: ContentNode, _renderChild: (child: ContentNode) => TemplateResult): TemplateResult;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
export declare class LitHeadingStrategy implements LitNodeRendererStrategy {
|
|
352
|
+
readonly type = "heading";
|
|
353
|
+
render(node: ContentNode, _renderChild: (child: ContentNode) => TemplateResult): TemplateResult;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
export declare class LitImageStrategy implements LitNodeRendererStrategy {
|
|
357
|
+
readonly type = "image";
|
|
358
|
+
render(node: ContentNode, _renderChild: (child: ContentNode) => TemplateResult): TemplateResult;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
export declare class LitLinkStrategy implements LitNodeRendererStrategy {
|
|
362
|
+
readonly type = "link";
|
|
363
|
+
render(node: ContentNode, _renderChild: (child: ContentNode) => TemplateResult): TemplateResult;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
export declare class LitListItemStrategy implements LitNodeRendererStrategy {
|
|
367
|
+
readonly type = "list-item";
|
|
368
|
+
render(node: ContentNode, _renderChild: (child: ContentNode) => TemplateResult): TemplateResult;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
export declare class LitListStrategy implements LitNodeRendererStrategy {
|
|
372
|
+
readonly type = "list";
|
|
373
|
+
render(node: ContentNode, renderChild: (child: ContentNode) => TemplateResult): TemplateResult;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
export declare interface LitNodeRendererStrategy {
|
|
377
|
+
/** The ContentNode type this strategy handles */
|
|
378
|
+
readonly type: string;
|
|
379
|
+
/** Render a node to a Lit TemplateResult */
|
|
380
|
+
render(node: ContentNode, renderChild: (child: ContentNode) => TemplateResult): TemplateResult;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
export declare class LitParagraphStrategy implements LitNodeRendererStrategy {
|
|
384
|
+
readonly type = "paragraph";
|
|
385
|
+
render(node: ContentNode, renderChild: (child: ContentNode) => TemplateResult): TemplateResult;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
export declare class LitRenderer {
|
|
389
|
+
private strategyRegistry;
|
|
390
|
+
/** Lazily created HTMLRenderer for string output, sharing the same config */
|
|
391
|
+
private htmlRenderer?;
|
|
392
|
+
constructor();
|
|
393
|
+
/** Access the strategy registry for customization. */
|
|
394
|
+
get strategies(): LitStrategyRegistry;
|
|
395
|
+
/**
|
|
396
|
+
* Render a single node to a Lit TemplateResult.
|
|
397
|
+
*/
|
|
398
|
+
renderNode(node: ContentNode): TemplateResult;
|
|
399
|
+
/**
|
|
400
|
+
* Render an array of nodes to a single Lit TemplateResult.
|
|
401
|
+
*/
|
|
402
|
+
renderNodes(nodes: ContentNode[]): TemplateResult;
|
|
403
|
+
/**
|
|
404
|
+
* Render nodes to a plain HTML string.
|
|
405
|
+
* Delegates to HTMLRenderer to avoid duplicating string rendering logic.
|
|
406
|
+
*
|
|
407
|
+
* Note: Uses default HTMLRenderer config (no classPrefix, scope anchors,
|
|
408
|
+
* or heading IDs). For full HTML rendering with those features,
|
|
409
|
+
* use HTMLRenderer directly.
|
|
410
|
+
*/
|
|
411
|
+
renderToHTMLString(nodes: ContentNode[]): string;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Registry of Lit renderer strategies.
|
|
416
|
+
*
|
|
417
|
+
* Two-tier lookup:
|
|
418
|
+
* 1. Dedicated strategy by node type
|
|
419
|
+
* 2. Fallback to a catch-all strategy (default: renders empty)
|
|
420
|
+
*/
|
|
421
|
+
export declare class LitStrategyRegistry {
|
|
422
|
+
private strategies;
|
|
423
|
+
private fallback;
|
|
424
|
+
constructor();
|
|
425
|
+
register(strategy: LitNodeRendererStrategy): void;
|
|
426
|
+
unregister(type: string): void;
|
|
427
|
+
get(type: string): LitNodeRendererStrategy;
|
|
428
|
+
has(type: string): boolean;
|
|
429
|
+
get types(): string[];
|
|
430
|
+
setFallback(strategy: LitNodeRendererStrategy): void;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
export declare class LitStrongStrategy implements LitNodeRendererStrategy {
|
|
434
|
+
readonly type = "strong";
|
|
435
|
+
render(node: ContentNode, _renderChild: (child: ContentNode) => TemplateResult): TemplateResult;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
export declare class LitTextStrategy implements LitNodeRendererStrategy {
|
|
439
|
+
readonly type = "text";
|
|
440
|
+
render(node: ContentNode, _renderChild: (child: ContentNode) => TemplateResult): TemplateResult;
|
|
441
|
+
}
|
|
442
|
+
|
|
242
443
|
export declare interface MarkdownContent {
|
|
243
444
|
title: string;
|
|
244
445
|
metadata?: Record<string, unknown>;
|
|
@@ -257,9 +458,16 @@ export declare class MarkdownParser {
|
|
|
257
458
|
private allowedAttributes;
|
|
258
459
|
private handlerRegistry;
|
|
259
460
|
private onUnhandledToken?;
|
|
461
|
+
private log;
|
|
462
|
+
private preprocessor;
|
|
463
|
+
private postprocessor;
|
|
260
464
|
constructor(options?: ParserOptions);
|
|
261
465
|
/** Access the handler registry for customization. */
|
|
262
466
|
get handlers(): TokenHandlerRegistry;
|
|
467
|
+
/** Access the preprocessor chain for customization. */
|
|
468
|
+
get preprocessors(): CompositePreprocessor;
|
|
469
|
+
/** Access the token postprocessor chain for customization. */
|
|
470
|
+
get postprocessors(): CompositeTokenPostprocessor;
|
|
263
471
|
private processImagePath;
|
|
264
472
|
private processInlineFormatting;
|
|
265
473
|
private processSlots;
|
|
@@ -279,41 +487,16 @@ export declare class MarkdownParser {
|
|
|
279
487
|
private filterTagAttributes;
|
|
280
488
|
private processRawHTML;
|
|
281
489
|
/**
|
|
282
|
-
* Build
|
|
283
|
-
*
|
|
490
|
+
* Build a ParserServices object that bridges the parser's private methods
|
|
491
|
+
* to the ParseContext factory. This keeps context creation decoupled.
|
|
284
492
|
*/
|
|
285
|
-
private
|
|
493
|
+
private buildServices;
|
|
286
494
|
/**
|
|
287
495
|
* Process an array of marked tokens into ContentNodes.
|
|
288
496
|
* When depth === 0 (root), creates a shared context that accumulates metadata.
|
|
289
497
|
* For recursive calls (depth > 0), creates a fresh context for each level.
|
|
290
498
|
*/
|
|
291
499
|
private parseTokens;
|
|
292
|
-
/**
|
|
293
|
-
* Pre-process markdown: convert `:::tag#id.class` container syntax
|
|
294
|
-
* into HTML comment markers that marked will preserve as html tokens,
|
|
295
|
-
* but won't affect markdown parsing of the inner content.
|
|
296
|
-
*
|
|
297
|
-
* Example:
|
|
298
|
-
* :::section#header
|
|
299
|
-
* # Heading inside container
|
|
300
|
-
* Some text
|
|
301
|
-
* :::
|
|
302
|
-
*
|
|
303
|
-
* Becomes:
|
|
304
|
-
* <!-- md-container:section#header -->
|
|
305
|
-
* # Heading inside container
|
|
306
|
-
* Some text
|
|
307
|
-
* <!-- /md-container -->
|
|
308
|
-
*/
|
|
309
|
-
private preprocessContainerBlocks;
|
|
310
|
-
/**
|
|
311
|
-
* Post-process marked tokens to collapse container block markers
|
|
312
|
-
* into structured containerBlock tokens with proper nesting.
|
|
313
|
-
*
|
|
314
|
-
* This handles nesting depth up to maxRecursionDepth.
|
|
315
|
-
*/
|
|
316
|
-
private postprocessTokens;
|
|
317
500
|
parse(markdown: string, options?: ParseOptions): MarkdownContent;
|
|
318
501
|
parseToNodes(markdown: string, options?: ParseOptions): ContentNode[];
|
|
319
502
|
}
|
|
@@ -322,6 +505,7 @@ export declare class MarkdownPipeline {
|
|
|
322
505
|
private parser;
|
|
323
506
|
private renderer;
|
|
324
507
|
private config;
|
|
508
|
+
private log;
|
|
325
509
|
constructor(config?: PipelineConfigV2);
|
|
326
510
|
parse(markdown: string): ContentNode[];
|
|
327
511
|
parseWithMetadata(markdown: string): MarkdownContent;
|
|
@@ -448,6 +632,8 @@ export declare interface ParseOptions {
|
|
|
448
632
|
}
|
|
449
633
|
|
|
450
634
|
export declare interface ParserOptions {
|
|
635
|
+
/** Optional telemetry logger */
|
|
636
|
+
logger?: LoggerInterface;
|
|
451
637
|
imagePathPrefix?: string;
|
|
452
638
|
imageBaseUrl?: string;
|
|
453
639
|
preserveRawHTML?: boolean;
|
|
@@ -474,6 +660,22 @@ export declare interface ParserOptions {
|
|
|
474
660
|
onUnhandledToken?: (type: string, token: Record<string, unknown>) => void;
|
|
475
661
|
}
|
|
476
662
|
|
|
663
|
+
/**
|
|
664
|
+
* Services needed by the ParseContext factory.
|
|
665
|
+
* This is the interface the parser exposes to context creation.
|
|
666
|
+
*/
|
|
667
|
+
export declare interface ParserServices {
|
|
668
|
+
preserveRawHTML: boolean;
|
|
669
|
+
errorRecovery: 'throw' | 'warn' | 'silent';
|
|
670
|
+
maxRecursionDepth: number;
|
|
671
|
+
processImagePath(src: string): string;
|
|
672
|
+
processInlineFormatting(text: string): string;
|
|
673
|
+
processSlots(text: string): string;
|
|
674
|
+
processRawHTML(html: string): string;
|
|
675
|
+
parseTokens(tokens: unknown[], depth: number): ContentNode[];
|
|
676
|
+
onUnhandledToken?: (type: string, token: Record<string, unknown>) => void;
|
|
677
|
+
}
|
|
678
|
+
|
|
477
679
|
export declare interface PipelineConfig {
|
|
478
680
|
imagePathPrefix?: string;
|
|
479
681
|
imageBaseUrl?: string;
|
|
@@ -485,6 +687,8 @@ export declare interface PipelineConfig {
|
|
|
485
687
|
* v2: Extended PipelineConfig with raw HTML passthrough, slot hooks, and error recovery.
|
|
486
688
|
*/
|
|
487
689
|
export declare interface PipelineConfigV2 extends PipelineConfig {
|
|
690
|
+
/** Optional telemetry logger for observability. Pass your own or a default console logger is used. */
|
|
691
|
+
logger?: LoggerInterface;
|
|
488
692
|
styleOptions?: StyleConfigV2;
|
|
489
693
|
/** Preserve raw HTML tags in markdown (img, style, div, span, etc.) (default: false) */
|
|
490
694
|
preserveRawHTML?: boolean;
|
|
@@ -507,6 +711,24 @@ export declare interface PipelineConfigV2 extends PipelineConfig {
|
|
|
507
711
|
allowedAttributes?: Record<string, string[]>;
|
|
508
712
|
}
|
|
509
713
|
|
|
714
|
+
/**
|
|
715
|
+
* Markdown Preprocessor
|
|
716
|
+
*
|
|
717
|
+
* Single responsibility: Transform markdown text before it reaches the lexer.
|
|
718
|
+
* Currently handles `:::` container block syntax conversion to HTML comments.
|
|
719
|
+
*
|
|
720
|
+
* This is the first stage in the parsing pipeline.
|
|
721
|
+
*
|
|
722
|
+
* Extensibility: Additional preprocessors can be composed via the
|
|
723
|
+
* CompositePipeline pattern (see composite-pipeline.ts).
|
|
724
|
+
*/
|
|
725
|
+
export declare interface Preprocessor {
|
|
726
|
+
/** Name identifier for logging/debugging */
|
|
727
|
+
readonly name: string;
|
|
728
|
+
/** Transform the markdown before lexing */
|
|
729
|
+
process(markdown: string): string;
|
|
730
|
+
}
|
|
731
|
+
|
|
510
732
|
/**
|
|
511
733
|
* Context passed to every render strategy, providing access to
|
|
512
734
|
* shared rendering services and configuration.
|
|
@@ -612,6 +834,22 @@ export declare class TokenHandlerRegistry {
|
|
|
612
834
|
getCatchAll(): TokenHandler;
|
|
613
835
|
}
|
|
614
836
|
|
|
837
|
+
/**
|
|
838
|
+
* Token Postprocessor
|
|
839
|
+
*
|
|
840
|
+
* Single responsibility: Transform the flat array of marked tokens into
|
|
841
|
+
* a structured tree. Currently handles collapsing HTML comment markers
|
|
842
|
+
* (from container block preprocessing) into structured `containerBlock` tokens.
|
|
843
|
+
*
|
|
844
|
+
* This is the third stage in the parsing pipeline (after lexing).
|
|
845
|
+
*/
|
|
846
|
+
export declare interface TokenPostprocessor {
|
|
847
|
+
/** Name identifier for logging/debugging */
|
|
848
|
+
readonly name: string;
|
|
849
|
+
/** Transform an array of tokens into an array of (possibly restructured) tokens */
|
|
850
|
+
process(tokens: unknown[]): unknown[];
|
|
851
|
+
}
|
|
852
|
+
|
|
615
853
|
/**
|
|
616
854
|
* Walk a ContentNode tree, applying a visitor at each node.
|
|
617
855
|
* Returns a new tree (immutable) — does not mutate the original.
|