@bernierllc/markdown-parser 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.
Files changed (61) hide show
  1. package/.eslintrc.js +27 -0
  2. package/README.md +325 -0
  3. package/__tests__/MarkdownParser.test.ts +787 -0
  4. package/__tests__/ast-utils.test.ts +319 -0
  5. package/__tests__/cache.test.ts +243 -0
  6. package/__tests__/plugins.test.ts +282 -0
  7. package/coverage/clover.xml +283 -0
  8. package/coverage/coverage-final.json +7 -0
  9. package/coverage/lcov-report/base.css +224 -0
  10. package/coverage/lcov-report/block-navigation.js +87 -0
  11. package/coverage/lcov-report/favicon.png +0 -0
  12. package/coverage/lcov-report/index.html +146 -0
  13. package/coverage/lcov-report/prettify.css +1 -0
  14. package/coverage/lcov-report/prettify.js +2 -0
  15. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  16. package/coverage/lcov-report/sorter.js +210 -0
  17. package/coverage/lcov-report/src/MarkdownParser.ts.html +1636 -0
  18. package/coverage/lcov-report/src/index.html +116 -0
  19. package/coverage/lcov-report/src/plugins/commonmark.ts.html +154 -0
  20. package/coverage/lcov-report/src/plugins/gfm.ts.html +154 -0
  21. package/coverage/lcov-report/src/plugins/index.html +146 -0
  22. package/coverage/lcov-report/src/plugins/index.ts.html +115 -0
  23. package/coverage/lcov-report/src/utils/ast-utils.ts.html +328 -0
  24. package/coverage/lcov-report/src/utils/cache.ts.html +403 -0
  25. package/coverage/lcov-report/src/utils/index.html +131 -0
  26. package/coverage/lcov.info +457 -0
  27. package/dist/MarkdownParser.d.ts +46 -0
  28. package/dist/MarkdownParser.d.ts.map +1 -0
  29. package/dist/MarkdownParser.js +458 -0
  30. package/dist/index.d.ts +6 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +31 -0
  33. package/dist/plugins/commonmark.d.ts +6 -0
  34. package/dist/plugins/commonmark.d.ts.map +1 -0
  35. package/dist/plugins/commonmark.js +23 -0
  36. package/dist/plugins/gfm.d.ts +6 -0
  37. package/dist/plugins/gfm.d.ts.map +1 -0
  38. package/dist/plugins/gfm.js +23 -0
  39. package/dist/plugins/index.d.ts +3 -0
  40. package/dist/plugins/index.d.ts.map +1 -0
  41. package/dist/plugins/index.js +25 -0
  42. package/dist/types.d.ts +78 -0
  43. package/dist/types.d.ts.map +1 -0
  44. package/dist/types.js +9 -0
  45. package/dist/utils/ast-utils.d.ts +22 -0
  46. package/dist/utils/ast-utils.d.ts.map +1 -0
  47. package/dist/utils/ast-utils.js +81 -0
  48. package/dist/utils/cache.d.ts +39 -0
  49. package/dist/utils/cache.d.ts.map +1 -0
  50. package/dist/utils/cache.js +91 -0
  51. package/jest.config.cjs +28 -0
  52. package/package.json +44 -0
  53. package/src/MarkdownParser.ts +517 -0
  54. package/src/index.ts +13 -0
  55. package/src/plugins/commonmark.ts +23 -0
  56. package/src/plugins/gfm.ts +23 -0
  57. package/src/plugins/index.ts +10 -0
  58. package/src/types.ts +114 -0
  59. package/src/utils/ast-utils.ts +81 -0
  60. package/src/utils/cache.ts +106 -0
  61. package/tsconfig.json +30 -0
