@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 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,iDAAiD;IACjD,GAAG,CAAC,EAAE,OAAO,CAAC;IAEd,oCAAoC;IACpC,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB,8BAA8B;IAC9B,OAAO,CAAC,EAAE,cAAc,EAAE,CAAC;IAE3B,mCAAmC;IACnC,KAAK,CAAC,EAAE;QACN,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC;IAEF,sBAAsB;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACxD,GAAG,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CACvD;AAED;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,MAAM,QAAQ,GAChB,MAAM,GACN,SAAS,GACT,WAAW,GACX,MAAM,GACN,UAAU,GACV,QAAQ,GACR,MAAM,GACN,OAAO,GACP,MAAM,GACN,WAAW,GACX,YAAY,GACZ,MAAM,GACN,UAAU,GACV,OAAO,GACP,UAAU,GACV,WAAW,GACX,MAAM,GACN,gBAAgB,GAChB,WAAW,GAEX,eAAe,GACf,UAAU,GACV,cAAc,GACd,UAAU,GACV,UAAU,GACV,mBAAmB,CAAC;AAExB;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE;QACT,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,OAAO,CAAC;KACjB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,OAAO,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB"}
package/dist/types.js ADDED
@@ -0,0 +1,9 @@
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 });
@@ -0,0 +1,22 @@
1
+ import { ASTNode } from '../types';
2
+ /**
3
+ * Count total nodes in AST
4
+ */
5
+ export declare function countNodes(node: ASTNode): number;
6
+ /**
7
+ * Visit each node in the AST
8
+ */
9
+ export declare function visitNodes(node: ASTNode, visitor: (node: ASTNode) => void): void;
10
+ /**
11
+ * Transform AST nodes recursively
12
+ */
13
+ export declare function transformNodes(node: ASTNode, transformer: (node: ASTNode) => ASTNode): ASTNode;
14
+ /**
15
+ * Find nodes matching a predicate
16
+ */
17
+ export declare function findNodes(node: ASTNode, predicate: (node: ASTNode) => boolean): ASTNode[];
18
+ /**
19
+ * Clone an AST node deeply
20
+ */
21
+ export declare function cloneNode(node: ASTNode): ASTNode;
22
+ //# sourceMappingURL=ast-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast-utils.d.ts","sourceRoot":"","sources":["../../src/utils/ast-utils.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAEnC;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAQhD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAOhF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,GAAG,OAAO,CAS9F;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,GAAG,OAAO,EAAE,CAWzF;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAYhD"}
@@ -0,0 +1,81 @@
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.countNodes = countNodes;
11
+ exports.visitNodes = visitNodes;
12
+ exports.transformNodes = transformNodes;
13
+ exports.findNodes = findNodes;
14
+ exports.cloneNode = cloneNode;
15
+ /**
16
+ * Count total nodes in AST
17
+ */
18
+ function countNodes(node) {
19
+ let count = 1;
20
+ if (node.children) {
21
+ for (const child of node.children) {
22
+ count += countNodes(child);
23
+ }
24
+ }
25
+ return count;
26
+ }
27
+ /**
28
+ * Visit each node in the AST
29
+ */
30
+ function visitNodes(node, visitor) {
31
+ visitor(node);
32
+ if (node.children) {
33
+ for (const child of node.children) {
34
+ visitNodes(child, visitor);
35
+ }
36
+ }
37
+ }
38
+ /**
39
+ * Transform AST nodes recursively
40
+ */
41
+ function transformNodes(node, transformer) {
42
+ const transformed = transformer(node);
43
+ if (transformed.children) {
44
+ return {
45
+ ...transformed,
46
+ children: transformed.children.map((child) => transformNodes(child, transformer)),
47
+ };
48
+ }
49
+ return transformed;
50
+ }
51
+ /**
52
+ * Find nodes matching a predicate
53
+ */
54
+ function findNodes(node, predicate) {
55
+ const results = [];
56
+ if (predicate(node)) {
57
+ results.push(node);
58
+ }
59
+ if (node.children) {
60
+ for (const child of node.children) {
61
+ results.push(...findNodes(child, predicate));
62
+ }
63
+ }
64
+ return results;
65
+ }
66
+ /**
67
+ * Clone an AST node deeply
68
+ */
69
+ function cloneNode(node) {
70
+ return {
71
+ ...node,
72
+ children: node.children ? node.children.map(cloneNode) : undefined,
73
+ attributes: node.attributes ? { ...node.attributes } : undefined,
74
+ position: node.position
75
+ ? {
76
+ start: { ...node.position.start },
77
+ end: { ...node.position.end },
78
+ }
79
+ : undefined,
80
+ };
81
+ }
@@ -0,0 +1,39 @@
1
+ import { ASTNode } from '../types';
2
+ /**
3
+ * Cache manager for parsed markdown AST
4
+ */
5
+ export declare class CacheManager {
6
+ private cache;
7
+ private maxSize;
8
+ private ttl;
9
+ constructor(maxSize?: number, ttl?: number);
10
+ /**
11
+ * Generate cache key from markdown content
12
+ */
13
+ generateKey(markdown: string): string;
14
+ /**
15
+ * Get AST from cache if valid
16
+ */
17
+ get(key: string): ASTNode | null;
18
+ /**
19
+ * Store AST in cache with size limit
20
+ */
21
+ set(key: string, ast: ASTNode): void;
22
+ /**
23
+ * Check if key exists in cache
24
+ */
25
+ has(key: string): boolean;
26
+ /**
27
+ * Clear all cache entries
28
+ */
29
+ clear(): void;
30
+ /**
31
+ * Get current cache size
32
+ */
33
+ size(): number;
34
+ /**
35
+ * Remove expired entries
36
+ */
37
+ prune(): number;
38
+ }
39
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/utils/cache.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,OAAO,EAAc,MAAM,UAAU,CAAC;AAG/C;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAA0B;IACvC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,GAAG,CAAS;gBAER,OAAO,GAAE,MAAa,EAAE,GAAG,GAAE,MAAa;IAMtD;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAIrC;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI;IAgBhC;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,IAAI;IAapC;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIzB;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,IAAI,IAAI,MAAM;IAId;;OAEG;IACH,KAAK,IAAI,MAAM;CAchB"}
@@ -0,0 +1,91 @@
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.CacheManager = void 0;
11
+ const crypto_1 = require("crypto");
12
+ /**
13
+ * Cache manager for parsed markdown AST
14
+ */
15
+ class CacheManager {
16
+ constructor(maxSize = 1000, ttl = 3600) {
17
+ this.cache = new Map();
18
+ this.maxSize = maxSize;
19
+ this.ttl = ttl;
20
+ }
21
+ /**
22
+ * Generate cache key from markdown content
23
+ */
24
+ generateKey(markdown) {
25
+ return (0, crypto_1.createHash)('sha256').update(markdown).digest('hex').substring(0, 16);
26
+ }
27
+ /**
28
+ * Get AST from cache if valid
29
+ */
30
+ get(key) {
31
+ const entry = this.cache.get(key);
32
+ if (!entry) {
33
+ return null;
34
+ }
35
+ // Check TTL
36
+ const age = (Date.now() - entry.timestamp) / 1000;
37
+ if (age > this.ttl) {
38
+ this.cache.delete(key);
39
+ return null;
40
+ }
41
+ return entry.ast;
42
+ }
43
+ /**
44
+ * Store AST in cache with size limit
45
+ */
46
+ set(key, ast) {
47
+ // Enforce max size (FIFO eviction)
48
+ if (this.cache.size >= this.maxSize) {
49
+ const oldestKey = this.cache.keys().next().value;
50
+ this.cache.delete(oldestKey);
51
+ }
52
+ this.cache.set(key, {
53
+ ast,
54
+ timestamp: Date.now(),
55
+ });
56
+ }
57
+ /**
58
+ * Check if key exists in cache
59
+ */
60
+ has(key) {
61
+ return this.get(key) !== null;
62
+ }
63
+ /**
64
+ * Clear all cache entries
65
+ */
66
+ clear() {
67
+ this.cache.clear();
68
+ }
69
+ /**
70
+ * Get current cache size
71
+ */
72
+ size() {
73
+ return this.cache.size;
74
+ }
75
+ /**
76
+ * Remove expired entries
77
+ */
78
+ prune() {
79
+ const now = Date.now();
80
+ let removed = 0;
81
+ for (const [key, entry] of this.cache.entries()) {
82
+ const age = (now - entry.timestamp) / 1000;
83
+ if (age > this.ttl) {
84
+ this.cache.delete(key);
85
+ removed++;
86
+ }
87
+ }
88
+ return removed;
89
+ }
90
+ }
91
+ exports.CacheManager = CacheManager;
@@ -0,0 +1,28 @@
1
+ /*
2
+ Copyright (c) 2025 Bernier LLC
3
+
4
+ This file is licensed to the client under a limited-use license.
5
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
6
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
7
+ */
8
+
9
+ module.exports = {
10
+ preset: 'ts-jest',
11
+ testEnvironment: 'node',
12
+ collectCoverageFrom: [
13
+ 'src/**/*.{ts,tsx}',
14
+ '!src/**/*.d.ts',
15
+ '!src/index.ts'
16
+ ],
17
+ coverageThreshold: {
18
+ global: {
19
+ branches: 90,
20
+ functions: 90,
21
+ lines: 90,
22
+ statements: 90
23
+ }
24
+ },
25
+ testMatch: [
26
+ '**/__tests__/**/*.test.ts'
27
+ ]
28
+ };
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@bernierllc/markdown-parser",
3
+ "version": "1.0.0",
4
+ "description": "High-performance markdown parser with CommonMark, GFM, and plugin support",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "keywords": [
8
+ "markdown",
9
+ "parser",
10
+ "ast",
11
+ "commonmark",
12
+ "gfm",
13
+ "github-flavored-markdown"
14
+ ],
15
+ "author": "Bernier LLC",
16
+ "license": "SEE LICENSE IN LICENSE",
17
+ "dependencies": {
18
+ "@bernierllc/logger": "^1.0.1",
19
+ "@bernierllc/crypto-utils": "^1.0.2"
20
+ },
21
+ "devDependencies": {
22
+ "@types/jest": "^29.0.0",
23
+ "@types/node": "^20.0.0",
24
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
25
+ "@typescript-eslint/parser": "^6.0.0",
26
+ "eslint": "^8.0.0",
27
+ "jest": "^29.0.0",
28
+ "rimraf": "^5.0.0",
29
+ "ts-jest": "^29.0.0",
30
+ "typescript": "^5.0.0"
31
+ },
32
+ "publishConfig": {
33
+ "access": "restricted"
34
+ },
35
+ "scripts": {
36
+ "build": "tsc",
37
+ "test": "jest --watch=false",
38
+ "test:watch": "jest --watch",
39
+ "test:run": "jest --watch=false",
40
+ "test:coverage": "jest --coverage --watch=false",
41
+ "lint": "eslint src __tests__ --ext .ts",
42
+ "clean": "rimraf dist"
43
+ }
44
+ }