kirograph 0.14.1 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +239 -20
- package/dist/assets/logo.png +0 -0
- package/dist/bin/commands/docs.js +357 -0
- package/dist/bin/commands/docs.js.map +7 -0
- package/dist/bin/commands/help.js +3 -0
- package/dist/bin/commands/help.js.map +2 -2
- package/dist/bin/commands/uninit.js +10 -13
- package/dist/bin/commands/uninit.js.map +2 -2
- package/dist/bin/installer/config-prompt.js +53 -23
- package/dist/bin/installer/config-prompt.js.map +2 -2
- package/dist/bin/installer/hooks.js +20 -1
- package/dist/bin/installer/hooks.js.map +2 -2
- package/dist/bin/installer/index.js +14 -4
- package/dist/bin/installer/index.js.map +2 -2
- package/dist/bin/installer/prompts.js +37 -6
- package/dist/bin/installer/prompts.js.map +2 -2
- package/dist/bin/installer/steering.js +40 -0
- package/dist/bin/installer/steering.js.map +2 -2
- package/dist/bin/installer/targets/aider.js +72 -0
- package/dist/bin/installer/targets/aider.js.map +7 -0
- package/dist/bin/installer/targets/amp.js +91 -0
- package/dist/bin/installer/targets/amp.js.map +7 -0
- package/dist/bin/installer/targets/antigravity.js +109 -0
- package/dist/bin/installer/targets/antigravity.js.map +7 -0
- package/dist/bin/installer/targets/augment.js +81 -0
- package/dist/bin/installer/targets/augment.js.map +7 -0
- package/dist/bin/installer/targets/claude.js +1 -1
- package/dist/bin/installer/targets/claude.js.map +2 -2
- package/dist/bin/installer/targets/cline.js +91 -0
- package/dist/bin/installer/targets/cline.js.map +7 -0
- package/dist/bin/installer/targets/codex.js +1 -1
- package/dist/bin/installer/targets/codex.js.map +2 -2
- package/dist/bin/installer/targets/continue.js +107 -0
- package/dist/bin/installer/targets/continue.js.map +7 -0
- package/dist/bin/installer/targets/copilot.js +123 -0
- package/dist/bin/installer/targets/copilot.js.map +7 -0
- package/dist/bin/installer/targets/cursor.js +143 -0
- package/dist/bin/installer/targets/cursor.js.map +7 -0
- package/dist/bin/installer/targets/devin.js +148 -0
- package/dist/bin/installer/targets/devin.js.map +7 -0
- package/dist/bin/installer/targets/gemini-cli.js +126 -0
- package/dist/bin/installer/targets/gemini-cli.js.map +7 -0
- package/dist/bin/installer/targets/generic.js +120 -0
- package/dist/bin/installer/targets/generic.js.map +7 -0
- package/dist/bin/installer/targets/goose.js +72 -0
- package/dist/bin/installer/targets/goose.js.map +7 -0
- package/dist/bin/installer/targets/index.js.map +1 -1
- package/dist/bin/installer/targets/junie.js +105 -0
- package/dist/bin/installer/targets/junie.js.map +7 -0
- package/dist/bin/installer/targets/kilo.js +122 -0
- package/dist/bin/installer/targets/kilo.js.map +7 -0
- package/dist/bin/installer/targets/kiro.js +3 -3
- package/dist/bin/installer/targets/kiro.js.map +2 -2
- package/dist/bin/installer/targets/opencode.js +135 -0
- package/dist/bin/installer/targets/opencode.js.map +7 -0
- package/dist/bin/installer/targets/openhands.js +90 -0
- package/dist/bin/installer/targets/openhands.js.map +7 -0
- package/dist/bin/installer/targets/replit.js +72 -0
- package/dist/bin/installer/targets/replit.js.map +7 -0
- package/dist/bin/installer/targets/roo.js +96 -0
- package/dist/bin/installer/targets/roo.js.map +7 -0
- package/dist/bin/installer/targets/tabnine.js +82 -0
- package/dist/bin/installer/targets/tabnine.js.map +7 -0
- package/dist/bin/installer/targets/trae.js +84 -0
- package/dist/bin/installer/targets/trae.js.map +7 -0
- package/dist/bin/installer/targets/warp.js +97 -0
- package/dist/bin/installer/targets/warp.js.map +7 -0
- package/dist/bin/installer/targets/windsurf.js +141 -0
- package/dist/bin/installer/targets/windsurf.js.map +7 -0
- package/dist/bin/kirograph.js +5 -1
- package/dist/bin/kirograph.js.map +3 -3
- package/dist/compression/naive-cost.js +33 -0
- package/dist/compression/naive-cost.js.map +2 -2
- package/dist/compression/tracker.js +27 -4
- package/dist/compression/tracker.js.map +2 -2
- package/dist/compression/types.js.map +1 -1
- package/dist/config.js +66 -1
- package/dist/config.js.map +2 -2
- package/dist/core/pipeline.js +23 -0
- package/dist/core/pipeline.js.map +2 -2
- package/dist/db/database.js +28 -0
- package/dist/db/database.js.map +2 -2
- package/dist/db/docs-schema.sql +50 -0
- package/dist/docs/formats/asciidoc.js +108 -0
- package/dist/docs/formats/asciidoc.js.map +7 -0
- package/dist/docs/formats/html.js +100 -0
- package/dist/docs/formats/html.js.map +7 -0
- package/dist/docs/formats/index.js +81 -0
- package/dist/docs/formats/index.js.map +7 -0
- package/dist/docs/formats/markdown.js +146 -0
- package/dist/docs/formats/markdown.js.map +7 -0
- package/dist/docs/formats/openapi.js +228 -0
- package/dist/docs/formats/openapi.js.map +7 -0
- package/dist/docs/formats/org.js +117 -0
- package/dist/docs/formats/org.js.map +7 -0
- package/dist/docs/formats/plaintext.js +119 -0
- package/dist/docs/formats/plaintext.js.map +7 -0
- package/dist/docs/formats/rdoc.js +105 -0
- package/dist/docs/formats/rdoc.js.map +7 -0
- package/dist/docs/formats/rst.js +121 -0
- package/dist/docs/formats/rst.js.map +7 -0
- package/dist/docs/indexer.js +340 -0
- package/dist/docs/indexer.js.map +7 -0
- package/dist/docs/linker.js +151 -0
- package/dist/docs/linker.js.map +7 -0
- package/dist/docs/lint.js +92 -0
- package/dist/docs/lint.js.map +7 -0
- package/dist/docs/queries.js +295 -0
- package/dist/docs/queries.js.map +7 -0
- package/dist/docs/section-id.js +57 -0
- package/dist/docs/section-id.js.map +7 -0
- package/dist/docs/summarizer.js +55 -0
- package/dist/docs/summarizer.js.map +7 -0
- package/dist/docs/types.js +17 -0
- package/dist/docs/types.js.map +7 -0
- package/dist/docs/vectors.js +217 -0
- package/dist/docs/vectors.js.map +7 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +2 -2
- package/dist/mcp/tool-names.js +10 -1
- package/dist/mcp/tool-names.js.map +2 -2
- package/dist/mcp/tools.js +476 -3
- package/dist/mcp/tools.js.map +2 -2
- package/package.json +1 -1
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var asciidoc_exports = {};
|
|
20
|
+
__export(asciidoc_exports, {
|
|
21
|
+
asciidocParser: () => asciidocParser
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(asciidoc_exports);
|
|
24
|
+
const HEADING_RE = /^(={1,6})\s+(.+?)(?:\s+=+)?$/;
|
|
25
|
+
function extractHeadings(content) {
|
|
26
|
+
const lines = content.split("\n");
|
|
27
|
+
const headings = [];
|
|
28
|
+
let byteOffset = 0;
|
|
29
|
+
let inBlock = false;
|
|
30
|
+
for (let i = 0; i < lines.length; i++) {
|
|
31
|
+
const line = lines[i];
|
|
32
|
+
const lineBytes = Buffer.byteLength(line, "utf8") + 1;
|
|
33
|
+
if (/^(-{4,}|={4,}|\.{4,}|\+{4,}|\*{4,}|_{4,})\s*$/.test(line)) {
|
|
34
|
+
inBlock = !inBlock;
|
|
35
|
+
byteOffset += lineBytes;
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (!inBlock) {
|
|
39
|
+
const match = line.match(HEADING_RE);
|
|
40
|
+
if (match) {
|
|
41
|
+
headings.push({
|
|
42
|
+
title: match[2].trim(),
|
|
43
|
+
level: match[1].length,
|
|
44
|
+
lineIndex: i,
|
|
45
|
+
byteOffset
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
byteOffset += lineBytes;
|
|
50
|
+
}
|
|
51
|
+
return headings;
|
|
52
|
+
}
|
|
53
|
+
function buildHierarchy(headings, content) {
|
|
54
|
+
const contentBytes = Buffer.byteLength(content, "utf8");
|
|
55
|
+
if (headings.length === 0) {
|
|
56
|
+
return [{
|
|
57
|
+
title: "(document)",
|
|
58
|
+
level: 0,
|
|
59
|
+
byteStart: 0,
|
|
60
|
+
byteEnd: contentBytes,
|
|
61
|
+
content,
|
|
62
|
+
children: []
|
|
63
|
+
}];
|
|
64
|
+
}
|
|
65
|
+
const sections = [];
|
|
66
|
+
for (let i = 0; i < headings.length; i++) {
|
|
67
|
+
const start = headings[i].byteOffset;
|
|
68
|
+
const end = i + 1 < headings.length ? headings[i + 1].byteOffset : contentBytes;
|
|
69
|
+
const sectionContent = Buffer.from(content, "utf8").slice(start, end).toString("utf8");
|
|
70
|
+
sections.push({ ...headings[i], byteEnd: end, content: sectionContent });
|
|
71
|
+
}
|
|
72
|
+
const root = [];
|
|
73
|
+
const stack = [];
|
|
74
|
+
for (const s of sections) {
|
|
75
|
+
const parsed = {
|
|
76
|
+
title: s.title,
|
|
77
|
+
level: s.level,
|
|
78
|
+
byteStart: s.byteOffset,
|
|
79
|
+
byteEnd: s.byteEnd,
|
|
80
|
+
content: s.content,
|
|
81
|
+
children: []
|
|
82
|
+
};
|
|
83
|
+
while (stack.length > 0 && stack[stack.length - 1].level >= s.level) {
|
|
84
|
+
stack.pop();
|
|
85
|
+
}
|
|
86
|
+
if (stack.length === 0) {
|
|
87
|
+
root.push(parsed);
|
|
88
|
+
} else {
|
|
89
|
+
stack[stack.length - 1].section.children.push(parsed);
|
|
90
|
+
}
|
|
91
|
+
stack.push({ section: parsed, level: s.level });
|
|
92
|
+
}
|
|
93
|
+
return root;
|
|
94
|
+
}
|
|
95
|
+
const asciidocParser = {
|
|
96
|
+
name: "asciidoc",
|
|
97
|
+
extensions: [".adoc", ".asciidoc"],
|
|
98
|
+
parse(content, _filePath) {
|
|
99
|
+
const headings = extractHeadings(content);
|
|
100
|
+
const sections = buildHierarchy(headings, content);
|
|
101
|
+
return { sections, format: "asciidoc" };
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
105
|
+
0 && (module.exports = {
|
|
106
|
+
asciidocParser
|
|
107
|
+
});
|
|
108
|
+
//# sourceMappingURL=asciidoc.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/docs/formats/asciidoc.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * AsciiDoc Section Parser\n *\n * Handles: .adoc, .asciidoc\n * Parsing strategy: = heading hierarchy (= Title, == Section, === Subsection)\n */\n\nimport type { DocFormatParser, ParseResult, ParsedSection } from '../types';\n\nconst HEADING_RE = /^(={1,6})\\s+(.+?)(?:\\s+=+)?$/;\n\ninterface RawHeading {\n title: string;\n level: number;\n lineIndex: number;\n byteOffset: number;\n}\n\nfunction extractHeadings(content: string): RawHeading[] {\n const lines = content.split('\\n');\n const headings: RawHeading[] = [];\n let byteOffset = 0;\n let inBlock = false;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const lineBytes = Buffer.byteLength(line, 'utf8') + 1;\n\n // Track delimited blocks (----, ====, ....)\n if (/^(-{4,}|={4,}|\\.{4,}|\\+{4,}|\\*{4,}|_{4,})\\s*$/.test(line)) {\n inBlock = !inBlock;\n byteOffset += lineBytes;\n continue;\n }\n\n if (!inBlock) {\n const match = line.match(HEADING_RE);\n if (match) {\n headings.push({\n title: match[2].trim(),\n level: match[1].length,\n lineIndex: i,\n byteOffset,\n });\n }\n }\n\n byteOffset += lineBytes;\n }\n\n return headings;\n}\n\nfunction buildHierarchy(headings: RawHeading[], content: string): ParsedSection[] {\n const contentBytes = Buffer.byteLength(content, 'utf8');\n\n if (headings.length === 0) {\n return [{\n title: '(document)',\n level: 0,\n byteStart: 0,\n byteEnd: contentBytes,\n content,\n children: [],\n }];\n }\n\n const sections: Array<RawHeading & { byteEnd: number; content: string }> = [];\n for (let i = 0; i < headings.length; i++) {\n const start = headings[i].byteOffset;\n const end = i + 1 < headings.length ? headings[i + 1].byteOffset : contentBytes;\n const sectionContent = Buffer.from(content, 'utf8').slice(start, end).toString('utf8');\n sections.push({ ...headings[i], byteEnd: end, content: sectionContent });\n }\n\n const root: ParsedSection[] = [];\n const stack: Array<{ section: ParsedSection; level: number }> = [];\n\n for (const s of sections) {\n const parsed: ParsedSection = {\n title: s.title,\n level: s.level,\n byteStart: s.byteOffset,\n byteEnd: s.byteEnd,\n content: s.content,\n children: [],\n };\n\n while (stack.length > 0 && stack[stack.length - 1].level >= s.level) {\n stack.pop();\n }\n\n if (stack.length === 0) {\n root.push(parsed);\n } else {\n stack[stack.length - 1].section.children.push(parsed);\n }\n\n stack.push({ section: parsed, level: s.level });\n }\n\n return root;\n}\n\nexport const asciidocParser: DocFormatParser = {\n name: 'asciidoc',\n extensions: ['.adoc', '.asciidoc'],\n\n parse(content: string, _filePath: string): ParseResult {\n const headings = extractHeadings(content);\n const sections = buildHierarchy(headings, content);\n return { sections, format: 'asciidoc' };\n },\n};\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AASA,MAAM,aAAa;AASnB,SAAS,gBAAgB,SAA+B;AACtD,QAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,QAAM,WAAyB,CAAC;AAChC,MAAI,aAAa;AACjB,MAAI,UAAU;AAEd,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,OAAO,MAAM,CAAC;AACpB,UAAM,YAAY,OAAO,WAAW,MAAM,MAAM,IAAI;AAGpD,QAAI,gDAAgD,KAAK,IAAI,GAAG;AAC9D,gBAAU,CAAC;AACX,oBAAc;AACd;AAAA,IACF;AAEA,QAAI,CAAC,SAAS;AACZ,YAAM,QAAQ,KAAK,MAAM,UAAU;AACnC,UAAI,OAAO;AACT,iBAAS,KAAK;AAAA,UACZ,OAAO,MAAM,CAAC,EAAE,KAAK;AAAA,UACrB,OAAO,MAAM,CAAC,EAAE;AAAA,UAChB,WAAW;AAAA,UACX;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAEA,kBAAc;AAAA,EAChB;AAEA,SAAO;AACT;AAEA,SAAS,eAAe,UAAwB,SAAkC;AAChF,QAAM,eAAe,OAAO,WAAW,SAAS,MAAM;AAEtD,MAAI,SAAS,WAAW,GAAG;AACzB,WAAO,CAAC;AAAA,MACN,OAAO;AAAA,MACP,OAAO;AAAA,MACP,WAAW;AAAA,MACX,SAAS;AAAA,MACT;AAAA,MACA,UAAU,CAAC;AAAA,IACb,CAAC;AAAA,EACH;AAEA,QAAM,WAAqE,CAAC;AAC5E,WAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,UAAM,QAAQ,SAAS,CAAC,EAAE;AAC1B,UAAM,MAAM,IAAI,IAAI,SAAS,SAAS,SAAS,IAAI,CAAC,EAAE,aAAa;AACnE,UAAM,iBAAiB,OAAO,KAAK,SAAS,MAAM,EAAE,MAAM,OAAO,GAAG,EAAE,SAAS,MAAM;AACrF,aAAS,KAAK,EAAE,GAAG,SAAS,CAAC,GAAG,SAAS,KAAK,SAAS,eAAe,CAAC;AAAA,EACzE;AAEA,QAAM,OAAwB,CAAC;AAC/B,QAAM,QAA0D,CAAC;AAEjE,aAAW,KAAK,UAAU;AACxB,UAAM,SAAwB;AAAA,MAC5B,OAAO,EAAE;AAAA,MACT,OAAO,EAAE;AAAA,MACT,WAAW,EAAE;AAAA,MACb,SAAS,EAAE;AAAA,MACX,SAAS,EAAE;AAAA,MACX,UAAU,CAAC;AAAA,IACb;AAEA,WAAO,MAAM,SAAS,KAAK,MAAM,MAAM,SAAS,CAAC,EAAE,SAAS,EAAE,OAAO;AACnE,YAAM,IAAI;AAAA,IACZ;AAEA,QAAI,MAAM,WAAW,GAAG;AACtB,WAAK,KAAK,MAAM;AAAA,IAClB,OAAO;AACL,YAAM,MAAM,SAAS,CAAC,EAAE,QAAQ,SAAS,KAAK,MAAM;AAAA,IACtD;AAEA,UAAM,KAAK,EAAE,SAAS,QAAQ,OAAO,EAAE,MAAM,CAAC;AAAA,EAChD;AAEA,SAAO;AACT;AAEO,MAAM,iBAAkC;AAAA,EAC7C,MAAM;AAAA,EACN,YAAY,CAAC,SAAS,WAAW;AAAA,EAEjC,MAAM,SAAiB,WAAgC;AACrD,UAAM,WAAW,gBAAgB,OAAO;AACxC,UAAM,WAAW,eAAe,UAAU,OAAO;AACjD,WAAO,EAAE,UAAU,QAAQ,WAAW;AAAA,EACxC;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var html_exports = {};
|
|
20
|
+
__export(html_exports, {
|
|
21
|
+
htmlParser: () => htmlParser
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(html_exports);
|
|
24
|
+
const HEADING_RE = /<h([1-6])[^>]*>([\s\S]*?)<\/h\1>/gi;
|
|
25
|
+
function stripHtmlTags(html) {
|
|
26
|
+
return html.replace(/<[^>]+>/g, "").trim();
|
|
27
|
+
}
|
|
28
|
+
function extractHeadings(content) {
|
|
29
|
+
const headings = [];
|
|
30
|
+
let match;
|
|
31
|
+
HEADING_RE.lastIndex = 0;
|
|
32
|
+
while ((match = HEADING_RE.exec(content)) !== null) {
|
|
33
|
+
const title = stripHtmlTags(match[2]);
|
|
34
|
+
if (title.length === 0) continue;
|
|
35
|
+
headings.push({
|
|
36
|
+
title,
|
|
37
|
+
level: parseInt(match[1], 10),
|
|
38
|
+
byteOffset: Buffer.byteLength(content.slice(0, match.index), "utf8")
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
return headings;
|
|
42
|
+
}
|
|
43
|
+
function buildHierarchy(headings, content) {
|
|
44
|
+
const contentBytes = Buffer.byteLength(content, "utf8");
|
|
45
|
+
if (headings.length === 0) {
|
|
46
|
+
const titleMatch = content.match(/<title[^>]*>([\s\S]*?)<\/title>/i);
|
|
47
|
+
const title = titleMatch ? stripHtmlTags(titleMatch[1]) : "(document)";
|
|
48
|
+
return [{
|
|
49
|
+
title,
|
|
50
|
+
level: 0,
|
|
51
|
+
byteStart: 0,
|
|
52
|
+
byteEnd: contentBytes,
|
|
53
|
+
content: stripHtmlTags(content),
|
|
54
|
+
children: []
|
|
55
|
+
}];
|
|
56
|
+
}
|
|
57
|
+
const sections = [];
|
|
58
|
+
for (let i = 0; i < headings.length; i++) {
|
|
59
|
+
const start = headings[i].byteOffset;
|
|
60
|
+
const end = i + 1 < headings.length ? headings[i + 1].byteOffset : contentBytes;
|
|
61
|
+
const rawContent = Buffer.from(content, "utf8").slice(start, end).toString("utf8");
|
|
62
|
+
sections.push({ ...headings[i], byteEnd: end, content: rawContent });
|
|
63
|
+
}
|
|
64
|
+
const root = [];
|
|
65
|
+
const stack = [];
|
|
66
|
+
for (const s of sections) {
|
|
67
|
+
const parsed = {
|
|
68
|
+
title: s.title,
|
|
69
|
+
level: s.level,
|
|
70
|
+
byteStart: s.byteOffset,
|
|
71
|
+
byteEnd: s.byteEnd,
|
|
72
|
+
content: s.content,
|
|
73
|
+
children: []
|
|
74
|
+
};
|
|
75
|
+
while (stack.length > 0 && stack[stack.length - 1].level >= s.level) {
|
|
76
|
+
stack.pop();
|
|
77
|
+
}
|
|
78
|
+
if (stack.length === 0) {
|
|
79
|
+
root.push(parsed);
|
|
80
|
+
} else {
|
|
81
|
+
stack[stack.length - 1].section.children.push(parsed);
|
|
82
|
+
}
|
|
83
|
+
stack.push({ section: parsed, level: s.level });
|
|
84
|
+
}
|
|
85
|
+
return root;
|
|
86
|
+
}
|
|
87
|
+
const htmlParser = {
|
|
88
|
+
name: "html",
|
|
89
|
+
extensions: [".html", ".htm"],
|
|
90
|
+
parse(content, _filePath) {
|
|
91
|
+
const headings = extractHeadings(content);
|
|
92
|
+
const sections = buildHierarchy(headings, content);
|
|
93
|
+
return { sections, format: "html" };
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
97
|
+
0 && (module.exports = {
|
|
98
|
+
htmlParser
|
|
99
|
+
});
|
|
100
|
+
//# sourceMappingURL=html.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/docs/formats/html.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * HTML Section Parser\n *\n * Handles: .html, .htm\n * Parsing strategy: <h1>\u2013<h6> heading tags.\n * Strips HTML tags from content for summary extraction.\n */\n\nimport type { DocFormatParser, ParseResult, ParsedSection } from '../types';\n\nconst HEADING_RE = /<h([1-6])[^>]*>([\\s\\S]*?)<\\/h\\1>/gi;\n\ninterface RawHeading {\n title: string;\n level: number;\n byteOffset: number;\n}\n\nfunction stripHtmlTags(html: string): string {\n return html.replace(/<[^>]+>/g, '').trim();\n}\n\nfunction extractHeadings(content: string): RawHeading[] {\n const headings: RawHeading[] = [];\n let match: RegExpExecArray | null;\n\n // Reset regex state\n HEADING_RE.lastIndex = 0;\n\n while ((match = HEADING_RE.exec(content)) !== null) {\n const title = stripHtmlTags(match[2]);\n if (title.length === 0) continue;\n\n headings.push({\n title,\n level: parseInt(match[1], 10),\n byteOffset: Buffer.byteLength(content.slice(0, match.index), 'utf8'),\n });\n }\n\n return headings;\n}\n\nfunction buildHierarchy(headings: RawHeading[], content: string): ParsedSection[] {\n const contentBytes = Buffer.byteLength(content, 'utf8');\n\n if (headings.length === 0) {\n // Try to extract title from <title> tag\n const titleMatch = content.match(/<title[^>]*>([\\s\\S]*?)<\\/title>/i);\n const title = titleMatch ? stripHtmlTags(titleMatch[1]) : '(document)';\n return [{\n title,\n level: 0,\n byteStart: 0,\n byteEnd: contentBytes,\n content: stripHtmlTags(content),\n children: [],\n }];\n }\n\n const sections: Array<RawHeading & { byteEnd: number; content: string }> = [];\n for (let i = 0; i < headings.length; i++) {\n const start = headings[i].byteOffset;\n const end = i + 1 < headings.length ? headings[i + 1].byteOffset : contentBytes;\n const rawContent = Buffer.from(content, 'utf8').slice(start, end).toString('utf8');\n sections.push({ ...headings[i], byteEnd: end, content: rawContent });\n }\n\n const root: ParsedSection[] = [];\n const stack: Array<{ section: ParsedSection; level: number }> = [];\n\n for (const s of sections) {\n const parsed: ParsedSection = {\n title: s.title,\n level: s.level,\n byteStart: s.byteOffset,\n byteEnd: s.byteEnd,\n content: s.content,\n children: [],\n };\n\n while (stack.length > 0 && stack[stack.length - 1].level >= s.level) {\n stack.pop();\n }\n\n if (stack.length === 0) {\n root.push(parsed);\n } else {\n stack[stack.length - 1].section.children.push(parsed);\n }\n\n stack.push({ section: parsed, level: s.level });\n }\n\n return root;\n}\n\nexport const htmlParser: DocFormatParser = {\n name: 'html',\n extensions: ['.html', '.htm'],\n\n parse(content: string, _filePath: string): ParseResult {\n const headings = extractHeadings(content);\n const sections = buildHierarchy(headings, content);\n return { sections, format: 'html' };\n },\n};\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAUA,MAAM,aAAa;AAQnB,SAAS,cAAc,MAAsB;AAC3C,SAAO,KAAK,QAAQ,YAAY,EAAE,EAAE,KAAK;AAC3C;AAEA,SAAS,gBAAgB,SAA+B;AACtD,QAAM,WAAyB,CAAC;AAChC,MAAI;AAGJ,aAAW,YAAY;AAEvB,UAAQ,QAAQ,WAAW,KAAK,OAAO,OAAO,MAAM;AAClD,UAAM,QAAQ,cAAc,MAAM,CAAC,CAAC;AACpC,QAAI,MAAM,WAAW,EAAG;AAExB,aAAS,KAAK;AAAA,MACZ;AAAA,MACA,OAAO,SAAS,MAAM,CAAC,GAAG,EAAE;AAAA,MAC5B,YAAY,OAAO,WAAW,QAAQ,MAAM,GAAG,MAAM,KAAK,GAAG,MAAM;AAAA,IACrE,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAEA,SAAS,eAAe,UAAwB,SAAkC;AAChF,QAAM,eAAe,OAAO,WAAW,SAAS,MAAM;AAEtD,MAAI,SAAS,WAAW,GAAG;AAEzB,UAAM,aAAa,QAAQ,MAAM,kCAAkC;AACnE,UAAM,QAAQ,aAAa,cAAc,WAAW,CAAC,CAAC,IAAI;AAC1D,WAAO,CAAC;AAAA,MACN;AAAA,MACA,OAAO;AAAA,MACP,WAAW;AAAA,MACX,SAAS;AAAA,MACT,SAAS,cAAc,OAAO;AAAA,MAC9B,UAAU,CAAC;AAAA,IACb,CAAC;AAAA,EACH;AAEA,QAAM,WAAqE,CAAC;AAC5E,WAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,UAAM,QAAQ,SAAS,CAAC,EAAE;AAC1B,UAAM,MAAM,IAAI,IAAI,SAAS,SAAS,SAAS,IAAI,CAAC,EAAE,aAAa;AACnE,UAAM,aAAa,OAAO,KAAK,SAAS,MAAM,EAAE,MAAM,OAAO,GAAG,EAAE,SAAS,MAAM;AACjF,aAAS,KAAK,EAAE,GAAG,SAAS,CAAC,GAAG,SAAS,KAAK,SAAS,WAAW,CAAC;AAAA,EACrE;AAEA,QAAM,OAAwB,CAAC;AAC/B,QAAM,QAA0D,CAAC;AAEjE,aAAW,KAAK,UAAU;AACxB,UAAM,SAAwB;AAAA,MAC5B,OAAO,EAAE;AAAA,MACT,OAAO,EAAE;AAAA,MACT,WAAW,EAAE;AAAA,MACb,SAAS,EAAE;AAAA,MACX,SAAS,EAAE;AAAA,MACX,UAAU,CAAC;AAAA,IACb;AAEA,WAAO,MAAM,SAAS,KAAK,MAAM,MAAM,SAAS,CAAC,EAAE,SAAS,EAAE,OAAO;AACnE,YAAM,IAAI;AAAA,IACZ;AAEA,QAAI,MAAM,WAAW,GAAG;AACtB,WAAK,KAAK,MAAM;AAAA,IAClB,OAAO;AACL,YAAM,MAAM,SAAS,CAAC,EAAE,QAAQ,SAAS,KAAK,MAAM;AAAA,IACtD;AAEA,UAAM,KAAK,EAAE,SAAS,QAAQ,OAAO,EAAE,MAAM,CAAC;AAAA,EAChD;AAEA,SAAO;AACT;AAEO,MAAM,aAA8B;AAAA,EACzC,MAAM;AAAA,EACN,YAAY,CAAC,SAAS,MAAM;AAAA,EAE5B,MAAM,SAAiB,WAAgC;AACrD,UAAM,WAAW,gBAAgB,OAAO;AACxC,UAAM,WAAW,eAAe,UAAU,OAAO;AACjD,WAAO,EAAE,UAAU,QAAQ,OAAO;AAAA,EACpC;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var formats_exports = {};
|
|
20
|
+
__export(formats_exports, {
|
|
21
|
+
getParser: () => getParser,
|
|
22
|
+
getRegisteredParsers: () => getRegisteredParsers,
|
|
23
|
+
getSupportedExtensions: () => getSupportedExtensions,
|
|
24
|
+
isSupportedDocFormat: () => isSupportedDocFormat,
|
|
25
|
+
parseDocFile: () => parseDocFile
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(formats_exports);
|
|
28
|
+
var import_markdown = require("./markdown");
|
|
29
|
+
var import_rst = require("./rst");
|
|
30
|
+
var import_asciidoc = require("./asciidoc");
|
|
31
|
+
var import_rdoc = require("./rdoc");
|
|
32
|
+
var import_org = require("./org");
|
|
33
|
+
var import_html = require("./html");
|
|
34
|
+
var import_plaintext = require("./plaintext");
|
|
35
|
+
var import_openapi = require("./openapi");
|
|
36
|
+
const parsers = [
|
|
37
|
+
import_markdown.markdownParser,
|
|
38
|
+
import_rst.rstParser,
|
|
39
|
+
import_asciidoc.asciidocParser,
|
|
40
|
+
import_rdoc.rdocParser,
|
|
41
|
+
import_org.orgParser,
|
|
42
|
+
import_html.htmlParser,
|
|
43
|
+
import_plaintext.plaintextParser
|
|
44
|
+
];
|
|
45
|
+
const extensionMap = /* @__PURE__ */ new Map();
|
|
46
|
+
for (const parser of parsers) {
|
|
47
|
+
for (const ext of parser.extensions) {
|
|
48
|
+
extensionMap.set(ext.toLowerCase(), parser);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function getParser(filePath) {
|
|
52
|
+
const ext = filePath.slice(filePath.lastIndexOf(".")).toLowerCase();
|
|
53
|
+
return extensionMap.get(ext) ?? null;
|
|
54
|
+
}
|
|
55
|
+
function parseDocFile(content, filePath) {
|
|
56
|
+
const ext = filePath.slice(filePath.lastIndexOf(".")).toLowerCase();
|
|
57
|
+
if ((ext === ".yaml" || ext === ".yml" || ext === ".json") && (0, import_openapi.isOpenAPI)(content, filePath)) {
|
|
58
|
+
return import_openapi.openapiParser.parse(content, filePath);
|
|
59
|
+
}
|
|
60
|
+
const parser = getParser(filePath);
|
|
61
|
+
if (!parser) return null;
|
|
62
|
+
return parser.parse(content, filePath);
|
|
63
|
+
}
|
|
64
|
+
function isSupportedDocFormat(filePath) {
|
|
65
|
+
return getParser(filePath) !== null;
|
|
66
|
+
}
|
|
67
|
+
function getSupportedExtensions() {
|
|
68
|
+
return [...extensionMap.keys()];
|
|
69
|
+
}
|
|
70
|
+
function getRegisteredParsers() {
|
|
71
|
+
return parsers.map((p) => p.name);
|
|
72
|
+
}
|
|
73
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
74
|
+
0 && (module.exports = {
|
|
75
|
+
getParser,
|
|
76
|
+
getRegisteredParsers,
|
|
77
|
+
getSupportedExtensions,
|
|
78
|
+
isSupportedDocFormat,
|
|
79
|
+
parseDocFile
|
|
80
|
+
});
|
|
81
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/docs/formats/index.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Documentation Format Registry\n *\n * Maps file extensions to their appropriate parser.\n * New parsers are registered here as they are implemented.\n */\n\nimport type { DocFormatParser, ParseResult } from '../types';\nimport { markdownParser } from './markdown';\nimport { rstParser } from './rst';\nimport { asciidocParser } from './asciidoc';\nimport { rdocParser } from './rdoc';\nimport { orgParser } from './org';\nimport { htmlParser } from './html';\nimport { plaintextParser } from './plaintext';\nimport { openapiParser, isOpenAPI } from './openapi';\n\n// \u2500\u2500 Registry \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst parsers: DocFormatParser[] = [\n markdownParser,\n rstParser,\n asciidocParser,\n rdocParser,\n orgParser,\n htmlParser,\n plaintextParser,\n];\n\n/** Extension \u2192 parser lookup (built once at module load) */\nconst extensionMap = new Map<string, DocFormatParser>();\nfor (const parser of parsers) {\n for (const ext of parser.extensions) {\n extensionMap.set(ext.toLowerCase(), parser);\n }\n}\n\n// \u2500\u2500 Public API \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Get the parser for a given file extension.\n * Returns null if no parser is registered for the extension.\n */\nexport function getParser(filePath: string): DocFormatParser | null {\n const ext = filePath.slice(filePath.lastIndexOf('.')).toLowerCase();\n return extensionMap.get(ext) ?? null;\n}\n\n/**\n * Parse a documentation file into sections.\n * Returns null if no parser is available for the file format.\n * Supports content-based detection for OpenAPI specs.\n */\nexport function parseDocFile(content: string, filePath: string): ParseResult | null {\n // Content-based detection: OpenAPI specs in .yaml/.yml/.json files\n const ext = filePath.slice(filePath.lastIndexOf('.')).toLowerCase();\n if ((ext === '.yaml' || ext === '.yml' || ext === '.json') && isOpenAPI(content, filePath)) {\n return openapiParser.parse(content, filePath);\n }\n\n const parser = getParser(filePath);\n if (!parser) return null;\n return parser.parse(content, filePath);\n}\n\n/**\n * Check if a file extension is supported for documentation parsing.\n */\nexport function isSupportedDocFormat(filePath: string): boolean {\n return getParser(filePath) !== null;\n}\n\n/**\n * Get all supported file extensions.\n */\nexport function getSupportedExtensions(): string[] {\n return [...extensionMap.keys()];\n}\n\n/**\n * Get all registered parser names.\n */\nexport function getRegisteredParsers(): string[] {\n return parsers.map(p => p.name);\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,sBAA+B;AAC/B,iBAA0B;AAC1B,sBAA+B;AAC/B,kBAA2B;AAC3B,iBAA0B;AAC1B,kBAA2B;AAC3B,uBAAgC;AAChC,qBAAyC;AAIzC,MAAM,UAA6B;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGA,MAAM,eAAe,oBAAI,IAA6B;AACtD,WAAW,UAAU,SAAS;AAC5B,aAAW,OAAO,OAAO,YAAY;AACnC,iBAAa,IAAI,IAAI,YAAY,GAAG,MAAM;AAAA,EAC5C;AACF;AAQO,SAAS,UAAU,UAA0C;AAClE,QAAM,MAAM,SAAS,MAAM,SAAS,YAAY,GAAG,CAAC,EAAE,YAAY;AAClE,SAAO,aAAa,IAAI,GAAG,KAAK;AAClC;AAOO,SAAS,aAAa,SAAiB,UAAsC;AAElF,QAAM,MAAM,SAAS,MAAM,SAAS,YAAY,GAAG,CAAC,EAAE,YAAY;AAClE,OAAK,QAAQ,WAAW,QAAQ,UAAU,QAAQ,gBAAY,0BAAU,SAAS,QAAQ,GAAG;AAC1F,WAAO,6BAAc,MAAM,SAAS,QAAQ;AAAA,EAC9C;AAEA,QAAM,SAAS,UAAU,QAAQ;AACjC,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,OAAO,MAAM,SAAS,QAAQ;AACvC;AAKO,SAAS,qBAAqB,UAA2B;AAC9D,SAAO,UAAU,QAAQ,MAAM;AACjC;AAKO,SAAS,yBAAmC;AACjD,SAAO,CAAC,GAAG,aAAa,KAAK,CAAC;AAChC;AAKO,SAAS,uBAAiC;AAC/C,SAAO,QAAQ,IAAI,OAAK,EAAE,IAAI;AAChC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var markdown_exports = {};
|
|
20
|
+
__export(markdown_exports, {
|
|
21
|
+
markdownParser: () => markdownParser
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(markdown_exports);
|
|
24
|
+
const ATX_HEADING = /^(#{1,6})\s+(.+?)(?:\s+#+)?$/;
|
|
25
|
+
const SETEXT_H1 = /^=+\s*$/;
|
|
26
|
+
const SETEXT_H2 = /^-+\s*$/;
|
|
27
|
+
const FENCE_OPEN = /^(`{3,}|~{3,})/;
|
|
28
|
+
function extractHeadings(content) {
|
|
29
|
+
const lines = content.split("\n");
|
|
30
|
+
const headings = [];
|
|
31
|
+
let inFence = false;
|
|
32
|
+
let fenceChar = "";
|
|
33
|
+
let fenceLen = 0;
|
|
34
|
+
let byteOffset = 0;
|
|
35
|
+
for (let i = 0; i < lines.length; i++) {
|
|
36
|
+
const line = lines[i];
|
|
37
|
+
const lineBytes = Buffer.byteLength(line, "utf8") + 1;
|
|
38
|
+
if (!inFence) {
|
|
39
|
+
const fenceMatch = line.match(FENCE_OPEN);
|
|
40
|
+
if (fenceMatch) {
|
|
41
|
+
inFence = true;
|
|
42
|
+
fenceChar = fenceMatch[1][0];
|
|
43
|
+
fenceLen = fenceMatch[1].length;
|
|
44
|
+
byteOffset += lineBytes;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
} else {
|
|
48
|
+
const closingPattern = new RegExp(`^${fenceChar}{${fenceLen},}\\s*$`);
|
|
49
|
+
if (closingPattern.test(line)) {
|
|
50
|
+
inFence = false;
|
|
51
|
+
}
|
|
52
|
+
byteOffset += lineBytes;
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
const atxMatch = line.match(ATX_HEADING);
|
|
56
|
+
if (atxMatch) {
|
|
57
|
+
headings.push({
|
|
58
|
+
title: atxMatch[2].trim(),
|
|
59
|
+
level: atxMatch[1].length,
|
|
60
|
+
lineIndex: i,
|
|
61
|
+
byteOffset
|
|
62
|
+
});
|
|
63
|
+
byteOffset += lineBytes;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if (i + 1 < lines.length && line.trim().length > 0) {
|
|
67
|
+
const nextLine = lines[i + 1];
|
|
68
|
+
if (SETEXT_H1.test(nextLine)) {
|
|
69
|
+
headings.push({
|
|
70
|
+
title: line.trim(),
|
|
71
|
+
level: 1,
|
|
72
|
+
lineIndex: i,
|
|
73
|
+
byteOffset
|
|
74
|
+
});
|
|
75
|
+
} else if (SETEXT_H2.test(nextLine)) {
|
|
76
|
+
headings.push({
|
|
77
|
+
title: line.trim(),
|
|
78
|
+
level: 2,
|
|
79
|
+
lineIndex: i,
|
|
80
|
+
byteOffset
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
byteOffset += lineBytes;
|
|
85
|
+
}
|
|
86
|
+
return headings;
|
|
87
|
+
}
|
|
88
|
+
function buildHierarchy(headings, content) {
|
|
89
|
+
const contentBytes = Buffer.byteLength(content, "utf8");
|
|
90
|
+
if (headings.length === 0) {
|
|
91
|
+
return [{
|
|
92
|
+
title: "(document)",
|
|
93
|
+
level: 0,
|
|
94
|
+
byteStart: 0,
|
|
95
|
+
byteEnd: contentBytes,
|
|
96
|
+
content,
|
|
97
|
+
children: []
|
|
98
|
+
}];
|
|
99
|
+
}
|
|
100
|
+
const sections = [];
|
|
101
|
+
for (let i = 0; i < headings.length; i++) {
|
|
102
|
+
const start = headings[i].byteOffset;
|
|
103
|
+
const end = i + 1 < headings.length ? headings[i + 1].byteOffset : contentBytes;
|
|
104
|
+
const sectionContent = Buffer.from(content, "utf8").slice(start, end).toString("utf8");
|
|
105
|
+
sections.push({ ...headings[i], byteEnd: end, content: sectionContent });
|
|
106
|
+
}
|
|
107
|
+
const root = [];
|
|
108
|
+
const stack = [];
|
|
109
|
+
for (const s of sections) {
|
|
110
|
+
const parsed = {
|
|
111
|
+
title: s.title,
|
|
112
|
+
level: s.level,
|
|
113
|
+
byteStart: s.byteOffset,
|
|
114
|
+
byteEnd: s.byteEnd,
|
|
115
|
+
content: s.content,
|
|
116
|
+
children: []
|
|
117
|
+
};
|
|
118
|
+
while (stack.length > 0 && stack[stack.length - 1].level >= s.level) {
|
|
119
|
+
stack.pop();
|
|
120
|
+
}
|
|
121
|
+
if (stack.length === 0) {
|
|
122
|
+
root.push(parsed);
|
|
123
|
+
} else {
|
|
124
|
+
stack[stack.length - 1].section.children.push(parsed);
|
|
125
|
+
}
|
|
126
|
+
stack.push({ section: parsed, level: s.level });
|
|
127
|
+
}
|
|
128
|
+
return root;
|
|
129
|
+
}
|
|
130
|
+
const markdownParser = {
|
|
131
|
+
name: "markdown",
|
|
132
|
+
extensions: [".md", ".mdx", ".cheatmd"],
|
|
133
|
+
parse(content, _filePath) {
|
|
134
|
+
const headings = extractHeadings(content);
|
|
135
|
+
const sections = buildHierarchy(headings, content);
|
|
136
|
+
return {
|
|
137
|
+
sections,
|
|
138
|
+
format: "markdown"
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
143
|
+
0 && (module.exports = {
|
|
144
|
+
markdownParser
|
|
145
|
+
});
|
|
146
|
+
//# sourceMappingURL=markdown.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/docs/formats/markdown.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Markdown Section Parser\n *\n * Handles: .md, .mdx, .cheatmd\n * Parsing strategy: ATX headings (# Heading) + setext headings (underline with = or -)\n *\n * Correctly ignores headings inside fenced code blocks (``` or ~~~).\n */\n\nimport type { DocFormatParser, ParseResult, ParsedSection } from '../types';\n\n// \u2500\u2500 ATX heading regex: # to ###### at start of line \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst ATX_HEADING = /^(#{1,6})\\s+(.+?)(?:\\s+#+)?$/;\n\n// \u2500\u2500 Setext heading: line followed by === or --- \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst SETEXT_H1 = /^=+\\s*$/;\nconst SETEXT_H2 = /^-+\\s*$/;\n\n// \u2500\u2500 Fenced code block markers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst FENCE_OPEN = /^(`{3,}|~{3,})/;\n\ninterface RawHeading {\n title: string;\n level: number;\n lineIndex: number;\n byteOffset: number;\n}\n\n/**\n * Extract all headings from Markdown content, respecting code fences.\n */\nfunction extractHeadings(content: string): RawHeading[] {\n const lines = content.split('\\n');\n const headings: RawHeading[] = [];\n let inFence = false;\n let fenceChar = '';\n let fenceLen = 0;\n let byteOffset = 0;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const lineBytes = Buffer.byteLength(line, 'utf8') + 1; // +1 for \\n\n\n // Track fenced code blocks\n if (!inFence) {\n const fenceMatch = line.match(FENCE_OPEN);\n if (fenceMatch) {\n inFence = true;\n fenceChar = fenceMatch[1][0];\n fenceLen = fenceMatch[1].length;\n byteOffset += lineBytes;\n continue;\n }\n } else {\n // Check for closing fence\n const closingPattern = new RegExp(`^${fenceChar}{${fenceLen},}\\\\s*$`);\n if (closingPattern.test(line)) {\n inFence = false;\n }\n byteOffset += lineBytes;\n continue;\n }\n\n // ATX heading\n const atxMatch = line.match(ATX_HEADING);\n if (atxMatch) {\n headings.push({\n title: atxMatch[2].trim(),\n level: atxMatch[1].length,\n lineIndex: i,\n byteOffset,\n });\n byteOffset += lineBytes;\n continue;\n }\n\n // Setext heading (check next line)\n if (i + 1 < lines.length && line.trim().length > 0) {\n const nextLine = lines[i + 1];\n if (SETEXT_H1.test(nextLine)) {\n headings.push({\n title: line.trim(),\n level: 1,\n lineIndex: i,\n byteOffset,\n });\n } else if (SETEXT_H2.test(nextLine)) {\n headings.push({\n title: line.trim(),\n level: 2,\n lineIndex: i,\n byteOffset,\n });\n }\n }\n\n byteOffset += lineBytes;\n }\n\n return headings;\n}\n\n/**\n * Build a section hierarchy from flat headings list.\n * Each section's content spans from its heading to the next heading of same or higher level.\n */\nfunction buildHierarchy(headings: RawHeading[], content: string): ParsedSection[] {\n const contentBytes = Buffer.byteLength(content, 'utf8');\n\n if (headings.length === 0) {\n // No headings \u2014 treat entire file as a single root section\n return [{\n title: '(document)',\n level: 0,\n byteStart: 0,\n byteEnd: contentBytes,\n content,\n children: [],\n }];\n }\n\n // Calculate byte ranges for each heading\n const sections: Array<RawHeading & { byteEnd: number; content: string }> = [];\n for (let i = 0; i < headings.length; i++) {\n const start = headings[i].byteOffset;\n const end = i + 1 < headings.length ? headings[i + 1].byteOffset : contentBytes;\n const sectionContent = Buffer.from(content, 'utf8').slice(start, end).toString('utf8');\n sections.push({ ...headings[i], byteEnd: end, content: sectionContent });\n }\n\n // Build tree using a stack-based approach\n const root: ParsedSection[] = [];\n const stack: Array<{ section: ParsedSection; level: number }> = [];\n\n for (const s of sections) {\n const parsed: ParsedSection = {\n title: s.title,\n level: s.level,\n byteStart: s.byteOffset,\n byteEnd: s.byteEnd,\n content: s.content,\n children: [],\n };\n\n // Pop stack until we find a parent with lower level\n while (stack.length > 0 && stack[stack.length - 1].level >= s.level) {\n stack.pop();\n }\n\n if (stack.length === 0) {\n root.push(parsed);\n } else {\n stack[stack.length - 1].section.children.push(parsed);\n }\n\n stack.push({ section: parsed, level: s.level });\n }\n\n return root;\n}\n\n// \u2500\u2500 Parser Export \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport const markdownParser: DocFormatParser = {\n name: 'markdown',\n extensions: ['.md', '.mdx', '.cheatmd'],\n\n parse(content: string, _filePath: string): ParseResult {\n const headings = extractHeadings(content);\n const sections = buildHierarchy(headings, content);\n\n return {\n sections,\n format: 'markdown',\n };\n },\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|