flex-md 4.7.1 → 4.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/README.md +5 -0
  2. package/athenices-ai-gateway.md +25 -0
  3. package/dist/__tests__/diagnostics.test.js +45 -47
  4. package/dist/__tests__/ofs.test.js +28 -30
  5. package/dist/__tests__/structural.test.js +19 -21
  6. package/dist/__tests__/validate.test.js +27 -29
  7. package/dist/cli/index.js +13 -15
  8. package/dist/detect/json/detectIntent.js +1 -4
  9. package/dist/detect/json/detectMarkdown.js +29 -35
  10. package/dist/detect/json/detectPresence.js +2 -6
  11. package/dist/detect/json/index.js +10 -31
  12. package/dist/detect/json/types.js +1 -2
  13. package/dist/extract/extract.js +11 -14
  14. package/dist/extract/types.js +1 -2
  15. package/dist/index.js +22 -69
  16. package/dist/logger.js +3 -6
  17. package/dist/md/match.js +1 -4
  18. package/dist/md/normalize.js +1 -4
  19. package/dist/md/outline.js +4 -8
  20. package/dist/md/parse.js +11 -20
  21. package/dist/ofs/adapter.js +45 -49
  22. package/dist/ofs/enricher.js +3 -8
  23. package/dist/ofs/infer.js +4 -7
  24. package/dist/ofs/issuesEnvelope.js +5 -10
  25. package/dist/ofs/memory.js +6 -10
  26. package/dist/ofs/parser.js +7 -13
  27. package/dist/ofs/stringify.js +1 -4
  28. package/dist/pipeline/enforce.js +12 -15
  29. package/dist/pipeline/kind.js +3 -6
  30. package/dist/pipeline/repair.js +8 -11
  31. package/dist/strictness/container.js +1 -4
  32. package/dist/strictness/processor.js +7 -10
  33. package/dist/strictness/types.js +1 -4
  34. package/dist/tokens/auto-fix.js +1 -4
  35. package/dist/tokens/cognitive-cost.js +6 -10
  36. package/dist/tokens/compliance.js +4 -8
  37. package/dist/tokens/confidence.js +6 -9
  38. package/dist/tokens/estimator.js +20 -26
  39. package/dist/tokens/improvements.js +12 -16
  40. package/dist/tokens/index.js +22 -40
  41. package/dist/tokens/parser.js +4 -7
  42. package/dist/tokens/patterns.js +2 -5
  43. package/dist/tokens/runtime-estimator.js +9 -12
  44. package/dist/tokens/smart-report.js +10 -14
  45. package/dist/tokens/spec-estimator.js +10 -15
  46. package/dist/tokens/types.js +1 -2
  47. package/dist/tokens/validator.js +3 -6
  48. package/dist/types.js +1 -2
  49. package/dist/validate/compliance.js +4 -8
  50. package/dist/validate/connection.js +5 -8
  51. package/dist/validate/types.js +1 -2
  52. package/dist/validate/validate.js +16 -19
  53. package/dist-cjs/__tests__/diagnostics.test.cjs +61 -0
  54. package/dist-cjs/__tests__/ofs.test.cjs +53 -0
  55. package/dist-cjs/__tests__/structural.test.cjs +30 -0
  56. package/dist-cjs/__tests__/validate.test.cjs +110 -0
  57. package/dist-cjs/cli/index.cjs +110 -0
  58. package/dist-cjs/detect/json/detectIntent.cjs +82 -0
  59. package/dist-cjs/detect/json/detectMarkdown.cjs +304 -0
  60. package/dist-cjs/detect/json/detectPresence.cjs +195 -0
  61. package/dist-cjs/detect/json/index.cjs +34 -0
  62. package/dist-cjs/detect/json/types.cjs +2 -0
  63. package/dist-cjs/extract/extract.cjs +72 -0
  64. package/dist-cjs/extract/types.cjs +2 -0
  65. package/dist-cjs/flex-md-loader.cjs +102 -0
  66. package/dist-cjs/index.cjs +79 -0
  67. package/dist-cjs/logger.cjs +22 -0
  68. package/dist-cjs/md/match.cjs +47 -0
  69. package/dist-cjs/md/normalize.cjs +13 -0
  70. package/dist-cjs/md/outline.cjs +49 -0
  71. package/dist-cjs/md/parse.cjs +199 -0
  72. package/dist-cjs/ofs/adapter.cjs +195 -0
  73. package/dist-cjs/ofs/enricher.cjs +151 -0
  74. package/dist-cjs/ofs/infer.cjs +63 -0
  75. package/dist-cjs/ofs/issuesEnvelope.cjs +76 -0
  76. package/dist-cjs/ofs/memory.cjs +26 -0
  77. package/dist-cjs/ofs/parser.cjs +373 -0
  78. package/dist-cjs/ofs/stringify.cjs +45 -0
  79. package/dist-cjs/pipeline/enforce.cjs +49 -0
  80. package/dist-cjs/pipeline/kind.cjs +30 -0
  81. package/dist-cjs/pipeline/repair.cjs +115 -0
  82. package/dist-cjs/strictness/container.cjs +49 -0
  83. package/dist-cjs/strictness/processor.cjs +32 -0
  84. package/dist-cjs/strictness/types.cjs +109 -0
  85. package/dist-cjs/tokens/auto-fix.cjs +59 -0
  86. package/dist-cjs/tokens/cognitive-cost.cjs +209 -0
  87. package/dist-cjs/tokens/compliance.cjs +74 -0
  88. package/dist-cjs/tokens/confidence.cjs +335 -0
  89. package/dist-cjs/tokens/estimator.cjs +157 -0
  90. package/dist-cjs/tokens/improvements.cjs +701 -0
  91. package/dist-cjs/tokens/index.cjs +74 -0
  92. package/dist-cjs/tokens/parser.cjs +100 -0
  93. package/dist-cjs/tokens/patterns.cjs +23 -0
  94. package/dist-cjs/tokens/runtime-estimator.cjs +74 -0
  95. package/dist-cjs/tokens/smart-report.cjs +191 -0
  96. package/dist-cjs/tokens/spec-estimator.cjs +125 -0
  97. package/dist-cjs/tokens/types.cjs +2 -0
  98. package/dist-cjs/tokens/validator.cjs +62 -0
  99. package/dist-cjs/types.cjs +2 -0
  100. package/dist-cjs/validate/compliance.cjs +103 -0
  101. package/dist-cjs/validate/connection.cjs +47 -0
  102. package/dist-cjs/validate/types.cjs +2 -0
  103. package/dist-cjs/validate/validate.cjs +319 -0
  104. package/docs/consumption.md +45 -0
  105. package/package.json +12 -8
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ /**
3
+ * Flex-MD Loader - ES Module Compatible Dynamic Import
4
+ *
5
+ * This module provides ES module compatible dynamic loading of the flex-md library,
6
+ * handling the case where dependencies might use require() in ES module environments.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.extractJsonFromFlexMd = extractJsonFromFlexMd;
10
+ exports.extractWithOfs = extractWithOfs;
11
+ exports.loadFlexMd = loadFlexMd;
12
+ /**
13
+ * Dynamically loads the flex-md library with ES module compatibility.
14
+ * Handles both ES module and CommonJS loading patterns.
15
+ */
16
+ async function loadFlexMd() {
17
+ try {
18
+ // First, try direct ES module import (preferred for modern environments)
19
+ const flexMdModule = await Promise.resolve().then(() => require('flex-md'));
20
+ return flexMdModule;
21
+ }
22
+ catch (esError) {
23
+ try {
24
+ // Fallback: Use Node.js createRequire for CommonJS compatibility
25
+ // This handles cases where flex-md or its dependencies use require()
26
+ const { createRequire } = await Promise.resolve().then(() => require('module'));
27
+ const require = createRequire(import.meta.url);
28
+ const flexMdModule = require('flex-md');
29
+ return flexMdModule;
30
+ }
31
+ catch (cjsError) {
32
+ // If both fail, try the dynamic Function approach as last resort
33
+ try {
34
+ const importFunc = new Function('specifier', 'return import(specifier)');
35
+ const flexMdModule = await importFunc('flex-md');
36
+ return flexMdModule;
37
+ }
38
+ catch (dynamicError) {
39
+ throw new Error(`flex-md import failed: ES module error: ${esError instanceof Error ? esError.message : String(esError)}, ` +
40
+ `CommonJS fallback error: ${cjsError instanceof Error ? cjsError.message : String(cjsError)}, ` +
41
+ `Dynamic import error: ${dynamicError instanceof Error ? dynamicError.message : String(dynamicError)}`);
42
+ }
43
+ }
44
+ }
45
+ }
46
+ /**
47
+ * Extracts structured JSON from markdown content using flex-md.
48
+ *
49
+ * @param content - The markdown content to parse
50
+ * @param spec - Optional Output Format Specification
51
+ * @param options - Extraction options
52
+ * @returns Promise resolving to extraction result
53
+ */
54
+ async function extractJsonFromFlexMd(content, spec, options = {}) {
55
+ try {
56
+ // Load flex-md library with compatibility handling
57
+ const flexMd = await loadFlexMd();
58
+ // Use the markdownToJson function for basic structured extraction
59
+ // This handles markdown with sections like # Short answer, # Full answer, etc.
60
+ const json = flexMd.markdownToJson(content);
61
+ return {
62
+ json,
63
+ success: true
64
+ };
65
+ }
66
+ catch (error) {
67
+ console.warn('Flex-md extraction failed - flex-md library compatibility issue');
68
+ console.warn('Error:', error instanceof Error ? error.message : String(error));
69
+ console.warn('Issue: flex-md uses require() in ES module context - needs fixing in flex-md-loader.ts');
70
+ return {
71
+ json: { rawText: content },
72
+ success: false,
73
+ error: error instanceof Error ? error.message : 'Unknown extraction error'
74
+ };
75
+ }
76
+ }
77
+ /**
78
+ * Alternative extraction using transformWithOfs if a spec is provided.
79
+ * This provides more structured extraction when an Output Format Spec is available.
80
+ */
81
+ async function extractWithOfs(content, spec, options = {}) {
82
+ try {
83
+ const flexMd = await loadFlexMd();
84
+ // If spec is provided, use the more advanced transformWithOfs
85
+ if (spec && flexMd.transformWithOfs) {
86
+ const result = flexMd.transformWithOfs(content, spec);
87
+ return {
88
+ json: result,
89
+ success: true
90
+ };
91
+ }
92
+ else {
93
+ // Fallback to basic markdownToJson
94
+ return extractJsonFromFlexMd(content, spec, options);
95
+ }
96
+ }
97
+ catch (error) {
98
+ console.warn('Flex-md OFS extraction failed:', error instanceof Error ? error.message : String(error));
99
+ // Fallback to basic extraction
100
+ return extractJsonFromFlexMd(content, spec, options);
101
+ }
102
+ }
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.jsonToMarkdown = exports.Schema = exports.MarkdownParser = exports.JSONTransformer = exports.enforceFlexMd = exports.repairToMarkdownLevel = exports.detectResponseKind = exports.buildIssuesEnvelopeAuto = exports.buildIssuesEnvelope = exports.parseIssuesEnvelope = exports.processResponseMarkdown = exports.extractFromMarkdown = exports.checkConnection = exports.hasFlexMdContract = exports.checkCompliance = exports.validateMarkdownAgainstOfs = exports.enrichInstructionsWithFlexMd = exports.enrichInstructions = exports.buildMarkdownGuidance = exports.stringifyOutputFormatSpec = exports.recall = exports.remember = exports.transformWithOfs = exports.ofsToSchema = exports.validateFormat = exports.parseFormatSpecs = exports.parseInputFormatSpec = exports.parseOutputFormatSpec = exports.buildOutline = exports.logger = void 0;
18
+ // Core SFMD Types
19
+ __exportStar(require("./types.cjs"), exports);
20
+ __exportStar(require("./strictness/types.cjs"), exports);
21
+ // Logging
22
+ var logger_js_1 = require("./logger.cjs");
23
+ Object.defineProperty(exports, "logger", { enumerable: true, get: function () { return logger_js_1.logger; } });
24
+ // Shared MD Parsing
25
+ __exportStar(require("./md/parse.cjs"), exports);
26
+ var outline_js_1 = require("./md/outline.cjs");
27
+ Object.defineProperty(exports, "buildOutline", { enumerable: true, get: function () { return outline_js_1.buildOutline; } });
28
+ // Output Format Spec (OFS)
29
+ var parser_js_1 = require("./ofs/parser.cjs");
30
+ Object.defineProperty(exports, "parseOutputFormatSpec", { enumerable: true, get: function () { return parser_js_1.parseOutputFormatSpec; } });
31
+ Object.defineProperty(exports, "parseInputFormatSpec", { enumerable: true, get: function () { return parser_js_1.parseInputFormatSpec; } });
32
+ Object.defineProperty(exports, "parseFormatSpecs", { enumerable: true, get: function () { return parser_js_1.parseFormatSpecs; } });
33
+ Object.defineProperty(exports, "validateFormat", { enumerable: true, get: function () { return parser_js_1.validateFormat; } });
34
+ var adapter_js_1 = require("./ofs/adapter.cjs");
35
+ Object.defineProperty(exports, "ofsToSchema", { enumerable: true, get: function () { return adapter_js_1.ofsToSchema; } });
36
+ Object.defineProperty(exports, "transformWithOfs", { enumerable: true, get: function () { return adapter_js_1.transformWithOfs; } });
37
+ var memory_js_1 = require("./ofs/memory.cjs");
38
+ Object.defineProperty(exports, "remember", { enumerable: true, get: function () { return memory_js_1.remember; } });
39
+ Object.defineProperty(exports, "recall", { enumerable: true, get: function () { return memory_js_1.recall; } });
40
+ var stringify_js_1 = require("./ofs/stringify.cjs");
41
+ Object.defineProperty(exports, "stringifyOutputFormatSpec", { enumerable: true, get: function () { return stringify_js_1.stringifyOutputFormatSpec; } });
42
+ var enricher_js_1 = require("./ofs/enricher.cjs");
43
+ Object.defineProperty(exports, "buildMarkdownGuidance", { enumerable: true, get: function () { return enricher_js_1.buildMarkdownGuidance; } });
44
+ Object.defineProperty(exports, "enrichInstructions", { enumerable: true, get: function () { return enricher_js_1.enrichInstructions; } });
45
+ Object.defineProperty(exports, "enrichInstructionsWithFlexMd", { enumerable: true, get: function () { return enricher_js_1.enrichInstructionsWithFlexMd; } });
46
+ // Validation & Extraction
47
+ var validate_js_1 = require("./validate/validate.cjs");
48
+ Object.defineProperty(exports, "validateMarkdownAgainstOfs", { enumerable: true, get: function () { return validate_js_1.validateMarkdownAgainstOfs; } });
49
+ var compliance_js_1 = require("./validate/compliance.cjs");
50
+ Object.defineProperty(exports, "checkCompliance", { enumerable: true, get: function () { return compliance_js_1.checkCompliance; } });
51
+ Object.defineProperty(exports, "hasFlexMdContract", { enumerable: true, get: function () { return compliance_js_1.hasFlexMdContract; } });
52
+ var connection_js_1 = require("./validate/connection.cjs");
53
+ Object.defineProperty(exports, "checkConnection", { enumerable: true, get: function () { return connection_js_1.checkConnection; } });
54
+ var extract_js_1 = require("./extract/extract.cjs");
55
+ Object.defineProperty(exports, "extractFromMarkdown", { enumerable: true, get: function () { return extract_js_1.extractFromMarkdown; } });
56
+ // Processor & Fallback
57
+ var processor_js_1 = require("./strictness/processor.cjs");
58
+ Object.defineProperty(exports, "processResponseMarkdown", { enumerable: true, get: function () { return processor_js_1.processResponseMarkdown; } });
59
+ var issuesEnvelope_js_1 = require("./ofs/issuesEnvelope.cjs");
60
+ Object.defineProperty(exports, "parseIssuesEnvelope", { enumerable: true, get: function () { return issuesEnvelope_js_1.parseIssuesEnvelope; } });
61
+ Object.defineProperty(exports, "buildIssuesEnvelope", { enumerable: true, get: function () { return issuesEnvelope_js_1.buildIssuesEnvelope; } });
62
+ Object.defineProperty(exports, "buildIssuesEnvelopeAuto", { enumerable: true, get: function () { return issuesEnvelope_js_1.buildIssuesEnvelopeAuto; } });
63
+ // Pipeline
64
+ var kind_js_1 = require("./pipeline/kind.cjs");
65
+ Object.defineProperty(exports, "detectResponseKind", { enumerable: true, get: function () { return kind_js_1.detectResponseKind; } });
66
+ var repair_js_1 = require("./pipeline/repair.cjs");
67
+ Object.defineProperty(exports, "repairToMarkdownLevel", { enumerable: true, get: function () { return repair_js_1.repairToMarkdownLevel; } });
68
+ var enforce_js_1 = require("./pipeline/enforce.cjs");
69
+ Object.defineProperty(exports, "enforceFlexMd", { enumerable: true, get: function () { return enforce_js_1.enforceFlexMd; } });
70
+ // JSON Detection
71
+ __exportStar(require("./detect/json/index.cjs"), exports);
72
+ // Token Estimation
73
+ __exportStar(require("./tokens/index.cjs"), exports);
74
+ // NX-MD-Parser Integration (Structured MD -> JSON)
75
+ var nx_md_parser_1 = require("nx-md-parser");
76
+ Object.defineProperty(exports, "JSONTransformer", { enumerable: true, get: function () { return nx_md_parser_1.JSONTransformer; } });
77
+ Object.defineProperty(exports, "MarkdownParser", { enumerable: true, get: function () { return nx_md_parser_1.MarkdownParser; } });
78
+ Object.defineProperty(exports, "Schema", { enumerable: true, get: function () { return nx_md_parser_1.Schema; } });
79
+ Object.defineProperty(exports, "jsonToMarkdown", { enumerable: true, get: function () { return nx_md_parser_1.jsonToMarkdown; } });
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.threshold = exports.logger = void 0;
4
+ const micro_logs_1 = require("micro-logs");
5
+ // Get DEBUG_LEVEL from environment, default to 'info'
6
+ const debugLevel = process.env.DEBUG_LEVEL || 'info';
7
+ // Map string levels to micro-logs levels
8
+ const levelMapping = {
9
+ 'verbose': 'verbose',
10
+ 'debug': 'debug',
11
+ 'info': 'info',
12
+ 'warn': 'warn',
13
+ 'error': 'error'
14
+ };
15
+ // Default to 'info' if invalid level provided
16
+ const threshold = levelMapping[debugLevel.toLowerCase()] || 'info';
17
+ exports.threshold = threshold;
18
+ exports.logger = new micro_logs_1.Logger({
19
+ packageName: 'flex-md',
20
+ envPrefix: 'FLEX_MD',
21
+ debugNamespace: 'flex-md:*'
22
+ });
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.matchSections = matchSections;
4
+ /**
5
+ * Matches sections from the outline against required section names.
6
+ * Supports merging multiple nodes of the same name and selecting highest-level matches.
7
+ */
8
+ function matchSections(outline, sectionNames, strategy = "merge") {
9
+ const normalizedTargets = new Map(sectionNames.map(n => [norm(n), n]));
10
+ const found = new Map();
11
+ walk(outline.nodes, (node) => {
12
+ const k = norm(node.title);
13
+ if (normalizedTargets.has(k)) {
14
+ if (!found.has(k))
15
+ found.set(k, []);
16
+ found.get(k).push(node);
17
+ }
18
+ });
19
+ const res = new Map();
20
+ for (const [nk, originalName] of normalizedTargets.entries()) {
21
+ const nodes = found.get(nk) ?? [];
22
+ if (!nodes.length)
23
+ continue;
24
+ // choose highest-level (smallest level number)
25
+ const minLevel = Math.min(...nodes.map(n => n.level));
26
+ const top = nodes.filter(n => n.level === minLevel);
27
+ let chosen;
28
+ if (strategy === "first") {
29
+ chosen = [top[0]];
30
+ }
31
+ else {
32
+ chosen = top; // merge same-level matches
33
+ }
34
+ const merged = chosen.map(n => n.content_md).join("\n").trimEnd() + "\n";
35
+ res.set(originalName, { name: originalName, nodes, chosen, mergedContent: merged });
36
+ }
37
+ return res;
38
+ }
39
+ function walk(nodes, fn) {
40
+ for (const n of nodes) {
41
+ fn(n);
42
+ walk(n.children, fn);
43
+ }
44
+ }
45
+ function norm(s) {
46
+ return s.trim().replace(/[:\-–—]\s*$/, "").trim().toLowerCase();
47
+ }
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeMarkdownInput = normalizeMarkdownInput;
4
+ /**
5
+ * Centralized normalization for Markdown input.
6
+ * Handles common LLM output artifacts like literal \n.
7
+ */
8
+ function normalizeMarkdownInput(md) {
9
+ if (!md)
10
+ return "";
11
+ // Handle literal \n common in LLM outputs delivered via JSON
12
+ return md.replace(/\\n/g, "\n");
13
+ }
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildOutline = buildOutline;
4
+ exports.slugify = slugify;
5
+ const parse_js_1 = require("./parse.cjs");
6
+ /**
7
+ * Builds a nested tree of headings (outline) from Markdown text.
8
+ */
9
+ function buildOutline(md) {
10
+ const sections = (0, parse_js_1.parseHeadingsAndSections)(md);
11
+ const roots = [];
12
+ const stack = [];
13
+ for (const s of sections) {
14
+ const h = s.heading;
15
+ const node = {
16
+ title: h.name,
17
+ level: h.level,
18
+ key: h.norm,
19
+ content_md: s.body,
20
+ children: []
21
+ };
22
+ // Pop from stack until we find a parent (level < node.level)
23
+ while (stack.length > 0 && stack[stack.length - 1].level >= node.level) {
24
+ stack.pop();
25
+ }
26
+ if (stack.length === 0) {
27
+ roots.push(node);
28
+ }
29
+ else {
30
+ stack[stack.length - 1].children.push(node);
31
+ }
32
+ stack.push(node);
33
+ }
34
+ return {
35
+ type: "md_outline",
36
+ nodes: roots
37
+ };
38
+ }
39
+ /**
40
+ * Slugifies a string into an internal key.
41
+ */
42
+ function slugify(text) {
43
+ return text
44
+ .toLowerCase()
45
+ .trim()
46
+ .replace(/[^\w\s-]/g, "")
47
+ .replace(/[\s_-]+/g, "-")
48
+ .replace(/^-+|-+$/g, "");
49
+ }
@@ -0,0 +1,199 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeName = normalizeName;
4
+ exports.extractFencedBlocks = extractFencedBlocks;
5
+ exports.parseHeadingsAndSections = parseHeadingsAndSections;
6
+ exports.extractBullets = extractBullets;
7
+ exports.parseMarkdownTable = parseMarkdownTable;
8
+ exports.isIssuesEnvelopeCheck = isIssuesEnvelopeCheck;
9
+ exports.markdownToJson = markdownToJson;
10
+ const nx_helpers_1 = require("nx-helpers");
11
+ const normalize_js_1 = require("./normalize.cjs");
12
+ function normalizeName(s) {
13
+ return s.trim().replace(/\s+/g, " ").toLowerCase();
14
+ }
15
+ function extractFencedBlocks(text) {
16
+ const rx = /```(\w+)?\s*\n([\s\S]*?)\n```/g;
17
+ const blocks = [];
18
+ let m;
19
+ while ((m = rx.exec(text)) !== null) {
20
+ const full = m[0];
21
+ const lang = String(m[1] ?? "").trim().toLowerCase();
22
+ const content = m[2] ?? "";
23
+ const start = m.index;
24
+ const end = start + full.length;
25
+ // compute content start/end (best-effort)
26
+ const headerLen = full.indexOf("\n") + 1; // after first newline
27
+ const contentEnd = end - 3; // "```" at end
28
+ const contentStart = start + headerLen;
29
+ blocks.push({
30
+ lang,
31
+ start,
32
+ end,
33
+ contentStart,
34
+ contentEnd,
35
+ content,
36
+ full,
37
+ });
38
+ }
39
+ return blocks;
40
+ }
41
+ function parseHeadingsAndSections(md, options = {}) {
42
+ // Standard headings #... and alternative ===key.
43
+ // Also optionally allow "- Section" if specified in bulletNames.
44
+ const rx = /^((?:#{1,6})[ \t]+(.+?)[ \t]*|===(.+?)[ \t]*|([-*+])[ \t]+(.+?)[ \t]*)$/gm;
45
+ const headings = [];
46
+ const bulletNamesNormal = new Set((options.bulletNames || []).map(normalizeName));
47
+ let m;
48
+ while ((m = rx.exec(md)) !== null) {
49
+ const full = m[1] ?? "";
50
+ let level;
51
+ let name;
52
+ if (full.startsWith("===")) {
53
+ level = 1; // Treat ===key as a top-level heading
54
+ name = (m[3] ?? "").trim();
55
+ }
56
+ else if (m[4]) {
57
+ // It's a bullet (- / * / +)
58
+ const bulletChar = m[4];
59
+ const bulletText = (m[5] ?? "").trim();
60
+ const norm = normalizeName(bulletText);
61
+ if (bulletNamesNormal.has(norm)) {
62
+ level = 1;
63
+ name = bulletText;
64
+ }
65
+ else {
66
+ // Not a recognized section header bullet, ignore it
67
+ continue;
68
+ }
69
+ }
70
+ else {
71
+ const hashesMatch = full.match(/^#+/);
72
+ const hashes = hashesMatch ? hashesMatch[0] : "";
73
+ level = hashes.length;
74
+ name = (m[2] ?? "").trim();
75
+ }
76
+ const raw = m[0] ?? "";
77
+ const start = m.index;
78
+ const end = start + raw.length;
79
+ headings.push({
80
+ level,
81
+ raw,
82
+ name,
83
+ norm: normalizeName(name),
84
+ start,
85
+ end,
86
+ });
87
+ }
88
+ // compute section bodies
89
+ const sections = [];
90
+ for (let i = 0; i < headings.length; i++) {
91
+ const h = headings[i];
92
+ const bodyStart = nextLineIndex(md, h.end);
93
+ let bodyEnd = md.length;
94
+ for (let j = i + 1; j < headings.length; j++) {
95
+ const nxt = headings[j];
96
+ bodyEnd = nxt.start;
97
+ break;
98
+ }
99
+ sections.push({
100
+ heading: h,
101
+ bodyStart,
102
+ bodyEnd,
103
+ body: md.slice(bodyStart, bodyEnd).trimEnd(),
104
+ });
105
+ }
106
+ return sections;
107
+ }
108
+ function nextLineIndex(text, idx) {
109
+ if (idx >= text.length)
110
+ return text.length;
111
+ if (text[idx] === "\n")
112
+ return idx + 1;
113
+ const n = text.indexOf("\n", idx);
114
+ return n === -1 ? text.length : n + 1;
115
+ }
116
+ function extractBullets(body) {
117
+ const lines = body.split(/\r?\n/);
118
+ const out = [];
119
+ for (const line of lines) {
120
+ const m = line.match(/^\s*[-*•]\s+(.*)\s*$/) || line.match(/^\s*\d+\.\s+(.*)\s*$/);
121
+ if (m)
122
+ out.push(m[1].trim());
123
+ }
124
+ return out;
125
+ }
126
+ function parseMarkdownTable(body, columns) {
127
+ const lines = body.split(/\r?\n/).map(l => l.trim()).filter(l => l.startsWith("|"));
128
+ if (lines.length < 2)
129
+ return [];
130
+ // Identification of header vs separator
131
+ const headerLine = lines[0];
132
+ const separatorLine = lines[1];
133
+ // Check if second line is a separator (e.g. |---|---|)
134
+ const isSeparator = separatorLine && /^[|\s-:]+$/.test(separatorLine);
135
+ const dataStartIndex = isSeparator ? 2 : 1;
136
+ const dataLines = lines.slice(dataStartIndex);
137
+ const results = [];
138
+ for (const line of dataLines) {
139
+ const cells = line.split("|").map(c => c.trim()).filter((_, i, arr) => i > 0 && i < arr.length - 1);
140
+ const row = {};
141
+ // Match cells to provided columns by index
142
+ for (let i = 0; i < columns.length; i++) {
143
+ row[columns[i]] = cells[i] || "";
144
+ }
145
+ results.push(row);
146
+ }
147
+ return results;
148
+ }
149
+ function isIssuesEnvelopeCheck(md) {
150
+ const parsed = parseHeadingsAndSections(md);
151
+ const want = ["status", "issues", "expected", "found", "how to fix"].map(normalizeName);
152
+ const got = new Set(parsed.map(s => s.heading.norm));
153
+ const ok = want.every(w => got.has(w));
154
+ const sections = {};
155
+ if (ok) {
156
+ for (const sec of parsed) {
157
+ if (want.includes(sec.heading.norm)) {
158
+ sections[sec.heading.norm] = {
159
+ heading: sec.heading.name,
160
+ body: sec.body.trim(),
161
+ bullets: extractBullets(sec.body),
162
+ };
163
+ }
164
+ }
165
+ }
166
+ return { isIssuesEnvelope: ok, sections };
167
+ }
168
+ function markdownToJson(md) {
169
+ // Robustly handle both actual newlines and literal \n (common in LLM JSON outputs)
170
+ const normalizedMd = (0, normalize_js_1.normalizeMarkdownInput)(md);
171
+ // Collect all bullet names that look like headers ("- Name")
172
+ // We look for patterns like "- Name\n" at the start of lines, ensuring it's not a sub-bullet.
173
+ const bulletNames = [];
174
+ const bulletLinesRx = /^[-*+]\s+([^—:\n\r]{2,50})$/gm;
175
+ let m;
176
+ while ((m = bulletLinesRx.exec(normalizedMd)) !== null) {
177
+ bulletNames.push(m[1].trim());
178
+ }
179
+ // Use Flex-MD's native parser (supports === headings and avoids colon-as-object bug)
180
+ const sections = parseHeadingsAndSections(normalizedMd, { bulletNames });
181
+ const result = {};
182
+ for (const sec of sections) {
183
+ const key = (0, nx_helpers_1.toCamelCase)(sec.heading.name);
184
+ const body = sec.body.trim();
185
+ // 1. Try to detect list
186
+ const bullets = extractBullets(body);
187
+ if (bullets.length > 0) {
188
+ result[key] = bullets;
189
+ continue;
190
+ }
191
+ // 2. Try to detect table (basic check)
192
+ const lines = body.split("\n").map(l => l.trim()).filter(l => l);
193
+ if (lines.length >= 2 && lines[0].startsWith("|") && /^[|\s-:]+$/.test(lines[1])) {
194
+ // It looks like a table - we could use nx-md-parser's table logic here safely
195
+ }
196
+ result[key] = body;
197
+ }
198
+ return result;
199
+ }