import type { Heading, RootContent, Root } from "mdast"; import { fromMarkdown } from "mdast-util-from-markdown"; import { toString } from "mdast-util-to-string"; import { parseMarkdownTable } from "../../../lib/parse-markdown-table"; export interface ParsedModuleCommand { module: string; command: string; } export interface ParsedResolverError { code: string; description: string; } export interface ParsedResolverDoc { resolverName: string; overview: string; moduleCommands: ParsedModuleCommand[]; errors: ParsedResolverError[]; } const MODULE_COMMAND_PATTERN = /([a-z][\w-]*)\.(\w+)/; export function parseResolverDoc(fileName: string, markdown: string): ParsedResolverDoc { const resolverName = fileName.charAt(0).toLowerCase() + fileName.slice(1); const tree = fromMarkdown(markdown); return { resolverName, overview: parseOverview(tree), moduleCommands: parseModuleCommands(tree), errors: parseErrors(markdown), }; } function isHeading(node: RootContent): node is Heading { return node.type === "heading"; } function getNodesUnderHeading(tree: Root, headingText: string): RootContent[] { const nodes: RootContent[] = []; let collecting = false; for (const node of tree.children) { if (isHeading(node)) { if (collecting) break; if (node.depth === 2 && toString(node) === headingText) { collecting = true; continue; } } if (collecting) { nodes.push(node); } } return nodes; } function normalizeInline(text: string): string { return text.replace(/\s+/g, " ").trim(); } function parseOverview(tree: Root): string { const nodes = getNodesUnderHeading(tree, "Overview"); const paragraph = nodes.find((node) => node.type === "paragraph"); return paragraph ? normalizeInline(toString(paragraph)) : ""; } function parseModuleCommands(tree: Root): ParsedModuleCommand[] { const nodes = getNodesUnderHeading(tree, "Modules Commands Used"); const commands: ParsedModuleCommand[] = []; for (const node of nodes) { if (node.type !== "list") continue; for (const item of node.children) { const text = toString(item); const match = MODULE_COMMAND_PATTERN.exec(text); if (match) { commands.push({ module: match[1], command: match[2] }); } } } return commands; } function parseErrors(markdown: string): ParsedResolverError[] { return parseMarkdownTable(markdown, "## Exception Handling") .filter((cells) => cells.length >= 2 && cells[0]) .map(([code, description]) => ({ code, description })); }