kirograph 0.15.0 → 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 +112 -1
- package/dist/bin/commands/docs.js +357 -0
- package/dist/bin/commands/docs.js.map +7 -0
- package/dist/bin/installer/config-prompt.js +17 -1
- package/dist/bin/installer/config-prompt.js.map +2 -2
- package/dist/bin/installer/index.js +6 -1
- package/dist/bin/installer/index.js.map +2 -2
- package/dist/bin/installer/steering.js +21 -0
- package/dist/bin/installer/steering.js.map +2 -2
- package/dist/bin/installer/targets/index.js.map +1 -1
- package/dist/bin/installer/targets/kiro.js +2 -2
- package/dist/bin/installer/targets/kiro.js.map +2 -2
- package/dist/bin/kirograph.js +3 -1
- package/dist/bin/kirograph.js.map +3 -3
- package/dist/compression/naive-cost.js +19 -0
- package/dist/compression/naive-cost.js.map +2 -2
- package/dist/compression/tracker.js +11 -2
- package/dist/compression/tracker.js.map +2 -2
- package/dist/compression/types.js.map +1 -1
- package/dist/config.js +34 -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 +11 -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/mcp/tool-names.js +6 -1
- package/dist/mcp/tool-names.js.map +2 -2
- package/dist/mcp/tools.js +245 -1
- package/dist/mcp/tools.js.map +2 -2
- package/package.json +1 -1
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,228 @@
|
|
|
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 openapi_exports = {};
|
|
20
|
+
__export(openapi_exports, {
|
|
21
|
+
isOpenAPI: () => isOpenAPI,
|
|
22
|
+
openapiParser: () => openapiParser
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(openapi_exports);
|
|
25
|
+
function isOpenAPIContent(content, filePath) {
|
|
26
|
+
const ext = filePath.slice(filePath.lastIndexOf(".")).toLowerCase();
|
|
27
|
+
if (ext === ".json") {
|
|
28
|
+
try {
|
|
29
|
+
const parsed = JSON.parse(content);
|
|
30
|
+
return "openapi" in parsed || "swagger" in parsed;
|
|
31
|
+
} catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return /^(openapi|swagger)\s*:/m.test(content);
|
|
36
|
+
}
|
|
37
|
+
function parseYAMLOperations(content) {
|
|
38
|
+
const operations = [];
|
|
39
|
+
const lines = content.split("\n");
|
|
40
|
+
let inPaths = false;
|
|
41
|
+
let currentPath = "";
|
|
42
|
+
let currentMethod = "";
|
|
43
|
+
let currentTags = [];
|
|
44
|
+
let currentSummary = "";
|
|
45
|
+
let currentDescription = "";
|
|
46
|
+
let opStart = 0;
|
|
47
|
+
let byteOffset = 0;
|
|
48
|
+
for (let i = 0; i < lines.length; i++) {
|
|
49
|
+
const line = lines[i];
|
|
50
|
+
const lineBytes = Buffer.byteLength(line, "utf8") + 1;
|
|
51
|
+
if (/^paths\s*:/.test(line)) {
|
|
52
|
+
inPaths = true;
|
|
53
|
+
byteOffset += lineBytes;
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if (inPaths && /^\S/.test(line) && !/^paths/.test(line)) {
|
|
57
|
+
if (currentPath && currentMethod) {
|
|
58
|
+
operations.push({
|
|
59
|
+
method: currentMethod.toUpperCase(),
|
|
60
|
+
path: currentPath,
|
|
61
|
+
summary: currentSummary,
|
|
62
|
+
description: currentDescription,
|
|
63
|
+
tags: currentTags.length > 0 ? currentTags : ["default"],
|
|
64
|
+
byteStart: opStart,
|
|
65
|
+
byteEnd: byteOffset
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
inPaths = false;
|
|
69
|
+
byteOffset += lineBytes;
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
if (inPaths) {
|
|
73
|
+
const pathMatch = line.match(/^\s{2}(['"]?)(\/[^'":\s]*)\1\s*:/);
|
|
74
|
+
if (pathMatch) {
|
|
75
|
+
if (currentPath && currentMethod) {
|
|
76
|
+
operations.push({
|
|
77
|
+
method: currentMethod.toUpperCase(),
|
|
78
|
+
path: currentPath,
|
|
79
|
+
summary: currentSummary,
|
|
80
|
+
description: currentDescription,
|
|
81
|
+
tags: currentTags.length > 0 ? currentTags : ["default"],
|
|
82
|
+
byteStart: opStart,
|
|
83
|
+
byteEnd: byteOffset
|
|
84
|
+
});
|
|
85
|
+
currentMethod = "";
|
|
86
|
+
currentSummary = "";
|
|
87
|
+
currentDescription = "";
|
|
88
|
+
currentTags = [];
|
|
89
|
+
}
|
|
90
|
+
currentPath = pathMatch[2];
|
|
91
|
+
}
|
|
92
|
+
const methodMatch = line.match(/^\s{4}(get|post|put|delete|patch|head|options)\s*:/);
|
|
93
|
+
if (methodMatch) {
|
|
94
|
+
if (currentMethod) {
|
|
95
|
+
operations.push({
|
|
96
|
+
method: currentMethod.toUpperCase(),
|
|
97
|
+
path: currentPath,
|
|
98
|
+
summary: currentSummary,
|
|
99
|
+
description: currentDescription,
|
|
100
|
+
tags: currentTags.length > 0 ? currentTags : ["default"],
|
|
101
|
+
byteStart: opStart,
|
|
102
|
+
byteEnd: byteOffset
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
currentMethod = methodMatch[1];
|
|
106
|
+
currentSummary = "";
|
|
107
|
+
currentDescription = "";
|
|
108
|
+
currentTags = [];
|
|
109
|
+
opStart = byteOffset;
|
|
110
|
+
}
|
|
111
|
+
const summaryMatch = line.match(/^\s{6}summary\s*:\s*['"]?(.+?)['"]?\s*$/);
|
|
112
|
+
if (summaryMatch) currentSummary = summaryMatch[1];
|
|
113
|
+
const descMatch = line.match(/^\s{6}description\s*:\s*['"]?(.+?)['"]?\s*$/);
|
|
114
|
+
if (descMatch) currentDescription = descMatch[1];
|
|
115
|
+
const tagMatch = line.match(/^\s{8}-\s*['"]?(.+?)['"]?\s*$/);
|
|
116
|
+
if (tagMatch && i > 0 && /^\s{6}tags\s*:/.test(lines[i - 1] || "")) {
|
|
117
|
+
currentTags.push(tagMatch[1]);
|
|
118
|
+
}
|
|
119
|
+
if (/^\s{6}tags\s*:/.test(line)) {
|
|
120
|
+
for (let j = i + 1; j < lines.length && /^\s{8}-/.test(lines[j]); j++) {
|
|
121
|
+
const t = lines[j].match(/^\s{8}-\s*['"]?(.+?)['"]?\s*$/);
|
|
122
|
+
if (t) currentTags.push(t[1]);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
byteOffset += lineBytes;
|
|
127
|
+
}
|
|
128
|
+
if (currentPath && currentMethod) {
|
|
129
|
+
operations.push({
|
|
130
|
+
method: currentMethod.toUpperCase(),
|
|
131
|
+
path: currentPath,
|
|
132
|
+
summary: currentSummary,
|
|
133
|
+
description: currentDescription,
|
|
134
|
+
tags: currentTags.length > 0 ? currentTags : ["default"],
|
|
135
|
+
byteStart: opStart,
|
|
136
|
+
byteEnd: byteOffset
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
return operations;
|
|
140
|
+
}
|
|
141
|
+
function parseJSONOperations(content) {
|
|
142
|
+
const operations = [];
|
|
143
|
+
try {
|
|
144
|
+
const spec = JSON.parse(content);
|
|
145
|
+
const paths = spec.paths || {};
|
|
146
|
+
const contentBytes = Buffer.byteLength(content, "utf8");
|
|
147
|
+
const methods = ["get", "post", "put", "delete", "patch", "head", "options"];
|
|
148
|
+
for (const [pathStr, pathItem] of Object.entries(paths)) {
|
|
149
|
+
if (!pathItem || typeof pathItem !== "object") continue;
|
|
150
|
+
for (const method of methods) {
|
|
151
|
+
const op = pathItem[method];
|
|
152
|
+
if (!op) continue;
|
|
153
|
+
operations.push({
|
|
154
|
+
method: method.toUpperCase(),
|
|
155
|
+
path: pathStr,
|
|
156
|
+
summary: op.summary || "",
|
|
157
|
+
description: op.description || "",
|
|
158
|
+
tags: Array.isArray(op.tags) ? op.tags : ["default"],
|
|
159
|
+
byteStart: 0,
|
|
160
|
+
byteEnd: contentBytes
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
} catch {
|
|
165
|
+
}
|
|
166
|
+
return operations;
|
|
167
|
+
}
|
|
168
|
+
function buildSections(operations, content) {
|
|
169
|
+
const contentBytes = Buffer.byteLength(content, "utf8");
|
|
170
|
+
if (operations.length === 0) {
|
|
171
|
+
return [{
|
|
172
|
+
title: "(API spec)",
|
|
173
|
+
level: 0,
|
|
174
|
+
byteStart: 0,
|
|
175
|
+
byteEnd: contentBytes,
|
|
176
|
+
content,
|
|
177
|
+
children: []
|
|
178
|
+
}];
|
|
179
|
+
}
|
|
180
|
+
const byTag = /* @__PURE__ */ new Map();
|
|
181
|
+
for (const op of operations) {
|
|
182
|
+
for (const tag of op.tags) {
|
|
183
|
+
if (!byTag.has(tag)) byTag.set(tag, []);
|
|
184
|
+
byTag.get(tag).push(op);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
const root = [];
|
|
188
|
+
for (const [tag, ops] of byTag) {
|
|
189
|
+
const children = ops.map((op) => ({
|
|
190
|
+
title: `${op.method} ${op.path}`,
|
|
191
|
+
level: 2,
|
|
192
|
+
byteStart: op.byteStart,
|
|
193
|
+
byteEnd: op.byteEnd,
|
|
194
|
+
content: [op.summary, op.description].filter(Boolean).join("\n") || `${op.method} ${op.path}`,
|
|
195
|
+
children: []
|
|
196
|
+
}));
|
|
197
|
+
root.push({
|
|
198
|
+
title: tag,
|
|
199
|
+
level: 1,
|
|
200
|
+
byteStart: ops[0]?.byteStart ?? 0,
|
|
201
|
+
byteEnd: ops[ops.length - 1]?.byteEnd ?? contentBytes,
|
|
202
|
+
content: `Tag: ${tag}
|
|
203
|
+
${ops.map((o) => `${o.method} ${o.path}`).join("\n")}`,
|
|
204
|
+
children
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
return root;
|
|
208
|
+
}
|
|
209
|
+
const openapiParser = {
|
|
210
|
+
name: "openapi",
|
|
211
|
+
extensions: [],
|
|
212
|
+
// Not registered by extension — detected by content
|
|
213
|
+
parse(content, filePath) {
|
|
214
|
+
const ext = filePath.slice(filePath.lastIndexOf(".")).toLowerCase();
|
|
215
|
+
const operations = ext === ".json" ? parseJSONOperations(content) : parseYAMLOperations(content);
|
|
216
|
+
const sections = buildSections(operations, content);
|
|
217
|
+
return { sections, format: "openapi" };
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
function isOpenAPI(content, filePath) {
|
|
221
|
+
return isOpenAPIContent(content, filePath);
|
|
222
|
+
}
|
|
223
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
224
|
+
0 && (module.exports = {
|
|
225
|
+
isOpenAPI,
|
|
226
|
+
openapiParser
|
|
227
|
+
});
|
|
228
|
+
//# sourceMappingURL=openapi.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/docs/formats/openapi.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * OpenAPI/Swagger Section Parser\n *\n * Handles: .yaml, .yml, .json (when detected as OpenAPI spec)\n * Parsing strategy: Operations grouped by tag.\n * Each tag becomes a level-1 section, each operation becomes a level-2 section.\n *\n * Detection: file must contain \"openapi:\" or \"swagger:\" (YAML) or\n * \"openapi\" / \"swagger\" keys at root level (JSON).\n */\n\nimport type { DocFormatParser, ParseResult, ParsedSection } from '../types';\n\ninterface OpenAPIOperation {\n method: string;\n path: string;\n summary?: string;\n description?: string;\n tags: string[];\n byteStart: number;\n byteEnd: number;\n}\n\nfunction isOpenAPIContent(content: string, filePath: string): boolean {\n const ext = filePath.slice(filePath.lastIndexOf('.')).toLowerCase();\n if (ext === '.json') {\n try {\n const parsed = JSON.parse(content);\n return 'openapi' in parsed || 'swagger' in parsed;\n } catch { return false; }\n }\n // YAML detection\n return /^(openapi|swagger)\\s*:/m.test(content);\n}\n\nfunction parseYAMLOperations(content: string): OpenAPIOperation[] {\n const operations: OpenAPIOperation[] = [];\n const lines = content.split('\\n');\n let inPaths = false;\n let currentPath = '';\n let currentMethod = '';\n let currentTags: string[] = [];\n let currentSummary = '';\n let currentDescription = '';\n let opStart = 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;\n\n // Detect paths: section\n if (/^paths\\s*:/.test(line)) {\n inPaths = true;\n byteOffset += lineBytes;\n continue;\n }\n\n // Exit paths section on next top-level key\n if (inPaths && /^\\S/.test(line) && !/^paths/.test(line)) {\n // Flush last operation\n if (currentPath && currentMethod) {\n operations.push({\n method: currentMethod.toUpperCase(),\n path: currentPath,\n summary: currentSummary,\n description: currentDescription,\n tags: currentTags.length > 0 ? currentTags : ['default'],\n byteStart: opStart,\n byteEnd: byteOffset,\n });\n }\n inPaths = false;\n byteOffset += lineBytes;\n continue;\n }\n\n if (inPaths) {\n // Path pattern: \" /users:\" or \" '/users/{id}':\"\n const pathMatch = line.match(/^\\s{2}(['\"]?)(\\/[^'\":\\s]*)\\1\\s*:/);\n if (pathMatch) {\n // Flush previous operation\n if (currentPath && currentMethod) {\n operations.push({\n method: currentMethod.toUpperCase(),\n path: currentPath,\n summary: currentSummary,\n description: currentDescription,\n tags: currentTags.length > 0 ? currentTags : ['default'],\n byteStart: opStart,\n byteEnd: byteOffset,\n });\n currentMethod = '';\n currentSummary = '';\n currentDescription = '';\n currentTags = [];\n }\n currentPath = pathMatch[2];\n }\n\n // Method pattern: \" get:\", \" post:\", etc.\n const methodMatch = line.match(/^\\s{4}(get|post|put|delete|patch|head|options)\\s*:/);\n if (methodMatch) {\n // Flush previous operation if same path different method\n if (currentMethod) {\n operations.push({\n method: currentMethod.toUpperCase(),\n path: currentPath,\n summary: currentSummary,\n description: currentDescription,\n tags: currentTags.length > 0 ? currentTags : ['default'],\n byteStart: opStart,\n byteEnd: byteOffset,\n });\n }\n currentMethod = methodMatch[1];\n currentSummary = '';\n currentDescription = '';\n currentTags = [];\n opStart = byteOffset;\n }\n\n // Summary\n const summaryMatch = line.match(/^\\s{6}summary\\s*:\\s*['\"]?(.+?)['\"]?\\s*$/);\n if (summaryMatch) currentSummary = summaryMatch[1];\n\n // Description\n const descMatch = line.match(/^\\s{6}description\\s*:\\s*['\"]?(.+?)['\"]?\\s*$/);\n if (descMatch) currentDescription = descMatch[1];\n\n // Tags\n const tagMatch = line.match(/^\\s{8}-\\s*['\"]?(.+?)['\"]?\\s*$/);\n if (tagMatch && i > 0 && /^\\s{6}tags\\s*:/.test(lines[i - 1] || '')) {\n currentTags.push(tagMatch[1]);\n }\n // Also handle inline tag after \"tags:\" line\n if (/^\\s{6}tags\\s*:/.test(line)) {\n // Look ahead for tag items\n for (let j = i + 1; j < lines.length && /^\\s{8}-/.test(lines[j]); j++) {\n const t = lines[j].match(/^\\s{8}-\\s*['\"]?(.+?)['\"]?\\s*$/);\n if (t) currentTags.push(t[1]);\n }\n }\n }\n\n byteOffset += lineBytes;\n }\n\n // Flush last operation\n if (currentPath && currentMethod) {\n operations.push({\n method: currentMethod.toUpperCase(),\n path: currentPath,\n summary: currentSummary,\n description: currentDescription,\n tags: currentTags.length > 0 ? currentTags : ['default'],\n byteStart: opStart,\n byteEnd: byteOffset,\n });\n }\n\n return operations;\n}\n\nfunction parseJSONOperations(content: string): OpenAPIOperation[] {\n const operations: OpenAPIOperation[] = [];\n try {\n const spec = JSON.parse(content);\n const paths = spec.paths || {};\n const contentBytes = Buffer.byteLength(content, 'utf8');\n const methods = ['get', 'post', 'put', 'delete', 'patch', 'head', 'options'];\n\n for (const [pathStr, pathItem] of Object.entries(paths)) {\n if (!pathItem || typeof pathItem !== 'object') continue;\n for (const method of methods) {\n const op = (pathItem as any)[method];\n if (!op) continue;\n operations.push({\n method: method.toUpperCase(),\n path: pathStr,\n summary: op.summary || '',\n description: op.description || '',\n tags: Array.isArray(op.tags) ? op.tags : ['default'],\n byteStart: 0,\n byteEnd: contentBytes,\n });\n }\n }\n } catch { /* invalid JSON */ }\n return operations;\n}\n\nfunction buildSections(operations: OpenAPIOperation[], content: string): ParsedSection[] {\n const contentBytes = Buffer.byteLength(content, 'utf8');\n\n if (operations.length === 0) {\n return [{\n title: '(API spec)',\n level: 0,\n byteStart: 0,\n byteEnd: contentBytes,\n content,\n children: [],\n }];\n }\n\n // Group by tag\n const byTag = new Map<string, OpenAPIOperation[]>();\n for (const op of operations) {\n for (const tag of op.tags) {\n if (!byTag.has(tag)) byTag.set(tag, []);\n byTag.get(tag)!.push(op);\n }\n }\n\n const root: ParsedSection[] = [];\n for (const [tag, ops] of byTag) {\n const children: ParsedSection[] = ops.map(op => ({\n title: `${op.method} ${op.path}`,\n level: 2,\n byteStart: op.byteStart,\n byteEnd: op.byteEnd,\n content: [op.summary, op.description].filter(Boolean).join('\\n') || `${op.method} ${op.path}`,\n children: [],\n }));\n\n root.push({\n title: tag,\n level: 1,\n byteStart: ops[0]?.byteStart ?? 0,\n byteEnd: ops[ops.length - 1]?.byteEnd ?? contentBytes,\n content: `Tag: ${tag}\\n${ops.map(o => `${o.method} ${o.path}`).join('\\n')}`,\n children,\n });\n }\n\n return root;\n}\n\nexport const openapiParser: DocFormatParser = {\n name: 'openapi',\n extensions: [], // Not registered by extension \u2014 detected by content\n\n parse(content: string, filePath: string): ParseResult {\n const ext = filePath.slice(filePath.lastIndexOf('.')).toLowerCase();\n const operations = ext === '.json'\n ? parseJSONOperations(content)\n : parseYAMLOperations(content);\n\n const sections = buildSections(operations, content);\n return { sections, format: 'openapi' };\n },\n};\n\n/**\n * Check if a file is an OpenAPI spec (used by the format registry for content-based detection).\n */\nexport function isOpenAPI(content: string, filePath: string): boolean {\n return isOpenAPIContent(content, filePath);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
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 org_exports = {};
|
|
20
|
+
__export(org_exports, {
|
|
21
|
+
orgParser: () => orgParser
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(org_exports);
|
|
24
|
+
const HEADING_RE = /^(\*{1,6})\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 (/^#\+BEGIN_/i.test(line)) {
|
|
34
|
+
inBlock = true;
|
|
35
|
+
byteOffset += lineBytes;
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (/^#\+END_/i.test(line)) {
|
|
39
|
+
inBlock = false;
|
|
40
|
+
byteOffset += lineBytes;
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (!inBlock) {
|
|
44
|
+
const match = line.match(HEADING_RE);
|
|
45
|
+
if (match) {
|
|
46
|
+
let title = match[2].trim();
|
|
47
|
+
title = title.replace(/^(TODO|DONE|NEXT|WAITING|CANCELLED)\s+/, "");
|
|
48
|
+
title = title.replace(/^\[#[A-Z]\]\s+/, "");
|
|
49
|
+
title = title.replace(/\s+:[^\s:]+(?::[^\s:]+)*:\s*$/, "");
|
|
50
|
+
headings.push({
|
|
51
|
+
title,
|
|
52
|
+
level: match[1].length,
|
|
53
|
+
lineIndex: i,
|
|
54
|
+
byteOffset
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
byteOffset += lineBytes;
|
|
59
|
+
}
|
|
60
|
+
return headings;
|
|
61
|
+
}
|
|
62
|
+
function buildHierarchy(headings, content) {
|
|
63
|
+
const contentBytes = Buffer.byteLength(content, "utf8");
|
|
64
|
+
if (headings.length === 0) {
|
|
65
|
+
return [{
|
|
66
|
+
title: "(document)",
|
|
67
|
+
level: 0,
|
|
68
|
+
byteStart: 0,
|
|
69
|
+
byteEnd: contentBytes,
|
|
70
|
+
content,
|
|
71
|
+
children: []
|
|
72
|
+
}];
|
|
73
|
+
}
|
|
74
|
+
const sections = [];
|
|
75
|
+
for (let i = 0; i < headings.length; i++) {
|
|
76
|
+
const start = headings[i].byteOffset;
|
|
77
|
+
const end = i + 1 < headings.length ? headings[i + 1].byteOffset : contentBytes;
|
|
78
|
+
const sectionContent = Buffer.from(content, "utf8").slice(start, end).toString("utf8");
|
|
79
|
+
sections.push({ ...headings[i], byteEnd: end, content: sectionContent });
|
|
80
|
+
}
|
|
81
|
+
const root = [];
|
|
82
|
+
const stack = [];
|
|
83
|
+
for (const s of sections) {
|
|
84
|
+
const parsed = {
|
|
85
|
+
title: s.title,
|
|
86
|
+
level: s.level,
|
|
87
|
+
byteStart: s.byteOffset,
|
|
88
|
+
byteEnd: s.byteEnd,
|
|
89
|
+
content: s.content,
|
|
90
|
+
children: []
|
|
91
|
+
};
|
|
92
|
+
while (stack.length > 0 && stack[stack.length - 1].level >= s.level) {
|
|
93
|
+
stack.pop();
|
|
94
|
+
}
|
|
95
|
+
if (stack.length === 0) {
|
|
96
|
+
root.push(parsed);
|
|
97
|
+
} else {
|
|
98
|
+
stack[stack.length - 1].section.children.push(parsed);
|
|
99
|
+
}
|
|
100
|
+
stack.push({ section: parsed, level: s.level });
|
|
101
|
+
}
|
|
102
|
+
return root;
|
|
103
|
+
}
|
|
104
|
+
const orgParser = {
|
|
105
|
+
name: "org",
|
|
106
|
+
extensions: [".org"],
|
|
107
|
+
parse(content, _filePath) {
|
|
108
|
+
const headings = extractHeadings(content);
|
|
109
|
+
const sections = buildHierarchy(headings, content);
|
|
110
|
+
return { sections, format: "org" };
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
114
|
+
0 && (module.exports = {
|
|
115
|
+
orgParser
|
|
116
|
+
});
|
|
117
|
+
//# sourceMappingURL=org.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/docs/formats/org.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Org-mode Section Parser\n *\n * Handles: .org\n * Parsing strategy: * heading hierarchy (* Title, ** Section, *** Subsection)\n */\n\nimport type { DocFormatParser, ParseResult, ParsedSection } from '../types';\n\nconst HEADING_RE = /^(\\*{1,6})\\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 source blocks (#+BEGIN_SRC ... #+END_SRC)\n if (/^#\\+BEGIN_/i.test(line)) { inBlock = true; byteOffset += lineBytes; continue; }\n if (/^#\\+END_/i.test(line)) { inBlock = false; byteOffset += lineBytes; continue; }\n\n if (!inBlock) {\n const match = line.match(HEADING_RE);\n if (match) {\n // Strip TODO keywords and priority cookies from title\n let title = match[2].trim();\n title = title.replace(/^(TODO|DONE|NEXT|WAITING|CANCELLED)\\s+/, '');\n title = title.replace(/^\\[#[A-Z]\\]\\s+/, '');\n // Strip tags at end (:tag1:tag2:)\n title = title.replace(/\\s+:[^\\s:]+(?::[^\\s:]+)*:\\s*$/, '');\n\n headings.push({\n title,\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 orgParser: DocFormatParser = {\n name: 'org',\n extensions: ['.org'],\n\n parse(content: string, _filePath: string): ParseResult {\n const headings = extractHeadings(content);\n const sections = buildHierarchy(headings, content);\n return { sections, format: 'org' };\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,cAAc,KAAK,IAAI,GAAG;AAAE,gBAAU;AAAM,oBAAc;AAAW;AAAA,IAAU;AACnF,QAAI,YAAY,KAAK,IAAI,GAAG;AAAE,gBAAU;AAAO,oBAAc;AAAW;AAAA,IAAU;AAElF,QAAI,CAAC,SAAS;AACZ,YAAM,QAAQ,KAAK,MAAM,UAAU;AACnC,UAAI,OAAO;AAET,YAAI,QAAQ,MAAM,CAAC,EAAE,KAAK;AAC1B,gBAAQ,MAAM,QAAQ,0CAA0C,EAAE;AAClE,gBAAQ,MAAM,QAAQ,kBAAkB,EAAE;AAE1C,gBAAQ,MAAM,QAAQ,iCAAiC,EAAE;AAEzD,iBAAS,KAAK;AAAA,UACZ;AAAA,UACA,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,YAA6B;AAAA,EACxC,MAAM;AAAA,EACN,YAAY,CAAC,MAAM;AAAA,EAEnB,MAAM,SAAiB,WAAgC;AACrD,UAAM,WAAW,gBAAgB,OAAO;AACxC,UAAM,WAAW,eAAe,UAAU,OAAO;AACjD,WAAO,EAAE,UAAU,QAAQ,MAAM;AAAA,EACnC;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|