@hstm-labs/forge-spec-parser 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +53 -0
- package/dist/default-registry.d.ts +19 -0
- package/dist/default-registry.d.ts.map +1 -0
- package/dist/default-registry.js +28 -0
- package/dist/default-registry.js.map +1 -0
- package/dist/detect.d.ts +16 -0
- package/dist/detect.d.ts.map +1 -0
- package/dist/detect.js +32 -0
- package/dist/detect.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/loader.d.ts +31 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +45 -0
- package/dist/loader.js.map +1 -0
- package/dist/parser-plugin.d.ts +23 -0
- package/dist/parser-plugin.d.ts.map +1 -0
- package/dist/parser-plugin.js +8 -0
- package/dist/parser-plugin.js.map +1 -0
- package/dist/parsers/json-parser.d.ts +35 -0
- package/dist/parsers/json-parser.d.ts.map +1 -0
- package/dist/parsers/json-parser.js +46 -0
- package/dist/parsers/json-parser.js.map +1 -0
- package/dist/parsers/markdown-parser.d.ts +41 -0
- package/dist/parsers/markdown-parser.d.ts.map +1 -0
- package/dist/parsers/markdown-parser.js +606 -0
- package/dist/parsers/markdown-parser.js.map +1 -0
- package/dist/parsers/structured-mapper.d.ts +22 -0
- package/dist/parsers/structured-mapper.d.ts.map +1 -0
- package/dist/parsers/structured-mapper.js +214 -0
- package/dist/parsers/structured-mapper.js.map +1 -0
- package/dist/parsers/yaml-parser.d.ts +35 -0
- package/dist/parsers/yaml-parser.d.ts.map +1 -0
- package/dist/parsers/yaml-parser.js +47 -0
- package/dist/parsers/yaml-parser.js.map +1 -0
- package/dist/registry.d.ts +57 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +80 -0
- package/dist/registry.js.map +1 -0
- package/dist/types.d.ts +85 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/dist/validate-stage.d.ts +18 -0
- package/dist/validate-stage.d.ts.map +1 -0
- package/dist/validate-stage.js +24 -0
- package/dist/validate-stage.js.map +1 -0
- package/dist/validation-types.d.ts +46 -0
- package/dist/validation-types.d.ts.map +1 -0
- package/dist/validation-types.js +9 -0
- package/dist/validation-types.js.map +1 -0
- package/dist/validators/completeness-checker.d.ts +29 -0
- package/dist/validators/completeness-checker.d.ts.map +1 -0
- package/dist/validators/completeness-checker.js +127 -0
- package/dist/validators/completeness-checker.js.map +1 -0
- package/dist/validators/cross-reference-validator.d.ts +17 -0
- package/dist/validators/cross-reference-validator.d.ts.map +1 -0
- package/dist/validators/cross-reference-validator.js +150 -0
- package/dist/validators/cross-reference-validator.js.map +1 -0
- package/dist/validators/schema-validator.d.ts +16 -0
- package/dist/validators/schema-validator.d.ts.map +1 -0
- package/dist/validators/schema-validator.js +146 -0
- package/dist/validators/schema-validator.js.map +1 -0
- package/dist/validators/spec-validator.d.ts +15 -0
- package/dist/validators/spec-validator.d.ts.map +1 -0
- package/dist/validators/spec-validator.js +52 -0
- package/dist/validators/spec-validator.js.map +1 -0
- package/package.json +29 -0
|
@@ -0,0 +1,606 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Markdown specification parser plugin.
|
|
3
|
+
*
|
|
4
|
+
* Converts rich Markdown specification documents into the canonical
|
|
5
|
+
* {@link ParsedSpecification} model using a two-phase pipeline:
|
|
6
|
+
* 1. Markdown → mdast (Abstract Syntax Tree) via unified/remark
|
|
7
|
+
* 2. mdast → ParsedSpecification via AST walking and extraction
|
|
8
|
+
*/
|
|
9
|
+
import { unified } from 'unified';
|
|
10
|
+
import remarkParse from 'remark-parse';
|
|
11
|
+
import remarkFrontmatter from 'remark-frontmatter';
|
|
12
|
+
import remarkGfm from 'remark-gfm';
|
|
13
|
+
import { parse as parseYaml } from 'yaml';
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// Constants
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
const REQUIREMENT_KEYWORDS = [
|
|
18
|
+
'requirements',
|
|
19
|
+
'features',
|
|
20
|
+
'functional requirements',
|
|
21
|
+
'user stories',
|
|
22
|
+
];
|
|
23
|
+
const ENTITY_KEYWORDS = [
|
|
24
|
+
'entities',
|
|
25
|
+
'data model',
|
|
26
|
+
'schema',
|
|
27
|
+
'models',
|
|
28
|
+
'database',
|
|
29
|
+
];
|
|
30
|
+
const WORKFLOW_KEYWORDS = [
|
|
31
|
+
'workflows',
|
|
32
|
+
'flows',
|
|
33
|
+
'use cases',
|
|
34
|
+
'user flows',
|
|
35
|
+
'processes',
|
|
36
|
+
];
|
|
37
|
+
/** Values that indicate a field is required (case-insensitive). */
|
|
38
|
+
const REQUIRED_VALUES = new Set(['yes', 'true', 'required', '✓', 'x']);
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
// Helper Functions
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
/** Extract plain text from an array of phrasing content nodes. */
|
|
43
|
+
function phrasingToText(nodes) {
|
|
44
|
+
return nodes
|
|
45
|
+
.map((node) => {
|
|
46
|
+
switch (node.type) {
|
|
47
|
+
case 'text':
|
|
48
|
+
case 'inlineCode':
|
|
49
|
+
case 'html':
|
|
50
|
+
return node.value;
|
|
51
|
+
case 'break':
|
|
52
|
+
return '\n';
|
|
53
|
+
case 'image':
|
|
54
|
+
case 'imageReference':
|
|
55
|
+
return node.alt ?? '';
|
|
56
|
+
case 'footnoteReference':
|
|
57
|
+
return '';
|
|
58
|
+
default:
|
|
59
|
+
// emphasis, strong, delete, link, linkReference — recurse
|
|
60
|
+
if ('children' in node) {
|
|
61
|
+
return phrasingToText(node.children);
|
|
62
|
+
}
|
|
63
|
+
return '';
|
|
64
|
+
}
|
|
65
|
+
})
|
|
66
|
+
.join('');
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Extract plain text from block-level content nodes.
|
|
70
|
+
*
|
|
71
|
+
* Accepts `RootContent[]` or structurally-compatible arrays (e.g.
|
|
72
|
+
* `(BlockContent | DefinitionContent)[]`). The union types overlap
|
|
73
|
+
* extensively so a single cast at the call-site is safe and avoids
|
|
74
|
+
* verbose per-node narrowing across the mdast hierarchy.
|
|
75
|
+
*/
|
|
76
|
+
function contentNodesToText(nodes) {
|
|
77
|
+
return nodes
|
|
78
|
+
.map((node) => {
|
|
79
|
+
switch (node.type) {
|
|
80
|
+
case 'paragraph':
|
|
81
|
+
return phrasingToText(node.children);
|
|
82
|
+
case 'heading':
|
|
83
|
+
return phrasingToText(node.children);
|
|
84
|
+
case 'code':
|
|
85
|
+
return node.value;
|
|
86
|
+
case 'blockquote':
|
|
87
|
+
// BlockContent[] is a subset of RootContent[]
|
|
88
|
+
return contentNodesToText(node.children);
|
|
89
|
+
case 'list':
|
|
90
|
+
return node.children
|
|
91
|
+
.map((item) => contentNodesToText(item.children))
|
|
92
|
+
.join('\n');
|
|
93
|
+
case 'html':
|
|
94
|
+
return node.value;
|
|
95
|
+
case 'yaml':
|
|
96
|
+
case 'thematicBreak':
|
|
97
|
+
return '';
|
|
98
|
+
default:
|
|
99
|
+
return '';
|
|
100
|
+
}
|
|
101
|
+
})
|
|
102
|
+
.filter(Boolean)
|
|
103
|
+
.join('\n');
|
|
104
|
+
}
|
|
105
|
+
/** Convert text to a URL-friendly slug. */
|
|
106
|
+
function slugify(text) {
|
|
107
|
+
return text
|
|
108
|
+
.toLowerCase()
|
|
109
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
110
|
+
.replace(/^-|-$/g, '');
|
|
111
|
+
}
|
|
112
|
+
/** Detect MoSCoW priority from text. */
|
|
113
|
+
function detectMoscow(text) {
|
|
114
|
+
const lower = text.toLowerCase();
|
|
115
|
+
if (/\bmust\b/.test(lower))
|
|
116
|
+
return 'must';
|
|
117
|
+
if (/\bshould\b/.test(lower))
|
|
118
|
+
return 'should';
|
|
119
|
+
if (/\bcould\b/.test(lower))
|
|
120
|
+
return 'could';
|
|
121
|
+
if (/\bwon'?t\b/.test(lower))
|
|
122
|
+
return 'wont';
|
|
123
|
+
return undefined;
|
|
124
|
+
}
|
|
125
|
+
/** Check whether a heading title matches any of the given keywords. */
|
|
126
|
+
function matchesKeywords(title, keywords) {
|
|
127
|
+
const lower = title.toLowerCase();
|
|
128
|
+
return keywords.some((kw) => lower.includes(kw));
|
|
129
|
+
}
|
|
130
|
+
/** Extract the first sentence or line from text. */
|
|
131
|
+
function firstSentence(text) {
|
|
132
|
+
const match = text.match(/^(.+?[.!?])(?:\s|$)/);
|
|
133
|
+
if (match?.[1])
|
|
134
|
+
return match[1].trim();
|
|
135
|
+
const firstLine = text.split('\n')[0];
|
|
136
|
+
return firstLine ? firstLine.trim() : text.trim();
|
|
137
|
+
}
|
|
138
|
+
/** Get the cell text content from a table row at a specific column index. */
|
|
139
|
+
function tableCellText(row, index) {
|
|
140
|
+
const cell = row.children[index];
|
|
141
|
+
return cell ? phrasingToText(cell.children) : '';
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Find sections in the AST whose headings match the given keywords.
|
|
145
|
+
* Collects all nodes belonging to each matched section (until the next
|
|
146
|
+
* heading at the same or higher level).
|
|
147
|
+
*/
|
|
148
|
+
function findKeywordSections(tree, keywords) {
|
|
149
|
+
const results = [];
|
|
150
|
+
let current = null;
|
|
151
|
+
for (const node of tree.children) {
|
|
152
|
+
if (node.type === 'heading') {
|
|
153
|
+
const title = phrasingToText(node.children);
|
|
154
|
+
if (matchesKeywords(title, keywords)) {
|
|
155
|
+
if (current)
|
|
156
|
+
results.push(current);
|
|
157
|
+
current = { heading: title, level: node.depth, nodes: [] };
|
|
158
|
+
}
|
|
159
|
+
else if (current && node.depth <= current.level) {
|
|
160
|
+
results.push(current);
|
|
161
|
+
current = null;
|
|
162
|
+
}
|
|
163
|
+
else if (current) {
|
|
164
|
+
current.nodes.push(node);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
else if (current && node.type !== 'yaml') {
|
|
168
|
+
current.nodes.push(node);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
if (current)
|
|
172
|
+
results.push(current);
|
|
173
|
+
return results;
|
|
174
|
+
}
|
|
175
|
+
// ---------------------------------------------------------------------------
|
|
176
|
+
// Relationship Extraction
|
|
177
|
+
// ---------------------------------------------------------------------------
|
|
178
|
+
const RELATIONSHIP_PATTERNS = [
|
|
179
|
+
{ pattern: /has\s+many\s+(\w+)/gi, type: 'one-to-many' },
|
|
180
|
+
{ pattern: /has\s+one\s+(\w+)/gi, type: 'one-to-one' },
|
|
181
|
+
{ pattern: /belongs\s+to\s+(\w+)/gi, type: 'one-to-many' },
|
|
182
|
+
{
|
|
183
|
+
pattern: /many\s+to\s+many\s+(?:with\s+)?(\w+)/gi,
|
|
184
|
+
type: 'many-to-many',
|
|
185
|
+
},
|
|
186
|
+
];
|
|
187
|
+
function extractRelationshipsFromText(text) {
|
|
188
|
+
const relationships = [];
|
|
189
|
+
for (const { pattern, type } of RELATIONSHIP_PATTERNS) {
|
|
190
|
+
// Reset lastIndex for each exec loop on global regex
|
|
191
|
+
pattern.lastIndex = 0;
|
|
192
|
+
let match;
|
|
193
|
+
while ((match = pattern.exec(text)) !== null) {
|
|
194
|
+
const target = match[1];
|
|
195
|
+
if (target) {
|
|
196
|
+
relationships.push({ target, type });
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return relationships;
|
|
201
|
+
}
|
|
202
|
+
// ---------------------------------------------------------------------------
|
|
203
|
+
// MarkdownParserPlugin
|
|
204
|
+
// ---------------------------------------------------------------------------
|
|
205
|
+
/**
|
|
206
|
+
* Parser plugin for Markdown specification files.
|
|
207
|
+
*
|
|
208
|
+
* Implements the two-phase Markdown → AST → ParsedSpecification pipeline.
|
|
209
|
+
* Supports YAML frontmatter, GFM tables, task lists, and ordered lists.
|
|
210
|
+
*/
|
|
211
|
+
export class MarkdownParserPlugin {
|
|
212
|
+
format = 'markdown';
|
|
213
|
+
extensions = ['.md'];
|
|
214
|
+
/**
|
|
215
|
+
* Parse a Markdown specification into the canonical model.
|
|
216
|
+
*
|
|
217
|
+
* @param content - Raw Markdown content
|
|
218
|
+
* @param sourcePath - Original file path
|
|
219
|
+
* @returns Parsed specification
|
|
220
|
+
*/
|
|
221
|
+
parse(content, sourcePath) {
|
|
222
|
+
// Phase 1: Markdown → AST
|
|
223
|
+
const tree = unified()
|
|
224
|
+
.use(remarkParse)
|
|
225
|
+
.use(remarkFrontmatter, ['yaml'])
|
|
226
|
+
.use(remarkGfm)
|
|
227
|
+
.parse(content);
|
|
228
|
+
// Phase 2: AST → ParsedSpecification
|
|
229
|
+
const metadata = this.extractMetadata(tree, sourcePath);
|
|
230
|
+
const sections = this.extractSections(tree);
|
|
231
|
+
const requirements = this.extractRequirements(tree);
|
|
232
|
+
const entities = this.extractEntities(tree);
|
|
233
|
+
const workflows = this.extractWorkflows(tree);
|
|
234
|
+
const apiStyle = this.detectApiStyle(content);
|
|
235
|
+
const result = {
|
|
236
|
+
metadata,
|
|
237
|
+
sections,
|
|
238
|
+
requirements,
|
|
239
|
+
entities,
|
|
240
|
+
workflows,
|
|
241
|
+
};
|
|
242
|
+
if (apiStyle !== undefined) {
|
|
243
|
+
result.apiStyle = apiStyle;
|
|
244
|
+
}
|
|
245
|
+
return result;
|
|
246
|
+
}
|
|
247
|
+
// -----------------------------------------------------------------------
|
|
248
|
+
// Metadata Extraction
|
|
249
|
+
// -----------------------------------------------------------------------
|
|
250
|
+
extractMetadata(tree, sourcePath) {
|
|
251
|
+
let title = '';
|
|
252
|
+
let version;
|
|
253
|
+
let description;
|
|
254
|
+
let authors;
|
|
255
|
+
// Try YAML frontmatter first
|
|
256
|
+
const yamlNode = tree.children.find((n) => n.type === 'yaml');
|
|
257
|
+
if (yamlNode && 'value' in yamlNode) {
|
|
258
|
+
try {
|
|
259
|
+
const fm = parseYaml(yamlNode.value);
|
|
260
|
+
if (typeof fm === 'object' && fm !== null) {
|
|
261
|
+
if (typeof fm['title'] === 'string')
|
|
262
|
+
title = fm['title'];
|
|
263
|
+
if (typeof fm['version'] === 'string')
|
|
264
|
+
version = fm['version'];
|
|
265
|
+
if (typeof fm['description'] === 'string')
|
|
266
|
+
description = fm['description'];
|
|
267
|
+
if (Array.isArray(fm['authors'])) {
|
|
268
|
+
authors = fm['authors'].filter((a) => typeof a === 'string');
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
catch {
|
|
273
|
+
// Malformed YAML — fall through to heading fallback
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
// Fallback: use first h1 heading as title
|
|
277
|
+
if (!title) {
|
|
278
|
+
const firstH1 = tree.children.find((n) => n.type === 'heading' && n.depth === 1);
|
|
279
|
+
if (firstH1) {
|
|
280
|
+
title = phrasingToText(firstH1.children);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
const metadata = {
|
|
284
|
+
title: title || 'Untitled',
|
|
285
|
+
sourcePath,
|
|
286
|
+
format: 'markdown',
|
|
287
|
+
};
|
|
288
|
+
if (version !== undefined)
|
|
289
|
+
metadata.version = version;
|
|
290
|
+
if (description !== undefined)
|
|
291
|
+
metadata.description = description;
|
|
292
|
+
if (authors !== undefined && authors.length > 0)
|
|
293
|
+
metadata.authors = authors;
|
|
294
|
+
return metadata;
|
|
295
|
+
}
|
|
296
|
+
// -----------------------------------------------------------------------
|
|
297
|
+
// Section Extraction
|
|
298
|
+
// -----------------------------------------------------------------------
|
|
299
|
+
extractSections(tree) {
|
|
300
|
+
const rootSections = [];
|
|
301
|
+
const stack = [];
|
|
302
|
+
let contentBuffer = [];
|
|
303
|
+
let currentSection = null;
|
|
304
|
+
for (const node of tree.children) {
|
|
305
|
+
if (node.type === 'heading') {
|
|
306
|
+
// Finalize previous section content
|
|
307
|
+
if (currentSection) {
|
|
308
|
+
currentSection.content = contentNodesToText(contentBuffer).trim();
|
|
309
|
+
}
|
|
310
|
+
contentBuffer = [];
|
|
311
|
+
const title = phrasingToText(node.children);
|
|
312
|
+
const newSection = {
|
|
313
|
+
id: slugify(title),
|
|
314
|
+
title,
|
|
315
|
+
level: node.depth,
|
|
316
|
+
content: '',
|
|
317
|
+
subsections: [],
|
|
318
|
+
};
|
|
319
|
+
// Pop stack until parent with lower level is found
|
|
320
|
+
while (stack.length > 0 &&
|
|
321
|
+
stack[stack.length - 1].level >= node.depth) {
|
|
322
|
+
stack.pop();
|
|
323
|
+
}
|
|
324
|
+
if (stack.length === 0) {
|
|
325
|
+
rootSections.push(newSection);
|
|
326
|
+
}
|
|
327
|
+
else {
|
|
328
|
+
stack[stack.length - 1].subsections.push(newSection);
|
|
329
|
+
}
|
|
330
|
+
stack.push(newSection);
|
|
331
|
+
currentSection = newSection;
|
|
332
|
+
}
|
|
333
|
+
else if (node.type !== 'yaml') {
|
|
334
|
+
contentBuffer.push(node);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
// Finalize last section
|
|
338
|
+
if (currentSection) {
|
|
339
|
+
currentSection.content = contentNodesToText(contentBuffer).trim();
|
|
340
|
+
}
|
|
341
|
+
return rootSections;
|
|
342
|
+
}
|
|
343
|
+
// -----------------------------------------------------------------------
|
|
344
|
+
// Requirement Extraction
|
|
345
|
+
// -----------------------------------------------------------------------
|
|
346
|
+
extractRequirements(tree) {
|
|
347
|
+
const sections = findKeywordSections(tree, REQUIREMENT_KEYWORDS);
|
|
348
|
+
const requirements = [];
|
|
349
|
+
let counter = 0;
|
|
350
|
+
for (const section of sections) {
|
|
351
|
+
const lists = section.nodes.filter((n) => n.type === 'list');
|
|
352
|
+
for (const list of lists) {
|
|
353
|
+
for (const item of list.children) {
|
|
354
|
+
counter++;
|
|
355
|
+
requirements.push(this.listItemToRequirement(item, counter));
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
return requirements;
|
|
360
|
+
}
|
|
361
|
+
listItemToRequirement(item, index) {
|
|
362
|
+
const id = `REQ-${String(index).padStart(3, '0')}`;
|
|
363
|
+
// Get text from the item's direct paragraph children
|
|
364
|
+
const paragraphs = item.children.filter((n) => n.type === 'paragraph');
|
|
365
|
+
const fullText = paragraphs
|
|
366
|
+
.map((p) => phrasingToText(p.children))
|
|
367
|
+
.join(' ');
|
|
368
|
+
const title = firstSentence(fullText);
|
|
369
|
+
const priority = detectMoscow(fullText);
|
|
370
|
+
// Extract acceptance criteria from nested task-list items
|
|
371
|
+
const acceptanceCriteria = [];
|
|
372
|
+
const nestedLists = item.children.filter((n) => n.type === 'list');
|
|
373
|
+
for (const nestedList of nestedLists) {
|
|
374
|
+
for (const nestedItem of nestedList.children) {
|
|
375
|
+
if (typeof nestedItem.checked === 'boolean') {
|
|
376
|
+
const criteriaText = contentNodesToText(nestedItem.children).trim();
|
|
377
|
+
if (criteriaText) {
|
|
378
|
+
acceptanceCriteria.push(criteriaText);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
const req = {
|
|
384
|
+
id,
|
|
385
|
+
title,
|
|
386
|
+
description: fullText,
|
|
387
|
+
acceptanceCriteria,
|
|
388
|
+
};
|
|
389
|
+
if (priority !== undefined)
|
|
390
|
+
req.priority = priority;
|
|
391
|
+
return req;
|
|
392
|
+
}
|
|
393
|
+
// -----------------------------------------------------------------------
|
|
394
|
+
// Entity Extraction
|
|
395
|
+
// -----------------------------------------------------------------------
|
|
396
|
+
extractEntities(tree) {
|
|
397
|
+
const sections = findKeywordSections(tree, ENTITY_KEYWORDS);
|
|
398
|
+
const entities = [];
|
|
399
|
+
for (const section of sections) {
|
|
400
|
+
entities.push(...this.extractEntitiesFromNodes(section.nodes, section.heading));
|
|
401
|
+
}
|
|
402
|
+
return entities;
|
|
403
|
+
}
|
|
404
|
+
extractEntitiesFromNodes(nodes, defaultName) {
|
|
405
|
+
const entities = [];
|
|
406
|
+
let currentName = defaultName;
|
|
407
|
+
let currentDescription;
|
|
408
|
+
let currentFields = [];
|
|
409
|
+
let currentRelationships = [];
|
|
410
|
+
let hasSubEntities = false;
|
|
411
|
+
for (const node of nodes) {
|
|
412
|
+
if (node.type === 'heading') {
|
|
413
|
+
// Flush previous entity if it has fields
|
|
414
|
+
if (hasSubEntities && currentFields.length > 0) {
|
|
415
|
+
entities.push(this.buildEntity(currentName, currentDescription, currentFields, currentRelationships));
|
|
416
|
+
}
|
|
417
|
+
hasSubEntities = true;
|
|
418
|
+
currentName = phrasingToText(node.children);
|
|
419
|
+
currentDescription = undefined;
|
|
420
|
+
currentFields = [];
|
|
421
|
+
currentRelationships = [];
|
|
422
|
+
}
|
|
423
|
+
else if (node.type === 'table') {
|
|
424
|
+
currentFields.push(...this.parseTableFields(node));
|
|
425
|
+
}
|
|
426
|
+
else if (node.type === 'list' &&
|
|
427
|
+
!node.ordered) {
|
|
428
|
+
currentFields.push(...this.parseListFields(node));
|
|
429
|
+
}
|
|
430
|
+
else if (node.type === 'paragraph') {
|
|
431
|
+
const text = phrasingToText(node.children);
|
|
432
|
+
currentRelationships.push(...extractRelationshipsFromText(text));
|
|
433
|
+
if (currentDescription === undefined) {
|
|
434
|
+
currentDescription = text;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
// Flush last entity
|
|
439
|
+
if (currentFields.length > 0) {
|
|
440
|
+
entities.push(this.buildEntity(currentName, currentDescription, currentFields, currentRelationships));
|
|
441
|
+
}
|
|
442
|
+
return entities;
|
|
443
|
+
}
|
|
444
|
+
buildEntity(name, description, fields, relationships) {
|
|
445
|
+
const entity = {
|
|
446
|
+
name,
|
|
447
|
+
fields,
|
|
448
|
+
relationships,
|
|
449
|
+
};
|
|
450
|
+
if (description !== undefined)
|
|
451
|
+
entity.description = description;
|
|
452
|
+
return entity;
|
|
453
|
+
}
|
|
454
|
+
parseTableFields(table) {
|
|
455
|
+
const rows = table.children;
|
|
456
|
+
if (rows.length < 2)
|
|
457
|
+
return [];
|
|
458
|
+
const headerRow = rows[0];
|
|
459
|
+
const headers = headerRow.children.map((cell) => phrasingToText(cell.children).toLowerCase().trim());
|
|
460
|
+
// Find column indices
|
|
461
|
+
const nameIdx = headers.findIndex((h) => h === 'name' || h === 'field' || h === 'column');
|
|
462
|
+
const typeIdx = headers.findIndex((h) => h === 'type' || h === 'data type' || h === 'datatype');
|
|
463
|
+
const reqIdx = headers.findIndex((h) => h === 'required' ||
|
|
464
|
+
h === 'req' ||
|
|
465
|
+
h === 'nullable' ||
|
|
466
|
+
h === 'null');
|
|
467
|
+
const descIdx = headers.findIndex((h) => h === 'description' || h === 'desc' || h === 'notes');
|
|
468
|
+
if (nameIdx === -1)
|
|
469
|
+
return [];
|
|
470
|
+
const fields = [];
|
|
471
|
+
for (let i = 1; i < rows.length; i++) {
|
|
472
|
+
const row = rows[i];
|
|
473
|
+
const name = tableCellText(row, nameIdx).trim();
|
|
474
|
+
if (!name)
|
|
475
|
+
continue;
|
|
476
|
+
const type = typeIdx >= 0 ? tableCellText(row, typeIdx).trim() : 'string';
|
|
477
|
+
const reqValue = reqIdx >= 0
|
|
478
|
+
? tableCellText(row, reqIdx).trim().toLowerCase()
|
|
479
|
+
: '';
|
|
480
|
+
const desc = descIdx >= 0 ? tableCellText(row, descIdx).trim() : undefined;
|
|
481
|
+
const required = REQUIRED_VALUES.has(reqValue);
|
|
482
|
+
const field = { name, type, required };
|
|
483
|
+
if (desc !== undefined && desc !== '')
|
|
484
|
+
field.description = desc;
|
|
485
|
+
fields.push(field);
|
|
486
|
+
}
|
|
487
|
+
return fields;
|
|
488
|
+
}
|
|
489
|
+
parseListFields(list) {
|
|
490
|
+
const fields = [];
|
|
491
|
+
for (const item of list.children) {
|
|
492
|
+
const text = contentNodesToText(item.children).trim();
|
|
493
|
+
if (!text)
|
|
494
|
+
continue;
|
|
495
|
+
// Try "name: type" or "name: type (required)" patterns
|
|
496
|
+
const colonMatch = text.match(/^(\w+)\s*:\s*(\w+)(?:\s*\(([^)]+)\))?/);
|
|
497
|
+
if (colonMatch?.[1] && colonMatch[2]) {
|
|
498
|
+
const meta = colonMatch[3]?.toLowerCase() ?? '';
|
|
499
|
+
fields.push({
|
|
500
|
+
name: colonMatch[1],
|
|
501
|
+
type: colonMatch[2],
|
|
502
|
+
required: meta.includes('required'),
|
|
503
|
+
});
|
|
504
|
+
continue;
|
|
505
|
+
}
|
|
506
|
+
// Try "name - type" pattern
|
|
507
|
+
const dashMatch = text.match(/^(\w+)\s+-\s+(\w+)/);
|
|
508
|
+
if (dashMatch?.[1] && dashMatch[2]) {
|
|
509
|
+
fields.push({
|
|
510
|
+
name: dashMatch[1],
|
|
511
|
+
type: dashMatch[2],
|
|
512
|
+
required: text.toLowerCase().includes('required'),
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
return fields;
|
|
517
|
+
}
|
|
518
|
+
// -----------------------------------------------------------------------
|
|
519
|
+
// Workflow Extraction
|
|
520
|
+
// -----------------------------------------------------------------------
|
|
521
|
+
extractWorkflows(tree) {
|
|
522
|
+
const sections = findKeywordSections(tree, WORKFLOW_KEYWORDS);
|
|
523
|
+
const workflows = [];
|
|
524
|
+
let counter = 0;
|
|
525
|
+
for (const section of sections) {
|
|
526
|
+
let currentName = section.heading;
|
|
527
|
+
let currentNodes = [];
|
|
528
|
+
let hasSubWorkflows = false;
|
|
529
|
+
for (const node of section.nodes) {
|
|
530
|
+
if (node.type === 'heading') {
|
|
531
|
+
if (currentNodes.length > 0) {
|
|
532
|
+
const wf = this.buildWorkflow(currentName, currentNodes, ++counter);
|
|
533
|
+
if (wf)
|
|
534
|
+
workflows.push(wf);
|
|
535
|
+
}
|
|
536
|
+
hasSubWorkflows = true;
|
|
537
|
+
currentName = phrasingToText(node.children);
|
|
538
|
+
currentNodes = [];
|
|
539
|
+
}
|
|
540
|
+
else {
|
|
541
|
+
currentNodes.push(node);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
// Flush: if no sub-headings, use the entire section
|
|
545
|
+
if (!hasSubWorkflows) {
|
|
546
|
+
currentNodes = section.nodes;
|
|
547
|
+
}
|
|
548
|
+
if (currentNodes.length > 0) {
|
|
549
|
+
const wf = this.buildWorkflow(currentName, currentNodes, ++counter);
|
|
550
|
+
if (wf)
|
|
551
|
+
workflows.push(wf);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
return workflows;
|
|
555
|
+
}
|
|
556
|
+
buildWorkflow(name, nodes, index) {
|
|
557
|
+
const orderedLists = nodes.filter((n) => n.type === 'list' && n.ordered === true);
|
|
558
|
+
if (orderedLists.length === 0)
|
|
559
|
+
return null;
|
|
560
|
+
const steps = [];
|
|
561
|
+
for (const list of orderedLists) {
|
|
562
|
+
let order = list.start ?? 1;
|
|
563
|
+
for (const item of list.children) {
|
|
564
|
+
const action = contentNodesToText(item.children).trim();
|
|
565
|
+
if (action) {
|
|
566
|
+
steps.push({ order, action });
|
|
567
|
+
order++;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
if (steps.length === 0)
|
|
572
|
+
return null;
|
|
573
|
+
// Detect actors from step text
|
|
574
|
+
const fullText = steps.map((s) => s.action).join(' ');
|
|
575
|
+
const actorPattern = /\b(User|Admin|System|Customer|Manager|Client|Server|Developer|Operator)\b/gi;
|
|
576
|
+
const actorMatches = fullText.match(actorPattern);
|
|
577
|
+
const actors = actorMatches
|
|
578
|
+
? [
|
|
579
|
+
...new Set(actorMatches.map((a) => a.charAt(0).toUpperCase() + a.slice(1).toLowerCase())),
|
|
580
|
+
]
|
|
581
|
+
: undefined;
|
|
582
|
+
const id = `WF-${String(index).padStart(3, '0')}`;
|
|
583
|
+
const workflow = {
|
|
584
|
+
id,
|
|
585
|
+
name,
|
|
586
|
+
steps,
|
|
587
|
+
};
|
|
588
|
+
if (actors !== undefined && actors.length > 0)
|
|
589
|
+
workflow.actors = actors;
|
|
590
|
+
return workflow;
|
|
591
|
+
}
|
|
592
|
+
// -----------------------------------------------------------------------
|
|
593
|
+
// API Style Detection
|
|
594
|
+
// -----------------------------------------------------------------------
|
|
595
|
+
detectApiStyle(content) {
|
|
596
|
+
const lower = content.toLowerCase();
|
|
597
|
+
if (lower.includes('rest api') || lower.includes('restful api'))
|
|
598
|
+
return 'rest';
|
|
599
|
+
if (lower.includes('graphql'))
|
|
600
|
+
return 'graphql';
|
|
601
|
+
if (lower.includes('grpc'))
|
|
602
|
+
return 'grpc';
|
|
603
|
+
return undefined;
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
//# sourceMappingURL=markdown-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-parser.js","sourceRoot":"","sources":["../../src/parsers/markdown-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared mapping logic for structured (YAML / JSON) specification files.
|
|
3
|
+
*
|
|
4
|
+
* Both the YAML and JSON parsers produce a raw `unknown` object after parsing
|
|
5
|
+
* their respective formats. This module validates the structure and maps it
|
|
6
|
+
* into the canonical {@link ParsedSpecification} model.
|
|
7
|
+
*/
|
|
8
|
+
import type { ParsedSpecification, SpecFormat } from '../types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Map a parsed structured object into the canonical specification model.
|
|
11
|
+
*
|
|
12
|
+
* Validates the data structure (title required, arrays are arrays, etc.)
|
|
13
|
+
* and maps to canonical types with safe defaults.
|
|
14
|
+
*
|
|
15
|
+
* @param data - Raw parsed data (from YAML or JSON)
|
|
16
|
+
* @param sourcePath - Original file path
|
|
17
|
+
* @param format - Specification format (`'yaml'` or `'json'`)
|
|
18
|
+
* @returns Parsed specification
|
|
19
|
+
* @throws {@link ForgeError} with code `FORGE-SPEC-001` if `title` is missing or data is not an object
|
|
20
|
+
*/
|
|
21
|
+
export declare function mapStructuredSpec(data: unknown, sourcePath: string, format: SpecFormat): ParsedSpecification;
|
|
22
|
+
//# sourceMappingURL=structured-mapper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"structured-mapper.d.ts","sourceRoot":"","sources":["../../src/parsers/structured-mapper.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EACV,mBAAmB,EASnB,UAAU,EACX,MAAM,aAAa,CAAC;AAiDrB;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,OAAO,EACb,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,UAAU,GACjB,mBAAmB,CAsCrB"}
|