@@ -0,0 +1,458 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.MarkdownParser = void 0;
11
+ const cache_1 = require("./utils/cache");
12
+ const ast_utils_1 = require("./utils/ast-utils");
13
+ /**
14
+ * High-performance markdown parser with caching and plugin support
15
+ */
16
+ class MarkdownParser {
17
+ constructor(config) {
18
+ this.config = {
19
+ gfm: config?.gfm ?? true,
20
+ commonmark: config?.commonmark ?? true,
21
+ plugins: config?.plugins ?? [],
22
+ cache: {
23
+ enabled: config?.cache?.enabled ?? false,
24
+ maxSize: config?.cache?.maxSize ?? 1000,
25
+ ttl: config?.cache?.ttl ?? 3600,
26
+ },
27
+ logger: config?.logger ?? console,
28
+ };
29
+ this.cacheManager = this.config.cache.enabled
30
+ ? new cache_1.CacheManager(this.config.cache.maxSize, this.config.cache.ttl)
31
+ : null;
32
+ this.logger = this.config.logger;
33
+ }
34
+ /**
35
+ * Parse markdown string to AST
36
+ */
37
+ async parse(markdown) {
38
+ const startTime = Date.now();
39
+ // Check cache
40
+ if (this.cacheManager) {
41
+ const cacheKey = this.cacheManager.generateKey(markdown);
42
+ const cached = this.cacheManager.get(cacheKey);
43
+ if (cached) {
44
+ this.logger.debug('Markdown parse cache hit', { cacheKey });
45
+ return {
46
+ success: true,
47
+ ast: cached,
48
+ metadata: {
49
+ parseTime: Date.now() - startTime,
50
+ nodeCount: (0, ast_utils_1.countNodes)(cached),
51
+ cached: true,
52
+ },
53
+ };
54
+ }
55
+ }
56
+ try {
57
+ // Parse markdown to AST
58
+ let ast = await this.parseToAST(markdown);
59
+ // Apply plugins
60
+ for (const plugin of this.config.plugins) {
61
+ ast = plugin.transform(ast);
62
+ }
63
+ // Cache result
64
+ if (this.cacheManager) {
65
+ const cacheKey = this.cacheManager.generateKey(markdown);
66
+ this.cacheManager.set(cacheKey, ast);
67
+ }
68
+ const parseTime = Date.now() - startTime;
69
+ this.logger.debug('Markdown parsed successfully', {
70
+ parseTime,
71
+ nodeCount: (0, ast_utils_1.countNodes)(ast),
72
+ });
73
+ return {
74
+ success: true,
75
+ ast,
76
+ metadata: {
77
+ parseTime,
78
+ nodeCount: (0, ast_utils_1.countNodes)(ast),
79
+ cached: false,
80
+ },
81
+ };
82
+ }
83
+ catch (err) {
84
+ const error = err instanceof Error ? err : new Error('Unknown parse error');
85
+ this.logger.error('Markdown parse failed', error);
86
+ return {
87
+ success: false,
88
+ error: error.message,
89
+ };
90
+ }
91
+ }
92
+ /**
93
+ * Core parsing logic (CommonMark + GFM)
94
+ */
95
+ async parseToAST(markdown) {
96
+ const lines = markdown.split('\n');
97
+ const root = { type: 'root', children: [] };
98
+ let lineNumber = 0;
99
+ let i = 0;
100
+ while (i < lines.length) {
101
+ const line = lines[i];
102
+ lineNumber = i + 1;
103
+ // Skip empty lines
104
+ if (!line.trim()) {
105
+ i++;
106
+ continue;
107
+ }
108
+ // Heading
109
+ const headingMatch = line.match(/^(#{1,6})\s+(.+)$/);
110
+ if (headingMatch) {
111
+ const level = headingMatch[1].length;
112
+ const text = headingMatch[2].trim();
113
+ root.children.push({
114
+ type: 'heading',
115
+ attributes: { level },
116
+ children: this.parseInline(text),
117
+ position: this.createPosition(lineNumber, 0, line.length),
118
+ });
119
+ i++;
120
+ continue;
121
+ }
122
+ // Horizontal rule
123
+ if (line.match(/^(\*{3,}|-{3,}|_{3,})$/)) {
124
+ root.children.push({
125
+ type: 'horizontalRule',
126
+ position: this.createPosition(lineNumber, 0, line.length),
127
+ });
128
+ i++;
129
+ continue;
130
+ }
131
+ // Code block (fenced)
132
+ if (line.match(/^```/)) {
133
+ const language = line.slice(3).trim();
134
+ const codeLines = [];
135
+ const startLine = lineNumber;
136
+ i++;
137
+ while (i < lines.length && !lines[i].match(/^```/)) {
138
+ codeLines.push(lines[i]);
139
+ i++;
140
+ }
141
+ root.children.push({
142
+ type: 'codeBlock',
143
+ value: codeLines.join('\n'),
144
+ attributes: { language: language || 'plaintext' },
145
+ position: this.createPosition(startLine, 0, i - startLine),
146
+ });
147
+ i++; // Skip closing ```
148
+ continue;
149
+ }
150
+ // Blockquote
151
+ if (line.match(/^>\s/)) {
152
+ const quoteLines = [];
153
+ const startLine = lineNumber;
154
+ while (i < lines.length && lines[i].match(/^>\s/)) {
155
+ quoteLines.push(lines[i].replace(/^>\s/, ''));
156
+ i++;
157
+ }
158
+ const quoteContent = quoteLines.join('\n');
159
+ const quotedAst = await this.parseToAST(quoteContent);
160
+ root.children.push({
161
+ type: 'blockquote',
162
+ children: quotedAst.children,
163
+ position: this.createPosition(startLine, 0, i - startLine),
164
+ });
165
+ continue;
166
+ }
167
+ // Task list (GFM) - Check BEFORE unordered list since "- [ ]" matches "- " pattern
168
+ if (this.config.gfm && line.match(/^[\s]*-\s\[\s*[ xX]\s*\]/)) {
169
+ const checked = line.includes('[x]') || line.includes('[X]');
170
+ const text = line.replace(/^[\s]*-\s\[\s*[ xX]\s*\]\s*/, '');
171
+ root.children.push({
172
+ type: 'taskListItem',
173
+ attributes: { checked },
174
+ children: this.parseInline(text),
175
+ position: this.createPosition(lineNumber, 0, line.length),
176
+ });
177
+ i++;
178
+ continue;
179
+ }
180
+ // Unordered list
181
+ if (line.match(/^[\s]*[-*+]\s/)) {
182
+ const listItems = [];
183
+ const startLine = lineNumber;
184
+ while (i < lines.length && lines[i].match(/^[\s]*[-*+]\s/)) {
185
+ const itemText = lines[i].replace(/^[\s]*[-*+]\s/, '');
186
+ listItems.push({
187
+ type: 'listItem',
188
+ children: this.parseInline(itemText),
189
+ });
190
+ i++;
191
+ }
192
+ root.children.push({
193
+ type: 'list',
194
+ attributes: { ordered: false },
195
+ children: listItems,
196
+ position: this.createPosition(startLine, 0, i - startLine),
197
+ });
198
+ continue;
199
+ }
200
+ // Ordered list
201
+ if (line.match(/^[\s]*\d+\.\s/)) {
202
+ const listItems = [];
203
+ const startLine = lineNumber;
204
+ while (i < lines.length && lines[i].match(/^[\s]*\d+\.\s/)) {
205
+ const itemText = lines[i].replace(/^[\s]*\d+\.\s/, '');
206
+ listItems.push({
207
+ type: 'listItem',
208
+ children: this.parseInline(itemText),
209
+ });
210
+ i++;
211
+ }
212
+ root.children.push({
213
+ type: 'list',
214
+ attributes: { ordered: true },
215
+ children: listItems,
216
+ position: this.createPosition(startLine, 0, i - startLine),
217
+ });
218
+ continue;
219
+ }
220
+ // Table (GFM)
221
+ if (this.config.gfm && i + 1 < lines.length && lines[i + 1].match(/^\|?[\s]*:?-+:?[\s]*\|/)) {
222
+ const table = this.parseTable(lines, i);
223
+ root.children.push(table.node);
224
+ i = table.nextIndex;
225
+ continue;
226
+ }
227
+ // Paragraph (default)
228
+ const paragraphLines = [line];
229
+ const startLine = lineNumber;
230
+ i++;
231
+ // Collect continuation lines
232
+ while (i < lines.length &&
233
+ lines[i].trim() &&
234
+ !lines[i].match(/^(#{1,6}\s|```|>\s|[-*+]\s|\d+\.\s|\*{3,}|-{3,}|_{3,})/)) {
235
+ paragraphLines.push(lines[i]);
236
+ i++;
237
+ }
238
+ const paragraphText = paragraphLines.join(' ');
239
+ root.children.push({
240
+ type: 'paragraph',
241
+ children: this.parseInline(paragraphText),
242
+ position: this.createPosition(startLine, 0, paragraphLines.length),
243
+ });
244
+ }
245
+ return root;
246
+ }
247
+ /**
248
+ * Parse inline formatting (bold, italic, code, links, images)
249
+ */
250
+ parseInline(text) {
251
+ const nodes = [];
252
+ let remaining = text;
253
+ while (remaining.length > 0) {
254
+ // Bold (**text** or __text__)
255
+ const boldMatch = remaining.match(/^(\*\*|__)(.+?)\1/);
256
+ if (boldMatch) {
257
+ nodes.push({
258
+ type: 'strong',
259
+ children: [{ type: 'text', value: boldMatch[2] }],
260
+ });
261
+ remaining = remaining.slice(boldMatch[0].length);
262
+ continue;
263
+ }
264
+ // Italic (*text* or _text_)
265
+ const italicMatch = remaining.match(/^(\*|_)(.+?)\1/);
266
+ if (italicMatch) {
267
+ nodes.push({
268
+ type: 'emphasis',
269
+ children: [{ type: 'text', value: italicMatch[2] }],
270
+ });
271
+ remaining = remaining.slice(italicMatch[0].length);
272
+ continue;
273
+ }
274
+ // Inline code (`code`)
275
+ const codeMatch = remaining.match(/^`([^`]+)`/);
276
+ if (codeMatch) {
277
+ nodes.push({
278
+ type: 'code',
279
+ value: codeMatch[1],
280
+ });
281
+ remaining = remaining.slice(codeMatch[0].length);
282
+ continue;
283
+ }
284
+ // Strikethrough (GFM: ~~text~~)
285
+ if (this.config.gfm) {
286
+ const strikeMatch = remaining.match(/^~~(.+?)~~/);
287
+ if (strikeMatch) {
288
+ nodes.push({
289
+ type: 'strikethrough',
290
+ children: [{ type: 'text', value: strikeMatch[1] }],
291
+ });
292
+ remaining = remaining.slice(strikeMatch[0].length);
293
+ continue;
294
+ }
295
+ }
296
+ // Image (![alt](url))
297
+ const imageMatch = remaining.match(/^!\[([^\]]*)\]\(([^)]+)\)/);
298
+ if (imageMatch) {
299
+ nodes.push({
300
+ type: 'image',
301
+ attributes: {
302
+ alt: imageMatch[1],
303
+ src: imageMatch[2],
304
+ },
305
+ });
306
+ remaining = remaining.slice(imageMatch[0].length);
307
+ continue;
308
+ }
309
+ // Link ([text](url))
310
+ const linkMatch = remaining.match(/^\[([^\]]+)\]\(([^)]+)\)/);
311
+ if (linkMatch) {
312
+ nodes.push({
313
+ type: 'link',
314
+ attributes: {
315
+ href: linkMatch[2],
316
+ },
317
+ children: [{ type: 'text', value: linkMatch[1] }],
318
+ });
319
+ remaining = remaining.slice(linkMatch[0].length);
320
+ continue;
321
+ }
322
+ // Autolink (GFM: https://example.com)
323
+ if (this.config.gfm) {
324
+ const autolinkMatch = remaining.match(/^(https?:\/\/[^\s]+)/);
325
+ if (autolinkMatch) {
326
+ nodes.push({
327
+ type: 'autolink',
328
+ attributes: {
329
+ href: autolinkMatch[1],
330
+ },
331
+ children: [{ type: 'text', value: autolinkMatch[1] }],
332
+ });
333
+ remaining = remaining.slice(autolinkMatch[0].length);
334
+ continue;
335
+ }
336
+ }
337
+ // Line break (two spaces + newline or backslash + newline)
338
+ if (remaining.match(/^( \n|\\\n)/)) {
339
+ nodes.push({ type: 'lineBreak' });
340
+ remaining = remaining.slice(remaining.match(/^( \n|\\\n)/)[0].length);
341
+ continue;
342
+ }
343
+ // Plain text (consume until next special character or URL)
344
+ const textMatch = remaining.match(/^((?:(?!https?:\/\/)[^*_`~!\[\n])+)/);
345
+ if (textMatch) {
346
+ nodes.push({
347
+ type: 'text',
348
+ value: textMatch[1],
349
+ });
350
+ remaining = remaining.slice(textMatch[1].length);
351
+ continue;
352
+ }
353
+ // Single character fallback
354
+ nodes.push({
355
+ type: 'text',
356
+ value: remaining[0],
357
+ });
358
+ remaining = remaining.slice(1);
359
+ }
360
+ return nodes;
361
+ }
362
+ /**
363
+ * Parse GFM table
364
+ */
365
+ parseTable(lines, startIndex) {
366
+ const headerLine = lines[startIndex];
367
+ const separatorLine = lines[startIndex + 1];
368
+ // Parse header
369
+ const headerCells = headerLine.split('|').filter((cell) => cell.trim());
370
+ const headerRow = {
371
+ type: 'tableRow',
372
+ children: headerCells.map((cell) => ({
373
+ type: 'tableCell',
374
+ attributes: { header: true },
375
+ children: this.parseInline(cell.trim()),
376
+ })),
377
+ };
378
+ // Parse alignment from separator
379
+ const alignments = separatorLine
380
+ .split('|')
381
+ .filter((cell) => cell.trim())
382
+ .map((cell) => {
383
+ const trimmed = cell.trim();
384
+ if (trimmed.startsWith(':') && trimmed.endsWith(':'))
385
+ return 'center';
386
+ if (trimmed.endsWith(':'))
387
+ return 'right';
388
+ if (trimmed.startsWith(':'))
389
+ return 'left';
390
+ return 'left';
391
+ });
392
+ // Parse body rows
393
+ const bodyRows = [];
394
+ let i = startIndex + 2;
395
+ while (i < lines.length && lines[i].includes('|')) {
396
+ const cells = lines[i].split('|').filter((cell) => cell.trim());
397
+ bodyRows.push({
398
+ type: 'tableRow',
399
+ children: cells.map((cell, index) => ({
400
+ type: 'tableCell',
401
+ attributes: {
402
+ header: false,
403
+ align: alignments[index] || 'left',
404
+ },
405
+ children: this.parseInline(cell.trim()),
406
+ })),
407
+ });
408
+ i++;
409
+ }
410
+ return {
411
+ node: {
412
+ type: 'table',
413
+ children: [headerRow, ...bodyRows],
414
+ position: this.createPosition(startIndex + 1, 0, i - startIndex),
415
+ },
416
+ nextIndex: i,
417
+ };
418
+ }
419
+ /**
420
+ * Create position information
421
+ */
422
+ createPosition(line, column, length) {
423
+ return {
424
+ start: { line, column, offset: 0 },
425
+ end: { line: line + length - 1, column: column + length, offset: 0 },
426
+ };
427
+ }
428
+ /**
429
+ * Clear the parse cache
430
+ */
431
+ clearCache() {
432
+ if (this.cacheManager) {
433
+ this.cacheManager.clear();
434
+ this.logger.debug('Markdown parse cache cleared');
435
+ }
436
+ }
437
+ /**
438
+ * Get cache statistics
439
+ */
440
+ getCacheStats() {
441
+ return {
442
+ size: this.cacheManager?.size() ?? 0,
443
+ enabled: this.config.cache.enabled,
444
+ };
445
+ }
446
+ /**
447
+ * Prune expired cache entries
448
+ */
449
+ pruneCache() {
450
+ if (this.cacheManager) {
451
+ const removed = this.cacheManager.prune();
452
+ this.logger.debug('Pruned expired cache entries', { removed });
453
+ return removed;
454
+ }
455
+ return 0;
456
+ }
457
+ }
458
+ exports.MarkdownParser = MarkdownParser;
@@ -0,0 +1,6 @@
1
+ export { MarkdownParser } from './MarkdownParser';
2
+ export * from './types';
3
+ export * from './plugins';
4
+ export * from './utils/ast-utils';
5
+ export { CacheManager } from './utils/cache';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ var desc = Object.getOwnPropertyDescriptor(m, k);
12
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
+ desc = { enumerable: true, get: function() { return m[k]; } };
14
+ }
15
+ Object.defineProperty(o, k2, desc);
16
+ }) : (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ o[k2] = m[k];
19
+ }));
20
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
21
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
22
+ };
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.CacheManager = exports.MarkdownParser = void 0;
25
+ var MarkdownParser_1 = require("./MarkdownParser");
26
+ Object.defineProperty(exports, "MarkdownParser", { enumerable: true, get: function () { return MarkdownParser_1.MarkdownParser; } });
27
+ __exportStar(require("./types"), exports);
28
+ __exportStar(require("./plugins"), exports);
29
+ __exportStar(require("./utils/ast-utils"), exports);
30
+ var cache_1 = require("./utils/cache");
31
+ Object.defineProperty(exports, "CacheManager", { enumerable: true, get: function () { return cache_1.CacheManager; } });
@@ -0,0 +1,6 @@
1
+ import { MarkdownPlugin } from '../types';
2
+ /**
3
+ * CommonMark specification plugin
4
+ */
5
+ export declare const commonmarkPlugin: MarkdownPlugin;
6
+ //# sourceMappingURL=commonmark.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commonmark.d.ts","sourceRoot":"","sources":["../../src/plugins/commonmark.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,cAAc,EAAW,MAAM,UAAU,CAAC;AAEnD;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,cAS9B,CAAC"}
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.commonmarkPlugin = void 0;
11
+ /**
12
+ * CommonMark specification plugin
13
+ */
14
+ exports.commonmarkPlugin = {
15
+ name: 'commonmark',
16
+ version: '1.0.0',
17
+ transform: (ast) => {
18
+ // This is a placeholder - CommonMark features are built into the main parser
19
+ // when commonmark config is enabled. This plugin can be used for additional
20
+ // post-processing transformations specific to CommonMark.
21
+ return ast;
22
+ },
23
+ };
@@ -0,0 +1,6 @@
1
+ import { MarkdownPlugin } from '../types';
2
+ /**
3
+ * GitHub-Flavored Markdown extensions plugin
4
+ */
5
+ export declare const gfmPlugin: MarkdownPlugin;
6
+ //# sourceMappingURL=gfm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gfm.d.ts","sourceRoot":"","sources":["../../src/plugins/gfm.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,cAAc,EAAW,MAAM,UAAU,CAAC;AAEnD;;GAEG;AACH,eAAO,MAAM,SAAS,EAAE,cASvB,CAAC"}
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.gfmPlugin = void 0;
11
+ /**
12
+ * GitHub-Flavored Markdown extensions plugin
13
+ */
14
+ exports.gfmPlugin = {
15
+ name: 'gfm',
16
+ version: '1.0.0',
17
+ transform: (ast) => {
18
+ // This is a placeholder - GFM features are built into the main parser
19
+ // when gfm config is enabled. This plugin can be used for additional
20
+ // post-processing transformations specific to GFM.
21
+ return ast;
22
+ },
23
+ };
@@ -0,0 +1,3 @@
1
+ export * from './gfm';
2
+ export * from './commonmark';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugins/index.ts"],"names":[],"mappings":"AAQA,cAAc,OAAO,CAAC;AACtB,cAAc,cAAc,CAAC"}
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ var desc = Object.getOwnPropertyDescriptor(m, k);
12
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
+ desc = { enumerable: true, get: function() { return m[k]; } };
14
+ }
15
+ Object.defineProperty(o, k2, desc);
16
+ }) : (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ o[k2] = m[k];
19
+ }));
20
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
21
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
22
+ };
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ __exportStar(require("./gfm"), exports);
25
+ __exportStar(require("./commonmark"), exports);
@@ -0,0 +1,78 @@
1
+ import { Logger } from '@bernierllc/logger';
2
+ /**
3
+ * Markdown Parser Configuration
4
+ */
5
+ export interface MarkdownParserConfig {
6
+ /** Enable GitHub-Flavored Markdown extensions */
7
+ gfm?: boolean;
8
+ /** Enable CommonMark strict mode */
9
+ commonmark?: boolean;
10
+ /** Custom plugins to apply */
11
+ plugins?: MarkdownPlugin[];
12
+ /** Enable caching of parsed AST */
13
+ cache?: {
14
+ enabled: boolean;
15
+ maxSize?: number;
16
+ ttl?: number;
17
+ };
18
+ /** Logger instance */
19
+ logger?: Logger;
20
+ }
21
+ /**
22
+ * Position information in source document
23
+ */
24
+ export interface Position {
25
+ start: {
26
+ line: number;
27
+ column: number;
28
+ offset: number;
29
+ };
30
+ end: {
31
+ line: number;
32
+ column: number;
33
+ offset: number;
34
+ };
35
+ }
36
+ /**
37
+ * Markdown Abstract Syntax Tree Node
38
+ */
39
+ export interface ASTNode {
40
+ type: NodeType;
41
+ value?: string;
42
+ children?: ASTNode[];
43
+ attributes?: Record<string, unknown>;
44
+ position?: Position;
45
+ }
46
+ /**
47
+ * Node types supported by the parser
48
+ */
49
+ export type NodeType = 'root' | 'heading' | 'paragraph' | 'text' | 'emphasis' | 'strong' | 'link' | 'image' | 'code' | 'codeBlock' | 'blockquote' | 'list' | 'listItem' | 'table' | 'tableRow' | 'tableCell' | 'html' | 'horizontalRule' | 'lineBreak' | 'strikethrough' | 'taskList' | 'taskListItem' | 'autolink' | 'footnote' | 'footnoteReference';
50
+ /**
51
+ * Parse result with metadata
52
+ */
53
+ export interface ParseResult {
54
+ success: boolean;
55
+ ast?: ASTNode;
56
+ error?: string;
57
+ metadata?: {
58
+ parseTime: number;
59
+ nodeCount: number;
60
+ cached: boolean;
61
+ };
62
+ }
63
+ /**
64
+ * Plugin interface for custom extensions
65
+ */
66
+ export interface MarkdownPlugin {
67
+ name: string;
68
+ version: string;
69
+ transform: (ast: ASTNode) => ASTNode;
70
+ }
71
+ /**
72
+ * Cache entry structure
73
+ */
74
+ export interface CacheEntry {
75
+ ast: ASTNode;
76
+ timestamp: number;
77
+ }
78
+ //# sourceMappingURL=types.d.ts.map