@hawkeyexl/manni 4.4.0 → 4.5.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/README.md +1 -1
- package/dist/{batch-DFRCLY77.js → batch-GOE3UXOD.js} +11 -11
- package/dist/{build-Q5C6SX5J.js → build-M7BMEHL2.js} +13 -11
- package/dist/{calibrate-XQILKXS3.js → calibrate-6RRAILUY.js} +12 -12
- package/dist/{capture-JQMOC3BW.js → capture-RJPQ6B4N.js} +12 -12
- package/dist/{check-NFZQLJKN.js → check-BQD64X3N.js} +11 -11
- package/dist/{check-HYNGXYJV.js → check-ESNS7ZBC.js} +4 -4
- package/dist/{check-U54XV6BP.js → check-RQIIIURI.js} +12 -12
- package/dist/{chunk-7QMCHA4N.js → chunk-3R5Y3XOL.js} +3 -3
- package/dist/{chunk-K3D6FPV6.js → chunk-3YHAYXBC.js} +2 -2
- package/dist/{chunk-JVTNMVYU.js → chunk-527HHQPS.js} +4 -4
- package/dist/{chunk-JVTNMVYU.js.map → chunk-527HHQPS.js.map} +1 -1
- package/dist/{chunk-6OYEI2VV.js → chunk-52PDIZKV.js} +3 -3
- package/dist/{chunk-UZC7LDAQ.js → chunk-6XTQDFGP.js} +2 -2
- package/dist/{chunk-UZC7LDAQ.js.map → chunk-6XTQDFGP.js.map} +1 -1
- package/dist/{chunk-NWZ2SLYL.js → chunk-7OQAU4EA.js} +5 -5
- package/dist/{chunk-5YXBLLAC.js → chunk-7ZUCEMCY.js} +8 -8
- package/dist/{chunk-M2JCK5F6.js → chunk-B7XUEQF3.js} +13 -2
- package/dist/chunk-B7XUEQF3.js.map +1 -0
- package/dist/{chunk-MYMBCTDE.js → chunk-BOIF2XGG.js} +2 -2
- package/dist/{chunk-H6FZ66XR.js → chunk-C3KI45RF.js} +8 -6
- package/dist/{chunk-H6FZ66XR.js.map → chunk-C3KI45RF.js.map} +1 -1
- package/dist/{chunk-3AFUD75K.js → chunk-C6HZ6C5T.js} +2 -2
- package/dist/{chunk-XYLUCIKQ.js → chunk-CP4ZM43V.js} +2 -2
- package/dist/chunk-DE7JSWXV.js +2462 -0
- package/dist/chunk-DE7JSWXV.js.map +1 -0
- package/dist/{chunk-YTCZRLTU.js → chunk-DX32P2DT.js} +2 -2
- package/dist/{chunk-644JVKJ4.js → chunk-EL2BZTDL.js} +137 -50
- package/dist/chunk-EL2BZTDL.js.map +1 -0
- package/dist/{chunk-JOHKIAVH.js → chunk-ELZ2IIOF.js} +332 -2522
- package/dist/chunk-ELZ2IIOF.js.map +1 -0
- package/dist/{chunk-OBFENF3U.js → chunk-F2OVHJNC.js} +10 -10
- package/dist/{chunk-5KHIFVD2.js → chunk-FLF6AECQ.js} +7 -7
- package/dist/{chunk-77HX34KD.js → chunk-GAZFKZHM.js} +4 -4
- package/dist/{chunk-KCGV52AM.js → chunk-HQFVJDEN.js} +7 -7
- package/dist/{chunk-RLR4TKUZ.js → chunk-HVFR66GQ.js} +2 -2
- package/dist/{chunk-2U3ORT6D.js → chunk-IA7BMIPE.js} +2 -2
- package/dist/{chunk-LAKAWRV5.js → chunk-JQU7FHYH.js} +6 -6
- package/dist/{chunk-YIL4XLLJ.js → chunk-K3U5F2QT.js} +183 -31
- package/dist/chunk-K3U5F2QT.js.map +1 -0
- package/dist/{chunk-X3BPBDGQ.js → chunk-MZC62HPZ.js} +2 -2
- package/dist/{chunk-V46OILVC.js → chunk-NAZRLJAK.js} +3 -3
- package/dist/{chunk-BUXDLRDT.js → chunk-NGK3N6F2.js} +3 -3
- package/dist/{chunk-WQE54PNH.js → chunk-NN4ASVTY.js} +3 -3
- package/dist/{chunk-PCHZY2I7.js → chunk-OIZ3XMKB.js} +13 -11
- package/dist/chunk-OIZ3XMKB.js.map +1 -0
- package/dist/{chunk-CYWHFSRT.js → chunk-QCBICNKC.js} +6 -6
- package/dist/chunk-QCBICNKC.js.map +1 -0
- package/dist/{chunk-YFQBFNQS.js → chunk-QLUMKWQQ.js} +3 -3
- package/dist/{chunk-YYBFZLAJ.js → chunk-QY3DOZMS.js} +4 -4
- package/dist/{chunk-IEQHSCZG.js → chunk-SJO2FTPG.js} +6 -6
- package/dist/{chunk-ERMSO34F.js → chunk-SNEHX4VE.js} +2 -2
- package/dist/{chunk-252LNOEG.js → chunk-TA42STP7.js} +4 -4
- package/dist/{chunk-CK7SKVHR.js → chunk-TBAMBLF3.js} +3 -12
- package/dist/chunk-TBAMBLF3.js.map +1 -0
- package/dist/{chunk-C6OH6CNF.js → chunk-TCC737IS.js} +3 -3
- package/dist/{chunk-H2DLH2JI.js → chunk-TVIX653Q.js} +3 -3
- package/dist/{chunk-G7NJSREW.js → chunk-UK2I3ACY.js} +3 -3
- package/dist/{chunk-XSLV76YK.js → chunk-XWFNO5PO.js} +3 -3
- package/dist/{chunk-PHF3D7ER.js → chunk-YA63PVWI.js} +5 -5
- package/dist/chunk-YGFIQ6Y5.js +17 -0
- package/dist/chunk-YGFIQ6Y5.js.map +1 -0
- package/dist/{chunk-MYC3O5EJ.js → chunk-ZX43SRZR.js} +3 -3
- package/dist/{cli-URZQXL4K.js → cli-6PGVHP7Y.js} +15 -15
- package/dist/{cli-2QPR2OZG.js → cli-AAG3N4NB.js} +16 -16
- package/dist/{cli-4IOPGZHR.js → cli-E3H6ZP4I.js} +2 -2
- package/dist/{cli-OFPZ5MAS.js → cli-HUIMNJT6.js} +20 -15
- package/dist/cli-HUIMNJT6.js.map +1 -0
- package/dist/{cli-LJLLIQB2.js → cli-MHTYPVOD.js} +16 -16
- package/dist/{cli-5FL73WHA.js → cli-PRZHQ3QB.js} +15 -13
- package/dist/{cli-5FL73WHA.js.map → cli-PRZHQ3QB.js.map} +1 -1
- package/dist/{cli-SRHFUZHA.js → cli-QKIJOXGW.js} +13 -13
- package/dist/{cli-C262QOWM.js → cli-TYGOHJOJ.js} +25 -25
- package/dist/{cli-SHSMSRQY.js → cli-YW6VWBHX.js} +9 -9
- package/dist/cli.js +11 -11
- package/dist/docmeta.js +8 -8
- package/dist/{github-QXL3VMK2.js → github-3WMSTNTK.js} +13 -13
- package/dist/{github-FE6KCNYJ.js → github-OXSJQ4PS.js} +11 -11
- package/dist/index.d.ts +30 -8
- package/dist/index.js +42 -38
- package/dist/index.js.map +1 -1
- package/dist/{json-SGZ6ZRFD.js → json-4DCKDGUV.js} +11 -11
- package/dist/lint-YDHVVZHT.js +30 -0
- package/dist/{list-7BKNYPSB.js → list-3ZO2NIYO.js} +11 -11
- package/dist/{list-6BAXTZUM.js → list-EJH6VAOW.js} +11 -11
- package/dist/{page-3U2GCFNE.js → page-QEDB7EVU.js} +10 -10
- package/dist/{pretty-N6DO4OOL.js → pretty-5DGEBZSV.js} +11 -11
- package/dist/{pretty-2H57QVTY.js → pretty-SQX33UM2.js} +12 -12
- package/dist/{reporters-N6GHXSS7.js → reporters-OHSI3RMV.js} +12 -11
- package/dist/{reporters-UCNEV7PH.js → reporters-YELDDYJD.js} +4 -4
- package/dist/{run-XZDAREJE.js → run-IP6NZHAG.js} +11 -11
- package/dist/{term-5ICGKPC3.js → term-2WMDZ4PY.js} +15 -15
- package/dist/{validate-GQRM77YN.js → validate-G6HH3YXL.js} +5 -5
- package/package.json +1 -1
- package/plugin/manni/.claude-plugin/plugin.json +1 -1
- package/plugin/manni/hooks/hooks.json +21 -4
- package/plugin/manni/hooks/manni.mjs +157 -0
- package/plugin/manni/skills/check/SKILL.md +3 -3
- package/plugin/manni/skills/evals/SKILL.md +2 -2
- package/plugin/manni/skills/fix/SKILL.md +3 -3
- package/plugin/manni/skills/setup/SKILL.md +3 -3
- package/dist/chunk-644JVKJ4.js.map +0 -1
- package/dist/chunk-CK7SKVHR.js.map +0 -1
- package/dist/chunk-CYWHFSRT.js.map +0 -1
- package/dist/chunk-JOHKIAVH.js.map +0 -1
- package/dist/chunk-M2JCK5F6.js.map +0 -1
- package/dist/chunk-PCHZY2I7.js.map +0 -1
- package/dist/chunk-YIL4XLLJ.js.map +0 -1
- package/dist/cli-OFPZ5MAS.js.map +0 -1
- package/dist/lint-DL4LJRAY.js +0 -28
- /package/dist/{batch-DFRCLY77.js.map → batch-GOE3UXOD.js.map} +0 -0
- /package/dist/{build-Q5C6SX5J.js.map → build-M7BMEHL2.js.map} +0 -0
- /package/dist/{calibrate-XQILKXS3.js.map → calibrate-6RRAILUY.js.map} +0 -0
- /package/dist/{capture-JQMOC3BW.js.map → capture-RJPQ6B4N.js.map} +0 -0
- /package/dist/{check-HYNGXYJV.js.map → check-BQD64X3N.js.map} +0 -0
- /package/dist/{check-NFZQLJKN.js.map → check-ESNS7ZBC.js.map} +0 -0
- /package/dist/{check-U54XV6BP.js.map → check-RQIIIURI.js.map} +0 -0
- /package/dist/{chunk-7QMCHA4N.js.map → chunk-3R5Y3XOL.js.map} +0 -0
- /package/dist/{chunk-K3D6FPV6.js.map → chunk-3YHAYXBC.js.map} +0 -0
- /package/dist/{chunk-6OYEI2VV.js.map → chunk-52PDIZKV.js.map} +0 -0
- /package/dist/{chunk-NWZ2SLYL.js.map → chunk-7OQAU4EA.js.map} +0 -0
- /package/dist/{chunk-5YXBLLAC.js.map → chunk-7ZUCEMCY.js.map} +0 -0
- /package/dist/{chunk-MYMBCTDE.js.map → chunk-BOIF2XGG.js.map} +0 -0
- /package/dist/{chunk-3AFUD75K.js.map → chunk-C6HZ6C5T.js.map} +0 -0
- /package/dist/{chunk-XYLUCIKQ.js.map → chunk-CP4ZM43V.js.map} +0 -0
- /package/dist/{chunk-YTCZRLTU.js.map → chunk-DX32P2DT.js.map} +0 -0
- /package/dist/{chunk-OBFENF3U.js.map → chunk-F2OVHJNC.js.map} +0 -0
- /package/dist/{chunk-5KHIFVD2.js.map → chunk-FLF6AECQ.js.map} +0 -0
- /package/dist/{chunk-77HX34KD.js.map → chunk-GAZFKZHM.js.map} +0 -0
- /package/dist/{chunk-KCGV52AM.js.map → chunk-HQFVJDEN.js.map} +0 -0
- /package/dist/{chunk-RLR4TKUZ.js.map → chunk-HVFR66GQ.js.map} +0 -0
- /package/dist/{chunk-2U3ORT6D.js.map → chunk-IA7BMIPE.js.map} +0 -0
- /package/dist/{chunk-LAKAWRV5.js.map → chunk-JQU7FHYH.js.map} +0 -0
- /package/dist/{chunk-X3BPBDGQ.js.map → chunk-MZC62HPZ.js.map} +0 -0
- /package/dist/{chunk-V46OILVC.js.map → chunk-NAZRLJAK.js.map} +0 -0
- /package/dist/{chunk-BUXDLRDT.js.map → chunk-NGK3N6F2.js.map} +0 -0
- /package/dist/{chunk-WQE54PNH.js.map → chunk-NN4ASVTY.js.map} +0 -0
- /package/dist/{chunk-YFQBFNQS.js.map → chunk-QLUMKWQQ.js.map} +0 -0
- /package/dist/{chunk-YYBFZLAJ.js.map → chunk-QY3DOZMS.js.map} +0 -0
- /package/dist/{chunk-IEQHSCZG.js.map → chunk-SJO2FTPG.js.map} +0 -0
- /package/dist/{chunk-ERMSO34F.js.map → chunk-SNEHX4VE.js.map} +0 -0
- /package/dist/{chunk-252LNOEG.js.map → chunk-TA42STP7.js.map} +0 -0
- /package/dist/{chunk-C6OH6CNF.js.map → chunk-TCC737IS.js.map} +0 -0
- /package/dist/{chunk-H2DLH2JI.js.map → chunk-TVIX653Q.js.map} +0 -0
- /package/dist/{chunk-G7NJSREW.js.map → chunk-UK2I3ACY.js.map} +0 -0
- /package/dist/{chunk-XSLV76YK.js.map → chunk-XWFNO5PO.js.map} +0 -0
- /package/dist/{chunk-PHF3D7ER.js.map → chunk-YA63PVWI.js.map} +0 -0
- /package/dist/{chunk-MYC3O5EJ.js.map → chunk-ZX43SRZR.js.map} +0 -0
- /package/dist/{cli-URZQXL4K.js.map → cli-6PGVHP7Y.js.map} +0 -0
- /package/dist/{cli-2QPR2OZG.js.map → cli-AAG3N4NB.js.map} +0 -0
- /package/dist/{cli-4IOPGZHR.js.map → cli-E3H6ZP4I.js.map} +0 -0
- /package/dist/{cli-LJLLIQB2.js.map → cli-MHTYPVOD.js.map} +0 -0
- /package/dist/{cli-SRHFUZHA.js.map → cli-QKIJOXGW.js.map} +0 -0
- /package/dist/{cli-C262QOWM.js.map → cli-TYGOHJOJ.js.map} +0 -0
- /package/dist/{cli-SHSMSRQY.js.map → cli-YW6VWBHX.js.map} +0 -0
- /package/dist/{github-FE6KCNYJ.js.map → github-3WMSTNTK.js.map} +0 -0
- /package/dist/{github-QXL3VMK2.js.map → github-OXSJQ4PS.js.map} +0 -0
- /package/dist/{json-SGZ6ZRFD.js.map → json-4DCKDGUV.js.map} +0 -0
- /package/dist/{lint-DL4LJRAY.js.map → lint-YDHVVZHT.js.map} +0 -0
- /package/dist/{list-6BAXTZUM.js.map → list-3ZO2NIYO.js.map} +0 -0
- /package/dist/{list-7BKNYPSB.js.map → list-EJH6VAOW.js.map} +0 -0
- /package/dist/{page-3U2GCFNE.js.map → page-QEDB7EVU.js.map} +0 -0
- /package/dist/{pretty-2H57QVTY.js.map → pretty-5DGEBZSV.js.map} +0 -0
- /package/dist/{pretty-N6DO4OOL.js.map → pretty-SQX33UM2.js.map} +0 -0
- /package/dist/{reporters-N6GHXSS7.js.map → reporters-OHSI3RMV.js.map} +0 -0
- /package/dist/{reporters-UCNEV7PH.js.map → reporters-YELDDYJD.js.map} +0 -0
- /package/dist/{run-XZDAREJE.js.map → run-IP6NZHAG.js.map} +0 -0
- /package/dist/{term-5ICGKPC3.js.map → term-2WMDZ4PY.js.map} +0 -0
- /package/dist/{validate-GQRM77YN.js.map → validate-G6HH3YXL.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lint/commands/lint.ts","../src/lint/parsers/markdown.ts","../src/lint/parsers/mdast.ts","../src/lint/parsers/sectionize.ts","../src/lint/parsers/metadata.ts","../src/lint/parsers/html.ts","../src/lint/parsers/rst.ts","../src/lint/parsers/xml.ts","../src/lint/parsers/asciidoc.ts","../src/lint/parsers/index.ts","../src/lint/core/template-registry.ts","../schemas/lint/template.json","../templates/lint/tgdp/manifest.json","../src/lint/core/resolve-template.ts","../src/lint/core/validator.ts","../src/lint/core/config.ts","../schemas/lint/config.json","../src/lint/tools/dita-ot.ts","../src/lint/tools/index.ts"],"sourcesContent":["/**\n * `lint` command core. Resolves targets, picks a parser per file, resolves a\n * template per file, and returns structured results. Free of CLI/IO plumbing so\n * it can be driven directly from tests and from the programmatic API.\n *\n * Template selection is per file, not per run: a page declares what it is\n * (`type: how-to`) and the template follows. `--template` still exists and\n * still overrides everything, but it is no longer required, which is what lets\n * one invocation lint a whole tree of mixed doctypes.\n */\nimport { readFile } from \"node:fs/promises\";\nimport { extname, relative, resolve } from \"node:path\";\nimport { errorMessage, ToolError } from \"../../shared/errors.js\";\nimport {\n LintError,\n type DocumentParser,\n type DocumentTree,\n type FileResult,\n type Finding,\n type Position,\n} from \"../types.js\";\nimport {\n parserByName,\n parserForExtension,\n supportedExtensions,\n} from \"../parsers/index.js\";\nimport type { Template, TemplateFile } from \"../core/template.js\";\nimport {\n classifyRef,\n refRelativeTo,\n listBuiltins,\n loadResolvedTemplate,\n loadTemplateFile,\n} from \"../core/template-registry.js\";\nimport {\n buildTypeIndex,\n knownTypes,\n resolveTemplateRef,\n FILE_TEMPLATE_KEY,\n type Resolution,\n type TemplateOverride,\n type TypeIndexEntry,\n} from \"../core/resolve-template.js\";\nimport { validateDocument } from \"../core/validator.js\";\nimport {\n resolveStructureTool,\n structureTools,\n type StructureToolDescriptor,\n} from \"../tools/index.js\";\nimport {\n ditaOt,\n runDitaOtValidate,\n type DitaOtMessage,\n} from \"../tools/dita-ot.js\";\nimport { ditaOtHome } from \"../../shared/tools.js\";\nimport {\n assertNonEmpty,\n gitignoreOptions,\n resolveTargetSet,\n STDIN_TOKEN,\n} from \"../../meta/internal.js\";\nimport { isErrorSeverity } from \"../../meta/index.js\";\nimport { resolveLintRun, type LintConfig } from \"../core/config.js\";\n\n/** File label used for a document read from stdin. */\nexport const STDIN_LABEL = \"<stdin>\";\n\nexport interface LintOptions {\n /**\n * Positional inputs: files, directories, or globs. `-` reads stdin. Empty\n * falls back to the `collections:` the config declares (proposal 0041).\n */\n inputs: string[];\n /** `--collection <name>`, repeatable: the collections this run covers. */\n collection?: string[];\n /**\n * `--tool`: which tool performs the structure job. Overrides the config's\n * own `lint.structure.tool`, and defaults to manni's engine.\n */\n tool?: string;\n /** `--template`: a built-in id, a path, or a name inside `templates`. */\n template?: string;\n /**\n * `--templates`: template files whose `types:` join the routing table. A bare\n * `--template <name>` is resolved as a name inside the *last* of them, which\n * is the pairing the manni docevals adapter invokes. Last, not first, to\n * agree with `buildTypeIndex`: a later file overrides an earlier one there,\n * so resolving a bare name against the first would make one name mean two\n * different templates depending on how it was written.\n */\n templates?: string | string[];\n /** `--as`: force an input format, by parser name. */\n as?: string;\n /** `--ext`: extensions kept during directory and glob expansion. */\n exts?: string[];\n /** `--exclude`: globs removed from directory/glob expansion. */\n exclude?: string[];\n cwd?: string;\n /** Content for the `-` input, injected by the CLI and by tests. */\n stdinContent?: string;\n /** `--explain`: record how each file's template was chosen. */\n explain?: boolean;\n /** Repo policy: first matching glob wins. Overrides the config's own. */\n overrides?: TemplateOverride[];\n /** Applied when a page declares no doctype. Overrides the config's own. */\n defaultTemplate?: string;\n /** Explicit doctype -> template ref map. Overrides the config's own. */\n types?: Record<string, string>;\n /** `--allow-empty`: zero matched files is a success, not an error. */\n allowEmpty?: boolean;\n /** `--no-gitignore`: only an explicit `false` travels, so config can decide. */\n respectGitignore?: boolean;\n /** `-c/--config`. */\n configPath?: string;\n /** `--no-config`: skip discovery and run on the built-in defaults. */\n noConfig?: boolean;\n /** Told which config governed the run, and where it came from. */\n onConfigLoaded?: (info: { path: string; dir: string }) => void;\n /** Told what the run had to say beside its findings. */\n onNotice?: (message: string) => void;\n /**\n * The DITA-OT seam, injected by tests, as `term lint` injects Vale's.\n *\n * There is no JVM and no DITA-OT on a CI runner of ours, so the only way to\n * exercise this branch end to end is to hand it the process boundary. The\n * shipped default is the real one.\n */\n runDitaOt?: typeof runDitaOtValidate;\n}\n\n/** Extensions that make a bare `--template` value a filename, not a name. */\nconst TEMPLATE_FILE_EXTENSIONS = [\".yaml\", \".yml\", \".json\"];\n\n/**\n * Run a family helper, rethrowing the error it raises as this tool's.\n *\n * The walker and its guards are meta's, and they throw `DocmetaError` - a\n * sibling of `LintError`, not a parent of it. `runLint` is exported from\n * `src/index.ts` and called in process by manni docevals, so a caller doing\n * the documented thing, `catch (err) { if (err instanceof LintError) … }`,\n * missed the two most ordinary operational failures there are: a mistyped path\n * and a pattern matching nothing. The message is the walker's own, which is\n * the part the user reads; only the class changes.\n */\nasync function asLintError<T>(run: () => T | Promise<T>): Promise<T> {\n try {\n return await run();\n } catch (err) {\n if (err instanceof LintError) throw err;\n // A `ToolError` from any sibling is operational and already worded for a\n // user. Anything else is a bug and keeps its class and its stack.\n if (err instanceof ToolError) throw new LintError(err.message);\n throw err;\n }\n}\n\n/** `--templates` accepts one path or several; normalize to a list. */\nfunction templateFiles(value: string | string[] | undefined): string[] {\n if (value == null) return [];\n return Array.isArray(value) ? value : [value];\n}\n\n/**\n * The options a tool can own, in the order the guard reports them, each paired\n * with how to tell that the caller passed it.\n *\n * `--templates` reads `opts` alone. A `templates:` key in the config describes\n * the repo rather than the invocation, so a repo that has written one must not\n * be refused the moment it points a different tool at the same tree.\n */\nconst TOOL_OPTIONS: {\n spelling: string;\n given: (opts: LintOptions) => boolean;\n}[] = [\n { spelling: \"--template\", given: (o) => o.template !== undefined },\n {\n spelling: \"--templates\",\n given: (o) => templateFiles(o.templates).length > 0,\n },\n { spelling: \"--explain\", given: (o) => o.explain === true },\n { spelling: \"--as\", given: (o) => o.as !== undefined },\n];\n\n/**\n * The options some other registered tool owns and this one does not, each with\n * the tool that does own it.\n *\n * Derived rather than written out per tool, because a hand-written chain is a\n * list the next tool has to remember to join - and the failure mode of\n * forgetting is a silently ignored option, which is a run that reports success\n * having done something other than what was asked.\n */\nfunction foreignOptions(\n tool: StructureToolDescriptor,\n): Map<string, StructureToolDescriptor> {\n const foreign = new Map<string, StructureToolDescriptor>();\n for (const other of structureTools()) {\n // By identity, not by name: the registry holds one descriptor per name, so\n // the tool this run resolved *is* its entry, and comparing the names is a\n // tautology to the compiler while `LintTool` carries one of them.\n if (other === tool) continue;\n for (const spelling of other.ownedOptions) {\n if (tool.ownedOptions.includes(spelling)) continue;\n if (!foreign.has(spelling)) foreign.set(spelling, other);\n }\n }\n return foreign;\n}\n\n/**\n * Refuse an option that belongs to a tool this run is not performing the job\n * with. One message, naming the first offending option.\n *\n * Ignoring it instead would be the quietest kind of wrong answer: the flag\n * reads as applied, the run exits 0, and nothing says the template, the format\n * override or the explanation was dropped on the floor.\n */\nfunction assertOptionsOwned(\n opts: LintOptions,\n tool: StructureToolDescriptor,\n usingStdin: boolean,\n): void {\n const foreign = foreignOptions(tool);\n if (foreign.size === 0) return;\n\n for (const { spelling, given } of TOOL_OPTIONS) {\n const owner = foreign.get(spelling);\n if (owner === undefined || !given(opts)) continue;\n throw new LintError(\n `${spelling} is an option of the ${owner.name} tool; ` +\n `the structure job's tool is ${tool.name}.`,\n );\n }\n\n // Stdin last, and in its own words: \"option\" is the wrong noun for a pipe,\n // and the advice a reader needs is what to pass instead.\n if (usingStdin && foreign.has(STDIN_TOKEN)) {\n throw new LintError(`${tool.name} cannot read stdin. Name files or a map.`);\n }\n}\n\nexport interface LintSummary {\n /** Files actually linted. Always `passed + failed`; skips are counted apart. */\n checked: number;\n passed: number;\n failed: number;\n skipped: number;\n}\n\n/**\n * A `FileResult` plus the human-readable reason a file was skipped.\n *\n * `types.ts` pins the fields manni docevals reads off the JSON reporter, so\n * this diagnostic lives here instead: it exists for pretty output, and the\n * JSON reporter never emits it.\n */\nexport interface LintFileResult extends FileResult {\n /** Why the file was skipped, in words. Set only alongside `skipped`. */\n reason?: string;\n /** How the template was chosen. Present when `--explain` asked for it. */\n resolution?: Resolution;\n /**\n * What the alignment block is rendered from. Present when `--explain` asked\n * for it, and only for a file that routed to a template.\n *\n * Nested rather than flat, because `FileResult.template` is already taken by\n * the template's *ref* - the string a reader sees on the routing line. A\n * loaded `Template` beside it under the same name would be two things called\n * one thing, and the reporter would read whichever it got.\n */\n alignment?: { tree: DocumentTree; template: Template };\n}\n\nexport interface LintRun {\n results: LintFileResult[];\n summary: LintSummary;\n}\n\n/** Zero-width span at the top of a file, for findings with nowhere better. */\nfunction origin(): Position {\n return {\n start: { line: 1, column: 1, offset: 0 },\n end: { line: 1, column: 1, offset: 0 },\n };\n}\n\nfunction skip(\n file: string,\n reason: string,\n cause: FileResult[\"skipped\"] = \"unsupported-format\",\n): LintFileResult {\n return {\n file,\n // `success` means \"linted and produced no findings\". A file that was never\n // linted is neither passing nor failing, and calling it a pass would hide\n // the gap from anyone reading CI output.\n success: false,\n findings: [],\n template: null,\n skipped: cause,\n reason,\n };\n}\n\nfunction parseFinding(message: string): Finding {\n return {\n type: \"parse_error\",\n heading: null,\n message,\n position: origin(),\n severity: \"error\",\n };\n}\n\n/**\n * A template ref, loaded once per run however many pages route to it.\n *\n * The registry deliberately leaves `extends` unresolved, so the merge happens\n * here. Skipping it would make inheritance silently inert: a template that\n * inherits every one of its sections would check nothing and report a clean\n * pass. `resolveExtends` is a no-op on a template without `extends`.\n */\nfunction templateLoader(): (ref: string) => Promise<Template> {\n const cache = new Map<string, Promise<Template>>();\n return (ref) => {\n let pending = cache.get(ref);\n if (!pending) {\n pending = loadResolvedTemplate(ref);\n cache.set(ref, pending);\n }\n return pending;\n };\n}\n\n/**\n * Normalize `--template` into a ref the registry understands.\n *\n * `--templates t.yaml --template how-to` is the pairing the manni docevals\n * adapter invokes, and it means \"the template named how-to inside t.yaml\".\n * A ref that already names a file, a URL, or a built-in is passed through.\n */\nfunction cliTemplateRef(\n template: string | undefined,\n templatePaths: string[],\n): string | undefined {\n if (!template) return undefined;\n // A ref that names itself is passed through. Sniffing for `#`, `/` and `\\`\n // missed built-in ids, which contain none of them, so `-t tgdp:how-to:1.6`\n // silently became a lookup for a template of that name inside the first\n // `--templates` file the moment one was given.\n if (template.includes(\"#\")) return template;\n if (classifyRef(template).kind !== \"file\") return template;\n if (template.includes(\"/\") || template.includes(\"\\\\\")) return template;\n // A bare filename names a file even without a separator: `--template\n // custom.yaml` means that file, not a template called \"custom.yaml\" inside\n // some other one.\n if (TEMPLATE_FILE_EXTENSIONS.some((e) => template.toLowerCase().endsWith(e))) {\n return template;\n }\n if (templatePaths.length === 0) return template;\n\n // A bare name is a name inside a `--templates` file. Search them last-first,\n // matching `buildTypeIndex`, so the file that wins routing also wins here.\n return `${templatePaths[templatePaths.length - 1] ?? \"\"}#${template}`;\n}\n\n/**\n * Which file a template came from and what it is called there.\n *\n * The validator and the matcher both name the template in messages - the\n * state-cap failure, and the warning about a rule a format cannot answer - and\n * neither can work either out from a `Template` object, which carries no\n * record of where it was loaded from. The ref does: `./templates.yaml#how-to`\n * is a file and a name, and a built-in id is both at once.\n */\nfunction templateIdentity(ref: string): { source: string; template: string } {\n const hash = ref.lastIndexOf(\"#\");\n if (hash === -1) return { source: ref, template: ref };\n return { source: ref.slice(0, hash), template: ref.slice(hash + 1) };\n}\n\n/** The finding a page gets when it declares a doctype nothing serves. */\nfunction unknownTypeFinding(\n resolution: Resolution,\n typeIndex: Map<string, TypeIndexEntry>,\n position: Position,\n): Finding {\n const suggestions = resolution.suggestions ?? [];\n const known = resolution.knownTypes ?? knownTypes(typeIndex);\n const hint = suggestions.length\n ? ` Did you mean ${suggestions.map((s) => `\"${s}\"`).join(\", \")}?`\n : ` Known doctypes: ${known.join(\", \") || \"(none)\"}.`;\n // `unknownType` is set whenever the cause is `unknown-type`, but the type\n // says `string | undefined` and only the resolver enforces the pairing. The\n // fallback keeps a future break from printing `type \"undefined\"`, which\n // would send the reader looking for a doctype they never wrote.\n const declared = resolution.unknownType ?? \"(none recorded)\";\n return {\n type: \"unknown_type\",\n heading: null,\n message:\n `No template serves type \"${declared}\".${hint} ` +\n `Declare it on a template with \"types:\", then pass that file with --templates.`,\n position,\n severity: \"error\",\n };\n}\n\ninterface LintContext {\n getTemplate: (ref: string) => Promise<Template>;\n /** Absolute, forward-slashed form of a display path, for override globs. */\n absoluteOf?: (file: string) => string;\n typeIndex: Map<string, TypeIndexEntry>;\n cliTemplate?: string;\n overrides?: TemplateOverride[];\n defaultTemplate?: string;\n explain: boolean;\n}\n\nasync function lintOne(\n label: string,\n content: string,\n parser: DocumentParser,\n ctx: LintContext,\n): Promise<LintFileResult> {\n let tree: DocumentTree;\n try {\n tree = parser.parse(content, label);\n } catch (err) {\n // A file that will not parse is that file's problem, not the run's: it is\n // reported and the run continues, so one broken page cannot hide the\n // findings in the other 199.\n return {\n file: label,\n success: false,\n findings: [parseFinding(errorMessage(err))],\n template: null,\n };\n }\n\n // Routing needs the frontmatter, so it happens after the parse rather than\n // before the read - which is also what makes `--explain` able to say what the\n // page actually declared.\n const resolution = resolveTemplateRef({\n filePath: label,\n absolutePath: ctx.absoluteOf?.(label),\n frontmatter: tree.frontmatter,\n cliTemplate: ctx.cliTemplate,\n overrides: ctx.overrides,\n typeIndex: ctx.typeIndex,\n defaultTemplate: ctx.defaultTemplate,\n });\n const withResolution = <T extends LintFileResult>(result: T): T =>\n ctx.explain ? { ...result, resolution } : result;\n\n // Anchor anything said about the frontmatter at the frontmatter.\n const metaPosition = tree.frontmatterPosition ?? origin();\n\n if (resolution.ref === null) {\n if (resolution.cause === \"unknown-type\") {\n // A declared type that resolves to nothing is a typo or a gap. Skipping\n // would mean a page silently stops being checked, which is the one\n // outcome worse than a false positive.\n return withResolution({\n file: label,\n success: false,\n findings: [unknownTypeFinding(resolution, ctx.typeIndex, metaPosition)],\n template: null,\n });\n }\n // An untyped page is manni meta's complaint, not this tool's - its OKF\n // schema already requires `type`. Skipping is what lets manni lint be\n // pointed at a whole tree on day one.\n return withResolution(\n skip(\n label,\n \"no type in frontmatter and no template resolved\",\n \"no-template\",\n ),\n );\n }\n\n /** A broken template, reported against this page rather than thrown. */\n const brokenTemplate = (err: unknown): LintFileResult =>\n withResolution({\n file: label,\n success: false,\n findings: [\n {\n type: \"template_error\",\n heading: null,\n message: errorMessage(err),\n position: metaPosition,\n severity: \"error\",\n },\n ],\n template: resolution.ref,\n });\n\n // A page may not send the linter to a URL of its own choosing.\n //\n // `type` comes out of the document too, but it only *selects* from the\n // routing table the operator assembled - a page can ask for a template on\n // offer, not introduce one. `$template` names a reference directly, which\n // makes it the one stage where a document says where a template comes from,\n // and documents are exactly what this tool is pointed at untrusted: a docset\n // from a fork, a contributor's branch, a vendored copy.\n // Left open, one line of frontmatter makes the linting host issue an\n // arbitrary request, which on CI means from inside the build network. The\n // `$ref` hole this mirrors was closed in the template loader; this is the\n // same hole one level up, where the ref itself is attacker-chosen.\n //\n // Refused rather than ignored, because silently falling through to `type`\n // would lint the page against something other than what it asked for and say\n // nothing. An operator who does want a remote template still has every other\n // stage: name it in `templates:`, map it under `types:`, or pass --template.\n if (\n resolution.stage === \"frontmatter-template\" &&\n classifyRef(resolution.ref).kind === \"url\"\n ) {\n return brokenTemplate(\n new LintError(\n `${FILE_TEMPLATE_KEY} may not name a URL (\"${resolution.ref}\"): a document ` +\n `must not choose what the linter fetches. Declare it in manni.config.yaml ` +\n `under \"templates:\" or \"types:\", or pass it with --template.`,\n ),\n );\n }\n\n // A relative `$template` means \"beside this page\", not \"beside wherever the\n // tool happened to be invoked from\". `extends` already follows that rule, and\n // for the same reason: resolved against the process cwd, `$template:\n // ./house.yaml` in `docs/guide.md` found the file only when the run started\n // in `docs/` - so the page routed correctly from one directory and reported\n // \"Template file not found\" from every other, including from CI.\n const ref =\n resolution.stage === \"frontmatter-template\"\n ? refRelativeTo(ctx.absoluteOf?.(label) ?? label, resolution.ref)\n : resolution.ref;\n\n let template: Template;\n try {\n template = await ctx.getTemplate(ref);\n } catch (err) {\n // One unloadable template must not abort a run over a whole tree; it is\n // reported against the pages that route to it.\n return brokenTemplate(err);\n }\n\n // `--explain` stops here, having promised to \"lint nothing\".\n //\n // The line is drawn after loading rather than before it, because loading is\n // part of the answer the flag exists to give: \"which template, and why\" is\n // not answered by naming a ref that does not resolve, and a broken\n // `--templates` path is exactly the surprise someone runs `--explain` to\n // find. Loading is also cheap in the way validation is not - templates are\n // cached, so a tree of one doctype loads once, while `validateDocument` runs\n // per file and its findings are then discarded unrendered.\n if (ctx.explain) {\n return withResolution({\n file: label,\n success: true,\n findings: [],\n template: resolution.ref,\n // The tree and the loaded template, for the alignment block. Both are\n // already in hand here, and neither survives this function otherwise.\n alignment: { tree, template },\n });\n }\n\n let findings: Finding[];\n try {\n findings = validateDocument(tree, template, {\n ...templateIdentity(ref),\n kinds: parser.kinds,\n });\n } catch (err) {\n // Validation can raise for the same reason loading can: a template the\n // author got wrong - an uncompilable `heading.pattern` is the live case.\n // Without this the raise escapes `runLint` and kills the run, so one bad\n // pattern hides the findings in every other page, which is the outcome the\n // load path above exists to prevent.\n if (err instanceof LintError) return brokenTemplate(err);\n throw err;\n }\n\n return withResolution({\n file: label,\n // \"Linted and found nothing wrong\", which is not the same as \"produced no\n // findings\". A `warning` - today, a rule this file's format cannot answer -\n // says something about the run rather than about the document, and the\n // exit code follows `success`, so counting it as a failure would turn a\n // docset of mixed formats permanently red. The family's rule, and the one\n // meta and cite already apply: `ok` is \"no error-severity finding\".\n success: !findings.some(isErrorSeverity),\n findings,\n template: resolution.ref,\n });\n}\n\n/** Everything manni's branch needs, settled once by the shared prefix. */\ninterface ManniRun {\n opts: LintOptions;\n config: LintConfig;\n /** The directory the resolved files are relative to. */\n cwd: string;\n /** The files the shared target resolution produced. */\n files: string[];\n /** The parser `--as` forced, when it did. */\n forcedParser?: DocumentParser;\n /** Whether `-` rode among the inputs. */\n usingStdin: boolean;\n}\n\n/**\n * Lint with manni's own engine.\n *\n * Everything below this line is manni's and nobody else's: the template files,\n * the doctype index, the parser registry, and the guard that fires when a run\n * checks nothing. The loading in particular has to sit here rather than in the\n * shared prefix, because it is file I/O a tool that reads no templates must\n * not be made to pay - and a missing `templates:` entry is then the loader's\n * error under manni and nothing at all under anybody else.\n */\nasync function lintWithManni(run: ManniRun): Promise<LintFileResult[]> {\n const { opts, config, cwd, files, forcedParser, usingStdin } = run;\n\n // The doctype -> template map. Built-ins go in first and user templates\n // overwrite them, so overriding `how-to` for a repo is one file with\n // `types: [how-to]` in it - no config entry, no flag.\n const templatePaths = templateFiles(opts.templates ?? config.templates);\n const getTemplate = templateLoader();\n\n const userFiles: { ref: string; file: TemplateFile }[] = [];\n for (const ref of templatePaths) {\n const file = await loadTemplateFile(ref);\n // `extends` is resolved before `types` is read. A template that inherits\n // its doctypes declares none of its own, so reading the raw file routes\n // nothing to it - the override loads, merges, and is silently inert while\n // the page goes to the built-in it meant to replace. The loader is cached,\n // so this costs nothing the lint would not already pay.\n const templates: Record<string, Template> = {};\n for (const name of Object.keys(file.templates ?? {})) {\n templates[name] = await getTemplate(`${ref}#${name}`);\n }\n userFiles.push({ ref, file: { ...file, templates } });\n }\n\n const typeIndex = buildTypeIndex({\n builtins: listBuiltins(),\n userFiles,\n explicitTypes: opts.types ?? config.types,\n });\n\n const ctx: LintContext = {\n getTemplate,\n absoluteOf: (file) => resolve(cwd, file).replace(/\\\\/g, \"/\"),\n typeIndex,\n cliTemplate: cliTemplateRef(opts.template, templatePaths),\n overrides: opts.overrides ?? config.overrides,\n // `template:` in config is the default for a page that declares no type -\n // the bottom of the chain, not the top. `--template` is the top.\n defaultTemplate: opts.defaultTemplate ?? config.template,\n explain: opts.explain === true,\n };\n\n // `--template` applies to every file, so a ref that will not load is bad\n // usage, not a property of any page. Resolved before a single page is linted\n // so it exits 2 with one message, rather than becoming an identical\n // `template_error` finding on all 200 pages and exiting 1 - which reads to\n // CI as \"the docs are wrong\".\n if (ctx.cliTemplate != null) await getTemplate(ctx.cliTemplate);\n\n const results: LintFileResult[] = [];\n\n // `forcedParser` is set whenever `usingStdin` is - the shared prefix refused\n // the run otherwise - but only that guard knows it, so the pair is tested\n // rather than asserted.\n if (usingStdin && forcedParser) {\n results.push(\n await lintOne(STDIN_LABEL, opts.stdinContent ?? \"\", forcedParser, ctx),\n );\n }\n\n for (const file of files) {\n const ext = extname(file);\n const parser = forcedParser ?? parserForExtension(ext);\n // The parser is chosen before the read, not after, because a file nothing\n // can parse must not depend on being readable to be reported. Reading\n // first pulls every skipped file into memory for nothing, and an\n // unreadable one - a denied permission, a file a doc build moved mid-run -\n // throws out of this loop, so a `.xyz` nobody asked us to parse takes the\n // whole run down with it: exit 2 and no verdict for any of the pages after\n // it, instead of one skip line and a report.\n if (!parser) {\n results.push(\n skip(\n file,\n `no parser is registered for \"${ext || file}\". Supported extensions: ${supportedExtensions().join(\", \")}. Use --as to override.`,\n ),\n );\n continue;\n }\n let content: string;\n try {\n content = await readFile(resolve(cwd, file), \"utf8\");\n } catch (err) {\n // The read is the other thing that can fail per file, and it failed out\n // of the loop: a denied permission, a symlink loop, or a page a doc\n // build moved between `resolveTargetSet` and here threw straight through\n // `runLint` to `fail()`. Exit 2, no report, and every result already\n // gathered discarded - which is exactly what moving the parser lookup\n // before the read was meant to prevent, one step further along.\n //\n // The OS message travels verbatim: \"permission denied\" and \"no such\n // file\" send the reader to different places, and this code cannot tell\n // which it was.\n results.push(\n skip(file, `could not be read: ${errorMessage(err)}`, \"unreadable\"),\n );\n continue;\n }\n results.push(await lintOne(file, content, parser, ctx));\n }\n\n return results;\n}\n\n/** Everything the DITA-OT branch needs, and nothing else. */\ninterface DitaOtRun {\n /** The directory the resolved files are relative to. */\n cwd: string;\n /** The files the shared target resolution produced, as it spelled them. */\n files: string[];\n /** `tools.dita-ot.home`, resolved; undefined means the `dita` on PATH. */\n home?: string;\n onNotice?: (message: string) => void;\n /** The seam. The shipped default starts the real launcher. */\n validate: typeof runDitaOtValidate;\n}\n\n/** One DITA-OT message as a finding. */\nfunction ditaOtFinding(message: DitaOtMessage): Finding {\n // The code is the finding's `type`, so `ruleId` yields\n // `manni:lint/structure/DOTX010E` and the JSON reporter publishes the code\n // DITA-OT's own message reference is indexed by.\n const point =\n message.line === undefined\n ? null\n : {\n line: message.line,\n // The log calls the column `row`; see `readMessage` in the seam.\n column: message.column ?? 1,\n // DITA-OT reports no byte offset, and nothing downstream needs one.\n offset: 0,\n };\n return {\n type: message.code,\n heading: null,\n message: message.message,\n position: point === null ? origin() : { start: point, end: point },\n severity: message.severity,\n };\n}\n\n/**\n * Lint with DITA Open Toolkit.\n *\n * One invocation per target, and the log is the verdict. A map's log speaks\n * about the topics it reached, so the findings are grouped by the file each\n * message named rather than by the file the run was pointed at - which is how\n * one map target produces a result per topic.\n */\nasync function lintWithDitaOt(run: DitaOtRun): Promise<LintFileResult[]> {\n const { cwd, files, onNotice } = run;\n\n /**\n * Only the formats this tool says it reads are handed to it.\n *\n * `manni lint tools` prints that list, and the rule the registry documents\n * is that a listed format is one that is read. Passing anything else on and\n * reporting whatever came back meant a `notes.md` named on the command line\n * came out as a clean pass, because DITA-OT shrugged and logged nothing to\n * disagree with. The manni branch skips a format no parser claims; this is\n * the same answer for the same reason.\n */\n const readable = ditaOt.formats().flatMap((format) => format.extensions);\n const reads = new Set(readable.map((ext) => ext.toLowerCase()));\n const targets: string[] = [];\n const unsupported: LintFileResult[] = [];\n for (const file of files) {\n if (reads.has(extname(file).toLowerCase())) targets.push(file);\n else {\n unsupported.push(\n skip(\n file,\n `dita-ot does not read \"${extname(file) || file}\". It reads ${readable.join(\", \")}.`,\n ),\n );\n }\n }\n\n // The label the run resolved is what the report says, whatever spelling the\n // absolute path comes back with.\n /**\n * One entry per absolute path, first spelling wins.\n *\n * **Defensive, not a fix for anything reachable today.** `resolveTargetSet`\n * normalizes every input to a cwd-relative posix path and holds them in a\n * `Set`, so two spellings of one file cannot arrive here. Review raised the\n * collision as a hazard and it is a real one in isolation: built naively the\n * later label replaces the earlier, `byFile` keeps both, and findings reach\n * only the survivor while the other reports as a clean pass.\n *\n * Kept because this function starts a JVM per target, so being correct on\n * its own terms rather than on its caller's is worth eight lines. Do not\n * write a test that claims to prove the collision: it cannot be reached\n * from `runLint`, and a test that passes either way proves nothing.\n */\n const labels = new Map<string, string>();\n for (const file of targets) {\n const absolute = resolve(cwd, file);\n if (!labels.has(absolute)) labels.set(absolute, file);\n }\n const unique = [...labels.values()];\n const labelOf = (absolute: string): string => {\n const known = labels.get(absolute);\n if (known !== undefined) return known;\n const near = relative(cwd, absolute).replace(/\\\\/g, \"/\");\n return near === \"\" ? absolute : near;\n };\n\n for (const file of unique) {\n // Checked, not skipped: a topic on its own is validated, it just resolves\n // fewer references than the same topic reached through its map. Calling it\n // a skip would say nothing was checked, which is false.\n if (extname(file).toLowerCase() !== \".ditamap\") {\n onNotice?.(\n `checked ${file} without a map; references outside it are not resolved.`,\n );\n }\n }\n\n // Nothing this tool can read is not a run: starting a JVM per target for an\n // empty list would be work with no answer at the end of it.\n if (unique.length === 0) return unsupported;\n\n const results = await run.validate({\n targets: [...labels.keys()],\n cwd,\n ...(run.home === undefined ? {} : { home: run.home }),\n });\n\n // Seeded with the targets, so a target DITA-OT had nothing to say about is a\n // result that passed rather than a file missing from the report.\n const byFile = new Map<string, Finding[]>(unique.map((file) => [file, []]));\n const findingsFor = (file: string): Finding[] => {\n let list = byFile.get(file);\n if (list === undefined) {\n list = [];\n byFile.set(file, list);\n }\n return list;\n };\n\n // A topic DITA-OT names that nobody targeted becomes a result of its own, so\n // `checked` can exceed the number of paths the user typed. That is the\n // answer, not an inflation of it: pointing at a map is how you ask about the\n // topics it gathers, and a finding against `topic.dita` has to be reported\n // against `topic.dita` for anyone to fix it. One map in, two files checked.\n for (const { target, messages } of results) {\n const invoked = labelOf(target);\n for (const message of messages) {\n // A message with no location belongs to the target the run was invoked\n // on, at a zero-width origin: DITA-OT's semantic messages routinely\n // carry no file, and discarding them would drop real errors.\n const file =\n message.file === undefined\n ? invoked\n : labelOf(resolve(cwd, message.file));\n findingsFor(file).push(ditaOtFinding(message));\n }\n }\n\n return [\n ...unsupported,\n ...[...byFile].map(([file, findings]) => ({\n file,\n // The family's rule, as manni's branch applies it: `ok` is \"no\n // error-severity finding\", so a warning-only file stays green.\n success: !findings.some(isErrorSeverity),\n findings,\n template: null,\n })),\n ];\n}\n\n/**\n * A run that found files and checked none of them is the worst thing this tool\n * can do quietly: it exits 0 and reads as a clean bill of health for a docset\n * nothing looked at. A repo that adopts manni lint in CI before backfilling\n * `type:` keys would get a permanently green job.\n *\n * This replaces a guard that tested `typeIndex.size === 0` before any file was\n * read. That could never fire - the index is always seeded with the built-ins\n * - so it protected nothing. Counting the outcome does.\n *\n * `--explain` is exempt: showing why nothing routed is exactly its job.\n */\nfunction assertSomethingWasChecked(\n results: LintFileResult[],\n explain: boolean,\n tool: StructureToolDescriptor,\n): void {\n const skipped = results.filter((r) => r.skipped != null).length;\n const checked = results.length - skipped;\n if (explain || checked > 0 || skipped === 0) return;\n\n // The advice has to follow the cause. The guard fires on any skip, but it\n // used to describe routing only - so a run over files no parser claims was\n // told to add a `type:` key, which changes nothing about an extension the\n // tool cannot read. Advice the reader cannot act on is only half a guard.\n const unrouted = results.filter((r) => r.skipped === \"no-template\").length;\n const unsupported = results.filter(\n (r) => r.skipped === \"unsupported-format\",\n ).length;\n const unreadable = results.filter((r) => r.skipped === \"unreadable\").length;\n const advice = [\n unrouted > 0\n ? `${unrouted} had no template: give a page a \"type:\" that a template ` +\n `serves, pass -t/--template <ref>, or set \"lint.template\" as a default.`\n : null,\n unsupported > 0\n ? // `--as` belongs to manni's engine, so offering it to someone running\n // another tool is advice that answers with a usage error. The formats\n // line is true for every tool, because every tool declares one.\n `${unsupported} ${unsupported === 1 ? \"is\" : \"are\"} in a format ` +\n `${tool.name} does not read: ` +\n (tool.ownedOptions.includes(\"--as\")\n ? `pass --as <format> to force one, or target files in a format `\n : `target files in a format `) +\n `\"manni lint tools\" lists.`\n : null,\n unreadable > 0\n ? `${unreadable} could not be read: check the permissions on those ` +\n `paths, or drop them from the run with --exclude <glob>.`\n : null,\n ]\n .filter((line): line is string => line !== null)\n .join(\" \");\n\n throw new LintError(\n `Nothing was checked: all ${skipped} file(s) were skipped. ${advice} ` +\n `Run \"manni lint structure <paths> --explain\" to see how each file resolved.`,\n );\n}\n\nexport async function runLint(opts: LintOptions): Promise<LintRun> {\n // Which config governs the run, and what it covers: positional paths, or\n // the `collections:` the family file declares. One base per run, so a\n // collection's globs resolve beside the config that wrote them.\n const run = await resolveLintRun({\n cwd: opts.cwd ?? process.cwd(),\n configPath: opts.configPath,\n noConfig: opts.noConfig,\n inputs: opts.inputs,\n collection: opts.collection,\n onConfigLoaded: opts.onConfigLoaded,\n });\n const config: LintConfig = run.config;\n const cwd = run.base;\n\n if (run.inputs.length === 0) {\n throw new LintError(\n \"No files to check. Pass paths/globs, or declare a collection under `collections:` in manni.config.yaml.\",\n );\n }\n\n // Which tool performs the structure job: `--tool` first, then the config's\n // `lint.structure.tool`, then manni's own engine. Settled before anything is\n // read, because it decides what \"anything\" even is - the extensions a walk\n // collects, and which of the options below the run may carry at all.\n const tool = resolveStructureTool(\n opts.tool ?? config.structure?.tool ?? \"manni\",\n );\n\n const usingStdin = run.inputs.includes(STDIN_TOKEN);\n assertOptionsOwned(opts, tool, usingStdin);\n\n // Resolve `--as` before anything is read: a typo should fail immediately,\n // not after walking a tree of files it was going to mis-parse anyway.\n //\n // A name no parser answers to is unknown, whatever it is meant to name: the\n // formats `manni lint tools` lists are exactly the ones `--as` accepts.\n const forcedParser = opts.as != null ? parserByName(opts.as) : undefined;\n if (opts.as != null && !forcedParser) {\n throw new LintError(\n `Unknown format \"${opts.as}\". Run \"manni lint tools\" to see the formats manni lint reads.`,\n );\n }\n\n // Before the targets are resolved, as cite does: a mistyped path beside `-`\n // was reported as \"File not found\", which names the wrong mistake when the\n // run could not have read stdin either way.\n if (usingStdin && !forcedParser) {\n throw new LintError(\n \"Reading from stdin (-) requires --as <format> to choose a parser.\",\n );\n }\n\n const fileInputs = run.inputs.filter((input) => input !== STDIN_TOKEN);\n // The resolved tool's own walk set is the default, not the walker's. Left\n // undefined, the family walker falls back to the *metadata* tool's extractor\n // extensions, which sweep in every format that tool reads - `.xml` among\n // them, where manni lint's registry honours `walkExtensions` and\n // deliberately walks `.dita` and not `.xml`, so an ordinary `pom.xml` cannot\n // fail a clean tree. Read off the descriptor rather than off that registry\n // directly, so a tool with input formats of its own walks for those.\n // Resolved here rather than at the walk, so `assertNonEmpty` names the same\n // set it filtered with.\n const exts = opts.exts ?? forcedParser?.extensions ?? tool.walkExtensions();\n const allowEmpty = opts.allowEmpty ?? config.allowEmpty;\n // A collection's `exclude:` shapes the collection, so it applies when the\n // inputs came from the collections and never to a path the operator typed.\n // `--exclude` filters either way; the union is deduplicated.\n const exclude = [\n ...new Set([\n ...(opts.exclude ?? []),\n ...(run.fromCollections ? run.collections.flatMap((c) => c.exclude) : []),\n ]),\n ];\n const { files, gitignoreSkipped } = await asLintError(() =>\n resolveTargetSet({\n inputs: fileInputs,\n exts,\n exclude,\n cwd,\n allowEmpty,\n ...gitignoreOptions({\n flag: opts.respectGitignore,\n onNotice: opts.onNotice,\n }),\n }),\n );\n // Resolving zero files is an operational error, not a pass: with no files\n // there is no verdict, and exit 0 would read as a clean bill of health.\n await asLintError(() => {\n assertNonEmpty({\n files,\n inputs: fileInputs,\n usingStdin,\n allowEmpty,\n exclude,\n exts,\n gitignoreSkipped,\n action: \"linted\",\n });\n });\n\n // The branch per tool. Reaching the refusal is an internal fault rather than\n // user error - every name the registry does not carry was refused by\n // `resolveStructureTool` above - and it is a `LintError` for that reason: a\n // bare `Error` escapes the bin runner and exits 1, the code that means \"the\n // documents have findings\".\n const name: string = tool.name;\n let results: LintFileResult[];\n if (name === \"manni\") {\n results = await lintWithManni({\n opts,\n config,\n cwd,\n files,\n forcedParser,\n usingStdin,\n });\n } else if (name === \"dita-ot\") {\n // `tools:` is the family's key, not the `lint:` section's, so the home is\n // resolved against the directory of the config that declared it.\n const home = ditaOtHome(run.tools, run.configDir ?? cwd);\n results = await lintWithDitaOt({\n cwd,\n files,\n ...(home === undefined ? {} : { home }),\n ...(opts.onNotice === undefined ? {} : { onNotice: opts.onNotice }),\n validate: opts.runDitaOt ?? runDitaOtValidate,\n });\n } else {\n throw new LintError(`No implementation is registered for the ${name} tool.`);\n }\n\n // Every tool, not just manni's. A run that resolved files and checked none\n // of them exits 0 and reads as a clean bill of health, which is the worst\n // thing this command can do quietly. It sat inside the manni branch until\n // `dita-ot` started skipping the formats it does not read, at which point\n // `manni lint structure notes.md` reported \"0 files checked, 1 skipped\" and\n // exited 0. One call here is one the next tool cannot forget to make.\n assertSomethingWasChecked(results, opts.explain === true, tool);\n\n const skipped = results.filter((r) => r.skipped != null).length;\n const failed = results.filter((r) => r.skipped == null && !r.success).length;\n const checked = results.length - skipped;\n\n return {\n results,\n summary: { checked, passed: checked - failed, failed, skipped },\n };\n}\n","/**\n * Markdown and MDX parsers.\n *\n * They share everything but the unified processor. MDX needs its own, selected\n * by extension rather than by a flag: `remark-mdx` reads `{` as an expression\n * delimiter, so ordinary Markdown prose containing a brace is a syntax error\n * under it. Running one processor for both formats would break either MDX\n * (without the plugin) or plain Markdown (with it).\n */\nimport { unified } from \"unified\";\nimport remarkParse from \"remark-parse\";\nimport remarkGfm from \"remark-gfm\";\nimport remarkFrontmatter from \"remark-frontmatter\";\nimport remarkMdx from \"remark-mdx\";\nimport { extractFrontmatter } from \"../../meta/index.js\";\nimport type { ContentKind, DocumentParser, DocumentTree } from \"../types.js\";\nimport { LintError } from \"../types.js\";\nimport { errorMessage } from \"../../shared/errors.js\";\nimport { documentEnd, toFragments } from \"./mdast.js\";\nimport { sectionize } from \"./sectionize.js\";\nimport { fencedPosition as frontmatterPosition, withMetadataTitle as withFrontmatterTitle } from \"./metadata.js\";\n\nconst markdownProcessor = unified()\n .use(remarkParse)\n .use(remarkGfm)\n .use(remarkFrontmatter, [\"yaml\", \"toml\"]);\n\nconst mdxProcessor = unified()\n .use(remarkParse)\n .use(remarkGfm)\n .use(remarkFrontmatter, [\"yaml\", \"toml\"])\n .use(remarkMdx);\n\n/**\n * Only `parse` is used, and unified's `Processor` generics differ between the\n * plain and MDX pipelines (their tree types are not the same), so the narrow\n * structural type is both sufficient and the one that lets both pass.\n */\ninterface Parseable {\n parse(content: string): unknown;\n}\n\nfunction parseWith(\n processor: Parseable,\n format: string,\n content: string,\n filePath: string,\n): DocumentTree {\n let root: unknown;\n try {\n root = processor.parse(content);\n } catch (err) {\n // MDX raises on malformed expressions; a parse failure is the file's\n // problem, not a crash, so it surfaces as an operational error naming it.\n throw new LintError(\n `${filePath}: could not parse as ${format}: ${errorMessage(err)}`,\n );\n }\n\n const meta = extractFrontmatter(content, format);\n const tree = root as Parameters<typeof toFragments>[0];\n\n const frontmatter = meta.present ? meta.data : null;\n const metaPosition = frontmatterPosition(content);\n\n return {\n format,\n filePath,\n frontmatter,\n frontmatterPosition: metaPosition,\n sections: sectionize(\n withFrontmatterTitle(toFragments(tree), frontmatter, metaPosition),\n documentEnd(tree),\n ),\n };\n}\n\n/**\n * What both formats emit. `element` is MDX's alone: plain Markdown has no JSX,\n * so `<Steps>` is raw HTML to it and no tree it produces carries an element.\n * Declaring one here would report a rule about elements as checked on every\n * `.md` file it silently could not see.\n */\nconst SHARED_KINDS: ContentKind[] = [\n \"paragraph\",\n \"codeBlock\",\n \"list\",\n \"listItem\",\n \"table\",\n \"tableRow\",\n \"tableCell\",\n \"admonition\",\n \"image\",\n \"blockquote\",\n];\n\nexport const markdownParser: DocumentParser = {\n name: \"markdown\",\n label: \"Markdown\",\n kinds: SHARED_KINDS,\n extensions: [\".md\", \".markdown\"],\n parse: (content, filePath) =>\n parseWith(markdownProcessor, \"markdown\", content, filePath),\n};\n\nexport const mdxParser: DocumentParser = {\n name: \"mdx\",\n label: \"MDX\",\n kinds: [...SHARED_KINDS, \"element\"],\n extensions: [\".mdx\"],\n parse: (content, filePath) => parseWith(mdxProcessor, \"mdx\", content, filePath),\n};\n","/**\n * mdast -> generic fragments. Shared by the Markdown and MDX parsers, which\n * differ only in which unified processor produced the tree.\n *\n * The mapping is onto the family content model (proposal 0065), never onto a\n * nearest neighbour: a blockquote is a `blockquote` and a table is a `table`,\n * because counting either as a paragraph would make `paragraphs: {max: 3}`\n * fail documents a reader would say satisfy it. A node type the model has no\n * kind for is still skipped with its subtree rather than approximated.\n *\n * MDX-only node types (`mdxJsxFlowElement`, and the expressions and comments\n * this file deliberately drops) appear only in trees the MDX processor\n * produced. The plain Markdown processor has no `remark-mdx`, so its trees\n * cannot carry them and `markdownParser` neither emits `element` nor declares\n * it. That is why one mapping serves both formats without a mode flag.\n */\nimport { toString as mdastToString } from \"mdast-util-to-string\";\nimport type { Position } from \"../types.js\";\nimport type {\n AdmonitionNode,\n ContentNode,\n ElementNode,\n ImageNode,\n ListItemNode,\n TableCellNode,\n TableRowNode,\n} from \"../types.js\";\nimport type { Fragment } from \"./sectionize.js\";\n\n/** An MDX JSX attribute, as `mdast-util-mdx-jsx` shapes it. */\ninterface MdAttribute {\n type: string;\n name?: string | null;\n /** A string for `a=\"b\"`, null for a bare `a`, an expression node for `a={b}`. */\n value?: string | { type?: string; value?: string } | null;\n}\n\n/** Minimal structural view of an mdast node; avoids depending on @types/mdast shapes. */\ninterface MdNode {\n type: string;\n position?: {\n start: { line: number; column: number; offset?: number };\n end: { line: number; column: number; offset?: number };\n };\n children?: MdNode[];\n depth?: number;\n lang?: string | null;\n ordered?: boolean | null;\n value?: string;\n url?: string;\n alt?: string | null;\n title?: string | null;\n /** MDX JSX only; null on a fragment (`<>`). */\n name?: string | null;\n attributes?: MdAttribute[];\n}\n\nconst ZERO: Position = {\n start: { line: 1, column: 1, offset: 0 },\n end: { line: 1, column: 1, offset: 0 },\n};\n\n/**\n * unist positions carry `offset` as optional. It is always present on a tree\n * remark parsed from a string, but the type does not say so, and a missing\n * offset would otherwise become `NaN` in a reporter.\n */\nexport function positionOf(node: MdNode): Position {\n const p = node.position;\n if (!p) return { start: { ...ZERO.start }, end: { ...ZERO.end } };\n return {\n start: { line: p.start.line, column: p.start.column, offset: p.start.offset ?? 0 },\n end: { line: p.end.line, column: p.end.column, offset: p.end.offset ?? 0 },\n };\n}\n\nfunction isContentNode(node: ContentNode | null): node is ContentNode {\n return node !== null;\n}\n\nfunction childContent(node: MdNode): ContentNode[] {\n return (node.children ?? []).map(toContentNode).filter(isContentNode);\n}\n\n/**\n * `AdmonitionNode.variant` is optional, for the formats that name a flavor\n * this vocabulary does not carry. A GitHub alert always names one of five, so\n * every admonition this file produces has one, and saying so here is what\n * keeps a missing lookup from being mistaken for a format that named nothing.\n */\ntype AlertVariant = NonNullable<AdmonitionNode[\"variant\"]>;\n\n/**\n * The five alert types GitHub defines. `danger` is in the model's `variant`\n * set but is not one of them, so `> [!DANGER]` renders as an ordinary\n * blockquote and is read as one here: a word outside the source's own set is\n * not an equivalence to invent.\n */\nconst ALERT_VARIANTS = new Map<string, AlertVariant>([\n [\"note\", \"note\"],\n [\"tip\", \"tip\"],\n [\"important\", \"important\"],\n [\"warning\", \"warning\"],\n [\"caution\", \"caution\"],\n]);\n\n/** The marker line, which must be the whole first line of the first paragraph. */\nconst ALERT_MARKER = /^\\[!([A-Za-z]+)\\][^\\S\\n]*$/;\n\n/**\n * The same marker where it sits at the head of a flattened string, with the\n * newline that followed it. `mdast-util-to-string` concatenates block children\n * without a separator, so the marker's paragraph may run straight into the\n * next one and there is no newline to consume.\n */\nconst ALERT_PREFIX = /^\\[!\\w+\\][^\\S\\n]*\\n?/;\n\n/**\n * A GitHub alert, which is a blockquote whose first paragraph opens with a\n * marker line. It is a check on that paragraph's text rather than a plugin,\n * because the marker is ordinary text to every Markdown parser.\n */\nfunction alertVariant(node: MdNode): AlertVariant | null {\n const first = node.children?.[0];\n if (!first || first.type !== \"paragraph\") return null;\n const text = mdastToString(first);\n const newline = text.indexOf(\"\\n\");\n const firstLine = newline === -1 ? text : text.slice(0, newline);\n const match = ALERT_MARKER.exec(firstLine);\n const word = match?.[1];\n // Case-insensitively, as GitHub matches it.\n return word ? (ALERT_VARIANTS.get(word.toLowerCase()) ?? null) : null;\n}\n\nfunction toAdmonition(node: MdNode, variant: AlertVariant): AdmonitionNode {\n const children = childContent(node);\n const first = children[0];\n // The marker is markup, not content, so it is stripped from the admonition's\n // own text and from the paragraph that carried it. A paragraph left holding\n // nothing but the marker is dropped rather than kept as an empty one.\n if (first && first.kind === \"paragraph\") {\n const stripped = first.text.replace(ALERT_PREFIX, \"\");\n if (stripped.length === 0) children.shift();\n else children[0] = { ...first, text: stripped };\n }\n return {\n kind: \"admonition\",\n position: positionOf(node),\n text: mdastToString(node).replace(ALERT_PREFIX, \"\"),\n variant,\n children,\n };\n}\n\n/**\n * The image a paragraph holds, when that is all it holds. An image inside\n * richer prose is part of what the paragraph says: promoting it would take the\n * sentence around it out of the paragraph count.\n */\nfunction soleImage(node: MdNode): MdNode | null {\n const meaningful = (node.children ?? []).filter(\n (child) => !(child.type === \"text\" && (child.value ?? \"\").trim().length === 0),\n );\n const only = meaningful.length === 1 ? meaningful[0] : undefined;\n return only && only.type === \"image\" ? only : null;\n}\n\nfunction toImage(node: MdNode): ImageNode {\n const alt = node.alt ?? \"\";\n return {\n kind: \"image\",\n position: positionOf(node),\n text: alt,\n url: node.url ?? \"\",\n alt,\n ...(node.title ? { title: node.title } : {}),\n };\n}\n\n/**\n * An MDX element's attributes, by their literal values: the string for\n * `a=\"b\"`, `true` for a bare `a`, and the braced source for `a={b}`, so a rule\n * can say \"its value is an expression\" rather than silently not matching a\n * value it cannot know. A spread (`{...rest}`) names no attribute and is\n * dropped, having no key to record it under.\n */\nfunction attributesOf(node: MdNode): Record<string, string | true> | undefined {\n const attributes: Record<string, string | true> = {};\n let any = false;\n for (const attribute of node.attributes ?? []) {\n if (attribute.type !== \"mdxJsxAttribute\") continue;\n const name = attribute.name;\n if (typeof name !== \"string\" || name.length === 0) continue;\n const value = attribute.value;\n if (value === null || value === undefined) attributes[name] = true;\n else if (typeof value === \"string\") attributes[name] = value;\n else attributes[name] = `{${value.value ?? \"\"}}`;\n any = true;\n }\n return any ? attributes : undefined;\n}\n\nfunction toElement(node: MdNode): ElementNode {\n const attributes = attributesOf(node);\n return {\n kind: \"element\",\n position: positionOf(node),\n text: mdastToString(node),\n // A fragment (`<>`) has no tag to name.\n name: node.name ?? \"\",\n ...(attributes ? { attributes } : {}),\n // The element's own children, never the enclosing section's: a section\n // holding one `<Steps>` holds one block, not the four paragraphs inside\n // it (proposal 0065, stress test 4). A heading inside one is dropped with\n // everything else the model has no kind for, which stress test 5 records.\n children: childContent(node),\n };\n}\n\nfunction toTableRow(row: MdNode, header: boolean): TableRowNode {\n return {\n kind: \"tableRow\",\n position: positionOf(row),\n text: mdastToString(row),\n header,\n children: (row.children ?? [])\n .filter((cell) => cell.type === \"tableCell\")\n .map(\n (cell): TableCellNode => ({\n kind: \"tableCell\",\n position: positionOf(cell),\n text: mdastToString(cell),\n // A GFM cell holds inline content only, so this is empty today. It\n // is mapped rather than assumed empty because the model's cell is\n // the one reStructuredText and DITA fill with blocks.\n children: childContent(cell),\n }),\n ),\n };\n}\n\nfunction toContentNode(node: MdNode): ContentNode | null {\n switch (node.type) {\n case \"paragraph\": {\n const image = soleImage(node);\n if (image) return toImage(image);\n return {\n kind: \"paragraph\",\n position: positionOf(node),\n text: mdastToString(node),\n };\n }\n case \"code\":\n return {\n kind: \"codeBlock\",\n position: positionOf(node),\n text: node.value ?? \"\",\n ...(node.lang ? { language: node.lang } : {}),\n };\n case \"list\":\n return {\n kind: \"list\",\n position: positionOf(node),\n text: mdastToString(node),\n ordered: Boolean(node.ordered),\n items: (node.children ?? [])\n .filter((child) => child.type === \"listItem\")\n .map(\n (item): ListItemNode => ({\n kind: \"listItem\",\n position: positionOf(item),\n text: mdastToString(item),\n children: childContent(item),\n }),\n ),\n };\n case \"table\":\n return {\n kind: \"table\",\n position: positionOf(node),\n text: mdastToString(node),\n // GFM guarantees the first row is the header, which is the one format\n // of six where reading it positionally is safe. Everywhere else the\n // format carries a real `thead` and this flag comes from it.\n children: (node.children ?? [])\n .filter((row) => row.type === \"tableRow\")\n .map((row, index) => toTableRow(row, index === 0)),\n };\n case \"blockquote\": {\n const variant = alertVariant(node);\n if (variant) return toAdmonition(node, variant);\n return {\n kind: \"blockquote\",\n position: positionOf(node),\n text: mdastToString(node),\n children: childContent(node),\n };\n }\n case \"mdxJsxFlowElement\":\n return toElement(node);\n default:\n return null;\n }\n}\n\n/**\n * The `{#anchor}` suffix Hugo and Docusaurus write on a heading. It names the\n * rendered id, and a reader never sees it, so a template matches the heading\n * without it.\n */\nconst HEADING_ANCHOR = /\\s*\\{#[^}\\s]*\\}\\s*$/;\n\nfunction headingTitle(node: MdNode): string {\n return mdastToString(node).replace(HEADING_ANCHOR, \"\").trim();\n}\n\n/** Flatten an mdast root's direct children into ordered fragments. */\nexport function toFragments(root: MdNode): Fragment[] {\n const fragments: Fragment[] = [];\n for (const node of root.children ?? []) {\n // Frontmatter is metadata, not body content; the caller reads it separately.\n if (node.type === \"yaml\" || node.type === \"toml\") continue;\n\n if (node.type === \"heading\") {\n fragments.push({\n type: \"heading\",\n level: node.depth ?? 1,\n title: headingTitle(node),\n position: positionOf(node),\n });\n continue;\n }\n\n const content = toContentNode(node);\n if (content) fragments.push({ type: \"content\", node: content });\n }\n return fragments;\n}\n\n/** End of the document, for closing the final sections. */\nexport function documentEnd(root: MdNode): Position[\"end\"] {\n return positionOf(root).end;\n}\n","/**\n * Fold a flat list of fragments into a nested section tree.\n *\n * Every format arrives here as an ordered list of `Fragment`s - a heading, or\n * a piece of content - and leaves as `SectionNode[]`. Keeping the fold in one\n * place is what makes a new format one `toFragments` function rather than a\n * second copy of the nesting, position, and slug logic.\n *\n * Named `Fragment` rather than `Block`, deliberately: \"block\" is the\n * block-level content vocabulary (`ContentKind`'s `table`, `blockquote`, and\n * so on), and this internal pipeline type never leaves `src/lint/parsers/`.\n *\n * Two position rules are deliberate:\n *\n * - A section ends where the *next section at its level or shallower* begins,\n * not at its own last child. A finding about a section therefore spans the\n * trailing blank lines a reader would consider part of it, and adjacent\n * sections tile the document with no gaps.\n * - Content appearing before any heading becomes an implicit lead section at\n * `level: 0`, so a headless document (frontmatter, prose, then `## ...`)\n * still has somewhere to hang its content and its later headings nest under\n * it rather than being dropped.\n */\nimport GithubSlugger from \"github-slugger\";\nimport type { ContentNode, Position, SectionNode } from \"../types.js\";\n\nexport interface HeadingFragment {\n type: \"heading\";\n /** 1-6. */\n level: number;\n title: string;\n position: Position;\n}\n\nexport interface ContentFragment {\n type: \"content\";\n node: ContentNode;\n}\n\nexport type Fragment = HeadingFragment | ContentFragment;\n\n/** Mutable while open; frozen into a `SectionNode` on close. */\ninterface OpenSection {\n node: SectionNode;\n /** End of the last block seen, the fallback when nothing follows. */\n lastEnd: Position[\"end\"];\n}\n\n/**\n * @param fragments Document fragments in source order, frontmatter excluded.\n * @param docEnd End of the document, used to close the final sections.\n */\nexport function sectionize(fragments: Fragment[], docEnd: Position[\"end\"]): SectionNode[] {\n const slugger = new GithubSlugger();\n const roots: SectionNode[] = [];\n const stack: OpenSection[] = [];\n\n /** Close every open section at `level` or deeper, ending it at `end`. */\n const closeTo = (level: number, end: Position[\"end\"]): void => {\n let top = stack.at(-1);\n while (top !== undefined && top.node.level >= level) {\n stack.pop();\n top.node.position.end = { ...end };\n top = stack.at(-1);\n }\n };\n\n /** Pushes `node` onto the stack and hands back the section it opened. */\n const push = (node: SectionNode): OpenSection => {\n const parent = stack[stack.length - 1];\n if (parent) {\n node.parentSlug = parent.node.slug;\n node.order = parent.node.sections.length + 1;\n parent.node.sections.push(node);\n } else {\n node.parentSlug = null;\n node.order = roots.length + 1;\n roots.push(node);\n }\n const open: OpenSection = { node, lastEnd: node.position.end };\n stack.push(open);\n return open;\n };\n\n /**\n * The implicit lead section. `level: 0` is below every real heading, so the\n * headings that follow nest inside it instead of closing it.\n */\n const openLead = (start: Position[\"start\"]): OpenSection =>\n push({\n slug: slugger.slug(\"(lead)\"),\n title: \"\",\n level: 0,\n order: 0,\n parentSlug: null,\n titlePosition: null,\n position: { start: { ...start }, end: { ...start } },\n children: [],\n sections: [],\n });\n\n for (const fragment of fragments) {\n if (fragment.type === \"heading\") {\n closeTo(fragment.level, fragment.position.start);\n push({\n slug: slugger.slug(fragment.title),\n title: fragment.title,\n level: fragment.level,\n order: 0,\n parentSlug: null,\n titlePosition: { ...fragment.position },\n position: { start: { ...fragment.position.start }, end: { ...fragment.position.end } },\n children: [],\n sections: [],\n });\n continue;\n }\n\n const current = stack.at(-1) ?? openLead(fragment.node.position.start);\n current.node.children.push(fragment.node);\n current.lastEnd = fragment.node.position.end;\n // Every enclosing section grows with its descendants, so a parent's span\n // always covers its children even before it is closed.\n for (const open of stack) open.node.position.end = { ...fragment.node.position.end };\n }\n\n closeTo(0, docEnd);\n return roots;\n}\n","/**\n * Metadata helpers shared by every format that has both metadata and headings.\n *\n * Both functions here were independently written four times, once per parser,\n * and were character-identical each time. They are rules about a `DocumentTree`\n * rather than about any one syntax, so they belong in one place: a subtlety\n * duplicated four ways is a subtlety that will be fixed one way.\n */\nimport { locateFrontmatter } from \"../../meta/index.js\";\nimport type { Position } from \"../types.js\";\nimport type { Fragment } from \"./sectionize.js\";\n\n/**\n * Span of a leading fenced metadata block (`--- … ---`, `+++ … +++`,\n * `;;; … ;;;`), or null when the content carries none.\n *\n * docmeta's locator reports character offsets against the original content, so\n * line numbers are recovered by counting newlines rather than by a second\n * parse - exact, because those offsets are byte-for-byte.\n */\nexport function fencedPosition(content: string): Position | null {\n const loc = locateFrontmatter(content);\n if (!loc) return null;\n const before = content.slice(0, loc.openStart);\n const startLine = before.split(\"\\n\").length;\n const lines = content.slice(loc.openStart, loc.closeEnd).split(\"\\n\");\n return {\n start: { line: startLine, column: 1, offset: loc.openStart },\n end: {\n line: startLine + lines.length - 1,\n // Taken from the last line's own length rather than fixed at 1. When the\n // block ends with a newline that line is empty and the column is 1\n // anyway; when the closing fence ends at EOF without one, the half-open\n // end is just past the delimiter - which `offset` already said, so a\n // fixed column contradicted it and pointed a reader's caret at the start\n // of the fence line instead of its end.\n // `split` always yields at least one entry, so the fallback is\n // unreachable; an empty last line is column 1 either way.\n column: (lines.at(-1) ?? \"\").length + 1,\n offset: loc.closeEnd,\n },\n };\n}\n\n/**\n * Treat a metadata `title` as the document's H1 when the body has none.\n *\n * Docusaurus, Hugo, and Starlight all render the page title from frontmatter,\n * so their pages legitimately start at `##`. Read literally, such a page has no\n * top-level section, and every doctype template - which models the title as its\n * outermost rule, because that is how the published templates are written -\n * misaligns against it and reports a cascade. The page is not malformed; the\n * title simply is not written where a naive reading looks for it.\n *\n * So a synthetic heading is prepended, positioned on the metadata that actually\n * carries the title. Everything downstream then sees the document the way a\n * reader sees it rendered.\n *\n * Only when the body has no level-1 heading of its own: prepending one where a\n * real title exists would nest it inside a synthetic parent, which is a\n * different document.\n *\n * See ADR 01006. Formats where the title is always a body element - XML, whose\n * \"metadata\" is the root element's own attributes - do not call this, and\n * should not.\n */\nexport function withMetadataTitle(\n fragments: Fragment[],\n metadata: Record<string, unknown> | null,\n position: Position | null,\n): Fragment[] {\n const declared = metadata?.[\"title\"];\n const title = typeof declared === \"string\" ? declared.trim() : null;\n // Trimmed, not merely non-empty: `title: \" \"` is as absent as no title at\n // all, and admitting it would give the document a synthetic H1 with a blank\n // heading - which every template then reports as the wrong title, naming\n // nothing the author could search for.\n if (title === null || title.length === 0) return fragments;\n if (position === null) return fragments;\n if (fragments.some((b) => b.type === \"heading\" && b.level === 1)) return fragments;\n\n return [{ type: \"heading\", level: 1, title, position }, ...fragments];\n}\n\n/**\n * The content with a leading fenced metadata block removed.\n *\n * docmeta's AsciiDoc and reStructuredText extractors short-circuit: when a\n * fence is present they return it and never look at the format's own metadata.\n * So a page carrying both a `---` fence and a native `:type: how-to` header\n * lost the `type` entirely and was skipped as untyped - while the same page in\n * HTML, whose extractor has no such branch, routed correctly. Running the\n * native extractor over the fence-free remainder is what lets both be read.\n *\n * Only the values are taken from that second read; positions would be shifted\n * by the removal and are not used.\n */\nexport function withoutFence(content: string): string {\n const loc = locateFrontmatter(content);\n return loc ? content.slice(loc.closeEnd) : content;\n}\n","/**\n * HTML parser: parse5's DOM -> generic blocks -> the shared `sectionize` fold.\n *\n * The job is the same one `mdast.ts` does for Markdown - flatten a format's own\n * tree into ordered `Fragment`s - and the same skipping discipline applies\n * where the content model has no kind at all. A `<div>` is not content and a\n * `<figure>` with no image inside it is dropped whole, because counting\n * either would make `paragraphs: {max: 3}` fail a page a reader would say\n * satisfies it. Proposal 0065 widened the model, so `blockquote`, `table`,\n * `figure`, and `dl` are no longer in that group: they map onto real nodes\n * now, alongside `admonition` from `<aside>`/`role=\"note\"` and `image` from\n * `<img>`.\n *\n * `parse` rather than `parseFragment`. Real documentation HTML is a document:\n * `<!DOCTYPE html><html><head>…</head><body>…`, and an HTML page's metadata\n * lives in `<head>`, which `parseFragment` (which parses in a `<body>` context)\n * drops on the floor - `<head>` is an ignored start tag in the \"in body\"\n * insertion mode. `parse` also handles a bare fragment, because HTML5 tree\n * construction synthesizes the missing `<html>`/`<head>`/`<body>` around it; the\n * only cost is that those synthesized elements carry no `sourceCodeLocation`,\n * which `positionOf` already has to tolerate.\n *\n * parse5 never throws on malformed input - HTML5 defines recovery for every\n * error - so unlike the MDX path there is no parse-failure branch here. A\n * document with unclosed tags parses into whatever a browser would build from\n * it, and lints against that.\n */\nimport { defaultTreeAdapter, parse } from \"parse5\";\nimport type { DefaultTreeAdapterTypes } from \"parse5\";\nimport { extractFrontmatter, extractorForExtension } from \"../../meta/index.js\";\nimport type {\n AdmonitionNode,\n BlockquoteNode,\n CodeNode,\n ContentNode,\n DefinitionItemNode,\n DefinitionListNode,\n DocumentParser,\n DocumentTree,\n ImageNode,\n ListItemNode,\n Position,\n TableCellNode,\n TableNode,\n TableRowNode,\n} from \"../types.js\";\nimport type { Fragment } from \"./sectionize.js\";\nimport { sectionize } from \"./sectionize.js\";\nimport { fencedPosition, withMetadataTitle } from \"./metadata.js\";\n\ntype Node = DefaultTreeAdapterTypes.Node;\ntype Element = DefaultTreeAdapterTypes.Element;\ntype ParentNode = DefaultTreeAdapterTypes.ParentNode;\n\n/**\n * What a walk does when it meets an element.\n *\n * - `heading`/`content`: the element *is* a block. It is emitted and never\n * descended into, because its whole subtree has already been folded into the\n * emitted node's text (or, for a container kind, its own `children`).\n * Descending would emit the same prose twice.\n * - `container`: the element is not content but its children may be. Descend\n * without emitting. This is the case that matters: real HTML wraps\n * everything in `<html><body><main><article><div>`, and a heading inside a\n * `<div>` is still a heading.\n * - `opaque`: neither content nor a container. Skip the subtree entirely.\n *\n * `container` is the default, so an unknown element - a web component, a\n * `<my-callout>` - still yields the headings and paragraphs inside it. `opaque`\n * is a short, explicit list, and every entry earns its place the same way: it\n * is metadata/machinery rather than prose, so the generic content model has no\n * kind for it at all.\n */\ntype Role = \"heading\" | \"content\" | \"container\" | \"opaque\";\n\nconst HEADING_LEVELS = new Map<string, number>([\n [\"h1\", 1],\n [\"h2\", 2],\n [\"h3\", 3],\n [\"h4\", 4],\n [\"h5\", 5],\n [\"h6\", 6],\n]);\n\n/**\n * Elements that are a block on their own: emitted as one content node, never\n * descended into. `table`, `blockquote`, `dl`, `img` and `figure` used to sit\n * in `OPAQUE_TAGS` and be dropped whole; proposal 0065 gave each a node shape,\n * so they move here instead. `aside` joins them because it is one of the two\n * HTML sources of `admonition` - the other, `role=\"note\"`, is not a tag and is\n * checked separately in `roleOf`.\n */\nconst CONTENT_TAGS = new Set([\"p\", \"pre\", \"ul\", \"ol\", \"table\", \"blockquote\", \"dl\", \"img\", \"figure\", \"aside\"]);\n\nconst OPAQUE_TAGS = new Set([\n // Metadata and machinery, not prose.\n \"head\",\n \"script\",\n \"style\",\n \"template\",\n \"noscript\",\n \"svg\",\n \"math\",\n]);\n\n/** Elements whose text is not document text, for the flattening helpers. */\nconst NON_TEXT_TAGS = new Set([\"script\", \"style\", \"template\"]);\n\nconst ADMONITION_VARIANTS = new Set([\n \"note\",\n \"tip\",\n \"important\",\n \"caution\",\n \"warning\",\n \"danger\",\n]);\n\nconst ZERO: Position = {\n start: { line: 1, column: 1, offset: 0 },\n end: { line: 1, column: 1, offset: 0 },\n};\n\nfunction tagOf(el: Element): string {\n return el.tagName.toLowerCase();\n}\n\n/** An element's attribute value, or `undefined` when it does not carry one. */\nfunction attrOf(el: Element, name: string): string | undefined {\n return el.attrs.find((a) => a.name === name)?.value;\n}\n\n/**\n * `admonition`'s two HTML sources: the `<aside>` tag, and `role=\"note\"` on any\n * element. Neither one is enough on its own - `aside` is a tag and `role` is\n * an attribute any element can carry - so this is checked ahead of the\n * tag-keyed `CONTENT_TAGS`/`OPAQUE_TAGS` lookup rather than folded into it.\n */\nfunction isAdmonitionSource(el: Element, tag: string): boolean {\n return tag === \"aside\" || attrOf(el, \"role\") === \"note\";\n}\n\nfunction roleOf(el: Element, tag: string): Role {\n if (HEADING_LEVELS.has(tag)) return \"heading\";\n if (isAdmonitionSource(el, tag)) return \"content\";\n if (CONTENT_TAGS.has(tag)) return \"content\";\n if (OPAQUE_TAGS.has(tag)) return \"opaque\";\n return \"container\";\n}\n\n/**\n * parse5's `sourceCodeLocation` maps onto `Position` one field at a time: its\n * lines and columns are 1-based, its offsets 0-based, and its `end*` is one\n * past the last character - the same half-open span `Position` documents. A\n * `<p>foo</p>` starting at column 1 reports `endCol` 12 for an 11-character\n * element, and `endOffset - startOffset` is its length.\n *\n * A node can carry no location at all: parse5 synthesizes `<html>`, `<head>`,\n * and `<body>` around a fragment, and those have none. Nothing synthesized is\n * ever emitted as a block, but the fallback keeps a missing location from\n * becoming `NaN` in a reporter.\n */\ninterface Located {\n sourceCodeLocation?: {\n startLine: number;\n startCol: number;\n startOffset: number;\n endLine: number;\n endCol: number;\n endOffset: number;\n } | null;\n}\n\nfunction positionOf(node: Located): Position {\n const loc = node.sourceCodeLocation;\n if (!loc) return { start: { ...ZERO.start }, end: { ...ZERO.end } };\n return {\n start: { line: loc.startLine, column: loc.startCol, offset: loc.startOffset },\n end: { line: loc.endLine, column: loc.endCol, offset: loc.endOffset },\n };\n}\n\n/** Concatenated text of a subtree, markup and all, verbatim. */\nfunction rawText(node: Node): string {\n if (defaultTreeAdapter.isTextNode(node)) return node.value;\n if (!defaultTreeAdapter.isElementNode(node)) return \"\";\n if (NON_TEXT_TAGS.has(tagOf(node))) return \"\";\n let out = \"\";\n for (const child of node.childNodes) out += rawText(child);\n return out;\n}\n\n/**\n * Text as a browser renders it: nested `<code>`, `<em>`, and `<a>` contribute\n * their text, and HTML's insignificant whitespace collapses, so a heading\n * written across three indented lines still equals `\"Overview\"` - which is what\n * a template's `heading: {const: Overview}` compares against.\n *\n * This is the HTML side of the bug the Markdown parser had before the rewrite,\n * where a title was built from `children.map(c => c.value)` and every inline\n * element vanished.\n */\nfunction flatText(node: Node): string {\n return rawText(node).replace(/\\s+/g, \" \").trim();\n}\n\n/** `language-x` from a `class`, per the HTML5 convention for code blocks. */\nfunction langOf(el: Element): string | undefined {\n const className = attrOf(el, \"class\");\n if (!className) return undefined;\n for (const token of className.split(/\\s+/)) {\n if (token.startsWith(\"language-\") && token.length > \"language-\".length) {\n return token.slice(\"language-\".length);\n }\n }\n return undefined;\n}\n\n/** `variant`, from `role=\"note\"` or a class naming one of the six - never invented. */\nfunction variantOf(el: Element): AdmonitionNode[\"variant\"] | undefined {\n const className = attrOf(el, \"class\");\n if (className) {\n for (const token of className.split(/\\s+/)) {\n if (ADMONITION_VARIANTS.has(token)) return token as AdmonitionNode[\"variant\"];\n }\n }\n if (attrOf(el, \"role\") === \"note\") return \"note\";\n return undefined;\n}\n\nfunction firstElementChild(el: Element, tag: string): Element | undefined {\n for (const child of el.childNodes) {\n if (defaultTreeAdapter.isElementNode(child) && tagOf(child) === tag) return child;\n }\n return undefined;\n}\n\n/** An element's direct element children, text and comment nodes excluded. */\nfunction elementChildren(el: Element): Element[] {\n const out: Element[] = [];\n for (const child of el.childNodes) {\n if (defaultTreeAdapter.isElementNode(child)) out.push(child);\n }\n return out;\n}\n\n/** The first `<img>` anywhere under `el`, depth-first - for a `<figure>`. */\nfunction findImage(el: Element): Element | undefined {\n for (const child of el.childNodes) {\n if (!defaultTreeAdapter.isElementNode(child)) continue;\n if (tagOf(child) === \"img\") return child;\n const nested = findImage(child);\n if (nested) return nested;\n }\n return undefined;\n}\n\n/**\n * `<pre>` (usually `<pre><code>`) as a code node.\n *\n * Whitespace is significant here, so this is the one place `rawText` is used\n * unnormalized. Two trims are deliberate: a newline directly after `<code>` is\n * an artifact of writing the block over several lines (the HTML parser already\n * drops one directly after `<pre>`, but not one after a nested `<code>`), and\n * dropping trailing whitespace matches mdast's `code.value`, which carries no\n * closing newline.\n */\nfunction codeNode(pre: Element): CodeNode {\n const inner = firstElementChild(pre, \"code\");\n const lang = langOf(pre) ?? (inner ? langOf(inner) : undefined);\n const text = rawText(pre).replace(/^\\r?\\n/, \"\").replace(/\\s+$/, \"\");\n return {\n kind: \"codeBlock\",\n position: positionOf(pre),\n text,\n ...(lang ? { language: lang } : {}),\n };\n}\n\n/**\n * `<img>` as an image node. A bare `<img>` carries no caption of its own; a\n * `<figure>` wrapping one supplies both the position (the whole figure, since\n * that construct - image and caption together - is what the one node stands\n * for) and, when present, its `<figcaption>` as `text`.\n */\nfunction imageNode(img: Element, position: Position, caption: string | null): ImageNode {\n const title = attrOf(img, \"title\");\n return {\n kind: \"image\",\n position,\n text: caption ?? \"\",\n url: attrOf(img, \"src\") ?? \"\",\n alt: attrOf(img, \"alt\") ?? \"\",\n ...(title ? { title } : {}),\n };\n}\n\n/**\n * `<figure>` as a single image node. A figure with no `<img>` anywhere inside\n * it maps to nothing - the same as before 0065, when the whole subtree was\n * opaque - because the content model has no other kind to give it.\n */\nfunction figureNode(figure: Element): ImageNode | null {\n const img = findImage(figure);\n if (!img) return null;\n const caption = firstElementChild(figure, \"figcaption\");\n return imageNode(img, positionOf(figure), caption ? flatText(caption) : null);\n}\n\n/** `<blockquote>` as a blockquote node, its own content mapped recursively. */\nfunction blockquoteNode(el: Element): BlockquoteNode {\n return {\n kind: \"blockquote\",\n position: positionOf(el),\n text: flatText(el),\n children: childContent(el),\n };\n}\n\n/**\n * `<aside>` or `role=\"note\"` as an admonition node. HTML names no admonition\n * type natively, so `variantOf` only ever returns one of the six when the\n * source itself said which - see its own comment. A bare `<aside>` that names\n * neither carries no `variant` at all, per `AdmonitionNode.variant`'s own\n * comment in `src/lint/types.ts`: defaulting it to `note` would make\n * `variant: note` pass on a page that never said note.\n */\nfunction admonitionNode(el: Element): AdmonitionNode {\n const variant = variantOf(el);\n return {\n kind: \"admonition\",\n position: positionOf(el),\n text: flatText(el),\n ...(variant ? { variant } : {}),\n children: childContent(el),\n };\n}\n\n/** One `<td>`/`<th>` as a table cell, its own content mapped recursively. */\nfunction cellNode(cell: Element): TableCellNode {\n return {\n kind: \"tableCell\",\n position: positionOf(cell),\n text: flatText(cell),\n children: childContent(cell),\n };\n}\n\n/**\n * Which grouping a row was found in. `none` is a bare `<tr>` under the table.\n *\n * A footer has to be told apart from a body, rather than both being \"not the\n * head\". `<tfoot><tr><th>Total</th></tr></tfoot>` is an ordinary way to label\n * a totals row, and the every-cell-is-a-`<th>` rule below would otherwise read\n * it as a header.\n */\ntype RowGroup = \"head\" | \"body\" | \"foot\" | \"none\";\n\n/** One `<tr>`. `header` is set from `<thead>` membership, or - failing that - from every cell being a `<th>`. Never inferred from position, and never in a footer. */\nfunction rowNode(tr: Element, group: RowGroup): TableRowNode {\n const cells: TableCellNode[] = [];\n let allHeaderCells = true;\n for (const child of elementChildren(tr)) {\n const tag = tagOf(child);\n if (tag !== \"td\" && tag !== \"th\") continue;\n if (tag !== \"th\") allHeaderCells = false;\n cells.push(cellNode(child));\n }\n return {\n kind: \"tableRow\",\n position: positionOf(tr),\n text: flatText(tr),\n header:\n group === \"head\" || (group !== \"foot\" && cells.length > 0 && allHeaderCells),\n children: cells,\n };\n}\n\n/** Rows from `<thead>`/`<tbody>`/`<tfoot>` or bare `<tr>` children, in document order. */\nfunction collectRows(parent: Element, out: TableRowNode[], group: RowGroup): void {\n for (const child of elementChildren(parent)) {\n const tag = tagOf(child);\n if (tag === \"thead\") {\n collectRows(child, out, \"head\");\n } else if (tag === \"tbody\") {\n collectRows(child, out, \"body\");\n } else if (tag === \"tfoot\") {\n collectRows(child, out, \"foot\");\n } else if (tag === \"tr\") {\n out.push(rowNode(child, group));\n }\n // `<caption>`/`<colgroup>` carry no rows and are not content of their own.\n }\n}\n\n/** `<table>` as a table node. */\nfunction tableNode(table: Element): TableNode {\n const rows: TableRowNode[] = [];\n collectRows(table, rows, \"none\");\n return {\n kind: \"table\",\n position: positionOf(table),\n text: flatText(table),\n children: rows,\n };\n}\n\n/**\n * `<dl>` as a definition list. Each `<dt>` pairs with the `<dd>` elements that\n * immediately follow it - up to the next `<dt>` or the end of the list - and\n * the `<dt>`'s own text becomes the item's `term`. An item's position spans\n * from its `<dt>` through its last `<dd>`, or the `<dt>` alone when it has\n * none.\n */\nfunction definitionListNode(dl: Element): DefinitionListNode {\n const children = elementChildren(dl);\n const items: DefinitionItemNode[] = [];\n\n for (let i = 0; i < children.length; i++) {\n const dt = children[i];\n if (!dt || tagOf(dt) !== \"dt\") continue;\n\n const dds: Element[] = [];\n let j = i + 1;\n while (j < children.length) {\n const next = children[j];\n if (!next || tagOf(next) !== \"dd\") break;\n dds.push(next);\n j++;\n }\n\n const term = flatText(dt);\n const definition = dds.flatMap((dd) => childContent(dd));\n const lastDd = dds.at(-1);\n const end = lastDd ? positionOf(lastDd).end : positionOf(dt).end;\n const text = [term, ...dds.map((dd) => flatText(dd))].filter((t) => t.length > 0).join(\" \");\n\n items.push({\n kind: \"definitionItem\",\n position: { start: positionOf(dt).start, end },\n text,\n term,\n definition,\n });\n }\n\n return {\n kind: \"definitionList\",\n position: positionOf(dl),\n text: flatText(dl),\n children: items,\n };\n}\n\n/**\n * `<li>` children of a list, with their own content mapped recursively.\n */\nfunction listItems(list: Element): ListItemNode[] {\n const items: ListItemNode[] = [];\n for (const child of list.childNodes) {\n if (!defaultTreeAdapter.isElementNode(child)) continue;\n if (tagOf(child) !== \"li\") continue;\n items.push({\n kind: \"listItem\",\n position: positionOf(child),\n text: flatText(child),\n children: childContent(child),\n });\n }\n return items;\n}\n\n/**\n * One container element's content, with its own loose prose kept as a\n * paragraph. Shared by every construct that holds generic content recursively\n * - `<li>`, `<blockquote>`, `<aside>`/`role=\"note\"`, `<td>`/`<th>`, `<dd>` -\n * so the same reconciliation applies everywhere rather than once per kind.\n *\n * An item's text is rarely wrapped in a block element, but mdast puts a list\n * item's principal text in a `paragraph` child regardless, and\n * `lists: {items: {paragraphs: {min: 1}}}` has to count the same thing in\n * every format. So the loose text is gathered into one, in the position it\n * occupies among the container's blocks.\n *\n * Gathering it rather than checking whether the container has any children is\n * what makes the two cases agree. `<li>text</li>` and `<li><p>text</p></li>`\n * were already reconciled; `<li>Parent<ul>…</ul></li>` was not, because the\n * nested list is a child, so the item looked accounted for and `Parent` became\n * a paragraph nothing counted - while its Markdown, AsciiDoc, and reST twins\n * all counted one.\n *\n * A container element that yields no blocks of its own is inline in practice -\n * `<strong>`, `<a>`, `<code>` - so its text joins the prose around it instead\n * of being dropped, which is again what mdast does with the same markup.\n */\nfunction childContent(parent: Element): ContentNode[] {\n const out: ContentNode[] = [];\n let text = \"\";\n let span: Position | null = null;\n\n const extend = (node: Located): void => {\n const at = positionOf(node);\n span = span === null ? at : { start: span.start, end: at.end };\n };\n\n const flush = (): void => {\n const value = text.trim();\n const at = span;\n text = \"\";\n span = null;\n if (value.length === 0) return;\n out.push({ kind: \"paragraph\", position: at ?? positionOf(parent), text: value });\n };\n\n for (const child of parent.childNodes) {\n if (defaultTreeAdapter.isTextNode(child)) {\n text += child.value;\n if (child.value.trim().length > 0) extend(child);\n continue;\n }\n if (!defaultTreeAdapter.isElementNode(child)) continue;\n\n const tag = tagOf(child);\n const role = roleOf(child, tag);\n if (role === \"heading\" || role === \"opaque\") continue;\n\n if (role === \"content\") {\n flush();\n const node = toContentNode(child, tag);\n if (node) out.push(node);\n continue;\n }\n\n const nested = contentIn(child);\n if (nested.length > 0) {\n flush();\n out.push(...nested);\n continue;\n }\n\n const inline = flatText(child);\n text += inline;\n if (inline.trim().length > 0) extend(child);\n }\n\n flush();\n return out;\n}\n\nfunction toContentNode(el: Element, tag: string): ContentNode | null {\n if (isAdmonitionSource(el, tag)) return admonitionNode(el);\n switch (tag) {\n case \"p\":\n return { kind: \"paragraph\", position: positionOf(el), text: flatText(el) };\n case \"pre\":\n return codeNode(el);\n case \"ul\":\n case \"ol\":\n return {\n kind: \"list\",\n position: positionOf(el),\n text: flatText(el),\n ordered: tag === \"ol\",\n items: listItems(el),\n };\n case \"table\":\n return tableNode(el);\n case \"blockquote\":\n return blockquoteNode(el);\n case \"dl\":\n return definitionListNode(el);\n case \"img\":\n return imageNode(el, positionOf(el), null);\n case \"figure\":\n return figureNode(el);\n default:\n return null;\n }\n}\n\n/**\n * Content nodes inside a container that is not itself a block - a wrapper\n * within one, reached from `childContent`. Same descend/skip rule as the\n * document walk, minus headings: a heading inside a list item does not open a\n * section, and mdast drops it the same way.\n */\nfunction contentIn(parent: ParentNode): ContentNode[] {\n const out: ContentNode[] = [];\n for (const child of parent.childNodes) {\n if (!defaultTreeAdapter.isElementNode(child)) continue;\n const tag = tagOf(child);\n const role = roleOf(child, tag);\n if (role === \"heading\" || role === \"opaque\") continue;\n if (role === \"content\") {\n const node = toContentNode(child, tag);\n if (node) out.push(node);\n continue;\n }\n out.push(...contentIn(child));\n }\n return out;\n}\n\n/**\n * Walk the document into ordered blocks.\n *\n * Structure comes from heading *levels* only. Explicit `<section>` nesting is\n * deliberately ignored, and `<section>` is just another container:\n *\n * - `sectionize` already derives nesting from heading level for every format.\n * Honoring `<section>` would mean a second nesting mechanism living in this\n * file, plus a rule for reconciling the two whenever a page's element\n * nesting and its heading levels disagree - which they routinely do, because\n * `<section>` is optional and is as often a layout wrapper\n * (`<section class=\"hero\">`) as a semantic one.\n * - The cross-format promise is that one template produces the same findings\n * on a page and its Markdown, AsciiDoc, or reST twin. Those formats have\n * nothing but heading level, so deriving HTML's structure from anything else\n * would let identical headings nest differently per format.\n * - Where `<section>` nesting agrees with the headings - which is the whole\n * point of writing it - honoring it changes nothing. It could only ever\n * matter when it disagrees, and there the headings are what the reader sees.\n */\nfunction walk(parent: ParentNode, out: Fragment[]): void {\n for (const child of parent.childNodes) {\n if (!defaultTreeAdapter.isElementNode(child)) continue;\n const tag = tagOf(child);\n const role = roleOf(child, tag);\n\n if (role === \"heading\") {\n out.push({\n type: \"heading\",\n level: HEADING_LEVELS.get(tag) ?? 1,\n title: flatText(child),\n position: positionOf(child),\n });\n continue;\n }\n\n if (role === \"content\") {\n const node = toContentNode(child, tag);\n if (node) out.push({ type: \"content\", node });\n continue;\n }\n\n if (role === \"opaque\") continue;\n\n walk(child, out);\n }\n}\n\n/** End of the document, for closing the final sections. */\nfunction documentEnd(content: string): Position[\"end\"] {\n const lines = content.split(\"\\n\");\n const last = lines[lines.length - 1] ?? \"\";\n return { line: lines.length, column: last.length + 1, offset: content.length };\n}\n\n/**\n * An HTML page's metadata, from both places it can be.\n *\n * `extractFrontmatter(content, \"html\")` - the call the Markdown parser makes -\n * turns out to read *only* a fenced `---`/`+++`/`;;;` block; the `format`\n * argument is a label on the result, not a dispatch key. On an ordinary HTML\n * page it returns `{present: false, data: {}}`, which would leave\n * `type: how-to` in a `<meta>` tag invisible and every `.html` file unrouted.\n *\n * The `<meta>` reading lives in docmeta's *extractor* registry instead, reached\n * by extension. So both are asked, and the results merged. That keeps docmeta\n * the single source of truth for metadata - including its `<title>` lift and\n * its YAML-scalar coercion of attribute values, so `content=\"[a, b]\"` is a list\n * here exactly as it would be in frontmatter - rather than growing a second\n * `<meta>` convention in this repository.\n *\n * A fenced block wins on a key collision: it is authored at the top of the\n * source file, and it is what every sibling format reads. The two coexist\n * rarely enough that the tie-break is a formality.\n *\n * The cost is that docmeta parses the document a second time. Re-reading\n * `<meta>` off the tree already in hand would avoid it and duplicate the\n * convention; the ADR's \"docmeta is the single source of truth for frontmatter\"\n * is worth one extra parse of a file we are already reading from disk.\n */\nfunction metadataOf(\n content: string,\n filePath: string,\n doc: DefaultTreeAdapterTypes.Document,\n): { frontmatter: Record<string, unknown> | null; position: Position | null } {\n const fenced = extractFrontmatter(content, \"html\");\n const extractor = extractorForExtension(\".html\");\n const headMeta = extractor\n ? extractor.extract(content, filePath)\n : { present: false, data: {} as Record<string, unknown> };\n\n if (!fenced.present && !headMeta.present) return { frontmatter: null, position: null };\n\n const frontmatter = { ...headMeta.data, ...fenced.data };\n\n // Anchor on whichever block the values actually came from. `<head>` is an\n // HTML document's frontmatter: it is where `<title>` and every `<meta>` sit,\n // and a finding about the page's metadata belongs there.\n if (fenced.present) return { frontmatter, position: fencedPosition(content) };\n\n // A `<head>` parse5 synthesized carries no source location. That happens\n // whenever anything precedes `<html>` - a BOM is the common case - and it\n // used to yield a null position, which silently switched off the synthetic\n // frontmatter title: `withMetadataTitle` bails when the position is null, so\n // the document lost its top-level section and every doctype template\n // misaligned against it. The metadata is real either way, so fall back to the\n // top of the file rather than disowning it.\n const head = findHead(doc);\n return {\n frontmatter,\n position: head?.sourceCodeLocation ? positionOf(head) : origin(),\n };\n}\n\n/** Zero-width span at the top of the file, for metadata with no located block. */\nfunction origin(): Position {\n return {\n start: { line: 1, column: 1, offset: 0 },\n end: { line: 1, column: 1, offset: 0 },\n };\n}\n\n/** The document's `<head>`, when the source actually wrote one. */\nfunction findHead(doc: DefaultTreeAdapterTypes.Document): Element | undefined {\n for (const child of doc.childNodes) {\n if (!defaultTreeAdapter.isElementNode(child)) continue;\n if (tagOf(child) === \"html\") return firstElementChild(child, \"head\");\n }\n return undefined;\n}\n\nfunction parseHtml(content: string, filePath: string): DocumentTree {\n const doc = parse(content, { sourceCodeLocationInfo: true });\n const fragments: Fragment[] = [];\n walk(doc, fragments);\n\n const { frontmatter, position } = metadataOf(content, filePath, doc);\n\n return {\n format: \"html\",\n filePath,\n frontmatter,\n frontmatterPosition: position,\n sections: sectionize(\n withMetadataTitle(fragments, frontmatter, position),\n documentEnd(content),\n ),\n };\n}\n\nexport const htmlParser: DocumentParser = {\n name: \"html\",\n label: \"HTML\",\n kinds: [\n \"paragraph\",\n \"codeBlock\",\n \"list\",\n \"listItem\",\n \"table\",\n \"tableRow\",\n \"tableCell\",\n \"admonition\",\n \"image\",\n \"blockquote\",\n \"definitionList\",\n \"definitionItem\",\n ],\n extensions: [\".html\", \".htm\"],\n parse: parseHtml,\n};\n","/**\n * reStructuredText -> generic blocks.\n *\n * Unlike its siblings this parser has no AST library under it. There is no\n * usable reStructuredText parser for JavaScript, so this reads the source\n * directly: a line scanner that answers one question - what sections does this\n * document have, and what content is in each - and then hands `sectionize` the\n * same `Fragment[]` every other format produces.\n *\n * ## Section levels\n *\n * RST has no fixed heading hierarchy. A title is a line underlined, and\n * optionally also overlined, by a run of punctuation at least as long as the\n * title. Which *level* an adornment style means is discovered, not fixed:\n *\n * \"Rather than imposing a fixed number and order of section title adornment\n * styles, the order enforced will be the order as encountered.\"\n * - the reStructuredText spec, \"Sections\"\n *\n * So the first style seen is level 1, the next new style level 2, and so on -\n * `===` then `+++` then `---` is a perfectly ordinary document, and a\n * hardcoded character-to-level table would get it wrong. The spec also makes\n * over-and-underlined styles distinct from underline-only ones using the same\n * character, so the style key carries both facts (`over:=` vs `under:=`).\n *\n * Levels are clamped to 6, because `SectionNode.level` is documented 1-6; a\n * document with seven adornment styles is beyond what the templates model.\n *\n * ## What this deliberately does not handle\n *\n * This is a structural scanner, not docutils. It does not implement, and\n * silently ignores:\n *\n * - **Substitutions** (`|name|` definitions and references) - a reference is\n * flattened to its bare name, a definition is skipped with other directives.\n * - **Includes** (`.. include::`) - the referenced file is never read, so\n * sections it would contribute are invisible.\n * - **Transitions** (a lone adornment run between paragraphs) - skipped, like\n * Markdown thematic breaks.\n * - **Option lists** and **line blocks** (`|`) - skipped, not mapped onto\n * anything. **Definition lists** are mapped: a term line followed by an\n * indented definition becomes a `definitionList`/`definitionItem` pair,\n * and consecutive pairs group into one list the way blank-separated bullet\n * items do.\n * - **Doctest blocks** (`>>>`) - recognised so they are not mis-read as prose,\n * but skipped rather than emitted as `codeBlock`.\n * - **Tables** - grid (`+---+`), simple (`=== ===`), `list-table`, and\n * `csv-table` all become `table` nodes. Grid and simple tables take their\n * columns from the border itself, so a spanning cell (a row border that\n * omits one `+`, or a simple-table row that straddles a column gap) is read\n * as if it were not spanned - the rectangular case, not the general grid\n * grammar. A simple table's body is one row per physical line; only its\n * header, if it has one, merges multiple lines into one row. `list-table`\n * and `csv-table` carry a header row only when `:header-rows:` (both) or\n * `:header:` (`csv-table`) says so - without one, the table has real rows\n * and no header, which is the honest answer. A `csv-table`'s external\n * `:file:`/`:url:` source is never read, the same call `include` gets.\n * - **Block quotes** (an indented block with no `::` ahead of it) - mapped to\n * `blockquote`, its own content parsed the same way a list item's is.\n * - **Quoted literal blocks** (an unindented literal block quoted with\n * punctuation) - not recognised; read as prose.\n * - **Enumerator styles beyond `1.`/`1)`/`#.`/`#)`** - alphabetic and Roman\n * enumerators (`a.`, `iv.`) and the parenthesised `(1)` form are read as\n * prose. They are ambiguous without docutils' second-item confirmation:\n * `A. Smith wrote this` is a sentence, not a list.\n * - **Roles and inline markup** beyond a regex flattening - `flattenInline`\n * strips the common constructs; it does not implement inline parsing, does\n * not process `\\` escapes, and leaves trailing reference underscores alone\n * (stripping them would eat `snake_case`).\n * - **Tab expansion** in indentation - a tab counts as one column, where\n * docutils expands to the next multiple of eight.\n * - **East Asian width** - adornment length is compared against the title's\n * code-point count, where the spec compares display columns.\n * - **Document title promotion** - docutils promotes a lone top-level section\n * to the document title. Here it stays a level-1 section, which is what the\n * doctype templates model (a title with its subsections hanging under it).\n * - **Directive options and content semantics beyond what is listed above** -\n * `code-block`/`code`/`sourcecode` become `codeBlock`; `note`, `tip`,\n * `important`, `caution`, `warning`, and `danger` become `admonition` with\n * that word as `variant`; `image` and `figure` become `image`; `list-table`\n * and `csv-table` become `table`. `attention`, `hint`, `error`, and the\n * generic `admonition` directive also become `admonition`, but with no\n * `variant` at all - `AdmonitionNode.variant` has no six-value member for\n * them, and inventing an equivalence (`hint` as `tip`, `error` as `danger`)\n * is exactly what this parser does not do. A plain count rule still counts\n * them; a `variant:` rule reports them as a mismatch instead of a false\n * match. Every other directive is skipped whole.\n * - **Anything an unterminated fenced block would need** - a *complete* fenced\n * front matter block is cut from the body before scanning, because `---`\n * reads as a transition and the YAML under it as prose. An unterminated one\n * is not front matter, and is scanned as the RST it literally is.\n *\n * One judgement call is worth stating plainly. The spec requires an adornment\n * run to extend \"at least as far as the right edge of the title text\", and\n * that is what is enforced here: a shorter run is not a section title, and the\n * line becomes a paragraph. docutils the implementation is more forgiving - it\n * reports \"Title underline too short\" and recovers - but taking the strict\n * reading is what keeps this parser agreeing with `docmeta`'s RST extractor,\n * which applies the same rule to the document title.\n */\nimport { extractFrontmatter, extractorForExtension, locateFrontmatter } from \"../../meta/index.js\";\nimport type {\n AdmonitionNode,\n ContentNode,\n DefinitionItemNode,\n DocumentParser,\n DocumentTree,\n ListItemNode,\n ListNode,\n Point,\n Position,\n TableCellNode,\n TableNode,\n TableRowNode,\n} from \"../types.js\";\nimport type { Fragment } from \"./sectionize.js\";\nimport { sectionize } from \"./sectionize.js\";\nimport {\n fencedPosition,\n withMetadataTitle as withFrontmatterTitle,\n withoutFence,\n} from \"./metadata.js\";\n\n/** Every character the spec allows as title adornment. */\nconst ADORNMENT_CHARS = new Set(\n \"!\\\"#$%&'()*+,-./:;<=>?@[\\\\]^_`{|}~\".split(\"\"),\n);\n\n/** Explicit markup: a directive, comment, target, or substitution definition. */\nconst EXPLICIT = /^[ \\t]*\\.\\.(?:[ \\t]|$)/;\n/** A directive with a parseable name, e.g. `.. code-block:: python`. */\nconst DIRECTIVE = /^([ \\t]*)\\.\\.[ \\t]+([\\w.+:-]+)::[ \\t]*(.*)$/;\n/** Directives that carry a literal block, with the language as the argument. */\nconst CODE_DIRECTIVES = new Set([\"code\", \"code-block\", \"sourcecode\"]);\n/** Admonition directives that name one of the six variants directly. */\nconst ADMONITION_VARIANTS = new Map<string, AdmonitionNode[\"variant\"]>([\n [\"note\", \"note\"],\n [\"tip\", \"tip\"],\n [\"important\", \"important\"],\n [\"caution\", \"caution\"],\n [\"warning\", \"warning\"],\n [\"danger\", \"danger\"],\n]);\n/**\n * Every admonition directive this parser reads, variant-naming or not.\n * `attention`, `hint`, `error`, and the generic `admonition` directive still\n * become an `admonition` node - just with no `variant`, since none of the six\n * is honestly theirs. See the file header.\n */\nconst ADMONITION_DIRECTIVES = new Set([\n ...ADMONITION_VARIANTS.keys(),\n \"attention\",\n \"hint\",\n \"error\",\n \"admonition\",\n]);\n/** A field-list entry: `:name:` or `:name: value`. */\nconst FIELD = /^[ \\t]*:[^:\\s][^:]*:(?:[ \\t]|$)/;\n/** A directive option inside a directive body, e.g. `:linenos:`. */\nconst OPTION = /^[ \\t]*:[\\w-]+:(?:[ \\t].*)?$/;\n/** A directive option, capturing its key and value: `:header-rows: 1`. */\nconst OPTION_KV = /^[ \\t]*:([\\w-]+):(?:[ \\t]+(.*))?$/;\n/** A bullet-list item. The marker must be followed by whitespace or nothing. */\nconst BULLET = /^([ \\t]*)([*+-])(?:([ \\t]+)(.*))?$/;\n/** An enumerated-list item, arabic or auto (`#`), with a `.` or `)` suffix. */\nconst ENUM = /^([ \\t]*)(\\d+|#)([.)])(?:([ \\t]+)(.*))?$/;\n/** A doctest block. */\nconst DOCTEST = /^[ \\t]*>>>[ \\t]/;\n/** A grid-table border. */\nconst GRID_TABLE = /^[ \\t]*\\+[-=+]+\\+[ \\t]*$/;\n/** A simple-table border: runs of `=` (or `-`, for column spans) with gaps. */\nconst SIMPLE_TABLE = /^[ \\t]*[-=]+(?:[ \\t]+[-=]+)+[ \\t]*$/;\n\n/**\n * The source, indexed by line.\n *\n * `text` is the array the scanner reads, and it is mutable on purpose: list\n * item markers are blanked out of it *in place, space for space*, so an item's\n * body can be scanned by the same code that scans the document body without\n * re-slicing anything. Every column and offset in `starts` stays exact by\n * construction rather than by bookkeeping.\n *\n * Line terminators are stripped, and CRLF is handled here so nothing below has\n * to know about it.\n */\ninterface Source {\n text: string[];\n /** Offset of the first character of each line. */\n starts: number[];\n /** End of the document, for closing the final sections. */\n end: Point;\n}\n\nfunction indexLines(content: string): Source {\n const text: string[] = [];\n const starts: number[] = [];\n let cursor = 0;\n for (;;) {\n starts.push(cursor);\n const nl = content.indexOf(\"\\n\", cursor);\n if (nl === -1) {\n text.push(content.slice(cursor));\n break;\n }\n const hadCr = nl > cursor && content.charCodeAt(nl - 1) === 13;\n text.push(content.slice(cursor, hadCr ? nl - 1 : nl));\n cursor = nl + 1;\n }\n return {\n text,\n starts,\n end: {\n line: text.length,\n column: (text[text.length - 1] ?? \"\").length + 1,\n offset: content.length,\n },\n };\n}\n\n/** Leading whitespace width. Tabs count as one column; see the header. */\nfunction indentOf(line: string): number {\n let i = 0;\n while (i < line.length && (line[i] === \" \" || line[i] === \"\\t\")) i++;\n return i;\n}\n\nfunction isBlank(line: string | undefined): boolean {\n return (line ?? \"\").trim() === \"\";\n}\n\n/**\n * A run of one repeated adornment character starting at column 1, or null.\n *\n * One character counts. docutils only rejects a run for being short when it is\n * also shorter than the title, so `A` over `=` is a section - and a lone\n * punctuation line that underlines nothing is a too-short transition marker,\n * which docutils drops. Skipping it, which is what the caller does with any\n * adornment that started no title, is the same outcome.\n */\nfunction adornmentOf(line: string | undefined): { char: string; length: number } | null {\n const trimmed = (line ?? \"\").replace(/[ \\t]+$/, \"\");\n const char = trimmed[0];\n if (char === undefined || !ADORNMENT_CHARS.has(char)) return null;\n for (let i = 1; i < trimmed.length; i++) {\n if (trimmed[i] !== char) return null;\n }\n return { char, length: trimmed.length };\n}\n\n/**\n * Strip the inline markup a heading or paragraph is likely to carry, so a title\n * matches a template's `heading.const` and a slug reads like the rendered page.\n * A regex pass, not an inline parser - see the header for what it misses.\n */\nfunction flattenInline(text: string): string {\n return text\n .replace(/``([^`]*)``/g, \"$1\")\n .replace(/:[\\w.+:-]+:`([^`]*)`/g, \"$1\")\n .replace(/`([^`]*?)[ \\t]*<[^<>]*>`__?/g, \"$1\")\n .replace(/`([^`]*)`__?/g, \"$1\")\n .replace(/`([^`]*)`/g, \"$1\")\n .replace(/\\*\\*([^*]+)\\*\\*/g, \"$1\")\n .replace(/\\*([^*]+)\\*/g, \"$1\")\n .replace(/\\|([^|\\s][^|]*)\\|/g, \"$1\")\n .trim();\n}\n\n/** Point at the start of `line`'s column `column` (1-based). */\nfunction pointAt(src: Source, line: number, column: number): Point {\n return {\n line: line + 1,\n column,\n offset: (src.starts[line] ?? 0) + column - 1,\n };\n}\n\n/**\n * Span of the source lines `first..last` inclusive, ending just past the last\n * non-whitespace character - the convention mdast uses, so a block's end never\n * runs into the heading that follows it.\n */\nfunction spanOf(src: Source, first: number, last: number, startColumn?: number): Position {\n const firstLine = src.text[first] ?? \"\";\n const lastLine = (src.text[last] ?? \"\").replace(/[ \\t]+$/, \"\");\n return {\n start: pointAt(src, first, startColumn ?? indentOf(firstLine) + 1),\n end: pointAt(src, last, lastLine.length + 1),\n };\n}\n\n/** A section title found at a line, with the adornment style that marked it. */\ninterface TitleHit {\n title: string;\n /** Style key; over-and-underlined is distinct from underline-only. */\n style: string;\n /** First line of the construct (the overline, or the title text). */\n first: number;\n /** Last line of the construct (always the underline). */\n last: number;\n}\n\n/**\n * A section title starting at `line`, or null.\n *\n * Both forms are checked: overline / text / matching underline, and text /\n * underline. The adornment must be at least as long as the title text, and an\n * overline must match its underline in both character and length - what the\n * spec requires, and what `docmeta`'s RST extractor enforces for the doctitle.\n */\nfunction titleAt(src: Source, line: number, limit: number): TitleHit | null {\n const over = adornmentOf(src.text[line]);\n if (over) {\n if (line + 2 >= limit) return null;\n const text = src.text[line + 1] ?? \"\";\n const under = adornmentOf(src.text[line + 2]);\n const title = flattenInline(text);\n if (\n title !== \"\" &&\n adornmentOf(text) === null &&\n under !== null &&\n under.char === over.char &&\n under.length === over.length &&\n over.length >= text.trim().length\n ) {\n return { title, style: `over:${over.char}`, first: line, last: line + 2 };\n }\n // A lone run is a transition, and a mismatched pair is not a title.\n return null;\n }\n\n if (line + 1 >= limit) return null;\n const text = src.text[line] ?? \"\";\n if (text.trim() === \"\" || indentOf(text) > 0) return null;\n const under = adornmentOf(src.text[line + 1]);\n if (under === null || under.length < text.trim().length) return null;\n const title = flattenInline(text);\n if (title === \"\") return null;\n return { title, style: `under:${under.char}`, first: line, last: line + 1 };\n}\n\n/**\n * End of an indented block opened at `from`: the first line at or after `from`\n * whose indent is at or below `base` and which is not blank. Returns the\n * exclusive end, trimmed of trailing blank lines.\n */\nfunction indentedBlockEnd(src: Source, from: number, to: number, base: number): number {\n let i = from;\n let last = from - 1;\n while (i < to) {\n const line = src.text[i] ?? \"\";\n if (isBlank(line)) {\n i++;\n continue;\n }\n if (indentOf(line) <= base) break;\n last = i;\n i++;\n }\n return last + 1;\n}\n\n/** The lines `from..to` with their common indent removed, joined by newlines. */\nfunction dedent(src: Source, from: number, to: number): string {\n let common = Infinity;\n for (let i = from; i < to; i++) {\n const line = src.text[i] ?? \"\";\n if (!isBlank(line)) common = Math.min(common, indentOf(line));\n }\n if (!Number.isFinite(common)) common = 0;\n const out: string[] = [];\n for (let i = from; i < to; i++) {\n const line = src.text[i] ?? \"\";\n out.push(isBlank(line) ? \"\" : line.slice(common).replace(/[ \\t]+$/, \"\"));\n }\n return out.join(\"\\n\").replace(/\\n+$/, \"\");\n}\n\n/** Last non-blank line in `from..to`, or `from - 1` when there is none. */\nfunction lastContentLine(src: Source, from: number, to: number): number {\n for (let i = to - 1; i >= from; i--) {\n if (!isBlank(src.text[i])) return i;\n }\n return from - 1;\n}\n\n/** Scanner state that outlives one range: the adornment styles seen so far. */\ninterface Levels {\n styles: string[];\n}\n\nfunction levelFor(levels: Levels, style: string): number {\n let index = levels.styles.indexOf(style);\n if (index === -1) {\n levels.styles.push(style);\n index = levels.styles.length - 1;\n }\n return Math.min(index + 1, 6);\n}\n\n/** A directive's `:key: value` option block, read up to the first non-option line. */\nfunction readOptions(\n src: Source,\n from: number,\n to: number,\n): { options: Record<string, string>; next: number } {\n const options: Record<string, string> = {};\n let i = from;\n while (i < to) {\n const match = OPTION_KV.exec(src.text[i] ?? \"\");\n if (!match) break;\n const key = (match[1] ?? \"\").toLowerCase();\n options[key] = (match[2] ?? \"\").trim();\n i++;\n }\n return { options, next: i };\n}\n\n/** First content line of a directive body, after its options and any blank lines. */\nfunction directiveContentStart(src: Source, from: number, to: number): number {\n const { next } = readOptions(src, from, to);\n let start = next;\n while (start < to && isBlank(src.text[start])) start++;\n return start;\n}\n\n/** Index of every `+` in a grid-table border line - the table's column edges. */\nfunction gridColumns(border: string): number[] {\n const cols: number[] = [];\n for (let i = 0; i < border.length; i++) {\n if (border[i] === \"+\") cols.push(i);\n }\n return cols;\n}\n\n/** The substrings a grid-table content line holds between `cols`' column edges. */\nfunction gridCells(line: string, cols: number[]): string[] {\n const cells: string[] = [];\n for (let k = 0; k < cols.length - 1; k++) {\n const start = (cols[k] ?? 0) + 1;\n const end = cols[k + 1] ?? line.length;\n cells.push(line.slice(start, end));\n }\n return cells;\n}\n\n/**\n * A grid table (`+---+---+` borders), read from its top border at `from`.\n *\n * Column edges come from the top border alone, so a row whose own border omits\n * a `+` (a spanning cell) is read as if it were not spanned - see the file\n * header. A row is `header: true` when the border that closes it carries `=`.\n */\nfunction parseGridTable(src: Source, from: number, to: number): { node: TableNode; next: number } {\n let end = from;\n while (end < to && !isBlank(src.text[end])) end++;\n\n const cols = gridColumns(src.text[from] ?? \"\");\n const rows: TableRowNode[] = [];\n let current: number[] = [];\n\n const flush = (header: boolean): void => {\n if (current.length === 0) return;\n const first = current[0] ?? from;\n const last = current[current.length - 1] ?? first;\n const perColumn: string[][] = cols.slice(0, -1).map(() => []);\n for (const lineIdx of current) {\n const cells = gridCells(src.text[lineIdx] ?? \"\", cols);\n cells.forEach((text, idx) => perColumn[idx]?.push(text));\n }\n const cellNodes: TableCellNode[] = perColumn.map((lines) => {\n const text = flattenInline(lines.join(\" \").trim());\n return {\n kind: \"tableCell\",\n position: spanOf(src, first, last),\n text,\n children: text === \"\" ? [] : [{ kind: \"paragraph\", position: spanOf(src, first, last), text }],\n };\n });\n rows.push({\n kind: \"tableRow\",\n header,\n position: spanOf(src, first, last),\n text: cellNodes.map((c) => c.text).join(\" | \"),\n children: cellNodes,\n });\n current = [];\n };\n\n for (let i = from + 1; i < end; i++) {\n const line = src.text[i] ?? \"\";\n if (GRID_TABLE.test(line)) {\n flush(/=/.test(line));\n continue;\n }\n current.push(i);\n }\n flush(false);\n\n const last = lastContentLine(src, from, end);\n return {\n node: {\n kind: \"table\",\n position: spanOf(src, from, Math.max(last, from)),\n text: rows.map((r) => r.text).join(\"\\n\"),\n children: rows,\n },\n next: end,\n };\n}\n\n/** Column spans (`[start, end)`) from a simple-table border's `=`/`-` runs. */\nfunction simpleColumns(border: string): [number, number][] {\n const spans: [number, number][] = [];\n const re = /[-=]+/g;\n let match: RegExpExecArray | null;\n while ((match = re.exec(border)) !== null) {\n spans.push([match.index, match.index + match[0].length]);\n }\n return spans;\n}\n\n/** One simple-table row, built from one or more physical lines over `spans`. */\nfunction simpleRow(\n src: Source,\n lines: number[],\n spans: [number, number][],\n header: boolean,\n): TableRowNode {\n const first = lines[0] ?? 0;\n const last = lines[lines.length - 1] ?? first;\n const perColumn: string[][] = spans.map(() => []);\n for (const lineIdx of lines) {\n const raw = src.text[lineIdx] ?? \"\";\n spans.forEach(([start, endCol], idx) => {\n const isLast = idx === spans.length - 1;\n perColumn[idx]?.push(raw.slice(start, isLast ? raw.length : endCol));\n });\n }\n const cells: TableCellNode[] = perColumn.map((columnLines) => {\n const text = flattenInline(columnLines.join(\" \").trim());\n return {\n kind: \"tableCell\",\n position: spanOf(src, first, last),\n text,\n children: text === \"\" ? [] : [{ kind: \"paragraph\", position: spanOf(src, first, last), text }],\n };\n });\n return {\n kind: \"tableRow\",\n header,\n position: spanOf(src, first, last),\n text: cells.map((c) => c.text).join(\" | \"),\n children: cells,\n };\n}\n\n/**\n * A simple table (`=== ===` rules), read from its top border at `from`.\n *\n * One physical line is one row, with one exception: every line between the\n * top border and the header separator, if there is one, merges into a single\n * multi-line header row. Without a header separator, the table has no header.\n */\nfunction parseSimpleTable(src: Source, from: number, to: number): { node: TableNode; next: number } {\n let end = from;\n while (end < to && !isBlank(src.text[end])) end++;\n\n const spans = simpleColumns(src.text[from] ?? \"\");\n const borders: number[] = [];\n for (let i = from; i < end; i++) {\n if (SIMPLE_TABLE.test(src.text[i] ?? \"\")) borders.push(i);\n }\n const top = borders[0] ?? from;\n const bottom = borders[borders.length - 1] ?? end - 1;\n const interior = borders.filter((idx) => idx !== top && idx !== bottom);\n const headerSep = interior[0];\n\n const headerLines: number[] = [];\n const bodyLines: number[] = [];\n for (let i = top + 1; i < bottom; i++) {\n if (interior.includes(i)) continue;\n if (headerSep !== undefined && i < headerSep) headerLines.push(i);\n else bodyLines.push(i);\n }\n\n const rows: TableRowNode[] = [];\n if (headerLines.length > 0) rows.push(simpleRow(src, headerLines, spans, true));\n for (const lineIdx of bodyLines) rows.push(simpleRow(src, [lineIdx], spans, false));\n\n const last = lastContentLine(src, from, end);\n return {\n node: {\n kind: \"table\",\n position: spanOf(src, from, Math.max(last, from)),\n text: rows.map((r) => r.text).join(\"\\n\"),\n children: rows,\n },\n next: end,\n };\n}\n\n/**\n * A `csv-table`'s own naive split: comma-delimited, `\"`-quoted fields with\n * `\"\"` as an escaped quote. Not the general CSV grammar, just enough for the\n * directive's inline rows.\n */\nfunction splitCsvLine(line: string): string[] {\n const fields: string[] = [];\n let field = \"\";\n let quoted = false;\n let i = 0;\n while (i < line.length) {\n const ch = line[i];\n // `i < line.length` already guarantees this, but `noUncheckedIndexedAccess`\n // cannot see it, and a `?? \"\"` fallback would silently swallow a real\n // bounds bug instead of ending the scan.\n if (ch === undefined) break;\n if (quoted) {\n if (ch === '\"') {\n if (line[i + 1] === '\"') {\n field += '\"';\n i += 2;\n continue;\n }\n quoted = false;\n i++;\n continue;\n }\n field += ch;\n i++;\n continue;\n }\n if (ch === '\"' && field.trim() === \"\") {\n quoted = true;\n i++;\n continue;\n }\n if (ch === \",\") {\n fields.push(field.trim());\n field = \"\";\n i++;\n continue;\n }\n field += ch;\n i++;\n }\n fields.push(field.trim());\n return fields;\n}\n\n/** One `csv-table` row, from already-split fields. */\nfunction csvRow(src: Source, lineIdx: number, fields: string[], header: boolean): TableRowNode {\n const cells: TableCellNode[] = fields.map((field) => {\n const text = flattenInline(field);\n return {\n kind: \"tableCell\",\n position: spanOf(src, lineIdx, lineIdx),\n text,\n children: text === \"\" ? [] : [{ kind: \"paragraph\", position: spanOf(src, lineIdx, lineIdx), text }],\n };\n });\n return {\n kind: \"tableRow\",\n header,\n position: spanOf(src, lineIdx, lineIdx),\n text: cells.map((c) => c.text).join(\" | \"),\n children: cells,\n };\n}\n\n/**\n * Scan `from..to` at indent `base` into ordered blocks.\n *\n * `headings` is false inside a list item: RST section titles only occur at the\n * document's own indent, and a heading emitted from inside an item would break\n * the fold.\n */\nfunction scanRange(\n src: Source,\n levels: Levels,\n from: number,\n to: number,\n base: number,\n headings: boolean,\n): Fragment[] {\n const fragments: Fragment[] = [];\n const content = (node: ContentNode): void => {\n fragments.push({ type: \"content\", node });\n };\n let i = from;\n\n while (i < to) {\n const line = src.text[i] ?? \"\";\n\n if (isBlank(line)) {\n i++;\n continue;\n }\n\n if (headings) {\n const hit = titleAt(src, i, to);\n if (hit) {\n fragments.push({\n type: \"heading\",\n level: levelFor(levels, hit.style),\n title: hit.title,\n position: spanOf(src, hit.first, hit.last),\n });\n i = hit.last + 1;\n continue;\n }\n }\n\n // `::` alone is the expanded form of the literal-block marker, and it also\n // reads as a two-character run of `:`. The marker wins: an adornment of\n // colons could only ever underline a title one or two characters wide.\n if (line.trim() === \"::\") {\n i = readParagraph(src, levels, fragments, i, to, base, headings);\n continue;\n }\n\n // A run of adornment that did not start a title is a transition, or the\n // stray underline of something that was not one. Either way, not content.\n if (adornmentOf(line) !== null) {\n i++;\n continue;\n }\n\n const lineIndent = indentOf(line);\n\n // Explicit markup: a directive, a comment, a target, or a substitution\n // definition. Some directives become a node of their own; every other\n // directive, comment, target, and substitution definition is skipped\n // whole - see the file header for exactly which.\n if (EXPLICIT.test(line)) {\n const bodyEnd = indentedBlockEnd(src, i + 1, to, lineIndent);\n const directive = DIRECTIVE.exec(line);\n const name = directive?.[2]?.toLowerCase();\n\n if (name && CODE_DIRECTIVES.has(name)) {\n const lang = (directive?.[3] ?? \"\").trim();\n // Drop the directive's own options (`:linenos:` and friends) before the\n // body; they are configuration, not code.\n let codeStart = i + 1;\n while (codeStart < bodyEnd && OPTION.test(src.text[codeStart] ?? \"\")) codeStart++;\n while (codeStart < bodyEnd && isBlank(src.text[codeStart])) codeStart++;\n const codeEnd = lastContentLine(src, codeStart, bodyEnd) + 1;\n content({\n kind: \"codeBlock\",\n position: spanOf(src, i, Math.max(codeEnd - 1, i)),\n text: codeStart < codeEnd ? dedent(src, codeStart, codeEnd) : \"\",\n ...(lang ? { language: lang } : {}),\n });\n } else if (name && ADMONITION_DIRECTIVES.has(name)) {\n const variant = ADMONITION_VARIANTS.get(name);\n const start = directiveContentStart(src, i + 1, bodyEnd);\n const children =\n start < bodyEnd\n ? scanRange(src, levels, start, bodyEnd, indentOf(src.text[start] ?? \"\"), false)\n .filter((f): f is Extract<Fragment, { type: \"content\" }> => f.type === \"content\")\n .map((f) => f.node)\n : [];\n const last = lastContentLine(src, i, bodyEnd);\n content({\n kind: \"admonition\",\n position: spanOf(src, i, Math.max(last, i)),\n text: children.map((c) => c.text).join(\"\\n\"),\n ...(variant ? { variant } : {}),\n children,\n });\n } else if (name === \"image\" || name === \"figure\") {\n const url = (directive?.[3] ?? \"\").trim();\n if (url) {\n const { options } = readOptions(src, i + 1, bodyEnd);\n const alt = options[\"alt\"] ?? \"\";\n const last = lastContentLine(src, i, bodyEnd);\n content({\n kind: \"image\",\n position: spanOf(src, i, Math.max(last, i)),\n text: alt,\n url,\n alt,\n });\n }\n } else if (name === \"list-table\") {\n const start = directiveContentStart(src, i + 1, bodyEnd);\n if (start < bodyEnd) {\n const { options } = readOptions(src, i + 1, bodyEnd);\n const headerRows = Number.parseInt(options[\"header-rows\"] ?? \"\", 10) || 0;\n const rowsFragment = scanRange(\n src,\n levels,\n start,\n bodyEnd,\n indentOf(src.text[start] ?? \"\"),\n false,\n ).find(\n (f): f is Extract<Fragment, { type: \"content\" }> =>\n f.type === \"content\" && f.node.kind === \"list\",\n );\n if (rowsFragment && rowsFragment.node.kind === \"list\") {\n const rows: TableRowNode[] = rowsFragment.node.items.map((item, index) => {\n const cellsList = item.children.find((c): c is ListNode => c.kind === \"list\");\n const cells: TableCellNode[] = (cellsList?.items ?? []).map((cellItem) => ({\n kind: \"tableCell\",\n position: cellItem.position,\n text: cellItem.text,\n children: cellItem.children,\n }));\n return {\n kind: \"tableRow\",\n header: index < headerRows,\n position: item.position,\n text: cells.map((c) => c.text).join(\" | \"),\n children: cells,\n };\n });\n const last = lastContentLine(src, i, bodyEnd);\n content({\n kind: \"table\",\n position: spanOf(src, i, Math.max(last, i)),\n text: rows.map((r) => r.text).join(\"\\n\"),\n children: rows,\n });\n }\n }\n } else if (name === \"csv-table\") {\n const { options } = readOptions(src, i + 1, bodyEnd);\n const bodyStart = directiveContentStart(src, i + 1, bodyEnd);\n const rowLines: number[] = [];\n for (let li = bodyStart; li < bodyEnd; li++) {\n if (!isBlank(src.text[li])) rowLines.push(li);\n }\n const headerOption = options[\"header\"];\n if (rowLines.length > 0 || headerOption !== undefined) {\n const headerRows = Number.parseInt(options[\"header-rows\"] ?? \"\", 10) || 0;\n const rows: TableRowNode[] = [];\n if (headerOption !== undefined) {\n rows.push(csvRow(src, i, splitCsvLine(headerOption), true));\n }\n rowLines.forEach((lineIdx, index) => {\n rows.push(csvRow(src, lineIdx, splitCsvLine(src.text[lineIdx] ?? \"\"), index < headerRows));\n });\n const last = lastContentLine(src, i, bodyEnd);\n content({\n kind: \"table\",\n position: spanOf(src, i, Math.max(last, i)),\n text: rows.map((r) => r.text).join(\"\\n\"),\n children: rows,\n });\n }\n }\n i = Math.max(bodyEnd, i + 1);\n continue;\n }\n\n // Field lists (docinfo, and bibliographic fields) are metadata, read\n // separately by `readMetadata`. Never body content.\n if (FIELD.test(line) && lineIndent === base) {\n i = Math.max(indentedBlockEnd(src, i + 1, to, lineIndent), i + 1);\n while (i < to && FIELD.test(src.text[i] ?? \"\") && indentOf(src.text[i] ?? \"\") === base) {\n i = Math.max(indentedBlockEnd(src, i + 1, to, lineIndent), i + 1);\n }\n continue;\n }\n\n if (DOCTEST.test(line)) {\n // Consume the run of non-blank lines the construct occupies.\n let end = i;\n while (end < to && !isBlank(src.text[end])) end++;\n i = end;\n continue;\n }\n\n if (GRID_TABLE.test(line)) {\n const table = parseGridTable(src, i, to);\n content(table.node);\n i = table.next;\n continue;\n }\n\n if (SIMPLE_TABLE.test(line)) {\n const table = parseSimpleTable(src, i, to);\n content(table.node);\n i = table.next;\n continue;\n }\n\n // An indented block with no `::` ahead of it is a block quote. Its own\n // content is parsed the same way a list item's body is.\n if (lineIndent > base) {\n const bqEnd = indentedBlockEnd(src, i, to, base);\n const children = scanRange(src, levels, i, bqEnd, lineIndent, false)\n .filter((f): f is Extract<Fragment, { type: \"content\" }> => f.type === \"content\")\n .map((f) => f.node);\n const last = lastContentLine(src, i, bqEnd);\n content({\n kind: \"blockquote\",\n position: spanOf(src, i, Math.max(last, i)),\n text: children.map((c) => c.text).join(\"\\n\"),\n children,\n });\n i = Math.max(bqEnd, i + 1);\n continue;\n }\n\n const bullet = BULLET.exec(line);\n if (bullet && indentOf(line) === base && bulletHasBody(bullet, src, i, to, base)) {\n const list = parseList(src, levels, i, to, base, false);\n content(list.node);\n i = list.next;\n continue;\n }\n\n const enumerated = ENUM.exec(line);\n if (enumerated && indentOf(line) === base && bulletHasBody(enumerated, src, i, to, base)) {\n const list = parseList(src, levels, i, to, base, true);\n content(list.node);\n i = list.next;\n continue;\n }\n\n // A term whose next line is indented is a definition list, not a paragraph\n // followed by a block quote.\n const next = src.text[i + 1];\n if (i + 1 < to && !isBlank(next) && indentOf(next ?? \"\") > base) {\n const dl = parseDefinitionList(src, levels, i, to, base);\n content(dl.node);\n i = dl.next;\n continue;\n }\n\n i = readParagraph(src, levels, fragments, i, to, base, headings);\n }\n\n return fragments;\n}\n\n/**\n * Does a matched list marker actually open an item?\n *\n * A marker with text after it always does. A bare marker opens one only when an\n * indented block follows, which is what separates an empty list item from a\n * line that merely starts with a hyphen.\n */\nfunction bulletHasBody(\n match: RegExpExecArray,\n src: Source,\n line: number,\n to: number,\n base: number,\n): boolean {\n // The content group is 4 for `BULLET` and 5 for `ENUM`, which has the extra\n // suffix group. Checking both is cheaper than threading the pattern's shape\n // through: only one of the two is ever a content group, and the other is\n // whitespace or undefined.\n if ((match[4] ?? \"\").trim() !== \"\" || (match[5] ?? \"\").trim() !== \"\") return true;\n for (let i = line + 1; i < to; i++) {\n const next = src.text[i] ?? \"\";\n if (isBlank(next)) continue;\n return indentOf(next) > base;\n }\n return false;\n}\n\n/** The marker text and the column its content starts at, for one item line. */\ninterface Marker {\n /** Width of the marker plus the whitespace after it. */\n width: number;\n /** Indent the item's body sits at. */\n contentIndent: number;\n}\n\nfunction markerOf(match: RegExpExecArray, ordered: boolean): Marker {\n const indent = (match[1] ?? \"\").length;\n const marker = ordered ? `${match[2] ?? \"\"}${match[3] ?? \"\"}` : (match[2] ?? \"\");\n const gap = (ordered ? match[4] : match[3]) ?? \" \";\n return { width: marker.length + gap.length, contentIndent: indent + marker.length + gap.length };\n}\n\n/**\n * Parse the run of list items starting at `from`.\n *\n * Each item's marker is blanked out of `src.text` - replaced by exactly as many\n * spaces - so the item body is an ordinary indented block that `scanRange` can\n * read with no special case. Offsets and columns are untouched by construction.\n */\nfunction parseList(\n src: Source,\n levels: Levels,\n from: number,\n to: number,\n base: number,\n ordered: boolean,\n): { node: ContentNode; next: number } {\n const pattern = ordered ? ENUM : BULLET;\n // `parseList` is only entered on a line that already matched, so the miss\n // falls through to the same defaults a matched line with no marker group\n // would have taken.\n const firstMatch = pattern.exec(src.text[from] ?? \"\");\n const markerChar = ordered ? (firstMatch?.[3] ?? \".\") : (firstMatch?.[2] ?? \"*\");\n const items: ListItemNode[] = [];\n // Where the list ends, excluding the blank lines between items - those belong\n // to whatever follows, so a list before a heading does not swallow the gap.\n let end = from;\n let i = from;\n\n while (i < to) {\n // Items may be separated by blank lines; the list ends at the first\n // non-blank line that is not another item at this indent.\n let start = i;\n while (start < to && isBlank(src.text[start])) start++;\n if (start >= to) break;\n\n const line = src.text[start] ?? \"\";\n if (indentOf(line) !== base) break;\n const match = pattern.exec(line);\n if (!match) break;\n // docutils ends a list when the marker style changes; so do we. The\n // defaults match `markerChar`'s above: a different fallback here would end\n // the list after its first item rather than read the style as unchanged.\n const thisChar = ordered ? (match[3] ?? \".\") : (match[2] ?? \"*\");\n if (thisChar !== markerChar) break;\n if (!bulletHasBody(match, src, start, to, base)) break;\n\n const marker = markerOf(match, ordered);\n // Blank the marker in place. Same length, so `starts` stays exact.\n src.text[start] = \" \".repeat(marker.contentIndent) + line.slice(marker.contentIndent);\n\n const bodyEnd = Math.max(indentedBlockEnd(src, start + 1, to, base), start + 1);\n const last = lastContentLine(src, start, bodyEnd);\n const children = scanRange(src, levels, start, bodyEnd, marker.contentIndent, false)\n .filter((b): b is Extract<Fragment, { type: \"content\" }> => b.type === \"content\")\n .map((b) => b.node);\n\n items.push({\n kind: \"listItem\",\n position: spanOf(src, start, Math.max(last, start), base + 1),\n text: children.map((c) => c.text).join(\"\\n\"),\n children,\n });\n i = bodyEnd;\n end = bodyEnd;\n }\n\n const last = lastContentLine(src, from, end);\n return {\n node: {\n kind: \"list\",\n position: spanOf(src, from, Math.max(last, from), base + 1),\n text: items.map((item) => item.text).join(\"\\n\"),\n ordered,\n items,\n },\n next: Math.max(i, from + 1),\n };\n}\n\n/**\n * A run of term/definition pairs starting at `from`: an unindented term line\n * immediately followed by an indented definition. Items may be separated by\n * blank lines, the same tolerance `parseList` gives bulleted items.\n */\nfunction parseDefinitionList(\n src: Source,\n levels: Levels,\n from: number,\n to: number,\n base: number,\n): { node: ContentNode; next: number } {\n const items: DefinitionItemNode[] = [];\n let i = from;\n let end = from;\n\n while (i < to) {\n let start = i;\n while (start < to && isBlank(src.text[start])) start++;\n if (start >= to) break;\n\n const line = src.text[start] ?? \"\";\n if (indentOf(line) !== base) break;\n const next = src.text[start + 1];\n if (start + 1 >= to || isBlank(next) || indentOf(next ?? \"\") <= base) break;\n\n const term = flattenInline(line.trim());\n const defStart = start + 1;\n const defIndent = indentOf(next ?? \"\");\n const defEnd = Math.max(indentedBlockEnd(src, defStart, to, base), defStart);\n const last = lastContentLine(src, start, defEnd);\n const definition = scanRange(src, levels, defStart, defEnd, defIndent, false)\n .filter((f): f is Extract<Fragment, { type: \"content\" }> => f.type === \"content\")\n .map((f) => f.node);\n\n items.push({\n kind: \"definitionItem\",\n position: spanOf(src, start, Math.max(last, start)),\n text: [term, ...definition.map((d) => d.text)].join(\"\\n\"),\n term,\n definition,\n });\n i = defEnd;\n end = defEnd;\n }\n\n const last = lastContentLine(src, from, end);\n return {\n node: {\n kind: \"definitionList\",\n position: spanOf(src, from, Math.max(last, from)),\n text: items.map((item) => item.text).join(\"\\n\"),\n children: items,\n },\n next: Math.max(i, from + 1),\n };\n}\n\n/**\n * Read one paragraph, and the literal block it may introduce.\n *\n * A paragraph ending in `::` opens a literal block: the indented block after\n * it becomes `code`, and the `::` is stripped from the paragraph's own text the\n * way docutils strips it - removed entirely when the paragraph is only `::` or\n * when whitespace precedes it, and collapsed to one colon otherwise.\n */\nfunction readParagraph(\n src: Source,\n levels: Levels,\n fragments: Fragment[],\n from: number,\n to: number,\n base: number,\n headings: boolean,\n): number {\n let end = from;\n while (end < to) {\n const line = src.text[end] ?? \"\";\n if (isBlank(line)) break;\n if (end > from) {\n // A line whose successor underlines it ends the paragraph and starts a\n // section, and a construct of any other kind ends it too.\n if (headings && titleAt(src, end, to)) break;\n if (adornmentOf(line) !== null) break;\n if (EXPLICIT.test(line)) break;\n if (indentOf(line) !== base) break;\n if (GRID_TABLE.test(line) || SIMPLE_TABLE.test(line) || DOCTEST.test(line)) break;\n }\n end++;\n }\n\n const rawText = flattenInline(\n src.text\n .slice(from, end)\n .map((l) => l.trim())\n .join(\"\\n\"),\n );\n const literal = /::$/.test(rawText);\n const text = !literal\n ? rawText\n : rawText === \"::\"\n ? \"\" // A paragraph that is only `::` is the marker, and nothing else.\n : rawText.replace(/(\\s*)::$/, (_m, space: string) => (space === \"\" ? \":\" : \"\"));\n\n if (text.trim() !== \"\") {\n fragments.push({\n type: \"content\",\n node: { kind: \"paragraph\", position: spanOf(src, from, end - 1), text },\n });\n }\n\n if (!literal) return end;\n\n // The literal block is the next indented block, after any blank lines.\n let start = end;\n while (start < to && isBlank(src.text[start])) start++;\n if (start >= to || indentOf(src.text[start] ?? \"\") <= base) return end;\n\n const blockEnd = indentedBlockEnd(src, start, to, base);\n const last = lastContentLine(src, start, blockEnd);\n fragments.push({\n type: \"content\",\n node: {\n kind: \"codeBlock\",\n position: spanOf(src, start, Math.max(last, start)),\n text: dedent(src, start, blockEnd),\n },\n });\n return Math.max(blockEnd, end);\n}\n\n/**\n * Span of the native docinfo block: the leading field list, or - when a page\n * carries only a title - the title line docmeta read it from.\n *\n * docmeta reports the block's start line but not its extent, and we are already\n * holding a line index, so the span is cheaper to recover here than to ask for.\n */\nfunction docinfoPosition(src: Source): Position | null {\n const limit = src.text.length;\n let i = 0;\n while (i < limit && isBlank(src.text[i])) i++;\n\n const hit = titleAt(src, i, limit);\n if (hit) i = hit.last + 1;\n while (i < limit && isBlank(src.text[i])) i++;\n\n const fieldStart = i;\n while (i < limit && FIELD.test(src.text[i] ?? \"\") && indentOf(src.text[i] ?? \"\") === 0) {\n i = Math.max(indentedBlockEnd(src, i + 1, limit, 0), i + 1);\n }\n if (i > fieldStart) return spanOf(src, fieldStart, i - 1);\n if (hit) return spanOf(src, hit.first, hit.last);\n return null;\n}\n\ninterface Metadata {\n frontmatter: Record<string, unknown> | null;\n position: Position | null;\n /**\n * First body line, 0-based. Non-zero only for a fenced block, whose lines\n * would otherwise be scanned as prose - `---` as a transition and the YAML\n * under it as a paragraph, which opens an implicit lead section and hands the\n * template's top-level slot the wrong thing. A docinfo field list needs no\n * such cut: it is inside the body, and the scanner skips field lists.\n */\n bodyStart: number;\n}\n\n/**\n * Read the page's metadata, from both places an RST page can put it.\n *\n * `extractFrontmatter(content, \"rst\")` - the call `markdown.ts` makes - reads\n * only a *fenced* block; its format argument is a label copied onto the result,\n * not a dispatch. On its own it would leave every page using the native docinfo\n * field list unrouted, and that field list is how RST authors actually declare\n * `:type: how-to`. The RST-aware reading lives in docmeta's extractor registry,\n * so both are read and merged.\n *\n * A fenced block wins a key collision: it is the author being deliberate about\n * metadata, where a docinfo `title` is often just the document's own heading\n * read a second time. `present` is the OR of the two - the same shape the HTML\n * parser landed on, so the formats stay consistent.\n *\n * That docinfo `title` is worth knowing about. In RST the page title genuinely\n * *is* the first section title, so a page with a title and no fields comes back\n * with non-null `frontmatter` holding just that. Nothing downstream is misled -\n * routing reads `type` and `$template` - and taking docmeta's answer verbatim\n * keeps one source of truth for what a format's metadata is.\n */\nfunction readMetadata(content: string, filePath: string, src: Source): Metadata {\n const fenced = extractFrontmatter(content, \"rst\");\n // Read the docinfo field list from the fence-free remainder: docmeta's reST\n // extractor returns the fence and stops when one is present, so asking it\n // about the whole file would discard `:type:` on any page that has both.\n const native = extractorForExtension(\".rst\")?.extract(\n fenced.present ? withoutFence(content) : content,\n filePath,\n );\n\n if (!fenced.present && !native?.present) {\n return { frontmatter: null, position: null, bodyStart: 0 };\n }\n\n const loc = fenced.present ? locateFrontmatter(content) : null;\n return {\n frontmatter: {\n ...(native?.present ? native.data : {}),\n ...(fenced.present ? fenced.data : {}),\n },\n position: fenced.present ? fencedPosition(content) : docinfoPosition(src),\n // `findIndex` returns -1 when no line starts at or after the closing fence,\n // i.e. the fence is the last thing in the file. `Math.max(-1, 0)` used to\n // launder that into line 0, restarting the scan inside the frontmatter and\n // reading the YAML as body prose - the exact thing `bodyStart` exists to\n // prevent. There is no body in that case, so start past the last line.\n bodyStart: loc\n ? (() => {\n const i = src.starts.findIndex((start) => start >= loc.closeEnd);\n return i === -1 ? src.starts.length : i;\n })()\n : 0,\n };\n}\n\nexport const rstParser: DocumentParser = {\n name: \"rst\",\n label: \"reStructuredText\",\n kinds: [\n \"paragraph\",\n \"codeBlock\",\n \"list\",\n \"listItem\",\n \"table\",\n \"tableRow\",\n \"tableCell\",\n \"admonition\",\n \"image\",\n \"blockquote\",\n \"definitionList\",\n \"definitionItem\",\n ],\n extensions: [\".rst\"],\n parse(content, filePath): DocumentTree {\n const src = indexLines(content);\n // Order is load-bearing: `readMetadata` must run before `scanRange`.\n // `scanRange` blanks consumed list lines in `src.text` in place so a later\n // pass cannot re-read them, and `docinfoPosition` inside `readMetadata`\n // reads those same lines to place the metadata span. Swapped, the docinfo\n // field list is already blank and every metadata position collapses.\n const { frontmatter, position, bodyStart } = readMetadata(content, filePath, src);\n const fragments = scanRange(\n src,\n { styles: [] },\n Math.max(bodyStart, 0),\n src.text.length,\n 0,\n true,\n );\n\n return {\n format: \"rst\",\n filePath,\n frontmatter,\n frontmatterPosition: position,\n sections: sectionize(\n withFrontmatterTitle(fragments, frontmatter, position),\n src.end,\n ),\n };\n },\n};\n","/**\n * XML -> generic blocks, through a declarative vocabulary mapping.\n *\n * ADR 01001 puts XML last \"because structure comes from the document's own\n * element nesting and needs a small per-vocabulary mapping\". This is that\n * mapping, and the reason it exists: XML has no headings. Markdown says `##`,\n * AsciiDoc says `==`, HTML says `<h2>` - one universal rule each. XML says\n * whatever its schema says. DITA nests `<topic>`/`<section>` and titles them\n * with `<title>`; DocBook nests `<chapter>`/`<section>`/`<sect1>` and titles\n * them with `<title>` too, but calls a paragraph `<para>` where DITA calls it\n * `<p>`; a house schema calls them something else again. Hardcoding DITA would\n * make \"the XML parser\" a lie.\n *\n * ## The mapping\n *\n * An `XmlVocabulary` sorts element names into four buckets and says nothing\n * about anything else:\n *\n * - `sections` open a section, titled by the first `titles` element among\n * their children (or inside a `titleWrappers` child, which is\n * how DocBook 5 hides `<title>` in `<info>`).\n * - `transparent` are structural wrappers with no meaning of their own -\n * DITA's `<body>`, `<taskbody>`, `<context>`. The walk passes\n * straight through them at the same level.\n * - `paragraphs` / `code` / `unorderedLists` / `orderedLists` / `listItems` /\n * `tables` / `admonitions` / `images` / `blockquotes` /\n * `definitionLists` are the format-neutral content kinds of\n * `types.ts`. The last five are optional buckets: a vocabulary\n * that leaves one out never emits that kind, same as leaving\n * an entry out of `kinds`.\n * - everything else is **skipped, with its subtree**, exactly as the Markdown\n * parser skips a blockquote. A DITA `<related-links>` is not a paragraph,\n * and its contents must not be counted as one, or `paragraphs: {max: 3}`\n * fails documents a reader would say satisfy it.\n *\n * That last rule is why `transparent` has to exist as its own bucket: without\n * it, skipping the unmapped `<body>` would skip the whole topic.\n *\n * ## Titles that are not elements, and sections that carry none\n *\n * Two more fields, both earned by a DITA map:\n *\n * - `titleAttributes` names attributes that title a section, for the schemas\n * that spell a title as one (`<topicref navtitle=\"Install\"/>`). An attribute\n * has no position of its own, so the heading ends where the start tag does.\n * - `untitledSections` says a `sections` element opens a section even with no\n * title at all. Off by default, because an untitled DITA `<section>` is\n * prose belonging to the topic around it. On for a map, where an entry names\n * its target by `@keyref` or `@href` and lets the referenced topic supply\n * the title, so untitled is the normal case and dropping those entries would\n * flatten the whole table of contents.\n *\n * ## Extending it for a bespoke schema\n *\n * Add one entry to `XML_VOCABULARIES` (or pass your own array to `parseXml`):\n *\n * { name: \"acme\", label: \"Acme Docs\",\n * namespaces: [\"https://acme.example/docs\"], roots: [\"manual\"],\n * sections: [\"manual\", \"chapter\"], titles: [\"heading\"],\n * titleWrappers: [], transparent: [\"content\"],\n * paragraphs: [\"text\"], code: [\"sample\"], codeLangAttributes: [\"lang\"],\n * unorderedLists: [\"bullets\"], orderedLists: [\"steps\"],\n * listItems: [\"item\"] }\n *\n * Tables, admonitions, images, blockquotes and definition lists are five more\n * buckets, all optional - a schema that never names one simply never emits\n * that kind. See each field's own doc comment below for the shape it expects.\n *\n * Nothing else changes: the walk, the levels, the positions, and the fold are\n * vocabulary-independent. This is deliberately not wired to `manni.config.yaml`\n * yet - the shape is the commitment, the config surface is a later decision.\n *\n * ## Which vocabulary a document is in\n *\n * Scored, not guessed: a declared namespace is decisive, then elements only\n * one candidate claims, then the root element name, then the elements they\n * share. That ordering is what settles the ambiguous cases - `<section>`,\n * `<title>` and `<reference>` belong to both built-ins, so a `<section>`-rooted\n * file is decided by whether its prose is in `<p>` or `<para>`. Nothing\n * recognized at all is an error, not an empty tree: see `chooseVocabulary`.\n *\n * ## Levels\n *\n * `sectionize` folds by heading *level*, so nesting is expressed as one: the\n * level is the number of enclosing elements that actually opened a section,\n * plus one. Transparent wrappers do not count, and neither does a section\n * element with no title - an untitled DITA `<section>` is legal, and the honest\n * reading is that it adds no heading and so no level, its content belonging to\n * the section that encloses it. Levels clamp at 6, the range `SectionNode`\n * declares.\n *\n * ## Positions\n *\n * `@xmldom/xmldom` records `lineNumber` (1-based, despite its `index.d.ts`\n * saying \"zero based\") and `columnNumber` (1-based) on every node, pointing at\n * the `<` of an element's start tag and at the first character of a text node.\n * There is no end position. But *every* node carries a start, including the\n * whitespace text nodes between elements, so the exclusive end of an element is\n * the start of the next node in document order - for indented XML that is the\n * character right after `</tag>`, exactly. Only when a node is last all the way\n * up to the root does that fall back to the end of the document, per the\n * house rule for formats whose parser reports no end.\n */\nimport { DOMParser } from \"@xmldom/xmldom\";\nimport type { Element as XmlElement, Node as XmlNode } from \"@xmldom/xmldom\";\nimport { extractorForExtension } from \"../../meta/index.js\";\nimport type {\n AdmonitionNode,\n ContentNode,\n DefinitionItemNode,\n DefinitionListNode,\n DocumentParser,\n DocumentTree,\n ImageNode,\n ListItemNode,\n Point,\n Position,\n TableCellNode,\n TableNode,\n TableRowNode,\n} from \"../types.js\";\nimport { LintError } from \"../types.js\";\nimport { errorMessage } from \"../../shared/errors.js\";\nimport type { Fragment } from \"./sectionize.js\";\nimport { sectionize } from \"./sectionize.js\";\n\n/**\n * One schema's answer to \"what is a section, and what is content?\".\n *\n * Every list is of lowercased local names - the prefix and namespace of an\n * element are not part of the match, so a document that binds DocBook to `db:`\n * maps the same as one that uses the default namespace.\n */\nexport interface XmlVocabulary {\n /** Stable id, used in error messages. */\n name: string;\n /** Human-readable label. */\n label: string;\n /** Namespace URIs that identify this vocabulary outright. */\n namespaces: readonly string[];\n /** Root element names that identify it. */\n roots: readonly string[];\n /** Elements that open a section when they carry a title. */\n sections: readonly string[];\n /** Elements that carry a section's title. */\n titles: readonly string[];\n /**\n * Attributes that carry a section's title when no `titles` element does,\n * first one present wins. A DITA map spells one `<topicref navtitle=\"...\">`.\n */\n titleAttributes?: readonly string[];\n /**\n * Whether a `sections` element with no title of any kind still opens a\n * section. Default false: an untitled container adds no heading, and its\n * content belongs to the section that encloses it.\n */\n untitledSections?: boolean;\n /** Children to look inside for a title (DocBook's `<info>`). */\n titleWrappers: readonly string[];\n /** Structural wrappers: no section, no content, walk through. */\n transparent: readonly string[];\n /** Elements that are one paragraph. */\n paragraphs: readonly string[];\n /** Elements that are one code block. */\n code: readonly string[];\n /** Attributes carrying a code block's language, first one present wins. */\n codeLangAttributes: readonly string[];\n /** Elements that are an unordered list. */\n unorderedLists: readonly string[];\n /** Elements that are an ordered list. */\n orderedLists: readonly string[];\n /** Elements that are one item of a list. */\n listItems: readonly string[];\n\n /** Elements that are a table, CALS-shaped or simple. */\n tables?: readonly string[];\n /** Elements whose direct children are cells: a header row or a body row. */\n tableRows?: readonly string[];\n /** Elements that are one cell of a row. */\n tableCells?: readonly string[];\n /** Wrapper elements whose descendant rows are all header rows (CALS `<thead>`). */\n tableHeaderWrappers?: readonly string[];\n /** Row elements that are inherently a header row on their own (DITA `<sthead>`). */\n tableHeaderRows?: readonly string[];\n\n /** Elements that may be an admonition. */\n admonitions?: readonly string[];\n /**\n * Attribute naming the admonition's variant (DITA's `<note>` `@type`). When\n * absent, an admonition element's own lowercased name is its variant -\n * DocBook's five admonition elements are themselves named `note`, `tip`,\n * `important`, `caution` and `warning`. Either way, a name outside the six\n * `AdmonitionNode` knows produces an admonition with no `variant` set,\n * rather than an invented equivalence - DITA's `restriction` and `fastpath`\n * are real `@type` values this model does not have a word for.\n */\n admonitionVariantAttribute?: string;\n\n /** Elements that are an image, standing alone or wrapping one. */\n images?: readonly string[];\n /**\n * Element carrying the image's own url attribute - itself, for a\n * self-contained image (DITA's `<image href>`), or a descendant found by\n * name (DocBook's `<imagedata fileref>` inside a `<mediaobject>`).\n */\n imageDataElements?: readonly string[];\n /** Attribute on an `imageDataElements` match that carries the url. */\n imageUrlAttribute?: string;\n /** Direct child of an `imageDataElements` match carrying the alt text. */\n imageAltElements?: readonly string[];\n\n /** Elements that are a block quote. */\n blockquotes?: readonly string[];\n\n /** Elements that are a definition list. */\n definitionLists?: readonly string[];\n /** Elements that are one entry, pairing a term with a definition. */\n definitionItems?: readonly string[];\n /** Elements that carry an entry's term(s); more than one join with \", \". */\n definitionTerms?: readonly string[];\n /** Elements that carry an entry's definition body. */\n definitionBodies?: readonly string[];\n}\n\n/**\n * DITA. No default namespace to detect on (DITA is conventionally\n * namespace-free, with only `ditaarch:` bound on the root), so recognition\n * leans on the topic types and on `<p>`/`<codeblock>`/`<body>`.\n *\n * `<prereq>`, `<context>`, `<result>` and friends are transparent rather than\n * sections: they are untitled parts of a task body that render as continuous\n * prose, so their paragraphs belong to the task. `<related-links>` and\n * `<prolog>` are in no bucket at all, so they and their contents are skipped -\n * the blockquote rule.\n *\n * A CALS `<table>` and an OASIS `<simpletable>` share one row/cell reading:\n * `<row>`/`<entry>` for the former, `<strow>`/`<stentry>` for the latter. A row\n * inside `<thead>` is a header row (the CALS shape); `<sthead>` is a header row\n * on its own, holding `<stentry>` cells directly rather than wrapping a row.\n */\nconst DITA: XmlVocabulary = {\n name: \"dita\",\n label: \"DITA\",\n namespaces: [],\n roots: [\"dita\", \"topic\", \"concept\", \"task\", \"reference\", \"glossentry\"],\n sections: [\n \"topic\",\n \"concept\",\n \"task\",\n \"reference\",\n \"glossentry\",\n \"section\",\n \"example\",\n ],\n // `<glossterm>` is how a `<glossentry>` titles itself. It never carries a\n // `<title>`, so a vocabulary listing `title` alone reads every real glossary\n // topic as untitled and refuses the whole file. DITA-OT's own docset has\n // thirteen of them. `src/term/core/readers/dita.ts` has always read\n // `<glossterm>` as the term, so the two halves of this package disagreed\n // until the vendored corpus made it visible.\n titles: [\"title\", \"glossterm\"],\n titleWrappers: [],\n transparent: [\n \"dita\",\n \"body\",\n \"conbody\",\n \"taskbody\",\n \"refbody\",\n \"glossbody\",\n \"abstract\",\n \"prereq\",\n \"context\",\n \"result\",\n \"postreq\",\n \"div\",\n \"bodydiv\",\n \"sectiondiv\",\n ],\n // `<cmd>` is the imperative line of a `<step>`; treating it as a paragraph is\n // what makes a DITA `<steps>` item shaped like a Markdown list item.\n //\n // `<glossdef>` is the definition, and it holds prose either directly or in\n // `<p>`s. A paragraph rather than a wrapper, because a wrapper would drop the\n // direct-text spelling, which is the common one.\n paragraphs: [\"p\", \"shortdesc\", \"cmd\", \"info\", \"glossdef\"],\n code: [\"codeblock\", \"pre\"],\n codeLangAttributes: [\"outputclass\"],\n unorderedLists: [\"ul\", \"sl\", \"steps-unordered\"],\n orderedLists: [\"ol\", \"steps\", \"substeps\"],\n listItems: [\"li\", \"sli\", \"step\", \"substep\"],\n\n tables: [\"table\", \"simpletable\"],\n tableRows: [\"row\", \"strow\", \"sthead\"],\n tableCells: [\"entry\", \"stentry\"],\n tableHeaderWrappers: [\"thead\"],\n tableHeaderRows: [\"sthead\"],\n\n admonitions: [\"note\"],\n admonitionVariantAttribute: \"type\",\n\n images: [\"image\", \"fig\"],\n imageDataElements: [\"image\"],\n imageUrlAttribute: \"href\",\n imageAltElements: [\"alt\"],\n\n blockquotes: [\"lq\"],\n\n definitionLists: [\"dl\"],\n definitionItems: [\"dlentry\"],\n definitionTerms: [\"dt\"],\n definitionBodies: [\"dd\"],\n};\n\n/**\n * DocBook 5 (and the DocBook 4 `<sectN>`/`<*info>` spellings, which cost two\n * entries and save a whole second vocabulary).\n */\nconst DOCBOOK: XmlVocabulary = {\n name: \"docbook\",\n label: \"DocBook\",\n namespaces: [\"http://docbook.org/ns/docbook\"],\n roots: [\n \"book\",\n \"article\",\n \"chapter\",\n \"section\",\n \"sect1\",\n \"part\",\n \"appendix\",\n \"preface\",\n \"reference\",\n ],\n sections: [\n \"book\",\n \"article\",\n \"part\",\n \"chapter\",\n \"appendix\",\n \"preface\",\n \"section\",\n \"simplesect\",\n \"sect1\",\n \"sect2\",\n \"sect3\",\n \"sect4\",\n \"sect5\",\n ],\n titles: [\"title\"],\n titleWrappers: [\n \"info\",\n \"bookinfo\",\n \"articleinfo\",\n \"chapterinfo\",\n \"sectioninfo\",\n ],\n transparent: [\"formalpara\"],\n paragraphs: [\"para\", \"simpara\"],\n code: [\"programlisting\", \"screen\", \"literallayout\", \"synopsis\"],\n codeLangAttributes: [\"language\"],\n unorderedLists: [\"itemizedlist\", \"simplelist\"],\n orderedLists: [\"orderedlist\", \"procedure\"],\n listItems: [\"listitem\", \"member\", \"step\"],\n\n tables: [\"table\", \"informaltable\"],\n tableRows: [\"row\"],\n tableCells: [\"entry\"],\n tableHeaderWrappers: [\"thead\"],\n tableHeaderRows: [],\n\n // No `admonitionVariantAttribute`: DocBook's five admonition elements are\n // themselves named `note`/`warning`/`caution`/`tip`/`important`.\n admonitions: [\"note\", \"warning\", \"caution\", \"tip\", \"important\"],\n\n images: [\"mediaobject\", \"figure\"],\n imageDataElements: [\"imagedata\"],\n imageUrlAttribute: \"fileref\",\n imageAltElements: [],\n\n blockquotes: [\"blockquote\"],\n\n definitionLists: [\"variablelist\"],\n definitionItems: [\"varlistentry\"],\n definitionTerms: [\"term\"],\n // DocBook reuses `<listitem>` for a variable list's own body, distinct from\n // the `listItems` bucket above which reads it inside `<itemizedlist>`.\n definitionBodies: [\"listitem\"],\n};\n\n/**\n * DITA maps, `<map>` and `<bookmap>`. No namespace to detect on, as with DITA\n * itself, so recognition leans on `<topicref>` and the rest of the navigation\n * vocabulary.\n *\n * A map is a table of contents, which is a tree of titled nodes - and a tree of\n * titled nodes is what a section tree is. `<topicref>` nesting is section\n * nesting. The one thing a map does that a topic never does is leave its nodes\n * untitled: a real entry points by `@keyref` or `@href` and lets the referenced\n * topic supply the title, so `untitledSections` is on and an untitled entry is\n * an untitled section rather than a failure. A titled entry may be titled\n * either way, as `<topicmeta><navtitle>` or as `@navtitle`, so `titles` and\n * `titleAttributes` both name it.\n *\n * `sections` is wide because navigation is. `<glossref>`, `<mapref>`,\n * `<navref>`, `<topicset>` and a bookmap's `<chapter>`/`<part>`/`<appendix>`\n * are all `<topicref>` specializations, and a map that nests its entries in one\n * of them - DITA-OT's own glossary map nests thirteen `<glossref>`s - would\n * otherwise parse to a tree with nothing in it.\n *\n * `<reltable>` and `<keydef>` are in no bucket at all, so they and their\n * contents are skipped, the blockquote rule. A relationship table states which\n * topics relate to each other, and a key definition binds a key to a resource.\n * Neither is navigation, and counting their `<topicref>`s as sections would\n * make every map's shape a lie. A `<glossref>` carrying `@keys` is the case\n * that looks like both, and it is a section: `<keydef>` defaults to\n * `processing-role=\"resource-only\"` and so never appears in a table of\n * contents, while `<glossref>` processes normally and does. That is a fact\n * about DITA, not a preference.\n *\n * `<topicmeta>` is both a title wrapper and transparent. Wrapping is how\n * `<navtitle>` is found; transparency is how the `<shortdesc>` and `<linktext>`\n * beside it are read, since a map has no other prose and they live nowhere\n * else. `<booktitle>` is a wrapper only: a bookmap titles itself\n * `<booktitle><mainbooktitle>`, and the optional `<booklibrary>` beside it\n * names the series rather than the book, so only `<mainbooktitle>` is a title.\n */\nconst DITAMAP: XmlVocabulary = {\n name: \"ditamap\",\n label: \"DITA map\",\n namespaces: [],\n roots: [\"map\", \"bookmap\"],\n sections: [\n \"map\",\n \"bookmap\",\n \"topicref\",\n \"topichead\",\n \"mapref\",\n \"glossref\",\n \"anchorref\",\n \"navref\",\n \"topicset\",\n \"topicsetref\",\n \"chapter\",\n \"part\",\n \"appendix\",\n \"appendices\",\n \"preface\",\n \"notices\",\n \"dedication\",\n \"colophon\",\n \"amendments\",\n ],\n // `navtitle` sits in both buckets on purpose, because DITA spells it either\n // way. The element form wins: `headingOf` asks `titleOf` first, so\n // `@navtitle` is read only when the entry has no `<topicmeta><navtitle>`.\n titles: [\"title\", \"navtitle\", \"mainbooktitle\"],\n titleAttributes: [\"navtitle\"],\n titleWrappers: [\"topicmeta\", \"booktitle\"],\n untitledSections: true,\n transparent: [\n \"topicgroup\",\n \"topicmeta\",\n \"frontmatter\",\n \"backmatter\",\n \"booklists\",\n ],\n paragraphs: [\"shortdesc\", \"linktext\"],\n code: [],\n codeLangAttributes: [],\n unorderedLists: [],\n orderedLists: [],\n listItems: [],\n};\n\n/**\n * The vocabularies tried, in declaration order (which breaks scoring ties).\n * Exported so a bespoke schema is an array entry rather than a fork.\n */\nexport const XML_VOCABULARIES: readonly XmlVocabulary[] = [\n DITA,\n DOCBOOK,\n DITAMAP,\n];\n\n/** Precomputed lookups for one vocabulary. */\ninterface Compiled {\n vocab: XmlVocabulary;\n sections: Set<string>;\n titles: Set<string>;\n titleWrappers: Set<string>;\n transparent: Set<string>;\n paragraphs: Set<string>;\n code: Set<string>;\n unordered: Set<string>;\n ordered: Set<string>;\n items: Set<string>;\n tables: Set<string>;\n tableRows: Set<string>;\n tableCells: Set<string>;\n tableHeaderWrappers: Set<string>;\n tableHeaderRows: Set<string>;\n admonitions: Set<string>;\n images: Set<string>;\n imageDataElements: Set<string>;\n imageAltElements: Set<string>;\n blockquotes: Set<string>;\n definitionLists: Set<string>;\n definitionItems: Set<string>;\n definitionTerms: Set<string>;\n definitionBodies: Set<string>;\n /** Every name the vocabulary claims, for scoring. */\n known: Set<string>;\n}\n\nconst lower = (names: readonly string[] = []): Set<string> =>\n new Set(names.map((n) => n.toLowerCase()));\n\nfunction compile(vocab: XmlVocabulary): Compiled {\n const c: Compiled = {\n vocab,\n sections: lower(vocab.sections),\n titles: lower(vocab.titles),\n titleWrappers: lower(vocab.titleWrappers),\n transparent: lower(vocab.transparent),\n paragraphs: lower(vocab.paragraphs),\n code: lower(vocab.code),\n unordered: lower(vocab.unorderedLists),\n ordered: lower(vocab.orderedLists),\n items: lower(vocab.listItems),\n tables: lower(vocab.tables),\n tableRows: lower(vocab.tableRows),\n tableCells: lower(vocab.tableCells),\n tableHeaderWrappers: lower(vocab.tableHeaderWrappers),\n tableHeaderRows: lower(vocab.tableHeaderRows),\n admonitions: lower(vocab.admonitions),\n images: lower(vocab.images),\n imageDataElements: lower(vocab.imageDataElements),\n imageAltElements: lower(vocab.imageAltElements),\n blockquotes: lower(vocab.blockquotes),\n definitionLists: lower(vocab.definitionLists),\n definitionItems: lower(vocab.definitionItems),\n definitionTerms: lower(vocab.definitionTerms),\n definitionBodies: lower(vocab.definitionBodies),\n known: new Set(),\n };\n for (const set of [\n c.sections,\n c.titles,\n c.titleWrappers,\n c.transparent,\n c.paragraphs,\n c.code,\n c.unordered,\n c.ordered,\n c.items,\n c.tables,\n c.tableRows,\n c.tableCells,\n c.tableHeaderWrappers,\n c.tableHeaderRows,\n c.admonitions,\n c.images,\n c.imageDataElements,\n c.imageAltElements,\n c.blockquotes,\n c.definitionLists,\n c.definitionItems,\n c.definitionTerms,\n c.definitionBodies,\n ]) {\n for (const name of set) c.known.add(name);\n }\n return c;\n}\n\nconst ELEMENT_NODE = 1;\n\n/** Lowercased local name, prefix and namespace discarded. */\nfunction localName(node: XmlNode): string {\n const el = node as XmlElement;\n const name = el.localName ?? node.nodeName.split(\":\").pop() ?? node.nodeName;\n return name.toLowerCase();\n}\n\nfunction* elementChildren(el: XmlNode): Generator<XmlElement> {\n for (let child = el.firstChild; child; child = child.nextSibling) {\n if (child.nodeType === ELEMENT_NODE) yield child as XmlElement;\n }\n}\n\n/** First direct child matching one of `names`, or null. */\nfunction findDirectChild(el: XmlElement, names: Set<string>): XmlElement | null {\n for (const child of elementChildren(el)) {\n if (names.has(localName(child))) return child;\n }\n return null;\n}\n\n/** First descendant matching one of `names`, in document order, or null. */\nfunction findDescendant(el: XmlElement, names: Set<string>): XmlElement | null {\n for (const child of elementChildren(el)) {\n if (names.has(localName(child))) return child;\n const nested = findDescendant(child, names);\n if (nested) return nested;\n }\n return null;\n}\n\n/** Collapse XML's indentation whitespace into the single spaces a reader sees. */\nfunction flatten(text: string | null): string {\n return (text ?? \"\").replace(/\\s+/g, \" \").trim();\n}\n\n/**\n * A code block's text, minus the layout the source added around it: the newline\n * that follows the start tag when the code is on its own line, and the\n * indentation before the end tag. Everything between is significant and is left\n * exactly as written, which is what mdast does with a fenced block's value.\n */\nfunction codeText(text: string | null): string {\n return (text ?? \"\").replace(/^[^\\S\\n]*\\n/, \"\").replace(/\\n[^\\S\\n]*$/, \"\");\n}\n\n/** The six variants `AdmonitionNode` knows. A name outside this set names no variant. */\ntype Variant = Exclude<AdmonitionNode[\"variant\"], undefined>;\nconst ADMONITION_VARIANTS = new Set<Variant>([\n \"note\",\n \"tip\",\n \"important\",\n \"caution\",\n \"warning\",\n \"danger\",\n]);\n\nfunction isAdmonitionVariant(name: string): name is Variant {\n return (ADMONITION_VARIANTS as ReadonlySet<string>).has(name);\n}\n\n/** Weights for `chooseVocabulary`, in the order they are meant to dominate. */\nconst NAMESPACE_MATCH = 1000;\nconst EXCLUSIVE_ELEMENT = 10;\nconst ROOT_NAME = 5;\nconst SHARED_ELEMENT = 1;\n\n/**\n * Score every vocabulary against the document and take the best.\n *\n * A namespace match on the root is decisive: a document that declares its\n * namespace has already said what it is. Failing that, what counts is elements\n * only one candidate claims - `<para>` and `<programlisting>` are DocBook's\n * alone, `<p>` and `<taskbody>` DITA's - because those are the ones whose\n * presence is an argument. Elements the candidates share (`<section>`,\n * `<title>`) are worth a point as a tiebreak and no more, since they are\n * evidence for everyone and therefore for no one.\n *\n * The root element name is weaker still, and deliberately weaker than a single\n * exclusive element. `<section>` is a DocBook root, so a bare `<section>` whose\n * prose is in `<p>` would otherwise be read as DocBook - and every `<p>` in it\n * would then be an unmapped element, silently skipped, leaving a titled section\n * with no content and no complaint. One `<p>` is better evidence about what a\n * file is than the name of its outermost tag.\n */\nfunction chooseVocabulary(\n root: XmlElement,\n compiled: Compiled[],\n): { best: Compiled; score: number } {\n const counts = new Map<string, number>();\n const tally = (node: XmlNode): void => {\n for (const child of elementChildren(node)) {\n const name = localName(child);\n counts.set(name, (counts.get(name) ?? 0) + 1);\n tally(child);\n }\n };\n counts.set(localName(root), 1);\n tally(root);\n\n /** How many candidates claim each name; 1 means the name is decisive. */\n const claims = new Map<string, number>();\n for (const c of compiled) {\n for (const name of c.known) claims.set(name, (claims.get(name) ?? 0) + 1);\n }\n\n const ns = (root.namespaceURI ?? \"\").toLowerCase();\n const rootName = localName(root);\n\n let best: Compiled | undefined;\n let bestScore = -1;\n for (const c of compiled) {\n let score = 0;\n if (ns && c.vocab.namespaces.some((u) => u.toLowerCase() === ns)) {\n score += NAMESPACE_MATCH;\n }\n if (lower(c.vocab.roots).has(rootName)) score += ROOT_NAME;\n for (const [name, n] of counts) {\n if (!c.known.has(name)) continue;\n score += n * (claims.get(name) === 1 ? EXCLUSIVE_ELEMENT : SHARED_ELEMENT);\n }\n if (score > bestScore) {\n best = c;\n bestScore = score;\n }\n }\n if (!best) {\n // The vocabulary list is the registry's own and is never empty; the loop\n // assigns on its first pass, because every score beats the -1 it starts\n // from. Saying so out loud beats returning a vocabulary nobody chose.\n throw new LintError(\"No XML vocabularies are registered.\");\n }\n return { best, score: bestScore };\n}\n\n/**\n * Line/column -> offset, over the content as it was read.\n *\n * xmldom normalizes line endings before parsing, so its line and column are\n * against a LF-only copy. Line *numbers* survive that normalization unchanged\n * and CRLF only ever differs at a line terminator, so indexing the original\n * content's line starts with xmldom's (line, column) lands on the same\n * character - which is what keeps `offset` an index into the file the reporter\n * will quote, not into a normalized copy of it.\n */\nclass SourceMap {\n private readonly lineStarts: number[] = [0];\n /** Byte-order mark length, added back to every offset. */\n private readonly bom: number;\n private readonly body: string;\n readonly docEnd: Point;\n\n constructor(content: string) {\n this.bom = content.charCodeAt(0) === 0xfeff ? 1 : 0;\n this.body = content.slice(this.bom);\n for (let i = 0; i < this.body.length; i++) {\n const ch = this.body[i];\n if (ch === \"\\n\") this.lineStarts.push(i + 1);\n else if (ch === \"\\r\") {\n if (this.body[i + 1] === \"\\n\") i++;\n this.lineStarts.push(i + 1);\n }\n }\n // `lineStarts` opens with 0 and is only ever appended to, so the fallback\n // is unreachable - and it is the start of the one and only line anyway.\n const lastStart = this.lineStarts.at(-1) ?? 0;\n this.docEnd = {\n line: this.lineStarts.length,\n column: this.body.length - lastStart + 1,\n offset: content.length,\n };\n }\n\n /** The source text, for the parser to hand to xmldom without the BOM. */\n get text(): string {\n return this.body;\n }\n\n /** Start point of a node, or null when the locator recorded none. */\n point(node: XmlNode | null | undefined): Point | null {\n if (!node) return null;\n const line = node.lineNumber;\n const column = node.columnNumber;\n if (typeof line !== \"number\" || typeof column !== \"number\") return null;\n const start = this.lineStarts[line - 1];\n if (start === undefined) return null;\n const offset = Math.min(start + column - 1, this.body.length) + this.bom;\n return { line, column, offset };\n }\n\n /** End of the line a point sits on, exclusive of its terminator. */\n endOfLine(line: number): Point {\n const start = this.lineStarts[line - 1];\n if (start === undefined) return { ...this.docEnd };\n const next = this.lineStarts[line];\n const end = next === undefined ? this.body.length : next - 1;\n return { line, column: end - start + 1, offset: end + this.bom };\n }\n}\n\n/**\n * The exclusive end of an element: where the next node in document order\n * starts. Whitespace text nodes carry positions too, so for indented XML that\n * is the character immediately after `</tag>`.\n */\nfunction nextInDocumentOrder(el: XmlNode): XmlNode | null {\n let node: XmlNode = el;\n for (;;) {\n if (node.nextSibling) return node.nextSibling;\n const parent: XmlNode | null = node.parentNode;\n if (!parent || parent.nodeType !== ELEMENT_NODE) return null;\n node = parent;\n }\n}\n\n/** Flattens one document into ordered fragments under one vocabulary. */\nclass Flattener {\n readonly fragments: Fragment[] = [];\n\n constructor(\n private readonly c: Compiled,\n private readonly map: SourceMap,\n ) {}\n\n private span(el: XmlNode): Position {\n const start = this.map.point(el) ?? { ...this.map.docEnd };\n const end =\n this.map.point(nextInDocumentOrder(el)) ?? { ...this.map.docEnd };\n // A malformed locator (or an element that ends the document) must never\n // produce a backwards span; rules sort findings by offset.\n return end.offset < start.offset ? { start, end: { ...start } } : { start, end };\n }\n\n /** The title element of a section container, direct or inside a wrapper. */\n private titleOf(el: XmlElement): XmlElement | null {\n for (const child of elementChildren(el)) {\n if (this.c.titles.has(localName(child))) return child;\n }\n for (const child of elementChildren(el)) {\n if (!this.c.titleWrappers.has(localName(child))) continue;\n for (const inner of elementChildren(child)) {\n if (this.c.titles.has(localName(inner))) return inner;\n }\n }\n return null;\n }\n\n /**\n * The exclusive end of an element's start tag: where its first child begins,\n * which for indented XML is the character right after `>`. A childless\n * element has no such node and falls back to the end of the element, which\n * for `<topicref keyref=\"a\"/>` is the same character anyway.\n */\n private startTagEnd(el: XmlElement): Point {\n return this.map.point(el.firstChild) ?? this.span(el).end;\n }\n\n /**\n * The heading a section container carries: its text, and where the heading\n * ends. A `titles` element ends it at its own end. An attribute title and an\n * absent one both end it at the end of the start tag, since neither has a\n * position and anything further would swallow a nested section's heading.\n * Null when the vocabulary says an untitled container is not a section.\n */\n private headingOf(el: XmlElement): { title: string; end: Point } | null {\n const title = this.titleOf(el);\n if (title) {\n return { title: flatten(title.textContent), end: this.span(title).end };\n }\n for (const attr of this.c.vocab.titleAttributes ?? []) {\n const value = el.getAttribute(attr);\n if (value) return { title: flatten(value), end: this.startTagEnd(el) };\n }\n if (this.c.vocab.untitledSections) {\n return { title: \"\", end: this.startTagEnd(el) };\n }\n return null;\n }\n\n /** Walk one element: section, wrapper, content, or skipped subtree. */\n visit(el: XmlElement, level: number): void {\n const name = localName(el);\n\n if (this.c.sections.has(name)) {\n const heading = this.headingOf(el);\n if (!heading) {\n // An untitled section container adds no heading, so it adds no level\n // either; its content belongs to the section that encloses it.\n this.walkChildren(el, level);\n return;\n }\n const next = Math.min(level + 1, 6);\n this.fragments.push({\n type: \"heading\",\n level: next,\n title: heading.title,\n // From the container's start tag through the end of its title: the\n // container is the section, so a section that began at its `<title>`\n // would leave its own opening tag outside itself and stop adjacent\n // sections from tiling the document.\n position: { start: this.span(el).start, end: heading.end },\n });\n this.walkChildren(el, next);\n return;\n }\n\n if (this.c.transparent.has(name)) {\n this.walkChildren(el, level);\n return;\n }\n\n const node = this.content(el);\n if (node) this.fragments.push({ type: \"content\", node });\n // Unmapped: skipped with its subtree, like a Markdown blockquote.\n }\n\n private walkChildren(el: XmlElement, level: number): void {\n for (const child of elementChildren(el)) this.visit(child, level);\n }\n\n /** One element as a content node, or null when it is not one. */\n private content(el: XmlElement): ContentNode | null {\n const name = localName(el);\n const position = this.span(el);\n\n if (this.c.paragraphs.has(name)) {\n return { kind: \"paragraph\", position, text: flatten(el.textContent) };\n }\n\n if (this.c.code.has(name)) {\n const lang = this.langOf(el);\n return {\n kind: \"codeBlock\",\n position,\n text: codeText(el.textContent),\n ...(lang ? { language: lang } : {}),\n };\n }\n\n const ordered = this.c.ordered.has(name);\n if (ordered || this.c.unordered.has(name)) {\n return {\n kind: \"list\",\n position,\n text: flatten(el.textContent),\n ordered,\n items: [...elementChildren(el)]\n .filter((item) => this.c.items.has(localName(item)))\n .map((item): ListItemNode => ({\n kind: \"listItem\",\n position: this.span(item),\n text: flatten(item.textContent),\n children: this.blockContent(item),\n })),\n };\n }\n\n if (this.c.tables.has(name)) return this.tableNode(el, position);\n\n if (this.c.admonitions.has(name)) {\n const variant = this.admonitionVariantOf(el, name);\n return {\n kind: \"admonition\",\n position,\n text: flatten(el.textContent),\n // A `@type`/name outside the six variants `AdmonitionNode` knows\n // leaves `variant` unset, rather than inventing an equivalence.\n ...(variant ? { variant } : {}),\n children: this.blockContent(el),\n };\n }\n\n if (this.c.images.has(name)) return this.imageNode(el, position);\n\n if (this.c.blockquotes.has(name)) {\n return {\n kind: \"blockquote\",\n position,\n text: flatten(el.textContent),\n children: this.blockContent(el),\n };\n }\n\n if (this.c.definitionLists.has(name)) return this.definitionListNode(el, position);\n\n return null;\n }\n\n /** A table's rows, from any of its CALS wrappers (`tgroup`, `tbody`, `thead`). */\n private tableNode(el: XmlElement, position: Position): TableNode {\n return {\n kind: \"table\",\n position,\n text: flatten(el.textContent),\n children: this.tableRowsOf(el, false),\n };\n }\n\n /**\n * Rows found anywhere under `el`, recursing through every wrapper - `tgroup`,\n * `tbody`, `thead` and the like - regardless of whether it is known\n * elsewhere. A table's internal grouping elements carry no content of their\n * own; only the rows and cells inside them do.\n *\n * `inheritedHeader` tracks whether an enclosing `tableHeaderWrappers` element\n * (CALS's `<thead>`) has been entered; `tableHeaderRows` (DITA's `<sthead>`)\n * marks a row as a header on its own, without a wrapper.\n */\n private tableRowsOf(el: XmlElement, inheritedHeader: boolean): TableRowNode[] {\n const rows: TableRowNode[] = [];\n for (const child of elementChildren(el)) {\n const name = localName(child);\n if (this.c.tableRows.has(name)) {\n rows.push(this.tableRow(child, inheritedHeader || this.c.tableHeaderRows.has(name)));\n continue;\n }\n rows.push(\n ...this.tableRowsOf(child, inheritedHeader || this.c.tableHeaderWrappers.has(name)),\n );\n }\n return rows;\n }\n\n private tableRow(el: XmlElement, header: boolean): TableRowNode {\n const cells: TableCellNode[] = [];\n for (const child of elementChildren(el)) {\n if (!this.c.tableCells.has(localName(child))) continue;\n cells.push({\n kind: \"tableCell\",\n position: this.span(child),\n text: flatten(child.textContent),\n children: this.blockContent(child),\n });\n }\n return {\n kind: \"tableRow\",\n position: this.span(el),\n text: flatten(el.textContent),\n header,\n children: cells,\n };\n }\n\n /**\n * An admonition's variant: the value of `admonitionVariantAttribute` when the\n * vocabulary names one (DITA's `<note type>`, defaulting to `note` when the\n * attribute is absent - DITA's own default), or the element's own lowercased\n * name otherwise (DocBook's `<warning>`, `<tip>`, and so on). Undefined when\n * neither names one of the six variants `AdmonitionNode` knows.\n */\n private admonitionVariantOf(el: XmlElement, name: string): Variant | undefined {\n const attr = this.c.vocab.admonitionVariantAttribute;\n const raw = (attr ? el.getAttribute(attr) : \"\") || name;\n const variant = raw.toLowerCase();\n return isAdmonitionVariant(variant) ? variant : undefined;\n }\n\n /**\n * An image, standing alone or wrapping one. `imageDataElements` names the\n * element carrying the url - `el` itself for a self-contained image (DITA's\n * `<image href>`), or a descendant found by name otherwise (DocBook's\n * `<imagedata fileref>` inside a `<mediaobject>`/`<figure>`). The caption\n * reuses `titleOf`, the same lookup a section uses for its heading - DITA's\n * `<fig><title>` and DocBook's `<figure><title>` are both a direct `<title>`\n * child.\n */\n private imageNode(el: XmlElement, position: Position): ImageNode {\n const name = localName(el);\n const dataEl = this.c.imageDataElements.has(name)\n ? el\n : findDescendant(el, this.c.imageDataElements);\n const attr = this.c.vocab.imageUrlAttribute;\n const url = (dataEl && attr ? dataEl.getAttribute(attr) : \"\") || \"\";\n const altEl = dataEl ? findDirectChild(dataEl, this.c.imageAltElements) : null;\n const title = this.titleOf(el);\n return {\n kind: \"image\",\n position,\n text: flatten(el.textContent),\n url,\n alt: altEl ? flatten(altEl.textContent) : \"\",\n ...(title ? { title: flatten(title.textContent) } : {}),\n };\n }\n\n private definitionListNode(el: XmlElement, position: Position): DefinitionListNode {\n const children: DefinitionItemNode[] = [];\n for (const child of elementChildren(el)) {\n if (this.c.definitionItems.has(localName(child))) {\n children.push(this.definitionItem(child));\n }\n }\n return {\n kind: \"definitionList\",\n position,\n text: flatten(el.textContent),\n children,\n };\n }\n\n /** One entry, pairing its term(s) - joined with \", \" when more than one - with its definition body. */\n private definitionItem(el: XmlElement): DefinitionItemNode {\n const terms: string[] = [];\n let body: XmlElement | null = null;\n for (const child of elementChildren(el)) {\n const name = localName(child);\n if (this.c.definitionTerms.has(name)) {\n terms.push(flatten(child.textContent));\n } else if (body === null && this.c.definitionBodies.has(name)) {\n body = child;\n }\n }\n return {\n kind: \"definitionItem\",\n position: this.span(el),\n text: flatten(el.textContent),\n term: terms.join(\", \"),\n definition: body ? this.blockContent(body) : [],\n };\n }\n\n /**\n * One container's content, with its own loose prose kept as a paragraph.\n * Shared by list items, table cells, admonitions, block quotes, and a\n * definition's body - anywhere the content model asks for a container's\n * `children` rather than a single block.\n *\n * mdast puts a list item's principal text in a `paragraph` child regardless\n * of markup, and `lists: {items: {paragraphs: {min: 1}}}` has to count the\n * same thing in every format. So the loose text is gathered into one, in the\n * position it occupies among the container's blocks.\n *\n * Gathering it rather than checking whether the container has any children is\n * what makes the two cases agree. `<li>bare text</li>` was already\n * reconciled; `<li>Parent<ul>…</ul></li>` was not, because the nested list is\n * a child, so the item looked accounted for and `Parent` became prose\n * nothing counted - while its Markdown, HTML, AsciiDoc, and reST twins all\n * counted one. This is the same fix `html.ts` carries, and the two should\n * stay in step.\n *\n * Unmapped elements contribute their text rather than being skipped, which is\n * what the old whole-item `textContent` did: inside a container they are\n * inline markup - DITA's `<b>`, `<xref>` - not structure worth dropping.\n */\n private blockContent(container: XmlElement): ContentNode[] {\n const out: ContentNode[] = [];\n let text = \"\";\n\n const flush = (): void => {\n const value = flatten(text);\n text = \"\";\n if (value.length === 0) return;\n out.push({ kind: \"paragraph\", position: this.span(container), text: value });\n };\n\n for (let child = container.firstChild; child; child = child.nextSibling) {\n if (child.nodeType !== ELEMENT_NODE) {\n text += child.nodeValue ?? \"\";\n continue;\n }\n\n const el = child as XmlElement;\n const nested = this.c.transparent.has(localName(el))\n ? this.contentChildren(el)\n : [this.content(el)].filter((n): n is ContentNode => n !== null);\n\n if (nested.length > 0) {\n flush();\n out.push(...nested);\n continue;\n }\n text += el.textContent ?? \"\";\n }\n\n flush();\n return out;\n }\n\n private contentChildren(el: XmlElement): ContentNode[] {\n const out: ContentNode[] = [];\n for (const child of elementChildren(el)) {\n if (this.c.transparent.has(localName(child))) {\n out.push(...this.contentChildren(child));\n continue;\n }\n const node = this.content(child);\n if (node) out.push(node);\n }\n return out;\n }\n\n /** A code block's language, with a `language-` prefix stripped. */\n private langOf(el: XmlElement): string | undefined {\n for (const attr of this.c.vocab.codeLangAttributes) {\n const value = el.getAttribute(attr);\n if (value) return value.replace(/^language-/, \"\");\n }\n return undefined;\n }\n}\n\n/**\n * Parse, refusing anything xmldom had to guess at.\n *\n * xmldom is lenient: it throws only on a `fatalError`, and reports `error` and\n * `warning` through the handler while carrying on with a repaired tree. The\n * line between them is drawn at `error` because in XML the element tree *is*\n * the structure - there is no second signal like a `##` to fall back on - so\n * linting a tree xmldom guessed at reports on a document nobody wrote. A\n * mismatched end tag or a stray `<` puts every following element at the wrong\n * depth, and the findings would be confident nonsense. `warning` is left alone:\n * xmldom recovers from an unquoted attribute value without changing the element\n * tree at all, and attributes here are metadata, not structure.\n *\n * This is also the line docmeta's XML extractor draws, so a file manni lint\n * lints is exactly a file docmeta will read metadata from.\n */\nfunction parseDocument(source: string, filePath: string): XmlElement {\n const problems: string[] = [];\n let doc;\n try {\n doc = new DOMParser({\n onError: (level, message) => {\n if (level === \"error\" || level === \"fatalError\") problems.push(message);\n },\n }).parseFromString(source, \"text/xml\");\n } catch (err) {\n const detail = problems[0] ?? errorMessage(err);\n throw new LintError(\n `${filePath}: could not parse as XML: ${firstLine(detail)}`,\n );\n }\n\n const [firstProblem] = problems;\n if (firstProblem !== undefined) {\n throw new LintError(\n `${filePath}: could not parse as XML: ${firstLine(firstProblem)}`,\n );\n }\n\n const root = doc.documentElement;\n if (!root) {\n throw new LintError(`${filePath}: could not parse as XML: no root element`);\n }\n return root;\n}\n\n/** xmldom appends the offending source to some messages; one line is enough. */\nfunction firstLine(message: string): string {\n const [first] = message.split(\"\\n\");\n return (first ?? message).trim();\n}\n\n/**\n * Metadata for routing, from docmeta.\n *\n * **Not `extractFrontmatter`.** `src/parsers/markdown.ts` calls it because for\n * Markdown it is the whole story, but in docmeta that function is specifically\n * the *fenced* `---` block reader (\"core front matter extraction shared by the\n * markdown, mdx, adoc, rst formats\"). An XML file has no fenced block, so\n * `extractFrontmatter(content, \"xml\")` returns `{ data: {}, present: false }`\n * for every XML document ever written, and `type:` routing for `.xml` would\n * silently never fire. docmeta's *registry* is the right door: its XML\n * extractor reads the root element's attributes (`<task type=\"how-to\">` ->\n * `{ type: \"how-to\" }`, minus `xmlns*`, with values parsed as YAML scalars)\n * plus the text of simple direct children as dotted keys (`task.title`). That\n * is a real `type`, so an `.xml` page does route.\n *\n * The HTML parser merges a fenced block with its native reading, fenced\n * winning a collision. This one does not, because an `.xml` file cannot carry a\n * fenced block and still be XML: a leading `---` is character data outside the\n * root element, which xmldom reports as an error and `parseDocument` refuses\n * before metadata is ever read. (HTML has no such rule - a comment or stray\n * text before `<html>` parses fine - which is why the merge is right there and\n * would be unreachable code here.)\n *\n * It throws on malformed XML, the same line `parseDocument` draws, but it is\n * called after the parse so in practice it cannot be the one to complain.\n */\nfunction readMetadata(\n content: string,\n filePath: string,\n): Record<string, unknown> | null {\n const extractor = extractorForExtension(\".xml\");\n if (!extractor) return null;\n try {\n const meta = extractor.extract(content, filePath);\n return meta.present ? meta.data : null;\n } catch (err) {\n throw new LintError(\n `${filePath}: could not read XML metadata: ${firstLine(errorMessage(err))}`,\n );\n }\n}\n\n/**\n * Note on the frontmatter-title rule.\n *\n * `withFrontmatterTitle` in the Markdown parser synthesizes an H1 from\n * `title:` when the body has none, because Docusaurus and Hugo render the page\n * title from frontmatter and their pages legitimately start at `##`. That\n * reasoning does not carry to XML and the rule is deliberately not applied\n * here. An XML document's title is an element - `<title>` - in the body, in\n * document order, exactly where the section fold already looks for it; there is\n * no publishing convention that moves it out. And what docmeta calls this\n * document's \"frontmatter\" is the *root element's own attributes*, so a `title`\n * attribute would be a second title on the very element that already carries\n * the real one: synthesizing a section from it would nest the document's actual\n * title underneath a duplicate of itself. A document with no title element at\n * all is not a page missing its H1, it is a document with no structure to lint,\n * and `parseXml` says so.\n */\n\n/**\n * Parse XML into the generic tree.\n *\n * @param vocabularies Overrides the built-ins; the extension point for a\n * bespoke schema until there is a config surface for it.\n */\nexport function parseXml(\n content: string,\n filePath: string,\n vocabularies: readonly XmlVocabulary[] = XML_VOCABULARIES,\n): DocumentTree {\n const map = new SourceMap(content);\n const root = parseDocument(map.text, filePath);\n\n const compiled = vocabularies.map(compile);\n if (compiled.length === 0) {\n throw new LintError(`${filePath}: no XML vocabularies are configured.`);\n }\n\n const { best, score } = chooseVocabulary(root, compiled);\n const names = compiled.map((c) => c.vocab.label).join(\", \");\n\n // Nothing recognized is an error rather than an empty tree. An empty tree\n // would lint as a document that is missing every section its template asks\n // for - a cascade of findings that says nothing about the page and points\n // nowhere useful. The gap is in the mapping, and this is where to say so.\n if (score <= 0) {\n throw new LintError(\n `${filePath}: no known XML vocabulary matched <${localName(root)}>. ` +\n `manni lint understands ${names}; add an entry to XML_VOCABULARIES ` +\n `in src/parsers/xml.ts to describe another schema.`,\n );\n }\n\n const flattener = new Flattener(best, map);\n flattener.visit(root, 0);\n const fragments = flattener.fragments;\n\n if (!fragments.some((b) => b.type === \"heading\")) {\n throw new LintError(\n `${filePath}: read as ${best.vocab.label}, but no titled section was found. ` +\n `A ${best.vocab.label} section is one of <${best.vocab.sections.join(\">, <\")}> ` +\n `carrying a <${best.vocab.titles.join(\">/<\")}>; without one the document has ` +\n `no structure to check.`,\n );\n }\n\n const frontmatter = readMetadata(content, filePath);\n\n return {\n format: \"xml\",\n filePath,\n frontmatter,\n // The metadata block is the root element's start tag: from its `<` to the\n // character after its `>`, which is where its first child begins.\n frontmatterPosition: frontmatter\n ? {\n start: map.point(root) ?? { ...map.docEnd },\n end:\n map.point(root.firstChild) ??\n map.endOfLine(map.point(root)?.line ?? 1),\n }\n : null,\n sections: sectionize(fragments, map.docEnd),\n };\n}\n\nexport const xmlParser: DocumentParser = {\n name: \"xml\",\n label: \"XML\",\n kinds: [\n \"paragraph\",\n \"codeBlock\",\n \"list\",\n \"listItem\",\n \"table\",\n \"tableRow\",\n \"tableCell\",\n \"admonition\",\n \"image\",\n \"blockquote\",\n \"definitionList\",\n \"definitionItem\",\n ],\n /**\n * `.dita` and `.ditamap` as well as `.xml`, because that is what a DITA topic\n * and a DITA map are actually called on disk and docmeta registers both — a\n * docset whose topics this parser was written for would otherwise be walked\n * past entirely.\n *\n * A map carries no prose, but it is a tree of navigation entries, and that is\n * the same thing a section tree is: `<topicref>` nesting is section nesting.\n * A docset of maps with no map template matches nothing and is skipped as\n * `no-template`, exactly as an untyped Markdown page is.\n */\n extensions: [\".xml\", \".dita\", \".ditamap\"],\n /**\n * A directory walk collects `.dita` and `.ditamap` but not `.xml`. Both of\n * those are documentation by definition; `.xml` is a container a repository\n * uses for build files, sitemaps, and project metadata, none of which match a\n * documentation vocabulary. Sweeping those in made one `pom.xml` fail an\n * otherwise clean tree. Naming an `.xml` file explicitly still parses it.\n */\n walkExtensions: [\".dita\", \".ditamap\"],\n parse: (content, filePath) => parseXml(content, filePath),\n};\n","/**\n * AsciiDoc parser.\n *\n * Asciidoctor already hands back a nested block tree, so the work here is the\n * same as `mdast.ts`'s: flatten it into ordered `Fragment`s and let `sectionize`\n * rebuild the nesting. `table`, `admonition`, `image`, `quote` and `dlist`\n * contexts map onto the shared content model (proposal 0065); a context that\n * still has no kind there - `sidebar`, a thematic break, `verse`, `example`,\n * and so on - is skipped whole rather than mapped to a nearest neighbour, for\n * the reason the Markdown parser skips a construct it does not model: a\n * sidebar is not a paragraph, and counting one as such would make\n * `paragraphs: {max: 3}` fail a document a reader would say satisfies it.\n *\n * Two things about Asciidoctor shape this file:\n *\n * - **Positions come from line numbers, and only line numbers.** `load()` is\n * given `sourcemap: true` so every block carries `getLineNumber()`; nothing\n * reports where a block *ends*, and there are no columns or offsets at all.\n * Those are derived from a line-start index built once over the content.\n * The pre-rewrite `parsers/asciidoc.js` instead reconstructed a `=== Title`\n * marker and ran `content.indexOf()` on it, which mismatches on attribute\n * lines, duplicate titles, and any non-canonical heading syntax.\n * - **Metadata arrives two ways.** AsciiDoc's own is the document header -\n * `= Title` plus `:key: value` entries - and that is how a real page says\n * `:type: how-to`. Some toolchains prepend a Markdown-style `---` fence\n * instead, which is a thematic break to Asciidoctor, so `skip-front-matter`\n * consumes it rather than letting it parse as body content; line numbering\n * is unaffected, so the body still indexes the original file. Both readings\n * run, and the results merge.\n */\nimport { createRequire } from \"node:module\";\nimport type asciidoctor from \"@asciidoctor/core\";\nimport { extractFrontmatter, extractorForExtension } from \"../../meta/index.js\";\nimport type {\n AdmonitionNode,\n ContentNode,\n DefinitionItemNode,\n DocumentParser,\n DocumentTree,\n ListItemNode,\n Point,\n Position,\n TableCellNode,\n TableRowNode,\n} from \"../types.js\";\nimport { LintError } from \"../types.js\";\nimport { errorMessage } from \"../../shared/errors.js\";\nimport type { Fragment } from \"./sectionize.js\";\nimport { sectionize } from \"./sectionize.js\";\nimport {\n fencedPosition,\n withMetadataTitle as withFrontmatterTitle,\n withoutFence,\n} from \"./metadata.js\";\n\n/**\n * `@asciidoctor/core`, not the `asciidoctor` meta-package.\n *\n * Only the parser is wanted here. The meta-package adds `@asciidoctor/cli`\n * (and yargs) plus the ejs, nunjucks and pug template engines, none of which\n * this file can reach - 63 lockfile entries that installed with manni so that\n * one `.adoc` file could be read. The core is the same Asciidoctor at the same\n * version, published as a real ESM module, so the default import is the\n * factory with no CJS interop to undo.\n *\n * Stay on 3.x. `@asciidoctor/core@4` is a rewrite whose `load()` returns a\n * promise, and `DocumentParser.parse` is synchronous for every format. Moving\n * to it would also drop `@asciidoctor/opal-runtime` and with it the deprecated\n * `glob`/`inflight` pair, which 3.x still brings in on its own.\n *\n * Required on the first `.adoc` file rather than imported: Asciidoctor and the\n * Opal runtime cost every `manni lint` and `manni check` run a tenth of a\n * second, and most never read AsciiDoc. `parse` is synchronous, so this is\n * the package's own CommonJS build through `require`, not `await import()`.\n */\nlet processor: ReturnType<typeof asciidoctor> | undefined;\n\nfunction getProcessor(): ReturnType<typeof asciidoctor> {\n if (processor === undefined) {\n const factory = createRequire(import.meta.url)(\"@asciidoctor/core\") as typeof asciidoctor;\n processor = factory();\n }\n return processor;\n}\n\n/**\n * Minimal structural view of an Asciidoctor node.\n *\n * `getBlocks()` is typed `any[]` upstream and is not even homogeneous - a\n * description list returns `[[terms], description]` tuples rather than nodes -\n * so everything is read back through `asNode`, which checks for the one method\n * every real block has.\n */\ninterface AdocNode {\n getContext(): string;\n getLineNumber?(): number | undefined;\n getBlocks?(): unknown[];\n getLevel?(): number;\n getTitle?(): string | undefined;\n getSource?(): string;\n getContent?(): string;\n getAttribute?(name: string): unknown;\n getItems?(): unknown[];\n getRows?(): AdocRows;\n}\n\n/** A list item. Its principal text is not among its blocks. */\ninterface AdocItem {\n getLineNumber?(): number | undefined;\n getText(): string;\n getBlocks(): unknown[];\n}\n\n/** A table cell, from either a head, body or foot row. */\ninterface AdocCell {\n getLineNumber?(): number | undefined;\n getText(): string;\n}\n\n/** `Table#getRows()`'s own shape: the three row groups, each an array of cell rows. */\ninterface AdocRows {\n getHead(): AdocCell[][];\n getBody(): AdocCell[][];\n getFoot(): AdocCell[][];\n}\n\ninterface AdocDocument extends AdocNode {\n hasHeader(): boolean;\n getHeader(): unknown;\n}\n\nfunction asNode(value: unknown): AdocNode | null {\n const node = value as AdocNode | null;\n return node && typeof node.getContext === \"function\" ? node : null;\n}\n\nfunction asItem(value: unknown): AdocItem | null {\n const item = value as AdocItem | null;\n return item && typeof item.getText === \"function\" ? item : null;\n}\n\n/** Blocks of a container, filtered down to the ones that really are nodes. */\nfunction childrenOf(node: AdocNode): AdocNode[] {\n const blocks = node.getBlocks?.() ?? [];\n return blocks.map(asNode).filter((n): n is AdocNode => n !== null);\n}\n\nfunction lineOf(node: { getLineNumber?(): number | undefined }): number {\n return node.getLineNumber?.() ?? 1;\n}\n\n// ---------------------------------------------------------------------------\n// Positions\n// ---------------------------------------------------------------------------\n\n/**\n * Line numbers to `Point`s.\n *\n * The offsets a reporter prints, and the offsets `validateDocument` sorts\n * findings by, do not exist anywhere in Asciidoctor's output. They are all\n * recovered from one pass over the content that records where each line\n * starts, so a lookup is an array index rather than a search through the text.\n */\ninterface LineIndex {\n /** Column 1 of `line`. */\n start(line: number): Point;\n /** Just past the last character of `line`, before its line break. */\n endOfLine(line: number): Point;\n /** End of the document, for closing the final sections. */\n documentEnd(): Point;\n}\n\nfunction lineIndex(content: string): LineIndex {\n const starts: number[] = [0];\n for (let i = 0; i < content.length; i++) {\n if (content[i] === \"\\n\") starts.push(i + 1);\n }\n\n /** Line numbers come from a third-party tree; keep them inside the file. */\n const clamp = (line: number): number =>\n Math.min(Math.max(Math.trunc(line) || 1, 1), starts.length);\n\n /**\n * Offset of column 1 of a clamped line. `starts` opens with 0 and `clamp`\n * keeps the index inside it, so the fallback is unreachable - and 0 is where\n * a line clamped to 1 starts anyway.\n */\n const startOf = (n: number): number => starts[n - 1] ?? 0;\n\n return {\n start(line) {\n const n = clamp(line);\n return { line: n, column: 1, offset: startOf(n) };\n },\n endOfLine(line) {\n const n = clamp(line);\n const from = startOf(n);\n const next = starts[n];\n let stop = next === undefined ? content.length : next - 1;\n if (stop > from && content[stop - 1] === \"\\r\") stop -= 1;\n return { line: n, column: stop - from + 1, offset: stop };\n },\n documentEnd() {\n return {\n line: starts.length,\n column: content.length - startOf(starts.length) + 1,\n offset: content.length,\n };\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Inline text\n// ---------------------------------------------------------------------------\n\nconst NAMED_ENTITIES: Record<string, string> = {\n amp: \"&\",\n lt: \"<\",\n gt: \">\",\n quot: '\"',\n apos: \"'\",\n nbsp: \" \",\n};\n\n/**\n * Asciidoctor's plain-text rendering, flattened.\n *\n * `getTitle()`, `getContent()`, and `ListItem#getText()` all return inline\n * *HTML*: a heading written with backtick-quoted `lint` comes back as\n * `Use the <code>lint</code> command`. Stripping the tags and decoding the\n * entities is this format's equivalent of `mdast-util-to-string`, and it is\n * what makes `heading: {const: \"Overview\"}` mean the same thing here as it does\n * in Markdown.\n *\n * The one place it is lossy is Asciidoctor's `replacements` substitution, which\n * fires before we ever see the string: a straight apostrophe arrives as\n * `’` and flattens to a curly one, where Markdown would leave it alone.\n * That is Asciidoctor's conversion, not ours, and it exposes no way to ask for\n * a title with quotes substituted but replacements skipped.\n */\nfunction flattenInline(html: string | undefined): string {\n if (!html) return \"\";\n return html\n .replace(/<[^>]*>/g, \"\")\n .replace(/&#(\\d+);/g, (_, dec: string) => String.fromCodePoint(Number(dec)))\n .replace(/&#x([0-9a-f]+);/gi, (_, hex: string) =>\n String.fromCodePoint(Number.parseInt(hex, 16)),\n )\n .replace(\n /&([a-z]+);/gi,\n (whole: string, name: string) => NAMED_ENTITIES[name.toLowerCase()] ?? whole,\n );\n}\n\n// ---------------------------------------------------------------------------\n// Asciidoctor's tree -> drafts\n// ---------------------------------------------------------------------------\n\n/**\n * A block with a start line but no span yet.\n *\n * The walk cannot assign spans as it goes, because a block's end is the start\n * of whatever comes after it - which is only known once the whole document is\n * flat. So the walk emits drafts and `place` closes them.\n */\ntype Draft =\n | { kind: \"heading\"; line: number; level: number; title: string }\n | { kind: \"paragraph\"; line: number; text: string }\n | { kind: \"codeBlock\"; line: number; text: string; language?: string }\n | { kind: \"list\"; line: number; ordered: boolean; items: DraftItem[] }\n | { kind: \"table\"; line: number; rows: DraftRow[] }\n | {\n kind: \"admonition\";\n line: number;\n variant: AdmonitionNode[\"variant\"];\n children: Draft[];\n }\n | { kind: \"image\"; line: number; url: string; alt: string; title?: string }\n | { kind: \"blockquote\"; line: number; children: Draft[] }\n | { kind: \"definitionList\"; line: number; items: DraftDefinitionItem[] };\n\n/** Every draft but a heading, which is the only kind that is not content. */\ntype ContentDraft = Exclude<Draft, { kind: \"heading\" }>;\n\ninterface DraftItem {\n line: number;\n text: string;\n children: Draft[];\n}\n\ninterface DraftCell {\n line: number;\n text: string;\n}\n\ninterface DraftRow {\n line: number;\n header: boolean;\n cells: DraftCell[];\n}\n\ninterface DraftDefinitionItem {\n line: number;\n term: string;\n children: Draft[];\n}\n\nfunction stringAttribute(node: AdocNode, name: string): string | undefined {\n const value = node.getAttribute?.(name);\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\nfunction draftList(node: AdocNode, ordered: boolean): Draft {\n const items: DraftItem[] = [];\n\n for (const raw of node.getItems?.() ?? []) {\n const item = asItem(raw);\n if (!item) continue;\n\n const line = lineOf(item);\n const text = flattenInline(item.getText());\n const children: Draft[] = [];\n\n // An item's principal text is not one of its blocks, but mdast puts it in\n // a paragraph child - so `lists: {items: {paragraphs: {min: 1}}}` counts\n // the same thing in both formats only if we put it there too.\n if (text.length > 0) children.push({ kind: \"paragraph\", line, text });\n collect(\n item.getBlocks().map(asNode).filter((n): n is AdocNode => n !== null),\n children,\n );\n\n items.push({ line, text, children });\n }\n\n return { kind: \"list\", line: lineOf(node), ordered, items };\n}\n\n/**\n * A block's own children, recursively drafted - the same walk `collect` does\n * at document level, reused for a container whose content is content in its\n * own right (an admonition, a blockquote) rather than a section's directly.\n */\nfunction draftChildren(node: AdocNode): Draft[] {\n const children: Draft[] = [];\n collect(childrenOf(node), children);\n return children;\n}\n\n/**\n * AsciiDoc's own admonition vocabulary is closed - `NOTE`, `TIP`, `IMPORTANT`,\n * `CAUTION`, `WARNING`, and nothing else; there is no `DANGER`. So unlike a\n * format with free-form admonition naming, every real admonition here maps\n * cleanly onto the shared vocabulary, and only a node whose `name` attribute\n * is missing or unrecognised - which real AsciiDoc input cannot produce -\n * fails to.\n */\nconst ADMONITION_VARIANTS = new Set<string>([\n \"note\",\n \"tip\",\n \"important\",\n \"caution\",\n \"warning\",\n]);\n\nfunction admonitionVariant(node: AdocNode): AdmonitionNode[\"variant\"] | null {\n const name = stringAttribute(node, \"name\")?.toLowerCase();\n return name && ADMONITION_VARIANTS.has(name)\n ? (name as AdmonitionNode[\"variant\"])\n : null;\n}\n\n/**\n * An admonition's content, whichever of the two forms it took.\n *\n * A compound admonition (`[TIP]\\n====\\n...\\n====`) has real blocks, and\n * `getContent()` on it returns their *rendered* concatenation - using both\n * would double the content. A simple one (`NOTE: text`) has no blocks at all;\n * its only content is `getContent()`, exactly as a paragraph's is.\n */\nfunction draftAdmonition(node: AdocNode, variant: AdmonitionNode[\"variant\"]): Draft {\n const children = draftChildren(node);\n if (children.length === 0) {\n const text = flattenInline(node.getContent?.());\n if (text.length > 0) children.push({ kind: \"paragraph\", line: lineOf(node), text });\n }\n return { kind: \"admonition\", line: lineOf(node), variant, children };\n}\n\n/** A quote block's content, by the same two-form rule as an admonition's. */\nfunction draftBlockquote(node: AdocNode): Draft {\n const children = draftChildren(node);\n if (children.length === 0) {\n const text = flattenInline(node.getContent?.());\n if (text.length > 0) children.push({ kind: \"paragraph\", line: lineOf(node), text });\n }\n return { kind: \"blockquote\", line: lineOf(node), children };\n}\n\nfunction draftTable(node: AdocNode): Draft {\n const rows = node.getRows?.();\n const toRow = (header: boolean) => (cells: AdocCell[]): DraftRow => ({\n line: cells[0]?.getLineNumber?.() ?? lineOf(node),\n header,\n cells: cells.map((cell) => ({\n line: cell.getLineNumber?.() ?? lineOf(node),\n text: flattenInline(cell.getText()),\n })),\n });\n return {\n kind: \"table\",\n line: lineOf(node),\n rows: [\n ...(rows?.getHead().map(toRow(true)) ?? []),\n ...(rows?.getBody().map(toRow(false)) ?? []),\n ...(rows?.getFoot().map(toRow(false)) ?? []),\n ],\n };\n}\n\n/**\n * A description list's items.\n *\n * `getItems()` does not hand back `ListItem`s for a `dlist` the way it does\n * for a `ulist`/`olist`; each entry is a `[terms, description]` tuple, and a\n * missing description arrives as AsciiDoctor's own `nil`, which is a real\n * object in the JS bridge rather than `null` or `undefined` - `asItem` rejects\n * it the same way it rejects anything else with no `getText`.\n */\nfunction draftDefinitionList(node: AdocNode): Draft {\n const items: DraftDefinitionItem[] = [];\n\n for (const entry of node.getItems?.() ?? []) {\n if (!Array.isArray(entry)) continue;\n const [rawTerms, rawDesc] = entry as [unknown, unknown];\n const terms = (Array.isArray(rawTerms) ? rawTerms : [])\n .map(asItem)\n .filter((t): t is AdocItem => t !== null);\n const first = terms[0];\n if (!first) continue;\n\n const children: Draft[] = [];\n const desc = asItem(rawDesc);\n if (desc) {\n const text = flattenInline(desc.getText());\n if (text.length > 0) children.push({ kind: \"paragraph\", line: lineOf(desc), text });\n collect(\n desc.getBlocks().map(asNode).filter((n): n is AdocNode => n !== null),\n children,\n );\n }\n\n items.push({\n line: lineOf(first),\n term: terms.map((t) => flattenInline(t.getText())).join(\", \"),\n children,\n });\n }\n\n return { kind: \"definitionList\", line: lineOf(node), items };\n}\n\n/** One block, or null when the content model has no kind for it. */\nfunction draftOf(node: AdocNode): Draft | null {\n switch (node.getContext()) {\n case \"paragraph\":\n return {\n kind: \"paragraph\",\n line: lineOf(node),\n text: flattenInline(node.getContent?.()),\n };\n case \"listing\":\n case \"literal\": {\n const lang = stringAttribute(node, \"language\");\n return {\n kind: \"codeBlock\",\n line: lineOf(node),\n // Raw, not converted: a code block's text is its source, and\n // `getContent()` would escape every `<` in it.\n text: node.getSource?.() ?? \"\",\n ...(lang ? { language: lang } : {}),\n };\n }\n case \"ulist\":\n return draftList(node, false);\n case \"olist\":\n return draftList(node, true);\n case \"table\":\n return draftTable(node);\n case \"admonition\": {\n const variant = admonitionVariant(node);\n return variant ? draftAdmonition(node, variant) : null;\n }\n case \"image\": {\n const url = stringAttribute(node, \"target\");\n if (!url) return null;\n const title = flattenInline(node.getTitle?.());\n return {\n kind: \"image\",\n line: lineOf(node),\n url,\n alt: stringAttribute(node, \"alt\") ?? \"\",\n ...(title.length > 0 ? { title } : {}),\n };\n }\n case \"quote\":\n return draftBlockquote(node);\n case \"dlist\":\n return draftDefinitionList(node);\n default:\n // Sidebars, thematic breaks, verses, and the rest the content model\n // does not name. Skipped whole: their children are not the section's\n // content either.\n return null;\n }\n}\n\n/**\n * Flatten a container's children into drafts, in document order.\n *\n * `section` contributes a heading and then its own children as siblings, which\n * is what turns Asciidoctor's nesting back into the flat stream `sectionize`\n * folds.\n *\n * Two containers are transparent - recursed through, contributing nothing of\n * their own - because neither is a construct the author meant as content:\n *\n * - `preamble`, a wrapper Asciidoctor inserts between a document title and the\n * first section. Skipping it would swallow the lead prose.\n * - `open` (`--`). That is how an author attaches several blocks to one list\n * item, so skipping it would make a numbered step's whole body invisible to\n * a template. The constructs a `--` block can be *turned into* do not arrive\n * here at all: `[NOTE]` becomes an `admonition`, `[quote]` a `quote`,\n * `[sidebar]` a `sidebar`, each with its own context and each skipped by the\n * default branch, which is the line mdast draws around a blockquote. So a\n * node still reporting `open` is the bare attach-blocks form by elimination.\n */\nfunction collect(nodes: AdocNode[], out: Draft[]): void {\n for (const node of nodes) {\n const context = node.getContext();\n\n if (context === \"section\") {\n out.push({\n kind: \"heading\",\n line: lineOf(node),\n // Asciidoctor's `=` title is level 0, so every level is one shallower\n // than the heading level the rest of the tool speaks in.\n level: (node.getLevel?.() ?? 0) + 1,\n title: flattenInline(node.getTitle?.()),\n });\n collect(childrenOf(node), out);\n continue;\n }\n\n if (context === \"preamble\" || context === \"open\") {\n collect(childrenOf(node), out);\n continue;\n }\n\n const draft = draftOf(node);\n if (draft) out.push(draft);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Drafts -> blocks\n// ---------------------------------------------------------------------------\n\n/**\n * Give every draft a span.\n *\n * A heading spans its own title line, the way an mdast heading spans its `#`\n * line. Everything else ends where the next block begins, and the last block at\n * `end` - the convention `sectionize` already uses for sections, applied one\n * level down because Asciidoctor reports where a block starts and nothing at\n * all about where it stops.\n */\nfunction place(drafts: Draft[], end: Point, index: LineIndex): Fragment[] {\n return drafts.map((draft, i): Fragment => {\n const next = drafts[i + 1];\n const boundary = next ? index.start(next.line) : end;\n\n if (draft.kind === \"heading\") {\n return {\n type: \"heading\",\n level: draft.level,\n title: draft.title,\n position: {\n start: index.start(draft.line),\n end: index.endOfLine(draft.line),\n },\n };\n }\n\n return {\n type: \"content\",\n node: contentNode(\n draft,\n { start: index.start(draft.line), end: boundary },\n index,\n ),\n };\n });\n}\n\n/** `place`, for content that cannot contain a heading. */\nfunction placeContent(drafts: Draft[], end: Point, index: LineIndex): ContentNode[] {\n return place(drafts, end, index).flatMap((fragment) =>\n fragment.type === \"content\" ? [fragment.node] : [],\n );\n}\n\nfunction placeItems(items: DraftItem[], end: Point, index: LineIndex): ListItemNode[] {\n return items.map((item, i) => {\n const next = items[i + 1];\n const boundary = next ? index.start(next.line) : end;\n return {\n kind: \"listItem\",\n position: { start: index.start(item.line), end: boundary },\n text: item.text,\n children: placeContent(item.children, boundary, index),\n };\n });\n}\n\n/**\n * A table cell's own span: its starting line only.\n *\n * Asciidoctor reports a line per cell, but several cells on one row commonly\n * share a single source line, so there is no line-based boundary between\n * them the way there is between rows or list items. A cell spans just the\n * line it starts on, the way a heading spans its own title line.\n */\nfunction placeCells(cells: DraftCell[], index: LineIndex): TableCellNode[] {\n return cells.map((cell) => ({\n kind: \"tableCell\",\n position: { start: index.start(cell.line), end: index.endOfLine(cell.line) },\n text: cell.text,\n children: [],\n }));\n}\n\nfunction placeRows(rows: DraftRow[], end: Point, index: LineIndex): TableRowNode[] {\n return rows.map((row, i) => {\n const next = rows[i + 1];\n const boundary = next ? index.start(next.line) : end;\n const cells = placeCells(row.cells, index);\n return {\n kind: \"tableRow\",\n position: { start: index.start(row.line), end: boundary },\n text: cells.map((cell) => cell.text).join(\" | \"),\n header: row.header,\n children: cells,\n };\n });\n}\n\nfunction placeDefinitionItems(\n items: DraftDefinitionItem[],\n end: Point,\n index: LineIndex,\n): DefinitionItemNode[] {\n return items.map((item, i) => {\n const next = items[i + 1];\n const boundary = next ? index.start(next.line) : end;\n const definition = placeContent(item.children, boundary, index);\n const definitionText = definition.map((node) => node.text).join(\" \");\n return {\n kind: \"definitionItem\",\n position: { start: index.start(item.line), end: boundary },\n text: definitionText.length > 0 ? `${item.term}: ${definitionText}` : item.term,\n term: item.term,\n definition,\n };\n });\n}\n\nfunction contentNode(\n draft: ContentDraft,\n position: Position,\n index: LineIndex,\n): ContentNode {\n switch (draft.kind) {\n case \"paragraph\":\n return { kind: \"paragraph\", position, text: draft.text };\n case \"codeBlock\":\n return {\n kind: \"codeBlock\",\n position,\n text: draft.text,\n ...(draft.language ? { language: draft.language } : {}),\n };\n case \"list\":\n return {\n kind: \"list\",\n position,\n // Informational only - no rule reads a list's own text - so the items\n // are joined one per line rather than run together the way\n // `mdast-util-to-string` concatenates them.\n text: draft.items.map((item) => item.text).join(\"\\n\"),\n ordered: draft.ordered,\n items: placeItems(draft.items, position.end, index),\n };\n case \"table\": {\n const rows = placeRows(draft.rows, position.end, index);\n return {\n kind: \"table\",\n position,\n text: rows.map((row) => row.text).join(\"\\n\"),\n children: rows,\n };\n }\n case \"admonition\": {\n const children = placeContent(draft.children, position.end, index);\n return {\n kind: \"admonition\",\n position,\n text: children.map((node) => node.text).join(\"\\n\\n\"),\n variant: draft.variant,\n children,\n };\n }\n case \"image\":\n return {\n kind: \"image\",\n position,\n text: draft.alt,\n url: draft.url,\n alt: draft.alt,\n ...(draft.title ? { title: draft.title } : {}),\n };\n case \"blockquote\": {\n const children = placeContent(draft.children, position.end, index);\n return {\n kind: \"blockquote\",\n position,\n text: children.map((node) => node.text).join(\"\\n\\n\"),\n children,\n };\n }\n case \"definitionList\": {\n const children = placeDefinitionItems(draft.items, position.end, index);\n return {\n kind: \"definitionList\",\n position,\n // `item.text`, which is `\"term: definition\"`, not `item.term`. A\n // node's `text` is its flattened rendering, so dropping the definition\n // bodies here would make a pattern rule find a word in every format\n // except this one.\n text: children.map((item) => item.text).join(\"\\n\"),\n children,\n };\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Document metadata\n// ---------------------------------------------------------------------------\n\n/**\n * The AsciiDoc-aware reader, which the plain `extractFrontmatter` is not.\n *\n * `extractFrontmatter(content, \"asciidoc\")` reads only the fenced `--- ... ---`\n * block some toolchains prepend - its format argument is a label copied onto\n * the result, not a parser selector. AsciiDoc's own metadata is the document\n * header: the `= Title` line plus `:key: value` attribute entries, up to the\n * first blank line. That is how a real page declares `:type: how-to`, and\n * reading it is what makes type routing work for `.adoc` at all.\n */\nconst nativeExtractor = extractorForExtension(\".adoc\");\n\ninterface Metadata {\n data: Record<string, unknown> | null;\n position: Position | null;\n}\n\n/**\n * Span of the native header: the run of lines before the first blank one,\n * which is exactly the range docmeta's extractor reads attributes from.\n */\nfunction headerPosition(content: string, index: LineIndex): Position | null {\n let last = 0;\n for (const [i, line] of content.split(/\\r?\\n/).entries()) {\n if (line.trim() === \"\") break;\n last = i + 1;\n }\n if (last === 0) return null;\n return { start: index.start(1), end: index.endOfLine(last) };\n}\n\n/**\n * Both metadata styles, merged, with the fenced block winning a key collision:\n * a file carrying a fence has chosen it as its metadata of record. `present` is\n * the OR of the two, so a page with only `:type: how-to` still reports\n * frontmatter and still routes.\n */\nfunction metadata(content: string, filePath: string, index: LineIndex): Metadata {\n const fenced = extractFrontmatter(content, \"asciidoc\");\n // Read the native header from the fence-free remainder: docmeta's AsciiDoc\n // extractor returns the fence and stops when one is present, so asking it\n // about the whole file would discard `:type:` on any page that has both.\n const native = nativeExtractor?.extract(\n fenced.present ? withoutFence(content) : content,\n filePath,\n );\n\n if (!fenced.present && !native?.present) return { data: null, position: null };\n\n return {\n data: { ...(native?.data ?? {}), ...(fenced.present ? fenced.data : {}) },\n position:\n (fenced.present ? fencedPosition(content) : null) ??\n headerPosition(content, index),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Parser\n// ---------------------------------------------------------------------------\n\nfunction load(content: string, filePath: string): AdocDocument {\n const asciidoc = getProcessor();\n try {\n return asciidoc.load(content, {\n // Without this every block's `getLineNumber()` is undefined and there are\n // no positions to derive at all.\n sourcemap: true,\n // A leading `---` fence is a thematic break in AsciiDoc; this consumes it\n // as metadata instead, without disturbing line numbering.\n attributes: { \"skip-front-matter\": true },\n }) as unknown as AdocDocument;\n } catch (err) {\n // Asciidoctor recovers from malformed *documents* - it warns about an\n // unterminated block and carries on - so this fires when the loader itself\n // refuses the input. Either way it is the file's problem, not a crash.\n throw new LintError(\n `${filePath}: could not parse as asciidoc: ${errorMessage(err)}`,\n );\n }\n}\n\n/**\n * The document title, as a heading block.\n *\n * `= Title` is not a block: Asciidoctor keeps it as the document header, and\n * `getDocumentTitle()` lies about it - with no header at all it falls back to\n * the first section's title - so this goes through `hasHeader()`. A header made\n * only of attribute entries has no title to contribute, and emitting an empty\n * heading for it would both invent a section and block the frontmatter title\n * those attributes may be carrying.\n */\nfunction headerDraft(doc: AdocDocument): Draft | null {\n if (!doc.hasHeader()) return null;\n const header = asNode(doc.getHeader());\n if (!header) return null;\n const title = flattenInline(header.getTitle?.());\n if (title.length === 0) return null;\n return {\n kind: \"heading\",\n line: lineOf(header),\n level: (header.getLevel?.() ?? 0) + 1,\n title,\n };\n}\n\nfunction parse(content: string, filePath: string): DocumentTree {\n const doc = load(content, filePath);\n const index = lineIndex(content);\n\n const drafts: Draft[] = [];\n const header = headerDraft(doc);\n if (header) drafts.push(header);\n collect(childrenOf(doc), drafts);\n\n const meta = metadata(content, filePath, index);\n const end = index.documentEnd();\n\n return {\n format: \"asciidoc\",\n filePath,\n frontmatter: meta.data,\n frontmatterPosition: meta.position,\n sections: sectionize(\n withFrontmatterTitle(place(drafts, end, index), meta.data, meta.position),\n end,\n ),\n };\n}\n\nexport const asciidocParser: DocumentParser = {\n name: \"asciidoc\",\n label: \"AsciiDoc\",\n kinds: [\n \"paragraph\",\n \"codeBlock\",\n \"list\",\n \"listItem\",\n \"table\",\n \"tableRow\",\n \"tableCell\",\n \"admonition\",\n \"image\",\n \"blockquote\",\n \"definitionList\",\n \"definitionItem\",\n ],\n extensions: [\".adoc\", \".asciidoc\"],\n parse,\n};\n","/**\n * Parser registry. Maps file extensions to parsers and resolves a parser by\n * name for the `--as` override.\n *\n * Shaped after docmeta's extractor registry, and for the same reason:\n * everything downstream of `parse()` operates on the generic `DocumentTree`, so\n * adding a format is one file plus one line here - no change to matching,\n * rules, templates, or reporting.\n *\n * A format is registered here when, and only when, a parser reads it. That is\n * what `manni lint tools` lists and what `--as` accepts, so neither can name a\n * format the tool does not read. An extension no parser claims is skipped by\n * name, never parsed as Markdown the way the pre-rewrite `inferFileType` did.\n */\nimport type { ContentKind, DocumentParser } from \"../types.js\";\nimport { markdownParser, mdxParser } from \"./markdown.js\";\nimport { htmlParser } from \"./html.js\";\nimport { rstParser } from \"./rst.js\";\nimport { xmlParser } from \"./xml.js\";\nimport { asciidocParser } from \"./asciidoc.js\";\n\nexport const PARSERS: DocumentParser[] = [\n markdownParser,\n mdxParser,\n htmlParser,\n asciidocParser,\n rstParser,\n xmlParser,\n];\n\nconst byExtension = new Map<string, DocumentParser>();\nconst byName = new Map<string, DocumentParser>();\nfor (const parser of PARSERS) {\n byName.set(parser.name, parser);\n for (const ext of parser.extensions) byExtension.set(ext.toLowerCase(), parser);\n}\n\n/** Resolve a parser for a file extension (including the dot). */\nexport function parserForExtension(ext: string): DocumentParser | undefined {\n return byExtension.get(ext.toLowerCase());\n}\n\n/** Resolve a parser by its `--as` name. */\nexport function parserByName(name: string): DocumentParser | undefined {\n return byName.get(name.toLowerCase());\n}\n\n/** Extensions collected from a directory walk. */\nexport function supportedExtensions(): string[] {\n return PARSERS.flatMap((p) => p.walkExtensions ?? p.extensions);\n}\n\n/** Every format the tool reads, for `manni lint tools`. */\nexport function listFormats(): {\n name: string;\n label: string;\n extensions: string[];\n kinds: ContentKind[];\n}[] {\n return PARSERS.map((p) => ({\n name: p.name,\n label: p.label,\n extensions: p.extensions,\n kinds: p.kinds,\n }));\n}\n","/**\n * Source of truth for templates. Holds the built-in doctype templates\n * (addressed by `vendor:name:version`-style ids) and knows how to load any\n * template reference - a built-in id, a local `.yaml`/`.yml`/`.json` path, or\n * an `http(s)` URL, optionally naming one template inside a file with a `#`\n * fragment (`./templates.yaml#how-to`).\n *\n * Two ordering decisions are load-bearing:\n *\n * - A file is dereferenced *before* it is validated. `$ref` is how a template\n * file shares one section rule between templates, and a section rule is\n * `additionalProperties: false`, so any `$ref` still standing at validation\n * time would be reported as an unexpected key.\n * - `instructions` is looked for by hand *before* Ajv runs. The schema rejects\n * it too (`not: {required: [\"instructions\"]}`), but a raw schema error says\n * nothing useful about where the feature went; scanning the parsed data\n * directly is both more reliable than reverse-engineering which Ajv error\n * came from the `not` keyword and the only way to quote the author's own\n * instruction back at them in the migration snippet.\n *\n * `extends` is deliberately *not* resolved by `loadTemplate`. Inheritance needs\n * a resolver that knows what a relative ref is relative to, which only the\n * caller knows, so `resolveExtends` takes that resolver as an argument.\n */\nimport { readFile } from \"node:fs/promises\";\nimport { dirname, isAbsolute, join, resolve as resolvePath } from \"node:path\";\nimport { packageRoot } from \"../../shared/package-root.js\";\nimport { parse as parseYaml } from \"yaml\";\nimport { dereference } from \"@apidevtools/json-schema-ref-parser\";\nimport * as AjvNs from \"ajv\";\nimport type { ErrorObject, SchemaObject, ValidateFunction } from \"ajv\";\nimport { LintError } from \"../types.js\";\nimport { errorMessage } from \"../../shared/errors.js\";\nimport { warn } from \"../../shared/warn.js\";\nimport { BLOCK_KINDS, isWildcard, occurrenceRange } from \"./template.js\";\nimport type {\n BlockRule,\n ListItemsRule,\n Occurrences,\n Rule,\n Template,\n TemplateFile,\n} from \"./template.js\";\nimport templateFileSchema from \"../../../schemas/lint/template.json\" with { type: \"json\" };\nimport tgdpManifest from \"../../../templates/lint/tgdp/manifest.json\" with { type: \"json\" };\n\n// ajv is CommonJS with a default export; under NodeNext the constructable\n// value lives on `.default`. Cast through the named default type so tsc sees a\n// constructor.\ntype AjvCtor = typeof import(\"ajv\").default;\nconst Ajv = AjvNs.default as unknown as AjvCtor;\n\n/**\n * Options for both `dereference` calls, named so the two cannot drift apart.\n *\n * `resolve.external: false` confines `$ref` to the file it is written in. A\n * template file is untrusted input - `loadTemplateFile` will fetch one over\n * `http(s)`, and a local one is only as trustworthy as whoever wrote it, who is\n * not necessarily whoever runs the lint. The dereferencer resolves a `$ref` by\n * reading the file or making the request it names, from the linting host and\n * with its privileges. Left on, `$ref: /etc/passwd` or\n * `$ref: http://169.254.169.254/latest/meta-data/` in a template turned a lint\n * run into an arbitrary read, and a remote template into one that reports back\n * what it found.\n *\n * Nothing in the template DSL wants it. `$ref` is documented as how one file\n * shares a section rule between its own templates, and reuse *across* files is\n * what `extends` is for - which goes through `loadTemplate`, is re-based against\n * the declaring file, and is cycle-checked. Same-document (`#/...`) pointers are\n * untouched; an external one is left standing instead, and the schema then\n * rejects it as an unexpected `$ref` key rather than following it.\n */\nconst DEREFERENCE_OPTIONS = { resolve: { external: false } };\n\nexport interface BuiltinInfo {\n id: string;\n title: string;\n types: string[];\n}\n\n/**\n * Built-in doctype templates.\n *\n * The manifest is a JSON import, so it is bundled and `listBuiltins()` stays\n * synchronous. The templates themselves are YAML files beside it, read on\n * demand: they are meant to be opened, read, and copied by anyone writing their\n * own template, and YAML is the format that survives that. They ship at the\n * package root as `templates/lint/**`, listed in `files`, and are found by\n * walking up from this module to `package.json`, which works identically from\n * source and from the built package.\n */\ninterface ManifestEntry {\n id: string;\n file: string;\n title: string;\n types: string[];\n /** Upstream file this was derived from, for provenance. */\n source?: string;\n}\n\ninterface Manifest {\n vendor: string;\n upstream: string;\n pin: string;\n templates: ManifestEntry[];\n}\n\nconst MANIFESTS: Manifest[] = [tgdpManifest];\n\nconst BUILTINS = new Map<string, ManifestEntry>();\nfor (const manifest of MANIFESTS) {\n for (const entry of manifest.templates) BUILTINS.set(entry.id, entry);\n}\n\n/** Parsed built-ins, keyed by id. Populated on first load. */\nconst builtinCache = new Map<string, Template>();\n\nexport function listBuiltins(): BuiltinInfo[] {\n return [...BUILTINS.values()].map((entry) => ({\n id: entry.id,\n title: entry.title,\n types: entry.types,\n }));\n}\n\n/**\n * Locate a built-in's YAML at the package root.\n *\n * The templates ship as `templates/lint/**` beside `package.json`. Resolving\n * from the package root rather than from `import.meta.url` is what keeps one\n * path correct both in the repo, where this module sits under\n * `src/lint/core/`, and in the bundle, where it sits in `dist/`.\n */\nasync function readBuiltinFile(id: string, file: string): Promise<string> {\n const path = join(packageRoot(import.meta.url), \"templates\", \"lint\", file);\n try {\n return await readFile(path, \"utf8\");\n } catch (err) {\n throw new LintError(\n `Built-in template \"${id}\" is registered but its file could not be read (${path}): ${errorMessage(err)}`,\n );\n }\n}\n\n/**\n * Read, validate, and cache one built-in.\n *\n * Built-ins go through exactly the same schema validation as a user's file. A\n * template we ship is not more trustworthy than one you write - it is only\n * better tested - and a shipped template that violates its own schema should\n * fail loudly here rather than behave strangely during matching.\n */\nasync function loadBuiltin(id: string): Promise<Template> {\n const cached = builtinCache.get(id);\n if (cached) return cached;\n\n // Every caller checks `BUILTINS.has` first, so this is an internal\n // invariant rather than a user error - but it fails loudly all the same,\n // because the alternative is a `TypeError` several lines later on a field\n // of `undefined`.\n const entry = BUILTINS.get(id);\n if (!entry) {\n throw new LintError(`No built-in template is registered under \"${id}\".`);\n }\n const raw = await readBuiltinFile(id, entry.file);\n\n // The same guard `loadTemplateFile` applies to an outside file. A built-in\n // is ours and should never fail it, which is the point: if one ever does,\n // this says which file and what it held, rather than letting `dereference`\n // report something opaque about a value it did not expect.\n const parsed: unknown = parseYaml(raw);\n if (!isRecord(parsed)) {\n throw new LintError(\n `Built-in template \"${id}\" (${entry.file}) is not a template file: ` +\n `expected an object at the top level, got ${\n parsed === null ? \"null\" : Array.isArray(parsed) ? \"an array\" : typeof parsed\n }.`,\n );\n }\n\n const file = validateTemplateFile(\n await dereference<Record<string, unknown>>(parsed, DEREFERENCE_OPTIONS),\n entry.file,\n );\n const names = Object.keys(file.templates ?? {});\n const template = file.templates?.[names[0] ?? \"\"];\n if (!template || names.length !== 1) {\n throw new LintError(\n `Built-in template \"${id}\" must define exactly one template, found ${names.length}.`,\n );\n }\n\n // `types` lives in the manifest so the type map can be built without reading\n // every YAML file; mirror it onto the template so both agree.\n const resolved: Template = { types: entry.types, ...template };\n builtinCache.set(id, resolved);\n return resolved;\n}\n\nexport type RefKind = \"builtin\" | \"file\" | \"url\";\n\n/**\n * A built-in id looks like `seg(:seg)+` using only [a-z0-9._-] segments, with\n * no path separators and no template-file extension. This deliberately\n * excludes Windows paths (`C:\\...`), URLs, and `.yaml`/`.yml`/`.json` files so\n * a typo'd built-in is reported as an unknown id rather than silently treated\n * as a missing file.\n */\nconst BUILTIN_ID = /^[a-z0-9][a-z0-9._-]*(?::[a-z0-9][a-z0-9._-]*)+$/i;\n\nconst FILE_EXTENSIONS = [\".yaml\", \".yml\", \".json\"];\n\nexport function classifyRef(ref: string): { kind: RefKind; ref: string } {\n if (/^https?:\\/\\//i.test(ref)) return { kind: \"url\", ref };\n const lower = ref.toLowerCase();\n if (\n !ref.includes(\"/\") &&\n !ref.includes(\"\\\\\") &&\n !FILE_EXTENSIONS.some((ext) => lower.endsWith(ext)) &&\n BUILTIN_ID.test(ref)\n ) {\n return { kind: \"builtin\", ref };\n }\n return { kind: \"file\", ref };\n}\n\n/** Default network timeout for fetching a remote (`http(s)`) template file. */\nconst DEFAULT_TIMEOUT_MS = 10_000;\n\nexport interface LoadTemplateOptions {\n /** Abort a remote fetch after this many ms (default 10_000). */\n timeoutMs?: number;\n}\n\n/* -------------------------------------------------------------------------- *\n * Validation\n * -------------------------------------------------------------------------- */\n\n// `useDefaults` is deliberately off, and the schema declares no `default`\n// anywhere. A default Ajv writes into the data is indistinguishable from a\n// value the author typed, so it beats the parent's real value in an `extends`\n// merge. Every default in this format lives in the code that reads it\n// (`occurrenceRange`), where an absent key stays absent.\nconst ajv = new Ajv();\n\nlet compiled: ValidateFunction | null = null;\n\nfunction fileValidator(): ValidateFunction {\n compiled ??= ajv.compile(templateFileSchema as SchemaObject);\n return compiled;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/** One `instructions` key found in a template file, and where it lives. */\ninterface InstructionsHit {\n /** Dotted path to the rule carrying it, e.g. `templates.how-to.sections.title`. */\n path: string;\n /** Suggested eval name, kebab-cased from the path. */\n name: string;\n /** The instruction strings, verbatim. */\n values: string[];\n}\n\n/** The strings in an `instructions:` value, whatever shape it was written in. */\nfunction stringsOf(value: unknown): string[] {\n if (typeof value === \"string\") return [value];\n if (Array.isArray(value)) return value.filter((v): v is string => typeof v === \"string\");\n return [];\n}\n\n/**\n * Name for the suggested eval: the path with the structural keys (`templates`,\n * `sections`) dropped, kebab-cased. `templates.how-to.sections.title` becomes\n * `how-to-title`.\n */\nfunction suggestEvalName(segments: string[]): string {\n const name = segments\n .filter((segment) => segment !== \"templates\" && segment !== \"sections\")\n .join(\"-\")\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n return name || \"section-instructions\";\n}\n\n/**\n * First `instructions` key anywhere in a parsed template file.\n *\n * Dereferencing can make two rules share one object, and a self-referential\n * `$ref` can make the tree cyclic, hence the `seen` set.\n */\nfunction findInstructions(\n node: unknown,\n segments: string[] = [],\n seen = new WeakSet(),\n): InstructionsHit | null {\n if (typeof node !== \"object\" || node === null) return null;\n if (seen.has(node)) return null;\n seen.add(node);\n\n if (Array.isArray(node)) {\n for (const [index, item] of node.entries()) {\n const hit = findInstructions(item, [...segments, String(index)], seen);\n if (hit) return hit;\n }\n return null;\n }\n\n const record = node as Record<string, unknown>;\n\n // Only a section's own `instructions` *property* is the legacy key. Inside a\n // `sections:` map the keys are section names the author chose, and a section\n // legitimately called \"instructions\" - TGDP's README doctype wants one - must\n // not be mistaken for it. So descend into a `sections` map without testing\n // its keys, and test the property everywhere else.\n const insideSectionsMap = segments.at(-1) === \"sections\";\n if (!insideSectionsMap && \"instructions\" in record) {\n return {\n path: segments.join(\".\"),\n name: suggestEvalName(segments),\n values: stringsOf(record.instructions),\n };\n }\n for (const [key, value] of Object.entries(record)) {\n const hit = findInstructions(value, [...segments, key], seen);\n if (hit) return hit;\n }\n return null;\n}\n\n/**\n * The message a template still carrying `instructions` gets: what replaced the\n * feature, and the config to paste, with the author's own instruction in it.\n */\nfunction instructionsMessage(source: string, hit: InstructionsHit): string {\n const assertion = hit.values[0] ?? \"\";\n return [\n `${source}: \"${hit.path}\" uses \\`instructions\\`, which manni lint no longer evaluates — structure checking is deterministic. Move it to a manni docevals assertion eval in manni.config.yaml:`,\n \"\",\n \" docevals:\",\n \" evals:\",\n ` ${hit.name}:`,\n ` assertion: ${assertion}`,\n \" grader: ai\",\n ].join(\"\\n\");\n}\n\n/* -------------------------------------------------------------------------- *\n * Refusing a v1 file\n *\n * v1 never shipped, so there is no migration mode and no alias. What there is\n * instead is a sentence per key naming the v2 spelling, because a v1 file is\n * what anyone who tried the format early still has on disk. Left to the schema\n * these all read as \"must NOT have additional properties\", which says nothing\n * about where the key went.\n *\n * The scan runs before Ajv, for the same reason the `instructions` scan does.\n * -------------------------------------------------------------------------- */\n\n/** v1 keys that are gone outright, and what to write instead. */\nconst V1_KEYS: Record<string, string> = {\n required: '\"required\" is not a template key. A rule is optional with \"min: 0\".',\n additionalSections:\n '\"additionalSections\" is not a template key. v2 has no equivalent, so drop it.',\n code_blocks: '\"code_blocks\" is not a template key. The v2 spelling is \"codeBlocks\".',\n};\n\nconst V1_SECTIONS_MAP =\n '\"sections\" is a list of rules, not a map. Name each rule with \"id\" and list them in order.';\n\nconst V1_REPEAT_BOOLEAN =\n '\"repeat\" is a list of rules, not a boolean. A rule repeats through \"min\" and \"max\".';\n\nconst V1_PARAGRAPH_PATTERNS =\n '\"patterns\" is not a paragraphs key. The v2 spelling is \"pattern\", one regular expression.';\n\n/**\n * The first v1 key anywhere under `templates` or `components`.\n *\n * `info` is skipped: it is free-form by contract, so a key of one of these\n * names in it is the author's own metadata rather than a template rule.\n *\n * A node carrying a `sections` *map* returns before its children are walked.\n * Inside such a map the keys are section names the author chose, and a v1\n * template with a section named `required` must not be reported as using the\n * `required` key.\n */\nfunction findV1Key(node: unknown, seen = new WeakSet()): string | null {\n if (typeof node !== \"object\" || node === null) return null;\n if (seen.has(node)) return null;\n seen.add(node);\n\n if (Array.isArray(node)) {\n for (const item of node) {\n const hit = findV1Key(item, seen);\n if (hit) return hit;\n }\n return null;\n }\n\n const record = node as Record<string, unknown>;\n for (const [key, message] of Object.entries(V1_KEYS)) {\n if (key in record) return message;\n }\n if (isRecord(record.sections)) return V1_SECTIONS_MAP;\n if (typeof record.repeat === \"boolean\") return V1_REPEAT_BOOLEAN;\n if (isRecord(record.paragraphs) && \"patterns\" in record.paragraphs) {\n return V1_PARAGRAPH_PATTERNS;\n }\n\n for (const value of Object.values(record)) {\n const hit = findV1Key(value, seen);\n if (hit) return hit;\n }\n return null;\n}\n\nfunction findV1File(data: unknown): string | null {\n if (!isRecord(data)) return null;\n return findV1Key(data.templates) ?? findV1Key(data.components);\n}\n\n/* -------------------------------------------------------------------------- *\n * Checks JSON Schema cannot express\n *\n * Three of these compare two siblings, which draft-07 has no keyword for, and\n * one compiles a regular expression, which it has no opinion about. The fifth\n * is a warning rather than an error: the template is legal, and only its author\n * can say whether the ambiguity is intended.\n * -------------------------------------------------------------------------- */\n\n/** How a rule is named in a message: its id where it has one, else its path. */\nfunction ruleLabel(rule: Rule, path: string): string {\n return rule.id === undefined ? path : `\"${rule.id}\"`;\n}\n\n/**\n * `max` below `min`, where the author wrote both.\n *\n * Only where both are written. `min` defaults to one, so comparing against the\n * default would refuse `max: 0`, which is how the format spells \"none of\n * these\".\n */\nfunction checkRange(range: Occurrences, source: string, label: string): void {\n const { min, max } = range;\n if (min !== undefined && max !== undefined && max < min) {\n throw new LintError(`${source}: rule ${label} sets max ${max} below min ${min}.`);\n }\n}\n\n/**\n * Whether two rules claim the same occurrence range, the one comparison the\n * ambiguity warning below needs. Compares what `occurrenceRange` resolves\n * `min`/`max` to, not the raw (possibly absent) fields, so a written `min: 1`\n * and an absent `min` - both one occurrence by default - count as the same.\n */\nfunction sameOccurrenceRange(a: Occurrences, b: Occurrences): boolean {\n const rangeA = occurrenceRange(a);\n const rangeB = occurrenceRange(b);\n return rangeA.min === rangeB.min && rangeA.max === rangeB.max;\n}\n\n/**\n * Compile an author's pattern here, so a broken one names the file it is in.\n *\n * \"Broken\" means it does not compile. A pattern that compiles can still hang\n * the run by backtracking, and this does not catch that; `compilePattern` in\n * `../rules/index.ts` carries the full note, including why a length cap is not\n * the mitigation it looks like.\n */\nfunction checkPattern(pattern: string | undefined, source: string): void {\n if (pattern === undefined) return;\n try {\n new RegExp(pattern);\n } catch (err) {\n throw new LintError(\n `Invalid pattern \"${pattern}\" in ${source}: ${errorMessage(err)}.`,\n );\n }\n}\n\nfunction checkListItems(items: ListItemsRule, source: string, path: string): void {\n checkRange(items, source, path);\n if (items.contains) checkBlockRule(items.contains, source, `${path}.contains`);\n items.sequence?.forEach((entry, index) => {\n checkBlockRule(entry, source, `${path}.sequence[${index}]`);\n });\n}\n\nfunction checkBlockRule(block: BlockRule, source: string, path: string): void {\n for (const kind of BLOCK_KINDS) {\n const counted: Occurrences | undefined = block[kind];\n if (counted) checkRange(counted, source, `${path}.${kind}`);\n }\n checkPattern(block.paragraphs?.pattern, source);\n if (block.lists?.items) {\n checkListItems(block.lists.items, source, `${path}.lists.items`);\n }\n const element = block.elements;\n if (element?.contains) {\n checkBlockRule(element.contains, source, `${path}.elements.contains`);\n }\n element?.sequence?.forEach((entry, index) => {\n checkBlockRule(entry, source, `${path}.elements.sequence[${index}]`);\n });\n}\n\n/** Everything a rule and a template share. A template is a rule. */\nfunction checkRuleBody(rule: Rule, source: string, path: string): void {\n const heading = rule.heading;\n if (typeof heading === \"object\" && !Array.isArray(heading)) {\n checkPattern(heading.pattern, source);\n }\n if (rule.contains) checkBlockRule(rule.contains, source, `${path}.contains`);\n rule.sequence?.forEach((entry, index) => {\n checkBlockRule(entry, source, `${path}.sequence[${index}]`);\n });\n checkRuleList(rule.repeat, source, `${path}.repeat`);\n checkRuleList(rule.sections, source, `${path}.sections`);\n}\n\n/**\n * One list of sibling rules: their ids, their ranges, and whether two\n * neighbours are told apart by nothing but their order.\n */\nfunction checkRuleList(rules: Rule[] | undefined, source: string, path: string): void {\n if (!rules) return;\n\n const ids = new Set<string>();\n for (const [index, rule] of rules.entries()) {\n const here = `${path}[${index}]`;\n if (rule.id !== undefined) {\n if (ids.has(rule.id)) {\n throw new LintError(`${source}: two sibling rules share the id \"${rule.id}\".`);\n }\n ids.add(rule.id);\n }\n checkRange(rule, source, ruleLabel(rule, here));\n checkRuleBody(rule, source, here);\n }\n\n // A warning, not an error. Two adjacent wildcards are how TGDP's \"{Task\n // name}\" then \"{Next task}\" is written, and that is legal. It is also how a\n // template accidentally describes one section twice, and nothing in the file\n // distinguishes the two cases - unless their occurrence ranges differ, in\n // which case the matcher can still tell them apart: one claims a fixed count\n // of sections and the other claims however many are left. That is\n // `reference-description` (`max: 1`) next to `structured-entry` (`min: 0`,\n // no `max`) in tgdp:reference - legal and unambiguous, so only a shared range\n // is flagged.\n for (const [index, rule] of rules.entries()) {\n const next = rules[index + 1];\n if (!next) break;\n if (\n isWildcard(rule) &&\n rule.repeat === undefined &&\n isWildcard(next) &&\n next.repeat === undefined &&\n sameOccurrenceRange(rule, next)\n ) {\n warn(\n `${source}: two adjacent rules have no heading and no repeat; only rule order tells them apart.`,\n );\n break;\n }\n }\n}\n\n/** The checks that run over a validated file, template by template. */\nfunction checkTemplateFile(file: TemplateFile, source: string): void {\n for (const [name, template] of Object.entries(file.templates ?? {})) {\n if (template.min !== undefined || template.max !== undefined) {\n throw new LintError(\n `${source}: a template may not set min or max; a page is one page.`,\n );\n }\n checkRuleBody(template, source, `templates.${name}`);\n }\n}\n\n/**\n * What each `not` constraint means, in the words its author needs.\n *\n * Ajv renders every `not` as \"must NOT be valid\", which names the path and\n * then says nothing whatsoever about what is wrong with it. The schema carries\n * a `description` on each of these; the sentence lives here instead because it\n * is user-facing text, and every other message in this file does too.\n */\nconst NOT_CONSTRAINTS: Record<string, string> = {\n oneOfSequenceOrContains:\n \"sets both sequence and contains; a rule says what it holds in order, or in any order, never both\",\n noHeadingOnRepeat:\n \"sets both heading and repeat; a repeat group has no heading of its own, so put the heading on the first rule inside it\",\n noInstructions: \"carries an instructions key, which this tool does not read\",\n};\n\n/** `/templates/how-to/sections/title must NOT have additional properties (foo)`. */\nfunction describeError(error: ErrorObject): string {\n const where = error.instancePath || \"/\";\n\n if (error.keyword === \"not\") {\n for (const [name, why] of Object.entries(NOT_CONSTRAINTS)) {\n if (error.schemaPath.includes(name)) return `${where} ${why}`;\n }\n }\n\n const params = error.params as { additionalProperty?: unknown };\n const extra =\n typeof params.additionalProperty === \"string\" ? ` (\"${params.additionalProperty}\")` : \"\";\n return `${where} ${error.message ?? \"is invalid\"}${extra}`;\n}\n\n/**\n * Validate a parsed, dereferenced template file, filling in rule defaults.\n *\n * Throws `LintError` naming `source` and the offending instance path. The\n * pre-rewrite loader threw a bare \"Template is invalid\" and passed the real\n * detail as `new Error(msg, {message: ...})` - an options bag that only\n * understands `cause` - so every schema error reached the user as four words.\n */\nexport function validateTemplateFile(data: unknown, source: string): TemplateFile {\n const instructions = findInstructions(data);\n if (instructions) throw new LintError(instructionsMessage(source, instructions));\n\n // Before Ajv, so a v1 file is told where its keys went rather than that it\n // has additional properties.\n const v1 = findV1File(data);\n if (v1) throw new LintError(`${source}: ${v1}`);\n\n const validate = fileValidator();\n if (!validate(data)) {\n const errors = validate.errors ?? [];\n const detail = errors.map(describeError).join(\"; \") || \"does not match the template schema\";\n throw new LintError(`${source} is not a valid template file: ${detail}.`);\n }\n const file = data as TemplateFile;\n checkTemplateFile(file, source);\n return file;\n}\n\n/* -------------------------------------------------------------------------- *\n * Loading\n * -------------------------------------------------------------------------- */\n\n/** Split `./templates.yaml#how-to` into its file part and template name. */\nfunction splitFragment(ref: string): { base: string; fragment: string | null } {\n const hash = ref.lastIndexOf(\"#\");\n if (hash === -1) return { base: ref, fragment: null };\n return { base: ref.slice(0, hash), fragment: ref.slice(hash + 1) || null };\n}\n\n/** The part of a ref an extension should be read off - a URL's path, not its query. */\nfunction extensionSource(ref: string, kind: RefKind): string {\n if (kind !== \"url\") return ref;\n try {\n return new URL(ref).pathname;\n } catch {\n return ref;\n }\n}\n\n/**\n * Parse a template file by extension. Anything unrecognized is parsed as YAML,\n * which is a superset of JSON, so an extensionless URL still loads.\n */\nfunction parseTemplateFile(raw: string, source: string, kind: RefKind): unknown {\n const lower = extensionSource(source, kind).toLowerCase();\n if (lower.endsWith(\".json\")) {\n try {\n return JSON.parse(raw) as unknown;\n } catch (err) {\n throw new LintError(`${source} is not valid JSON: ${errorMessage(err)}`);\n }\n }\n try {\n return parseYaml(raw) as unknown;\n } catch (err) {\n throw new LintError(`${source} is not valid YAML: ${errorMessage(err)}`);\n }\n}\n\n/**\n * Read a local template file, saying which way the read failed.\n *\n * Every failure used to be reported as \"not found\", which is the one wording\n * that contradicts `ls -la`: a directory named `templates.yaml` (EISDIR), a\n * file the user cannot open (EACCES), and a process out of descriptors\n * (EMFILE) are three different problems with three different fixes, and the\n * reader was sent after a path that is plainly there. Only ENOENT is a missing\n * file; anything else keeps the OS's own message.\n */\nasync function readText(ref: string): Promise<string> {\n try {\n return await readFile(ref, \"utf8\");\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | null)?.code;\n if (code === \"ENOENT\") {\n throw new LintError(`Template file not found: \"${ref}\".`);\n }\n throw new LintError(\n `Template file \"${ref}\" could not be read: ${errorMessage(err)}`,\n );\n }\n}\n\nconst urlCache = new Map<string, TemplateFile>();\n\n/**\n * Drop the parsed-template caches.\n *\n * Nothing in the CLI needs this: a process lints one docset and exits, and the\n * caches are what keep a tree of one doctype from re-reading and re-validating\n * the same template per page. It exists for the other caller - a long-lived\n * process using this as a library - where the two behave differently: the\n * memory grows with the number of distinct refs seen, and a `urlCache` entry\n * for a remote template is served for the life of the process, so a template\n * republished upstream is never picked up.\n */\nexport function clearTemplateCaches(): void {\n builtinCache.clear();\n urlCache.clear();\n}\n\nasync function fetchText(ref: string, timeoutMs: number): Promise<string> {\n let res: Response;\n try {\n res = await fetch(ref, { signal: AbortSignal.timeout(timeoutMs) });\n } catch (err) {\n const e = err as Error;\n if (e.name === \"TimeoutError\" || e.name === \"AbortError\") {\n throw new LintError(\n `Failed to fetch template file \"${ref}\": timed out after ${timeoutMs}ms.`,\n );\n }\n throw new LintError(`Failed to fetch template file \"${ref}\": ${e.message}`);\n }\n if (!res.ok) {\n throw new LintError(`Failed to fetch template file \"${ref}\": HTTP ${res.status}.`);\n }\n return await res.text();\n}\n\n/** Resolve every `$ref` in place, so validation never sees one. */\nasync function dereferenceTemplates(\n data: Record<string, unknown>,\n source: string,\n): Promise<Record<string, unknown>> {\n try {\n return await dereference<Record<string, unknown>>(data, DEREFERENCE_OPTIONS);\n } catch (err) {\n throw new LintError(`${source}: could not resolve a \"$ref\": ${errorMessage(err)}`);\n }\n}\n\n/** Load, dereference, and validate a whole template file. */\nexport async function loadTemplateFile(\n ref: string,\n options: LoadTemplateOptions = {},\n): Promise<TemplateFile> {\n const { kind } = classifyRef(ref);\n if (kind === \"builtin\") {\n throw new LintError(\n `\"${ref}\" is a built-in template id, not a template file. Load it with loadTemplate().`,\n );\n }\n\n const cached = kind === \"url\" ? urlCache.get(ref) : undefined;\n if (cached) return cached;\n\n const raw =\n kind === \"url\"\n ? await fetchText(ref, options.timeoutMs ?? DEFAULT_TIMEOUT_MS)\n : await readText(ref);\n\n const parsed = parseTemplateFile(raw, ref, kind);\n if (!isRecord(parsed)) {\n throw new LintError(\n `${ref} is not a template file: expected an object at the top level, got ${\n parsed === null ? \"null\" : Array.isArray(parsed) ? \"an array\" : typeof parsed\n }.`,\n );\n }\n\n const file = validateTemplateFile(await dereferenceTemplates(parsed, ref), ref);\n if (kind === \"url\") urlCache.set(ref, file);\n return file;\n}\n\n/**\n * Resolve a single template.\n *\n * A built-in id names one directly. A file or URL may name one inside itself\n * with a `#` fragment; without a fragment a single-template file resolves\n * unambiguously and anything else is an error listing what is on offer.\n *\n * `extends` is left unresolved - see `resolveExtends`.\n */\nexport async function loadTemplate(\n ref: string,\n options: LoadTemplateOptions = {},\n): Promise<Template> {\n const { base, fragment } = splitFragment(ref);\n const { kind } = classifyRef(base);\n\n if (kind === \"builtin\") {\n // A fragment here was silently dropped, so `tgdp:how-to:1.6#typo` loaded\n // `tgdp:how-to:1.6` and succeeded - the same quiet-wrong-answer as the\n // prototype lookup below, where a configuration error selects a different\n // template than the author wrote and nothing says so. A built-in id names\n // exactly one template, so there is nothing a fragment could select.\n if (fragment !== null) {\n throw new LintError(\n `\"${ref}\" adds a \"#${fragment}\" fragment to a built-in template id. ` +\n `A built-in id names one template on its own - drop the fragment and ` +\n `use \"${base}\". Fragments name a template inside a file, as in ` +\n `\"./templates.yaml#how-to\".`,\n );\n }\n if (!BUILTINS.has(base)) {\n const available = [...BUILTINS.keys()].join(\", \");\n throw new LintError(\n `Unknown built-in template \"${base}\". Available: ${available || \"(none)\"}.`,\n );\n }\n return loadBuiltin(base);\n }\n\n const file = await loadTemplateFile(base, options);\n const templates = file.templates ?? {};\n const names = Object.keys(templates);\n\n if (fragment !== null) {\n // An own-property check, not a truthiness test on the lookup. `templates`\n // is a plain object parsed from YAML, so `#constructor` and `#toString`\n // name members it inherits from `Object.prototype`. Those are truthy, so\n // such a fragment sailed past this guard and a function came back as a\n // template - one with no `sections`, which checks the document against\n // nothing. The bad fragment therefore produced silence rather than an\n // error: the page was reported as passing, not as naming a template that\n // does not exist.\n const named = Object.hasOwn(templates, fragment)\n ? templates[fragment]\n : undefined;\n if (named === undefined) {\n throw new LintError(\n `${base} has no template named \"${fragment}\". Available: ${names.join(\", \") || \"(none)\"}.`,\n );\n }\n return named;\n }\n\n const [only] = Object.values(templates);\n if (names.length === 1 && only !== undefined) return only;\n if (names.length === 0) throw new LintError(`${base} defines no templates.`);\n // Past both branches above, `names.length` is at least two, so `names[0]` is\n // there and the example fragment is never empty. The `?? \"\"` is\n // `noUncheckedIndexedAccess` paperwork rather than a case to look for.\n throw new LintError(\n `${base} defines ${names.length} templates; name one with a \"#\" fragment ` +\n `(e.g. \"${base}#${names[0] ?? \"\"}\"). Available: ${names.join(\", \")}.`,\n );\n}\n\n/* -------------------------------------------------------------------------- *\n * Inheritance\n * -------------------------------------------------------------------------- */\n\n/** How `resolveExtends` turns an `extends` ref into a template. */\nexport type TemplateResolver = (ref: string) => Promise<Template>;\n\n/**\n * Merge a child template onto its parent.\n *\n * Recursion follows `sections` and stops there. A rule's own keys are units:\n * overriding `contains` means replacing it, not merging a child's `min` into\n * the parent's `max` and hoping the pair still means something. But `sections`\n * is a container, not a rule. Replacing it wholesale would mean that tightening\n * one nested rule silently discards every sibling the parent declared, which is\n * the opposite of what `extends` is for.\n *\n * `sections` is a list in v2, so \"merges by key\" now means \"merges by `id`\". A\n * child rule carrying an id the parent also uses replaces that rule where the\n * parent had it, keeping the parent's order. A child rule with no id, or with\n * an id the parent does not use, is appended. Every other key the child sets\n * replaces the parent's outright, `repeat` included: a repeated run is one\n * unit, and merging two of them by position would be guesswork.\n */\nfunction mergeRuleLists(\n parent: Rule[] | undefined,\n child: Rule[] | undefined,\n): Rule[] | undefined {\n if (!parent) return child;\n if (!child) return parent;\n\n // Parent order first, so inherited rules keep the document order the parent\n // declared and child-only additions land at the end.\n const merged: Rule[] = [...parent];\n for (const childRule of child) {\n const id = childRule.id;\n const index =\n id === undefined ? -1 : merged.findIndex((rule) => rule.id === id);\n const target = index === -1 ? undefined : merged[index];\n if (target === undefined) merged.push(childRule);\n else merged[index] = mergeRules(target, childRule);\n }\n return merged;\n}\n\nfunction mergeRules(parent: Rule, child: Rule): Rule {\n // `sections` is dropped from both spreads and merged on its own. Every other\n // key replaces outright, which is what a spread does; sections merge by `id`,\n // which it cannot. Leaving the child's raw array in the spread and then\n // overwriting it worked, but it read as though the spread were the whole\n // answer.\n const sections = mergeRuleLists(parent.sections, child.sections);\n const { sections: _parentSections, ...parentRest } = parent;\n const { sections: _childSections, ...childRest } = child;\n const merged: Rule = { ...parentRest, ...childRest };\n // `!== undefined` rather than truthiness. The two are equivalent here, since\n // `mergeRuleLists` returns `Rule[] | undefined` and an empty array is truthy\n // in any case - but a rule may legitimately carry `sections: []`, meaning it\n // allows none, and a reader should not have to know that `[]` survives a\n // truthiness test to be sure that case is kept.\n if (sections !== undefined) merged.sections = sections;\n return merged;\n}\n\nfunction mergeTemplates(parent: Template, child: Template): Template {\n // Shaped like `mergeRules` above, and for the same reasons: merge first,\n // drop `sections` from both spreads, and test for `undefined` rather than\n // truthiness.\n const sections = mergeRuleLists(parent.sections, child.sections);\n const { sections: _parentSections, ...parentRest } = parent;\n const { sections: _childSections, ...childRest } = child;\n const merged: Template = { ...parentRest, ...childRest };\n if (sections !== undefined) merged.sections = sections;\n // The chain is resolved; leaving `extends` on would invite resolving twice.\n delete merged.extends;\n return merged;\n}\n\n/**\n * Resolve a template's `extends` chain, innermost first.\n *\n * `load` is injected because a relative `extends` is relative to the file the\n * child came from, which this function has no way to know. `chain` is internal\n * bookkeeping for cycle detection.\n */\nexport async function resolveExtends(\n template: Template,\n load: TemplateResolver = loadTemplate,\n chain: string[] = [],\n): Promise<Template> {\n const parentRef = template.extends;\n if (parentRef === undefined) return template;\n\n if (chain.includes(parentRef)) {\n throw new LintError(\n `Template \"extends\" cycle: ${[...chain, parentRef].join(\" -> \")}.`,\n );\n }\n\n const parent = await resolveExtends(await load(parentRef), load, [...chain, parentRef]);\n return mergeTemplates(parent, template);\n}\n\n/* -------------------------------------------------------------------------- *\n * Resolution relative to the declaring file\n * -------------------------------------------------------------------------- */\n\n/**\n * Re-base a ref against the file that declared it.\n *\n * A built-in id, a URL, and an absolute path all name themselves and are\n * returned unchanged. A relative path means \"beside the file I am written in\",\n * which is the one reading `loadTemplate` cannot produce on its own - it reads\n * against the process working directory, so `extends: ./base.yaml` in\n * `tpl/house.yaml` looked for `./base.yaml` at the cwd and found either nothing\n * or, worse, an unrelated file of that name.\n */\nexport function refRelativeTo(baseRef: string, ref: string): string {\n const { base, fragment } = splitFragment(ref);\n if (classifyRef(base).kind !== \"file\" || isAbsolute(base)) return ref;\n\n const { base: fromBase } = splitFragment(baseRef);\n const from = classifyRef(fromBase).kind;\n\n // A template fetched over HTTP names its neighbours the same way a local one\n // does, and `./base.yaml` beside it is a URL, not a path. Resolved as a path\n // it became a read of the process working directory - a local file quietly\n // standing in for the remote one, or a \"file not found\" naming a path that\n // appears nowhere in the template.\n if (from === \"url\") {\n const rebased = new URL(base, fromBase).href;\n return fragment === null ? rebased : `${rebased}#${fragment}`;\n }\n\n if (from !== \"file\") return ref;\n\n const rebased = resolvePath(dirname(fromBase), base);\n return fragment === null ? rebased : `${rebased}#${fragment}`;\n}\n\n/**\n * Load a template with its `extends` chain resolved, re-basing each relative\n * ref against the file that declared it.\n *\n * This is what a caller should use. `resolveExtends` stays exported for callers\n * that supply their own resolver, but its default is the cwd-relative\n * `loadTemplate`, and reaching that default silently is the bug this exists to\n * avoid - `.then(resolveExtends)` passes one argument, so the default is\n * exactly what you get.\n */\nexport async function loadResolvedTemplate(\n ref: string,\n options: LoadTemplateOptions = {},\n chain: string[] = [],\n): Promise<Template> {\n // Seeded with this ref when the caller started here, so the reported cycle\n // starts where the reader did. Chained from the parent only, `a -> b -> a`\n // was reported as `b -> a -> b`: the file the run was pointed at never\n // appeared in the cycle it was said to be part of, which is the one name in\n // the message the reader can act on.\n const seen = chain.length === 0 ? [ref] : chain;\n const template = await loadTemplate(ref, options);\n const parentRef = template.extends;\n if (parentRef === undefined) return template;\n\n const absolute = refRelativeTo(ref, parentRef);\n if (seen.includes(absolute)) {\n throw new LintError(\n `Template \"extends\" cycle: ${[...seen, absolute].join(\" -> \")}.`,\n );\n }\n\n const parent = await loadResolvedTemplate(absolute, options, [\n ...seen,\n absolute,\n ]);\n return mergeTemplates(parent, template);\n}\n","{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"manni-lint:template:2\",\n \"title\": \"manni lint template file\",\n \"description\": \"A template file: named doctype templates, plus the reusable fragments they point at with `$ref`. Validated after dereferencing, so no `$ref` survives to be seen here. A template is itself a rule: it describes the page, and it takes every rule key plus `title`, `types` and `extends`.\",\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"templates\"],\n \"properties\": {\n \"$schema\": {\n \"description\": \"URL of this schema, so an editor can offer completion. Read by editors, never by the linter.\",\n \"type\": \"string\"\n },\n \"info\": {\n \"description\": \"Free-form metadata about the file (title, version, author). Never read by the linter; declared so a file that carries it is not rejected.\",\n \"type\": \"object\"\n },\n \"templates\": {\n \"description\": \"The doctype templates this file defines, keyed by name.\",\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"patternProperties\": {\n \"^[A-Za-z][A-Za-z0-9-_]*$\": { \"$ref\": \"#/definitions/template\" }\n }\n },\n \"components\": {\n \"description\": \"Reusable fragments, targeted by `$ref` from elsewhere in the file. Left unconstrained: a fragment is validated where it is inlined, not where it is declared.\",\n \"type\": \"object\"\n }\n },\n \"definitions\": {\n \"min\": {\n \"description\": \"Fewest occurrences. Absent means one. Deliberately carries no JSON Schema `default`, and neither does any other key in this file: Ajv's `useDefaults` would write one in at load time, and a written-in value is indistinguishable from a value the author typed, so it wins the `extends` merge against the parent's real value. The code reads `undefined` instead.\",\n \"type\": \"integer\",\n \"minimum\": 0\n },\n \"max\": {\n \"description\": \"Most occurrences. Absent is unbounded, so write `max: 1` for exactly once and `max: 0` to forbid. Must be at least `min` where both are written; the loader checks that, because JSON Schema cannot compare two siblings.\",\n \"type\": \"integer\",\n \"minimum\": 0\n },\n \"id\": {\n \"description\": \"Handle for this rule, unique among its siblings. It appears in messages, and `extends` targets it to replace one inherited rule in place.\",\n \"type\": \"string\",\n \"pattern\": \"^[A-Za-z][A-Za-z0-9-_]*$\"\n },\n \"description\": {\n \"description\": \"Prose description of what the rule is for. Never checked.\",\n \"type\": \"string\"\n },\n \"heading\": {\n \"description\": \"The heading of the section this rule describes. Absent means any heading, or none. A string is exact text, a list is one-of, `{ pattern }` is an unanchored regular expression, and `false` means the section has no heading of its own.\",\n \"oneOf\": [\n { \"type\": \"string\", \"minLength\": 1 },\n {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": { \"type\": \"string\", \"minLength\": 1 }\n },\n {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"pattern\"],\n \"properties\": {\n \"pattern\": { \"type\": \"string\", \"minLength\": 1 }\n }\n },\n { \"const\": false }\n ]\n },\n \"attributes\": {\n \"description\": \"Literal attributes the node must carry. A string is the required value; `true` requires the attribute to be present, and `false` requires it to be absent.\",\n \"type\": \"object\",\n \"additionalProperties\": {\n \"oneOf\": [{ \"type\": \"string\" }, { \"type\": \"boolean\" }]\n }\n },\n \"oneOfSequenceOrContains\": {\n \"description\": \"A rule says what it holds in order (`sequence`) or in any order (`contains`), never both.\",\n \"type\": \"object\",\n \"not\": { \"required\": [\"sequence\", \"contains\"] }\n },\n \"noHeadingOnRepeat\": {\n \"description\": \"`repeat` groups sibling rules into one repeated unit, so the group has no heading of its own. Put the heading on the first rule inside it.\",\n \"type\": \"object\",\n \"not\": { \"required\": [\"heading\", \"repeat\"] }\n },\n \"noInstructions\": {\n \"description\": \"`instructions` was the language-model hook of doc-structure-lint. manni lint is deterministic and has no model, so a template carrying it is rejected outright rather than silently ignored; the loader turns this into a migration message pointing at manni docevals.\",\n \"type\": \"object\",\n \"not\": { \"required\": [\"instructions\"] }\n },\n \"template\": {\n \"description\": \"One doctype template. A template is a rule describing the page itself, so it takes every rule key, plus `title`, `types` and `extends`.\",\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"allOf\": [\n { \"$ref\": \"#/definitions/noInstructions\" },\n { \"$ref\": \"#/definitions/oneOfSequenceOrContains\" },\n { \"$ref\": \"#/definitions/noHeadingOnRepeat\" }\n ],\n \"properties\": {\n \"title\": {\n \"description\": \"Human-readable name for the template, shown by `manni lint templates`.\",\n \"type\": \"string\"\n },\n \"types\": {\n \"description\": \"Doctypes this template serves, matched against a page's `type` frontmatter.\",\n \"type\": \"array\",\n \"items\": { \"type\": \"string\", \"minLength\": 1 }\n },\n \"extends\": {\n \"description\": \"Template reference (built-in id, path, or URL, optionally with a `#name` fragment) whose rules this template inherits.\",\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"id\": { \"$ref\": \"#/definitions/id\" },\n \"description\": { \"$ref\": \"#/definitions/description\" },\n \"heading\": { \"$ref\": \"#/definitions/heading\" },\n \"repeat\": { \"$ref\": \"#/definitions/repeat\" },\n \"min\": {\n \"description\": \"Refused on a template: a page is one page. Declared here only so the loader can say that in a sentence, rather than leaving Ajv to report an unexpected key.\",\n \"type\": \"integer\",\n \"minimum\": 0\n },\n \"max\": {\n \"description\": \"Refused on a template, for the same reason as `min`.\",\n \"type\": \"integer\",\n \"minimum\": 0\n },\n \"sequence\": { \"$ref\": \"#/definitions/sequence\" },\n \"contains\": { \"$ref\": \"#/definitions/blockRules\" },\n \"sections\": { \"$ref\": \"#/definitions/rules\" }\n }\n },\n \"rule\": {\n \"description\": \"One rule. It describes a section of the page, or, with `repeat`, a run of sections matched as one unit.\",\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"allOf\": [\n { \"$ref\": \"#/definitions/noInstructions\" },\n { \"$ref\": \"#/definitions/oneOfSequenceOrContains\" },\n { \"$ref\": \"#/definitions/noHeadingOnRepeat\" }\n ],\n \"properties\": {\n \"id\": { \"$ref\": \"#/definitions/id\" },\n \"description\": { \"$ref\": \"#/definitions/description\" },\n \"heading\": { \"$ref\": \"#/definitions/heading\" },\n \"repeat\": { \"$ref\": \"#/definitions/repeat\" },\n \"min\": { \"$ref\": \"#/definitions/min\" },\n \"max\": { \"$ref\": \"#/definitions/max\" },\n \"sequence\": { \"$ref\": \"#/definitions/sequence\" },\n \"contains\": { \"$ref\": \"#/definitions/blockRules\" },\n \"sections\": { \"$ref\": \"#/definitions/rules\" }\n }\n },\n \"rules\": {\n \"description\": \"Rules for the subsections, in document order.\",\n \"type\": \"array\",\n \"items\": { \"$ref\": \"#/definitions/rule\" }\n },\n \"repeat\": {\n \"description\": \"Rules matched in order as one unit, repeated by this rule's `min` and `max`.\",\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": { \"$ref\": \"#/definitions/rule\" }\n },\n \"sequence\": {\n \"description\": \"What the section holds, in order. Each entry is one run of one content kind.\",\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": {\n \"allOf\": [\n { \"$ref\": \"#/definitions/blockRules\" },\n { \"type\": \"object\", \"maxProperties\": 1 }\n ]\n }\n },\n \"blockRules\": {\n \"description\": \"Block rules, keyed by content kind. The key is plural because it carries a count: the node model says `codeBlock`, a template says `codeBlocks: { min: 1 }`.\",\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"minProperties\": 1,\n \"properties\": {\n \"paragraphs\": { \"$ref\": \"#/definitions/paragraphs\" },\n \"codeBlocks\": { \"$ref\": \"#/definitions/codeBlocks\" },\n \"lists\": { \"$ref\": \"#/definitions/lists\" },\n \"tables\": { \"$ref\": \"#/definitions/tables\" },\n \"admonitions\": { \"$ref\": \"#/definitions/admonitions\" },\n \"images\": { \"$ref\": \"#/definitions/images\" },\n \"blockquotes\": { \"$ref\": \"#/definitions/counted\" },\n \"definitionLists\": { \"$ref\": \"#/definitions/counted\" },\n \"elements\": { \"$ref\": \"#/definitions/elements\" }\n }\n },\n \"counted\": {\n \"description\": \"A block rule that only counts.\",\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"min\": { \"$ref\": \"#/definitions/min\" },\n \"max\": { \"$ref\": \"#/definitions/max\" }\n }\n },\n \"paragraphs\": {\n \"description\": \"Paragraph requirements.\",\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"min\": { \"$ref\": \"#/definitions/min\" },\n \"max\": { \"$ref\": \"#/definitions/max\" },\n \"pattern\": {\n \"description\": \"Unanchored regular expression every paragraph in the run must match.\",\n \"type\": \"string\",\n \"minLength\": 1\n }\n }\n },\n \"codeBlocks\": {\n \"description\": \"Code block requirements.\",\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"min\": { \"$ref\": \"#/definitions/min\" },\n \"max\": { \"$ref\": \"#/definitions/max\" },\n \"language\": {\n \"description\": \"Language every code block must be tagged with, as the node model spells it. A list is one-of: the block must declare one of them.\",\n \"oneOf\": [\n { \"type\": \"string\", \"minLength\": 1 },\n {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": { \"type\": \"string\", \"minLength\": 1 }\n }\n ]\n },\n \"fenceInfo\": {\n \"description\": \"Info-string tail after the language, where the format carries one.\",\n \"type\": \"string\"\n }\n }\n },\n \"lists\": {\n \"description\": \"List requirements.\",\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"min\": { \"$ref\": \"#/definitions/min\" },\n \"max\": { \"$ref\": \"#/definitions/max\" },\n \"ordered\": {\n \"description\": \"Whether the list must be ordered. Absent accepts either.\",\n \"type\": \"boolean\"\n },\n \"items\": { \"$ref\": \"#/definitions/listItems\" }\n }\n },\n \"listItems\": {\n \"description\": \"Requirements applied to every item of every list in the run. Recurses arbitrarily deep.\",\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"allOf\": [{ \"$ref\": \"#/definitions/oneOfSequenceOrContains\" }],\n \"properties\": {\n \"min\": { \"$ref\": \"#/definitions/min\" },\n \"max\": { \"$ref\": \"#/definitions/max\" },\n \"sequence\": { \"$ref\": \"#/definitions/sequence\" },\n \"contains\": { \"$ref\": \"#/definitions/blockRules\" }\n }\n },\n \"tables\": {\n \"description\": \"Table requirements.\",\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"min\": { \"$ref\": \"#/definitions/min\" },\n \"max\": { \"$ref\": \"#/definitions/max\" },\n \"columns\": {\n \"description\": \"The header cells, in order.\",\n \"type\": \"array\",\n \"items\": { \"type\": \"string\" }\n }\n }\n },\n \"admonitions\": {\n \"description\": \"Admonition requirements.\",\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"min\": { \"$ref\": \"#/definitions/min\" },\n \"max\": { \"$ref\": \"#/definitions/max\" },\n \"variant\": {\n \"description\": \"Which flavor of admonition. The node model's `variant`, not any one format's spelling.\",\n \"enum\": [\n \"note\",\n \"tip\",\n \"important\",\n \"caution\",\n \"warning\",\n \"danger\"\n ]\n }\n }\n },\n \"images\": {\n \"description\": \"Image requirements.\",\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"min\": { \"$ref\": \"#/definitions/min\" },\n \"max\": { \"$ref\": \"#/definitions/max\" },\n \"url\": {\n \"description\": \"Where the image must point.\",\n \"type\": \"string\"\n },\n \"alt\": {\n \"description\": \"Alternative text the image must carry.\",\n \"type\": \"string\"\n },\n \"attributes\": { \"$ref\": \"#/definitions/attributes\" }\n }\n },\n \"elements\": {\n \"description\": \"Named-wrapper requirements. `sequence` and `contains` here describe what the element holds, which is never the enclosing section's content.\",\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"allOf\": [{ \"$ref\": \"#/definitions/oneOfSequenceOrContains\" }],\n \"properties\": {\n \"min\": { \"$ref\": \"#/definitions/min\" },\n \"max\": { \"$ref\": \"#/definitions/max\" },\n \"tag\": {\n \"description\": \"The element's name, as an author of the format would write it. A list is one-of: an element counts when it carries any of them.\",\n \"oneOf\": [\n { \"type\": \"string\", \"minLength\": 1 },\n {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": { \"type\": \"string\", \"minLength\": 1 }\n }\n ]\n },\n \"attributes\": { \"$ref\": \"#/definitions/attributes\" },\n \"sequence\": { \"$ref\": \"#/definitions/sequence\" },\n \"contains\": { \"$ref\": \"#/definitions/blockRules\" }\n }\n }\n }\n}\n","{\n \"$comment\": \"Built-in doctype templates derived from The Good Docs Project templates, pinned to release v1.6.0 (\\\"Iron\\\"): https://gitlab.com/tgdp/templates/-/tree/v1.6.0. Each entry's `file` is a YAML template beside this manifest; `source` is the upstream Markdown it was derived from, vendored under test/lint/fixtures/tgdp/ and linted against the derived template so the two cannot drift. Run `npm run check:tgdp-pin` to see whether upstream has moved past the pin.\",\n \"vendor\": \"tgdp\",\n \"upstream\": \"https://gitlab.com/tgdp/templates\",\n \"pin\": \"v1.6.0\",\n \"templates\": [\n {\n \"id\": \"tgdp:how-to:1.6\",\n \"file\": \"tgdp/how-to.yaml\",\n \"title\": \"How-to guide (The Good Docs Project)\",\n \"types\": [\"how-to\"],\n \"source\": \"how-to/template_how-to.md\"\n },\n {\n \"id\": \"tgdp:tutorial:1.6\",\n \"file\": \"tgdp/tutorial.yaml\",\n \"title\": \"Tutorial (The Good Docs Project)\",\n \"types\": [\"tutorial\"],\n \"source\": \"tutorial/template_tutorial.md\"\n },\n {\n \"id\": \"tgdp:reference:1.6\",\n \"file\": \"tgdp/reference.yaml\",\n \"title\": \"Reference (The Good Docs Project)\",\n \"types\": [\"reference\"],\n \"source\": \"reference/template_reference.md\"\n },\n {\n \"id\": \"tgdp:concept:1.6\",\n \"file\": \"tgdp/concept.yaml\",\n \"title\": \"Concept (The Good Docs Project)\",\n \"types\": [\"concept\", \"explanation\"],\n \"source\": \"concept/template_concept.md\"\n },\n {\n \"id\": \"tgdp:troubleshooting:1.6\",\n \"file\": \"tgdp/troubleshooting.yaml\",\n \"title\": \"Troubleshooting (The Good Docs Project)\",\n \"types\": [\"troubleshooting\"],\n \"source\": \"troubleshooting/template_troubleshooting.md\"\n },\n {\n \"id\": \"tgdp:release-notes:1.6\",\n \"file\": \"tgdp/release-notes.yaml\",\n \"title\": \"Release notes (The Good Docs Project)\",\n \"types\": [\"release-notes\"],\n \"source\": \"release-notes/template_release-notes.md\"\n },\n {\n \"id\": \"tgdp:readme:1.6\",\n \"file\": \"tgdp/readme.yaml\",\n \"title\": \"README (The Good Docs Project)\",\n \"types\": [\"readme\"],\n \"source\": \"readme/template_readme.md\"\n }\n ]\n}\n","/**\n * Decide which template describes a given page.\n *\n * The headline case is the last one: a page declares what it is in its\n * frontmatter (`type: how-to`), and the template follows from that. It is the\n * same key `manni meta`'s OKF, Diataxis, and TGDP schemas validate, so a repo\n * that already types its pages gets routing for free, and one run can lint a\n * whole tree with each page checked against the doctype it claims.\n *\n * The precedence chain mirrors docmeta's `resolveSchemaSet`: an explicit\n * instruction beats a per-page declaration, which beats repo policy, which\n * beats the page's own vocabulary, which beats a blanket default.\n *\n * 1. `--template` an operator overriding everything, for one run\n * 2. `$template` this page, specifically, is an exception\n * 3. config override repo policy: \"everything under docs/api is a reference\"\n * 4. `type` what the page says it is\n * 5. config default what to assume when a page says nothing\n *\n * Every step is recorded, because \"why was this page linted with that\n * template?\" is otherwise a question only the source can answer. `--explain`\n * prints the record.\n */\nimport picomatch from \"picomatch\";\nimport type { Template, TemplateFile } from \"./template.js\";\n\n/** Where a resolution came from, in precedence order. */\nexport type ResolutionStage =\n | \"cli\"\n | \"frontmatter-template\"\n | \"config-override\"\n | \"type\"\n | \"config-default\";\n\nexport type SkipCause = \"no-type\" | \"unknown-type\";\n\nexport interface ResolutionStep {\n stage: ResolutionStage;\n /** What the stage found, or null when it had nothing to say. */\n ref: string | null;\n /** Human-readable account of what the stage saw. */\n detail: string;\n}\n\nexport interface Resolution {\n /** The template ref to lint with, or null when the page is not linted. */\n ref: string | null;\n /** Which stage decided, when one did. */\n stage: ResolutionStage | null;\n /** Why no template was found. Only set when `ref` is null. */\n cause?: SkipCause;\n /**\n * The `type` the page declared but that resolved to nothing. Set only for\n * `unknown-type`, so the caller can name it and suggest near misses.\n */\n unknownType?: string;\n /** Near-miss doctypes, for an unknown-type message. */\n suggestions?: string[];\n /**\n * Every doctype something serves, for an unknown-type message with no near\n * miss to offer. Carried on the resolution rather than looked up by each\n * reporter, because the type index does not reach them - which is how the\n * pretty reporter came to print the list and `--explain` came to print\n * nothing, for the same page.\n */\n knownTypes?: string[];\n /** The full chain, for `--explain`. */\n steps: ResolutionStep[];\n}\n\n/** Per-glob repo policy, from `manni.config.yaml`'s `lint.overrides`. */\nexport interface TemplateOverride {\n files: string;\n template: string;\n}\n\nexport interface TypeIndexEntry {\n /** Ref that `loadTemplate` understands. */\n ref: string;\n /** Where the mapping came from; later sources outrank earlier ones. */\n source: \"builtin\" | \"user\" | \"config\";\n}\n\n/** The frontmatter key a page uses to override its doctype's template. */\nexport const FILE_TEMPLATE_KEY = \"$template\";\n/** The frontmatter key a page uses to declare its doctype. */\nexport const TYPE_KEY = \"type\";\n\n/**\n * Build the doctype -> template map.\n *\n * Built-ins go in first and user templates overwrite them, so overriding\n * `how-to` for a repo is one file with `types: [how-to]` in it - no config, no\n * flag. Within each source, a later entry wins, which makes the last\n * `--templates` file the one that decides.\n */\nexport function buildTypeIndex(params: {\n builtins?: { id: string; types: string[] }[];\n /** User template files, in the order they were supplied. */\n userFiles?: { ref: string; file: TemplateFile }[];\n /**\n * The config's explicit `types:` map. Highest precedence of the three, because\n * it is the only one where someone wrote down this exact pairing on purpose -\n * `types:` on a template says what that template is for, while this says what\n * this repo does about a doctype.\n */\n explicitTypes?: Record<string, string>;\n}): Map<string, TypeIndexEntry> {\n const index = new Map<string, TypeIndexEntry>();\n\n for (const builtin of params.builtins ?? []) {\n for (const type of builtin.types) {\n index.set(type, { ref: builtin.id, source: \"builtin\" });\n }\n }\n\n for (const { ref, file } of params.userFiles ?? []) {\n for (const [name, template] of Object.entries(file.templates ?? {})) {\n for (const type of template.types ?? []) {\n index.set(type, { ref: `${ref}#${name}`, source: \"user\" });\n }\n }\n }\n\n for (const [type, ref] of Object.entries(params.explicitTypes ?? {})) {\n index.set(type, { ref, source: \"config\" });\n }\n\n return index;\n}\n\nconst matcherCache = new Map<string, (p: string) => boolean>();\n\n/** Drop the compiled override-glob matchers. See `clearCaches`. */\nexport function clearMatcherCache(): void {\n matcherCache.clear();\n}\n\nfunction matchesGlob(glob: string, filePath: string): boolean {\n let m = matcherCache.get(glob);\n if (!m) {\n m = picomatch(glob, { dot: true });\n matcherCache.set(glob, m);\n }\n // Globs are written with forward slashes whatever the platform uses.\n return m(filePath.replace(/\\\\/g, \"/\"));\n}\n\n/**\n * Doctypes close enough to a typo to be worth naming. Edit distance of one or\n * two on short strings, or a shared prefix - enough to catch `how-two` and\n * `refernce` without listing the whole vocabulary at someone.\n */\nfunction suggestTypes(unknown: string, known: Iterable<string>): string[] {\n const target = unknown.toLowerCase();\n const scored: { type: string; distance: number }[] = [];\n\n for (const type of known) {\n const distance = editDistance(target, type.toLowerCase());\n const threshold = target.length <= 4 ? 1 : 3;\n if (distance <= threshold) scored.push({ type, distance });\n }\n\n return scored\n .sort((a, b) => a.distance - b.distance || a.type.localeCompare(b.type))\n .slice(0, 3)\n .map((s) => s.type);\n}\n\n/**\n * Levenshtein, two rows. Inputs here are doctype slugs, so size is not a\n * concern.\n *\n * Each cell needs three neighbours: the one to its left, the one above, and\n * the one above-left. Only the one above is read out of the previous row; the\n * other two are carried in locals from the cell just written and the previous\n * `above`. So the loop reads no array slot back by a computed index, which is\n * what `noUncheckedIndexedAccess` cannot prove is filled.\n *\n * The characters are compared as code units for the same reason: `a[i]` is\n * typed `string | undefined`, so comparing the two would either need an\n * assertion or a guard for a case the loop bounds already rule out.\n * `charCodeAt` returns `NaN` past the end and `NaN !== NaN`, so an index that\n * did escape its bounds costs an edit rather than matching by accident - the\n * invariant expressed rather than asserted.\n */\nfunction editDistance(a: string, b: string): number {\n if (a === b) return 0;\n let prev = Array.from({ length: b.length + 1 }, (_, i) => i);\n // The answer when `a` is empty: every character of `b` is an insertion.\n let last = b.length;\n for (let i = 0; i < a.length; i++) {\n const row = [i + 1];\n let left = i + 1;\n let diagonal = i;\n for (const [j, above] of prev.slice(1).entries()) {\n const cost = a.charCodeAt(i) === b.charCodeAt(j) ? 0 : 1;\n const cell = Math.min(left + 1, above + 1, diagonal + cost);\n row.push(cell);\n diagonal = above;\n left = cell;\n }\n prev = row;\n last = left;\n }\n return last;\n}\n\n/** A frontmatter value that should be a template ref. Non-strings are ignored. */\nfunction refFromFrontmatter(\n frontmatter: Record<string, unknown> | null,\n key: string,\n): string | null {\n const value = frontmatter?.[key];\n return typeof value === \"string\" && value.length > 0 ? value : null;\n}\n\nexport interface ResolveParams {\n /** Path used for override glob matching. */\n filePath: string;\n /**\n * Absolute path of the same file, matched as a fallback.\n *\n * `overrides[].files` globs are written relative to the config file, while\n * `filePath` is relative to the working directory. Those agree only when the\n * tool is run from the config's own directory; anywhere else the glob matched\n * nothing, the page fell through to its own `type`, and the run exited 0 with\n * the repo's policy silently unapplied. The CLI now rebases the globs to\n * absolute, so matching the absolute path too is what makes them land.\n */\n absolutePath?: string;\n /** The page's frontmatter, or null when it carries none. */\n frontmatter: Record<string, unknown> | null;\n /** `--template`: applies to every file in the run. */\n cliTemplate?: string;\n /** Repo policy, first match wins. */\n overrides?: TemplateOverride[];\n /** Doctype -> template, from `buildTypeIndex`. */\n typeIndex?: Map<string, TypeIndexEntry>;\n /** Applied when a page declares no doctype and nothing else matches. */\n defaultTemplate?: string;\n}\n\nexport function resolveTemplateRef(params: ResolveParams): Resolution {\n const steps: ResolutionStep[] = [];\n const typeIndex = params.typeIndex ?? new Map<string, TypeIndexEntry>();\n\n const decide = (stage: ResolutionStage, ref: string): Resolution => ({\n ref,\n stage,\n steps,\n });\n\n if (params.cliTemplate) {\n steps.push({ stage: \"cli\", ref: params.cliTemplate, detail: \"--template\" });\n return decide(\"cli\", params.cliTemplate);\n }\n steps.push({ stage: \"cli\", ref: null, detail: \"--template not given\" });\n\n const fileTemplate = refFromFrontmatter(params.frontmatter, FILE_TEMPLATE_KEY);\n if (fileTemplate) {\n steps.push({\n stage: \"frontmatter-template\",\n ref: fileTemplate,\n detail: `${FILE_TEMPLATE_KEY} in frontmatter`,\n });\n return decide(\"frontmatter-template\", fileTemplate);\n }\n steps.push({\n stage: \"frontmatter-template\",\n ref: null,\n detail: `no ${FILE_TEMPLATE_KEY} in frontmatter`,\n });\n\n for (const override of params.overrides ?? []) {\n if (\n matchesGlob(override.files, params.filePath) ||\n (params.absolutePath !== undefined &&\n matchesGlob(override.files, params.absolutePath))\n ) {\n steps.push({\n stage: \"config-override\",\n ref: override.template,\n detail: `matched override \"${override.files}\"`,\n });\n return decide(\"config-override\", override.template);\n }\n }\n steps.push({\n stage: \"config-override\",\n ref: null,\n detail: (params.overrides ?? []).length\n ? \"no override glob matched\"\n : \"no overrides configured\",\n });\n\n const type = refFromFrontmatter(params.frontmatter, TYPE_KEY);\n if (type) {\n const entry = typeIndex.get(type);\n if (entry) {\n steps.push({\n stage: \"type\",\n ref: entry.ref,\n detail: `type: ${type} -> ${entry.source} template`,\n });\n return decide(\"type\", entry.ref);\n }\n\n // A declared type that resolves to nothing is a typo or a gap, and either\n // way silently not checking the page is the wrong answer.\n steps.push({\n stage: \"type\",\n ref: null,\n detail: `type: ${type} matches no template`,\n });\n return {\n ref: null,\n stage: null,\n cause: \"unknown-type\",\n unknownType: type,\n suggestions: suggestTypes(type, typeIndex.keys()),\n knownTypes: knownTypes(typeIndex),\n steps,\n };\n }\n steps.push({ stage: \"type\", ref: null, detail: \"no type in frontmatter\" });\n\n if (params.defaultTemplate) {\n steps.push({\n stage: \"config-default\",\n ref: params.defaultTemplate,\n detail: \"config default\",\n });\n return decide(\"config-default\", params.defaultTemplate);\n }\n steps.push({ stage: \"config-default\", ref: null, detail: \"no default configured\" });\n\n // An untyped page is manni meta's complaint, not this tool's: its OKF schema\n // already requires `type`. Skipping rather than failing is what lets you\n // point manni lint at a whole tree on day one.\n return { ref: null, stage: null, cause: \"no-type\", steps };\n}\n\n/** The doctypes a resolved index can serve, sorted, for error messages. */\nexport function knownTypes(index: Map<string, TypeIndexEntry>): string[] {\n return [...index.keys()].sort();\n}\n\nexport type { Template };\n","/**\n * Run a template over a parsed document.\n *\n * Matching and checking are deliberately separate: `match.ts` decides which\n * section each rule is talking about, and this module asks the content rules\n * about the pairs it produced. The old code fused the two - it inferred which\n * section a rule meant by running the rules and seeing whether they passed -\n * which made \"does this section match?\" and \"is this section valid?\" the same\n * question, so a section could never be both matched and wrong.\n *\n * Everything here is synchronous. It was async only to await a language model,\n * which this tool no longer has.\n *\n * Two things beyond that wiring live here, and both are about the document as a\n * whole rather than about any one section.\n *\n * **A template is a rule, and its subject is the page.** Its `heading`\n * constrains the page's own title, its `sequence`/`contains` describe what sits\n * before the first heading, and its `sections` describe what follows. See\n * `pageSection` for which section that makes the subject.\n *\n * **A rule the format cannot answer is said out loud.** A parser declares the\n * content kinds it emits (proposal 0065), and a rule about a kind absent from\n * that list is dropped and reported as a `warning` rather than silently passing\n * - or, worse, failing a document for holding none of something its format\n * cannot express.\n */\nimport type {\n ContentKind,\n DocumentTree,\n Finding,\n Position,\n SectionNode,\n} from \"../types.js\";\nimport {\n checkContains,\n checkContainsIn,\n checkHeading,\n checkSequence,\n checkSequenceIn,\n type RuleContext,\n} from \"../rules/index.js\";\nimport { parserByName } from \"../parsers/index.js\";\nimport { matchSections, type MatchOptions } from \"./match.js\";\nimport { BLOCK_KINDS, BLOCK_KIND_NODE } from \"./template.js\";\nimport type {\n BlockKind,\n BlockRule,\n ElementsRule,\n ListItemsRule,\n ListsRule,\n Rule,\n TablesRule,\n Template,\n} from \"./template.js\";\n\n/** What a caller can tell the validator beyond the tree and the template. */\nexport interface ValidateOptions {\n /** Template file the rules came from. Names the state-cap failure. */\n source?: string;\n /** Template within that file. Named in messages about the template. */\n template?: string;\n /**\n * Content kinds the parser that produced this tree emits. Defaults to what\n * the registry declares for `tree.format`, which is what the CLI wants; a\n * caller holding a tree from somewhere else passes its own.\n */\n kinds?: ContentKind[];\n}\n\n/* -------------------------------------------------------------------------- *\n * The page as the template's subject\n * -------------------------------------------------------------------------- */\n\n/** A zero-width span at the top of a file, for a document with no sections. */\nfunction origin(): Position {\n return {\n start: { line: 1, column: 1, offset: 0 },\n end: { line: 1, column: 1, offset: 0 },\n };\n}\n\n/** First section's start through the last one's end. */\nfunction span(sections: SectionNode[]): Position {\n const first = sections[0];\n const last = sections[sections.length - 1];\n if (!first || !last) return origin();\n return { start: { ...first.position.start }, end: { ...last.position.end } };\n}\n\n/**\n * The section the template describes: the page itself.\n *\n * A page whose body is one `# Title` with everything nested under it *is* that\n * section, and a page whose content starts before any heading is the implicit\n * lead section `sectionize` opens for it - which has no heading of its own, so\n * `heading: false` matches it and `heading: \"Overview\"` does not.\n *\n * Anything else - several top-level headings, or a body that starts at `##`,\n * which is what a page whose title lives in frontmatter looks like - has no one\n * section standing for the page, so one is synthesised. It has no heading and\n * no content of its own: content before the first heading always opens a lead\n * section, so a document that reaches this branch has none.\n */\nfunction pageSection(tree: DocumentTree): SectionNode {\n const [only] = tree.sections;\n if (tree.sections.length === 1 && only && only.level <= 1) return only;\n return {\n slug: \"\",\n title: \"\",\n level: 0,\n order: 0,\n parentSlug: null,\n titlePosition: null,\n position: span(tree.sections),\n children: [],\n sections: tree.sections,\n };\n}\n\n/* -------------------------------------------------------------------------- *\n * Rules the format cannot answer\n * -------------------------------------------------------------------------- */\n\n/** One rule that will not run here, and what the parser does not report. */\ninterface UncheckedRule {\n /** The template key, as the author wrote it. */\n rule: string;\n /** What is missing, in words: `tables`, `table columns`, `list items`. */\n noun: string;\n}\n\n/** What each block-rule key asks about, as a message says it. */\nconst BLOCK_NOUNS: Record<BlockKind, string> = {\n paragraphs: \"paragraphs\",\n codeBlocks: \"code blocks\",\n lists: \"lists\",\n tables: \"tables\",\n admonitions: \"admonitions\",\n images: \"images\",\n blockquotes: \"blockquotes\",\n definitionLists: \"definition lists\",\n elements: \"elements\",\n};\n\n/**\n * A template with the rules this format cannot answer removed, and the list of\n * what was removed.\n *\n * Removing them is the point, not a side effect. A `tables: { min: 1 }` left\n * standing against a parser that never emits a table counts zero tables and\n * fails the page, which is a verdict on the format rather than on the document\n * - and it would contradict, in the same report, the warning saying the rule\n * was not checked.\n */\nclass Pruner {\n private readonly emitted: Set<ContentKind>;\n /** Keyed by message, so one rule asked twice is reported once. */\n private readonly missing = new Map<string, UncheckedRule>();\n\n constructor(kinds: ContentKind[]) {\n this.emitted = new Set(kinds);\n }\n\n get gaps(): UncheckedRule[] {\n return [...this.missing.values()];\n }\n\n private emits(kind: ContentKind): boolean {\n return this.emitted.has(kind);\n }\n\n private drop(rule: string, noun: string): void {\n this.missing.set(`${rule}: ${noun}`, { rule, noun });\n }\n\n /** A table rule without its `columns`, when the parser reports no cells. */\n private tables(rule: TablesRule): TablesRule {\n if (rule.columns === undefined || this.emits(\"tableCell\")) return rule;\n this.drop(\"columns\", \"table columns\");\n const { columns: _columns, ...kept } = rule;\n return kept;\n }\n\n /**\n * A list rule with its `items` pruned.\n *\n * `items` has no capability of its own to check. A parser that reports a\n * list reports its items, since `ListNode.items` is not optional, and\n * `listItem` is not one of the `BLOCK_KINDS` a block rule can target. So\n * the `lists` gap covers the whole rule, and only what the items *hold* can\n * go unchecked.\n *\n * `listItem` is a `ContentKind` and parsers do declare it. That is a fact\n * about the node model rather than about this pruner: a template names\n * `lists`, and reaches an item only through `items`, so there is no rule\n * whose capability would be `listItem` on its own.\n */\n private lists(rule: ListsRule): ListsRule {\n const items = rule.items;\n if (items === undefined) return rule;\n const pruned = this.listItems(items);\n return pruned === items ? rule : { ...rule, items: pruned };\n }\n\n private listItems(rule: ListItemsRule): ListItemsRule {\n return this.holder(rule);\n }\n\n private elements(rule: ElementsRule): ElementsRule {\n return this.holder(rule);\n }\n\n /** The `sequence`/`contains` pair every content holder carries. */\n private holder<T extends { sequence?: BlockRule[]; contains?: BlockRule }>(\n rule: T,\n ): T {\n const kept = { ...rule };\n let changed = false;\n\n if (rule.sequence) {\n const sequence = this.sequence(rule.sequence);\n if (sequence === undefined) {\n delete kept.sequence;\n changed = true;\n } else if (sequence !== rule.sequence) {\n kept.sequence = sequence;\n changed = true;\n }\n }\n\n if (rule.contains) {\n const contains = this.block(rule.contains);\n if (contains === undefined) {\n delete kept.contains;\n changed = true;\n } else if (contains !== rule.contains) {\n kept.contains = contains;\n changed = true;\n }\n }\n\n return changed ? kept : rule;\n }\n\n /**\n * One `sequence`, with the runs this format cannot see taken out.\n *\n * Taking the entry out rather than leaving it empty is what keeps the rest of\n * the sequence meaningful: a run of a kind the parser never emits can never\n * appear among the actual runs, so an entry left standing would report an\n * order error on every file of that format. `undefined` means the key goes.\n */\n private sequence(entries: BlockRule[]): BlockRule[] | undefined {\n const kept: BlockRule[] = [];\n let changed = false;\n for (const entry of entries) {\n const pruned = this.block(entry);\n if (pruned === undefined) {\n changed = true;\n continue;\n }\n if (pruned !== entry) changed = true;\n kept.push(pruned);\n }\n if (!changed) return entries;\n return kept.length > 0 ? kept : undefined;\n }\n\n /** One block rule, or `undefined` when nothing in it can be checked. */\n private block(block: BlockRule): BlockRule | undefined {\n const kept: BlockRule = { ...block };\n let changed = false;\n\n for (const key of BLOCK_KINDS) {\n if (kept[key] === undefined) continue;\n if (this.emits(BLOCK_KIND_NODE[key])) continue;\n this.drop(key, BLOCK_NOUNS[key]);\n // Cleared rather than deleted. A computed `delete` is banned here, and\n // nothing that reads a block rule asks whether the key is present - every\n // one of them tests the value against `undefined`.\n Object.assign(kept, { [key]: undefined });\n changed = true;\n }\n\n const tables = kept.tables;\n if (tables) {\n const pruned = this.tables(tables);\n if (pruned !== tables) {\n kept.tables = pruned;\n changed = true;\n }\n }\n\n const lists = kept.lists;\n if (lists) {\n const pruned = this.lists(lists);\n if (pruned !== lists) {\n kept.lists = pruned;\n changed = true;\n }\n }\n\n const elements = kept.elements;\n if (elements) {\n const pruned = this.elements(elements);\n if (pruned !== elements) {\n kept.elements = pruned;\n changed = true;\n }\n }\n\n if (!changed) return block;\n return BLOCK_KINDS.some((key) => kept[key] !== undefined) ? kept : undefined;\n }\n\n private rules(rules: Rule[]): Rule[] {\n const kept: Rule[] = [];\n let changed = false;\n for (const rule of rules) {\n const pruned = this.rule(rule);\n if (pruned !== rule) changed = true;\n kept.push(pruned);\n }\n return changed ? kept : rules;\n }\n\n rule<T extends Rule>(rule: T): T {\n const kept = this.holder(rule);\n let changed = kept !== rule;\n const out = changed ? kept : { ...rule };\n\n if (rule.repeat) {\n const repeat = this.rules(rule.repeat);\n if (repeat !== rule.repeat) {\n out.repeat = repeat;\n changed = true;\n }\n }\n\n if (rule.sections) {\n const sections = this.rules(rule.sections);\n if (sections !== rule.sections) {\n out.sections = sections;\n changed = true;\n }\n }\n\n return changed ? out : rule;\n }\n}\n\n/** A pruned template and what pruning it took out. */\ninterface Pruned {\n template: Template;\n gaps: UncheckedRule[];\n}\n\n/**\n * Pruned templates, keyed by the template and the format's kinds.\n *\n * The identity matters as much as the saving. `match.ts` caches one compiled\n * automaton per rule *array*, so a fresh copy of `sections` per file would\n * recompile the template for every page of a docset. A template that needs no\n * pruning is therefore returned as-is, and one that does is pruned once per\n * format.\n */\nconst pruneCache = new WeakMap<Template, Map<string, Pruned>>();\n\nfunction prune(template: Template, kinds: ContentKind[]): Pruned {\n const key = [...kinds].sort().join(\",\");\n let byKinds = pruneCache.get(template);\n if (!byKinds) {\n byKinds = new Map<string, Pruned>();\n pruneCache.set(template, byKinds);\n }\n const hit = byKinds.get(key);\n if (hit) return hit;\n\n const pruner = new Pruner(kinds);\n const pruned: Pruned = { template: pruner.rule(template), gaps: pruner.gaps };\n byKinds.set(key, pruned);\n return pruned;\n}\n\n/** The warning one unchecked rule gets, anchored at the top of the file. */\nfunction uncheckedFinding(\n format: string,\n name: string,\n gap: UncheckedRule,\n): Finding {\n return {\n type: \"unsupported_content_kind\",\n heading: null,\n message:\n `The ${format} parser does not report ${gap.noun}, so the ` +\n `\"${gap.rule}\" rule in template \"${name}\" is not checked for this file.`,\n position: origin(),\n // A warning, because nothing about the document is wrong: the rule asks\n // about something this format cannot express. It never changes the exit\n // code - `runLint` counts a file as failed only on an error-severity\n // finding - so a docset of mixed formats stays green while still saying\n // which rules went unchecked, and where.\n severity: \"warning\",\n };\n}\n\n/* -------------------------------------------------------------------------- *\n * The walk\n * -------------------------------------------------------------------------- */\n\n/** Content and heading rules for one matched pair, without recursion. */\nfunction checkSection(section: SectionNode, rule: Rule): Finding[] {\n return [\n ...checkHeading(section, rule.heading),\n ...checkSequence(section, rule.sequence),\n ...checkContains(section, rule.contains),\n ];\n}\n\n/** Match one level of sections, check each pair, then recurse. */\nexport function validateSections(\n sections: SectionNode[],\n rules: Rule[] | undefined,\n options: MatchOptions = {},\n): Finding[] {\n const { matches, findings } = matchSections(sections, rules, options);\n const all = [...findings];\n\n for (const match of matches) {\n all.push(...checkSection(match.section, match.rule));\n all.push(\n ...validateSections(match.section.sections, match.rule.sections, {\n ...options,\n parent: match.section,\n }),\n );\n }\n\n return all;\n}\n\n/** Findings for one document against one template, in document order. */\nexport function validateDocument(\n tree: DocumentTree,\n template: Template,\n options: ValidateOptions = {},\n): Finding[] {\n // An unrecognised format falls back to *no* kinds rather than to no pruning.\n // Every tree the CLI builds carries a registered parser's own name, so this\n // is only reachable through the exported API, with a tree somebody else\n // parsed. Such a format has promised nothing, so no content rule can be said\n // to have run against it, and the alternative is the one 0065 rules out:\n // applying every rule to a format that may answer none of them, which makes\n // a green run mean two different things.\n const kinds = options.kinds ?? parserByName(tree.format)?.kinds ?? [];\n const pruned = prune(template, kinds);\n const rules = pruned.template;\n // The template's own name, for the messages that have to say which template\n // asked. The caller knows it; `title` is the next best thing a file carries.\n const name = options.template ?? template.title ?? \"unnamed\";\n\n const findings: Finding[] = pruned.gaps.map((gap) =>\n uncheckedFinding(tree.format, name, gap),\n );\n\n // The page is the template's subject. Its content is checked through the\n // `*In` rules rather than the section-shaped ones so that a finding about a\n // page with no heading of its own carries no heading either, instead of the\n // empty string a headless section's title is.\n const page = pageSection(tree);\n const ctx: RuleContext = {\n heading: page.title || null,\n position: page.position,\n };\n findings.push(...checkHeading(page, rules.heading));\n findings.push(...checkSequenceIn(page.children, rules.sequence, ctx));\n findings.push(...checkContainsIn(page.children, rules.contains, ctx));\n findings.push(\n ...validateSections(page.sections, rules.sections, {\n parent: page,\n source: options.source,\n template: options.template,\n }),\n );\n\n // Rules fire in rule order, which is not necessarily document order once a\n // template mixes optional sections and subsections. Readers scan a report top\n // to bottom against the file, so sort by where the finding actually is.\n return findings.sort(\n (a, b) => a.position.start.offset - b.position.start.offset,\n );\n}\n","/**\n * The `lint:` section of `manni.config.yaml`.\n *\n * The file is shared across the manni family - manni docevals, manni meta and\n * this tool all read one file per repo, each taking its own top-level key. So\n * the root is a mapping of tool name to that tool's settings, and manni lint\n * reads `lint:` and nothing else: sibling keys are neither read nor validated,\n * which is what keeps the family decoupled - no registry of known tools, no\n * coordination, no version coupling. See agentevals ADR 01009.\n *\n * Finding the file is the family's job (`src/shared/config-file.ts`): it walks\n * up from the working directory to the repository root, reads the `lint:` key\n * of the first family file that has one, and hands this module the slice. What\n * the slice may contain is decided here. The pre-family\n * `doc-structure-lint.config.yaml` is no longer discovered: its whole document\n * was a `lint:` section written in keys this one no longer takes, so reading it\n * could only produce the moved-key refusal from a file the author is not\n * looking at.\n *\n * The document set is not a `lint:` key. Proposal 0041 declares it once for\n * every tool, under the family-level `collections:`, which the shared loader\n * parses and `resolveLintRun` selects from; `paths:` and `exclude:` under\n * `lint:` are refused by name.\n *\n * That leaves the root unvalidatable by any single tool, so the two ways an\n * author can lose a whole config to this convention are caught by shape\n * instead: keys left at the top level, and a wrapper differing only in case. A\n * wrapper misspelled any other way (`lnt:`) is indistinguishable from another\n * tool's section and still yields defaults - the accepted cost of having no\n * registry.\n *\n * Inside the section, `config.json` is the authority and `additionalProperties`\n * is false at every level, so a typo'd key is a loud failure rather than a\n * silent default. Defaults themselves live with the consumers, not here: this\n * returns exactly what the author wrote.\n */\nimport { dirname, isAbsolute, resolve } from \"node:path\";\nimport { parse as parseYaml } from \"yaml\";\nimport * as AjvNs from \"ajv\";\nimport type { ErrorObject, SchemaObject, ValidateFunction } from \"ajv\";\nimport configSchema from \"../../../schemas/lint/config.json\" with { type: \"json\" };\nimport { selectCollections, type CollectionConfig } from \"../../shared/collections.js\";\nimport {\n FAMILY_CONFIG_NAMES,\n findConfigFile,\n readConfigFile,\n type ConfigFile,\n type ConfigFileOptions,\n} from \"../../shared/config-file.js\";\nimport { LintError } from \"../types.js\";\nimport { errorMessage } from \"../../shared/errors.js\";\nimport type { ToolsConfig } from \"../../shared/tools.js\";\nimport type { TemplateOverride } from \"./resolve-template.js\";\nimport { refRelativeTo } from \"./template-registry.js\";\n\n// ajv is CommonJS with a default export; under NodeNext the constructable\n// value is on `.default`, which the namespace import reaches without the\n// esModuleInterop-only call signature TypeScript otherwise complains about.\ntype AjvCtor = typeof import(\"ajv\").default;\nconst Ajv = AjvNs.default as unknown as AjvCtor;\n\n/**\n * Everything the `lint:` section can carry. Every key is optional, and an\n * absent one means \"the consumer's default\", never a value written in here.\n *\n * `overrides[].template` and the `types` values are template refs, left as the\n * strings they were written as: `resolve-template.ts` owns what a ref means.\n */\nexport interface LintConfig {\n /** Zero matched files is a success, not an operational error. */\n allowEmpty?: boolean;\n /** The structure job: what `lint structure` runs and `lint check` includes. */\n structure?: LintJobConfig;\n /** Template files to load; their `types:` join the routing table. */\n templates?: string[];\n /** Template for a page that declares no doctype. */\n template?: string;\n /** Explicit doctype -> template ref map. */\n types?: Record<string, string>;\n /** Repo policy, first matching glob wins. */\n overrides?: TemplateOverride[];\n}\n\nexport type { TemplateOverride };\n\n/** One job's settings. The tool that performs it is all a job configures. */\nexport interface LintJobConfig {\n tool?: LintTool;\n}\n\n/**\n * The tools that can perform a lint job: manni's own engine, and DITA Open\n * Toolkit for a DITA docset.\n */\nexport const LINT_TOOLS = [\"manni\", \"dita-ot\"] as const;\nexport type LintTool = (typeof LINT_TOOLS)[number];\n\n/** The jobs `lint check` runs: `structure`. */\nexport const LINT_JOBS = [\"structure\"] as const;\nexport type LintJob = (typeof LINT_JOBS)[number];\n\n/** The tools each job accepts, in the order its message lists them. */\nexport const TOOLS_BY_JOB: Readonly<Record<LintJob, readonly LintTool[]>> = {\n structure: [\"manni\", \"dita-ot\"],\n};\n\nexport function isLintTool(value: string): value is LintTool {\n return (LINT_TOOLS as readonly string[]).includes(value);\n}\n\n/** The top-level key manni lint owns inside the shared manni config. */\nexport const SECTION_KEY = \"lint\";\n\n/** The family filenames discovery accepts, in the order it tries them. */\nexport const CONFIG_FILENAMES: readonly string[] = FAMILY_CONFIG_NAMES;\n\n/**\n * How the family loader finds and slices this tool's config.\n *\n * `legacyNames` is empty on purpose. `doc-structure-lint.config.yaml` was this\n * tool's file before the family file, and its whole document was the `lint:`\n * section - written in `paths:` and `exclude:`, which the section no longer\n * takes. Reading one now could only refuse it, from a file the author is not\n * looking at, so discovery no longer knows the name at all.\n */\nconst CONFIG_FILE: ConfigFileOptions = {\n section: SECTION_KEY,\n legacyNames: [],\n toError: (message) => new LintError(message),\n};\n\n/**\n * The keys this tool owns, read off the schema rather than restated here.\n *\n * Finding any of them at the root of a manni config means the file was never\n * nested under `lint:`. Deriving the list from `config.json` is what stops it\n * drifting from the real key set the next time a key is added - a restated\n * list that fell behind would let exactly the un-nested config it exists to\n * catch fall through to defaults instead.\n */\nconst SECTION_KEYS: readonly string[] = Object.keys(configSchema.properties);\n\n/** The keys one job takes. Read off the schema for the same reason. */\nconst STRUCTURE_KEYS: readonly string[] = Object.keys(\n configSchema.properties.structure.properties,\n);\n\n/**\n * Where the metadata tool's configuration reference documents `collections:`.\n * The literal cite's `config.ts` carries, repeated for the same reason: that\n * module is meta's own, and sibling tools import only its public and family\n * barrels.\n */\nconst CONFIG_REF = \"https://hawkeyexl.github.io/manni/meta/reference/configuration/\";\n\n/**\n * The two keys proposal 0041 moved out of `lint:` and up to the family level.\n * Refused rather than aliased, as meta and cite refuse them: an alias would be\n * a second place to declare a document set that is meant to be declared once.\n */\nconst MOVED_KEYS: readonly string[] = [\"paths\", \"exclude\"];\n\n/**\n * Refuse a moved key before the unknown-key check, which would otherwise call\n * `paths` a typo. Same sentence as meta's and cite's, with the section renamed.\n */\nfunction assertNoMovedKeys(raw: Record<string, unknown>, source: string): void {\n for (const key of MOVED_KEYS) {\n if (Object.hasOwn(raw, key)) {\n throw new LintError(\n `${source}: \"${key}\" is no longer a ${SECTION_KEY} key. Document sets are declared once for every tool, under a top-level collections: list. See ${CONFIG_REF}#collections`,\n );\n }\n }\n}\n\n/**\n * A key the parser does not know is a typo, not a no-op. Naming every key the\n * mapping takes is what turns `allowEmtpy: true` from a line that reads as\n * configured and does nothing into a failure the author can act on. `where` is\n * the mapping as the user spells it: `lint` or `lint.structure`.\n */\nfunction rejectUnknownKeys(\n obj: Record<string, unknown>,\n allowed: readonly string[],\n where: string,\n source: string,\n): void {\n for (const key of Object.keys(obj)) {\n if (!allowed.includes(key)) {\n throw new LintError(\n `Unknown key \"${key}\" under ${where}: in ${source}. Supported keys: ${allowed.join(\", \")}.`,\n );\n }\n }\n}\n\n/**\n * The job mappings, checked before Ajv so the messages name the key set and\n * the tool list rather than restating a schema keyword. A tool nobody\n * implements is refused by name: silently falling back to manni's engine would\n * make `tool: vale` read as configured and lint with something else.\n */\nfunction checkJobs(section: Record<string, unknown>, source: string): void {\n for (const job of LINT_JOBS) {\n const value = section[job];\n if (value == null || !isRecord(value)) continue;\n rejectUnknownKeys(value, STRUCTURE_KEYS, `${SECTION_KEY}.${job}`, source);\n const tool = value.tool;\n if (tool === undefined) continue;\n if (typeof tool !== \"string\" || !TOOLS_BY_JOB[job].includes(tool as LintTool)) {\n throw new LintError(\n `${source}: ${SECTION_KEY}.${job}.tool must be one of: ${TOOLS_BY_JOB[job].join(\", \")}.`,\n );\n }\n }\n}\n\n// No `useDefaults`: the schema declares no defaults, deliberately. A default\n// written into the parsed object is indistinguishable from a value the author\n// wrote, which is the trap `template.json` documents on its `required` key.\nconst ajv = new Ajv({ allErrors: true });\n\nlet compiled: ValidateFunction<LintConfig> | null = null;\n\nfunction sectionValidator(): ValidateFunction<LintConfig> {\n compiled ??= ajv.compile<LintConfig>(configSchema as SchemaObject);\n return compiled;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/**\n * One Ajv error, as a path an author can find in their file.\n *\n * Ajv's `instancePath` is relative to the section, so it is prefixed back to\n * `lint`: a bare `/overrides/0/files` names a path that is not in the file.\n */\nfunction describeError(error: ErrorObject): string {\n const params = error.params as { additionalProperty?: unknown };\n const extra =\n typeof params.additionalProperty === \"string\"\n ? ` (\"${params.additionalProperty}\")`\n : \"\";\n return `${SECTION_KEY}${error.instancePath} ${error.message ?? \"is invalid\"}${extra}`;\n}\n\n/** The un-nested config: our own keys at the root, with no `lint:` wrapper. */\nfunction rejectUnNested(root: Record<string, unknown>, source: string): void {\n const stray = SECTION_KEYS.filter((key) => key in root);\n if (stray.length === 0) return;\n // The convention is named after the shared file, but the message must\n // describe the file the user actually passed: telling someone who ran\n // `-c my-custom.yaml` about `manni.config.yaml` reads as a complaint about a\n // file they never mentioned, and sends them looking for the wrong one.\n throw new LintError(\n `${source}: found ${stray.map((key) => `\"${key}:\"`).join(\", \")} at the top level, ` +\n `but no \"${SECTION_KEY}:\" key. This file is shared across the manni family, ` +\n `so every manni lint setting belongs under a top-level \"${SECTION_KEY}:\" key. ` +\n `Indent the file's contents one level and add that key.`,\n );\n}\n\n/**\n * The miscased wrapper: `Lint:`, which the stray-key check cannot see, because\n * the keys under it are nested rather than at the top level.\n */\nfunction rejectMiscasedWrapper(\n root: Record<string, unknown>,\n source: string,\n): void {\n const miscased = Object.keys(root).find(\n (key) => key !== SECTION_KEY && key.toLowerCase() === SECTION_KEY,\n );\n if (miscased === undefined) return;\n throw new LintError(\n `${source}: found \"${miscased}:\" at the top level, but the key is case-sensitive ` +\n `and manni lint reads \"${SECTION_KEY}:\" exactly. Rename \"${miscased}:\" to \"${SECTION_KEY}:\".`,\n );\n}\n\n/**\n * Validate the `lint:` section itself, whatever file it came from.\n *\n * `source` names the file in every message. `null` is the section written\n * with nothing under it, which an author means as \"defaults\"; it is not a\n * broken section.\n */\nexport function parseConfigSection(section: unknown, source: string): LintConfig {\n if (section == null) return {};\n\n // Before Ajv, which would call a moved key an additional property and an\n // unknown one a schema keyword. Both messages have to name what to do.\n if (isRecord(section)) {\n assertNoMovedKeys(section, source);\n rejectUnknownKeys(section, SECTION_KEYS, SECTION_KEY, source);\n checkJobs(section, source);\n }\n\n const validate = sectionValidator();\n if (!validate(section)) {\n const detail =\n (validate.errors ?? []).map(describeError).join(\"; \") ||\n `does not match the ${SECTION_KEY} config schema`;\n throw new LintError(\n `${source}: invalid \"${SECTION_KEY}\" section: ${detail}.`,\n );\n }\n return section;\n}\n\n/**\n * Parse a whole `manni.config.yaml` and return its `lint:` section.\n *\n * `source` names the file in every message. A file that is empty, or that\n * carries only other tools' sections, returns `{}` rather than throwing - that\n * is the case that keeps one shared file usable by a project which has not\n * adopted this tool yet.\n */\nexport function parseConfig(text: string, source: string): LintConfig {\n let raw: unknown;\n try {\n raw = parseYaml(text);\n } catch (err) {\n throw new LintError(\n `${source}: invalid YAML: ${errorMessage(err)}`,\n );\n }\n\n // An empty file configures nothing; it is not a broken one.\n if (raw == null) return {};\n if (!isRecord(raw)) {\n throw new LintError(\n `${source}: top level must be a mapping of tool name to that tool's settings, ` +\n `with manni lint's under \"${SECTION_KEY}:\".`,\n );\n }\n\n if (!(SECTION_KEY in raw)) {\n rejectUnNested(raw, source);\n rejectMiscasedWrapper(raw, source);\n // Every remaining root key belongs to a sibling tool. Reading none of them\n // is the whole point of the convention.\n return {};\n }\n\n return parseConfigSection(raw[SECTION_KEY], source);\n}\n\n/**\n * Load the config from an explicit path, or by walking up from `cwd`.\n *\n * Discovery is the family's: the nearest `manni.config.yaml` with a `lint:`\n * key or a family key wins, and a family file with neither belongs to a\n * sibling and is passed over. An explicit path skips discovery and errors if\n * it is missing; its `lint:` key is unwrapped when present and the whole\n * document is the section otherwise, so a file passed by hand may be called\n * anything.\n *\n * A wrapper differing from `lint:` only in case is still caught on an\n * un-wrapped document: nothing else in the section's schema would name it.\n *\n * Returns null when discovery finds no config, which is not an error - a repo\n * whose pages all declare their `type` needs no config at all.\n */\nexport async function loadConfig(\n explicitPath?: string,\n cwd: string = process.cwd(),\n): Promise<{ config: LintConfig; path: string } | null> {\n const file = await readLintConfigFile(explicitPath, cwd);\n if (file === null) return null;\n return { config: sectionOf(file), path: file.path };\n}\n\n/** The family file itself, found or named, before its `lint:` slice is read. */\nfunction readLintConfigFile(\n explicitPath: string | undefined,\n cwd: string,\n): Promise<ConfigFile | null> {\n return explicitPath\n ? readConfigFile(explicitPath, cwd, CONFIG_FILE)\n : findConfigFile(cwd, CONFIG_FILE);\n}\n\n/** One found file's `lint:` section, parsed, with the shape checks a file gets. */\nfunction sectionOf(file: ConfigFile): LintConfig {\n if (!file.wrapped && isRecord(file.value)) {\n rejectMiscasedWrapper(file.value, file.source);\n }\n return parseConfigSection(file.value, file.source);\n}\n\n/**\n * Re-base everything a config declares against the config file's own\n * directory.\n *\n * `loadConfig` returns the file's `path` precisely so this can happen, and\n * discarding it made the same config mean different things depending on where\n * the tool was invoked from. Running from a subdirectory turned `templates:`\n * into \"file not found\" - and turned `overrides:` into nothing at all,\n * silently: the glob stopped matching, every page fell through to its own\n * `type`, and the run exited 0 having applied none of the repo's policy.\n *\n * Refs go through `refRelativeTo`, which leaves built-in ids, URLs, and\n * absolute paths alone. Globs become absolute, which is what the run matches\n * them against. Every non-absolute glob is relative to the config, `**\\/*.md`\n * included: exempting a leading `**` left the original bug half-open, because\n * from a subdirectory that pattern expanded against the working directory.\n */\nexport function rebaseConfig(\n found: { config: LintConfig; path: string } | null,\n): LintConfig {\n if (!found) return {};\n const dir = dirname(resolve(found.path));\n const config = found.config;\n\n const ref = (value: string): string => refRelativeTo(found.path, value);\n const glob = (value: string): string =>\n isAbsolute(value) ? value : resolve(dir, value).replace(/\\\\/g, \"/\");\n\n return {\n ...config,\n ...(config.templates ? { templates: config.templates.map(ref) } : {}),\n ...(config.template ? { template: ref(config.template) } : {}),\n ...(config.types\n ? {\n types: Object.fromEntries(\n Object.entries(config.types).map(([type, value]) => [type, ref(value)]),\n ),\n }\n : {}),\n ...(config.overrides\n ? {\n overrides: config.overrides.map((o) => ({\n files: glob(o.files),\n template: ref(o.template),\n })),\n }\n : {}),\n };\n}\n\n/** The stdin token, repeated so this module does not depend on the file loader. */\nconst STDIN = \"-\";\n\nexport interface LintRunOptions {\n cwd: string;\n /** `-c/--config`. */\n configPath?: string;\n /** `--no-config`: skip discovery and run on the built-in defaults. */\n noConfig?: boolean;\n /** Positional inputs; empty means fall back to the selected collections' `paths:`. */\n inputs: string[];\n /**\n * `--collection <name>`, repeatable: the collections this run covers. Empty\n * or absent means every declared one, the same thing, because commander's\n * collector hands `[]` over when the flag was never typed.\n */\n collection?: string[];\n onConfigLoaded?: (info: { path: string; dir: string }) => void;\n}\n\n/** What every lint command settles before it touches a file. */\nexport interface ResolvedLintRun {\n /** The `lint:` section, rebased against the config's directory. */\n config: LintConfig;\n /** What to resolve: the positional inputs, or the collections' `paths:`. */\n inputs: string[];\n /** The directory `inputs` resolve from. */\n base: string;\n /** The collections this run covers; `[]` with no config. */\n collections: CollectionConfig[];\n /** Whether `inputs` came from the collections rather than the command line. */\n fromCollections: boolean;\n /**\n * The document's top-level `tools:`, an outside tool's settings (proposal\n * 0052). `{}` with no config. It is not part of the `lint:` section and is\n * not rebased here: a path in it is resolved against `configDir` by the run\n * that needs it, through the helpers in `src/shared/tools.ts`.\n */\n tools: ToolsConfig;\n configDir?: string;\n configPath?: string;\n configSource?: string;\n}\n\n/**\n * Settle which config governs the run and what it covers. The same shape cite\n * uses, for the same reason: positional inputs are typed from a shell and stay\n * cwd-relative, while a collection's `paths:` was written next to the config\n * and resolves there, so one run has exactly one base.\n */\nexport async function resolveLintRun(\n opts: LintRunOptions,\n): Promise<ResolvedLintRun> {\n const cwd = resolve(opts.cwd);\n\n // `--collection` names something only a config can define, and selects a set\n // the operator did not type, so it composes with neither positional paths\n // nor `--no-config`. The same two sentences meta, a11y and cite use. Stdin\n // is one more input rather than a path, so it rides beside the flag.\n const wanted = opts.collection ?? [];\n if (wanted.length > 0 && opts.inputs.some((input) => input !== STDIN)) {\n throw new LintError(\n \"--collection selects a configured collection; it cannot be combined with paths.\",\n );\n }\n\n const file = opts.noConfig ? null : await readLintConfigFile(opts.configPath, cwd);\n if (wanted.length > 0 && file === null) {\n throw new LintError(\"--collection needs a config file to select from.\");\n }\n if (file !== null) opts.onConfigLoaded?.({ path: file.path, dir: file.dir });\n\n const config = rebaseConfig(\n file === null ? null : { config: sectionOf(file), path: file.path },\n );\n // Selected whatever the inputs are: a typed file is still a member of the\n // collections that contain it. An unknown name is the shared helper's error.\n const collections =\n file === null\n ? []\n : selectCollections(\n file.collections,\n wanted,\n file.source,\n (message) => new LintError(message),\n );\n\n // `--collection` is a request the run has to honour, as in cite and meta:\n // the named collection's pages are resolved even when stdin rides beside the\n // flag. Counting `-` as a path made `lint check - --as markdown --collection\n // guides` lint the piped document, open not one file of `guides`, and exit 0\n // over a docset nothing read. The implicit fallback is not a request, and a\n // lone `-` cancels it: a piped page is a run of its own.\n const fromCollections = wanted.length > 0 || opts.inputs.length === 0;\n const collectionPaths = fromCollections ? collections.flatMap((c) => c.paths) : [];\n // Stdin keeps its typed position; the globs follow it in declaration order.\n const inputs = fromCollections ? [...opts.inputs, ...collectionPaths] : opts.inputs;\n // Only a path needs a base, so it follows the globs when they contributed\n // and stays at the working directory otherwise, stdin included.\n const base = collectionPaths.length > 0 && file ? file.dir : cwd;\n\n return {\n config,\n inputs,\n base,\n collections,\n fromCollections,\n tools: file?.tools ?? {},\n ...(file === null\n ? {}\n : { configDir: file.dir, configPath: file.path, configSource: file.source }),\n };\n}\n","{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"manni-lint:config:1\",\n \"title\": \"manni lint config section\",\n \"description\": \"The `lint:` section of a shared `manni.config.yaml`. The file's root is a mapping of tool name to that tool's settings, so this schema describes the section only - never the file. The document set is not here: proposal 0041 declares it once for every tool, under the family-level `collections:` key, and `paths`/`exclude` under `lint:` are refused by name. Every key is optional: a repo that configures no manni lint at all is a legitimate config, and so is one that carries only a sibling tool's section. `additionalProperties: false` applies at every level below `lint:`, which is what turns a typo'd key into a loud failure instead of a silent default.\",\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"allowEmpty\": {\n \"description\": \"Treat a run that matched zero files as a success rather than an operational error. The same key, with the same meaning, as `cite.allowEmpty`: for a shared CI template or a pre-commit hook whose file list may legitimately be empty. `--allow-empty` on the command line sets it for one run.\",\n \"type\": \"boolean\"\n },\n \"overrides\": {\n \"description\": \"Repo policy: everything under a glob is linted with one template, whatever the pages say they are. First matching entry wins, and an override outranks a page's own `type`.\",\n \"type\": \"array\",\n \"items\": {\n \"description\": \"One policy entry. Both keys are required: an entry naming no template, or no files, is a line that silently does nothing.\",\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"files\", \"template\"],\n \"properties\": {\n \"files\": {\n \"description\": \"Glob matched against each file's path, written with forward slashes whatever the platform uses.\",\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"template\": {\n \"description\": \"Template ref applied to the files this entry matches.\",\n \"type\": \"string\",\n \"minLength\": 1\n }\n }\n }\n },\n \"structure\": {\n \"description\": \"The structure job, which `manni lint structure` and `manni lint check` both run. Declaring it with no keys is how a repo says the job applies. Its one setting is the tool that performs it.\",\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"tool\": {\n \"description\": \"Which tool performs the job. `manni` is manni's own template-structure engine; `dita-ot` is DITA Open Toolkit, which validates a DITA map and the topics it reaches and is located through the top-level `tools.dita-ot.home`. `--tool <name>` on the command line names the same thing.\",\n \"type\": \"string\",\n \"enum\": [\"manni\", \"dita-ot\"]\n }\n }\n },\n \"template\": {\n \"description\": \"Template ref applied to a page that declares no doctype and matches no override. The last stage of the resolution chain, not an override: `--template`, a page's `$template`, an `overrides` entry, and the page's own `type` all outrank it.\",\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"templates\": {\n \"description\": \"Template files to load. Their templates' `types:` join the doctype routing table, outranking the built-ins, so adopting a repo's own how-to shape is one entry here and no flag.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"types\": {\n \"description\": \"Explicit doctype -> template ref map, for a doctype no template file claims with its own `types:`. Keys are the vocabulary a page's `type` frontmatter is written in, so they are the author's names rather than this schema's - constrained only to the shape a doctype slug takes, not to a fixed set.\",\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"patternProperties\": {\n \"^[A-Za-z0-9._:-]+$\": {\n \"description\": \"A template ref: a built-in id, a path, or a URL, optionally with a `#name` fragment.\",\n \"type\": \"string\",\n \"minLength\": 1\n }\n }\n }\n }\n}\n","/**\n * The DITA Open Toolkit process seam: the only module that starts `dita`.\n *\n * Written in the shape `src/term/core/vale.ts` set, for the same reasons. The\n * launcher is started with an argv and never a shell string, the buffer is\n * raised because a build log is not small, and what comes back is validated\n * here, because it crosses a process boundary.\n *\n * **The test suite starts no DITA-OT, and needs no JVM.** Every unit test\n * injects a stub spawn. What the parser is fed is real output, though: the\n * logs under `test/lint/fixtures/dita-ot/logs/` are captures of DITA-OT 4.4.1\n * runs over the fixtures beside them, with only absolute paths rewritten.\n * Their README records what each one holds and where each field name comes\n * from.\n *\n * The verdict is the log, not the exit code: DITA-OT publishes no exit-code\n * contract, so a non-zero exit with a parseable log is findings, and only a\n * log that is missing or unreadable *and* a non-zero exit is a failure to run.\n */\nimport { execFile } from \"node:child_process\";\nimport { mkdtemp, readFile, rm, stat } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { delimiter, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { Severity } from \"../../shared/severity.js\";\nimport { ditaOtHome } from \"../../shared/tools.js\";\nimport { LintError } from \"../types.js\";\n// Type-only, and erased at runtime: `./index.js` imports this module to put the\n// descriptor in its initial map, so a value import here would be a cycle.\nimport type { FormatInfo } from \"../commands/tools.js\";\nimport type { StructureToolDescriptor, ToolProbe, ToolProbeContext } from \"./index.js\";\n\n/** What the launcher did. `code` is null when a signal ended it. */\nexport interface DitaOtProcessResult {\n code: number | null;\n /**\n * The signal that ended it, when one did, and `code` is then null. Optional\n * because absent means what it says: the run was not killed.\n */\n signal?: string | null;\n stdout: string;\n stderr: string;\n}\n\n/**\n * Start `launcher` with `args` and wait for it. Resolves for any exit; rejects\n * when the process could not start, with an error whose `code` is `ENOENT`\n * when there is no such launcher. Tests inject a stub.\n */\nexport type DitaOtSpawn = (\n launcher: string,\n args: string[],\n opts: { cwd?: string },\n) => Promise<DitaOtProcessResult>;\n\nconst MAX_BUFFER = 64 * 1024 * 1024;\n\n/** The two refusals a user reads, worded once. */\nconst NOT_ON_PATH =\n \"dita is not on PATH. Install DITA Open Toolkit to lint structure, or set tools.dita-ot.home.\";\n\nconst noLauncher = (home: string): string =>\n `no DITA Open Toolkit at \"${home}\". tools.dita-ot.home must be a DITA-OT installation directory.`;\n\n/**\n * `<home>/bin/dita`, or the bare name for the one on PATH. Windows has its own\n * launcher, `dita.bat`, which is what makes `ditaOtCommandLine` necessary.\n *\n * `platform` is a parameter so the mapping can be tested on either host.\n */\nexport function ditaOtLauncher(\n home: string | undefined,\n platform: NodeJS.Platform = process.platform,\n): string {\n const name = platform === \"win32\" ? \"dita.bat\" : \"dita\";\n return home === undefined ? name : join(home, \"bin\", name);\n}\n\n/** How a launcher is actually started. */\nexport interface DitaOtCommandLine {\n command: string;\n argv: string[];\n /** Windows: the argv is already one quoted string and must not be re-quoted. */\n verbatim: boolean;\n}\n\nfunction isBatch(launcher: string): boolean {\n const lower = launcher.toLowerCase();\n return lower.endsWith(\".bat\") || lower.endsWith(\".cmd\");\n}\n\n/**\n * Quote one token for `cmd.exe`. A `\"` inside a Windows path is impossible -\n * the character is not legal in a filename - so a value carrying one is a\n * shape this cannot quote safely, and it is refused rather than passed on.\n */\nfunction quoteForCmd(value: string): string {\n if (value.includes('\"')) {\n throw new LintError(\n `DITA Open Toolkit cannot be given an argument containing a quote: ${value}`,\n );\n }\n return `\"${value}\"`;\n}\n\n/**\n * How to start `launcher`, given what it is.\n *\n * Node refuses to `execFile` a `.bat` or `.cmd` without a shell, and\n * `shell: true` joins the argv into one string **with no quoting at all**. Our\n * argv carries user-supplied paths, so that is a command-injection hole, not a\n * convenience. The documented alternative is this one: run `cmd.exe` directly,\n * do the quoting here, and pass the whole command as one verbatim argument.\n * `/s` then strips exactly the outer pair of quotes, which is why the string\n * is wrapped a second time. The next reader will find `shell: true` simpler;\n * it is also the version with the hole in it.\n */\nexport function ditaOtCommandLine(\n launcher: string,\n args: string[],\n): DitaOtCommandLine {\n if (!isBatch(launcher)) {\n return { command: launcher, argv: args, verbatim: false };\n }\n const line = [launcher, ...args].map(quoteForCmd).join(\" \");\n return {\n command: process.env[\"COMSPEC\"] ?? \"cmd.exe\",\n argv: [\"/d\", \"/s\", \"/c\", `\"${line}\"`],\n verbatim: true,\n };\n}\n\nexport const spawnDitaOt: DitaOtSpawn = (launcher, args, opts) =>\n new Promise((settle, reject) => {\n const line = ditaOtCommandLine(launcher, args);\n execFile(\n line.command,\n line.argv,\n {\n cwd: opts.cwd,\n windowsHide: true,\n windowsVerbatimArguments: line.verbatim,\n maxBuffer: MAX_BUFFER,\n encoding: \"utf8\",\n },\n (error, stdout, stderr) => {\n if (!error) {\n settle({ code: 0, stdout, stderr });\n return;\n }\n if (typeof error.code === \"number\") {\n settle({ code: error.code, stdout, stderr });\n return;\n }\n // Killed by a signal. Node reports the exit code as **null** here, not\n // as undefined, so testing for undefined never matched and a killed\n // run rejected as though the launcher had failed to start. The log is\n // still read: a run cut short may have written findings before it died.\n if (error.code == null && typeof error.signal === \"string\") {\n settle({ code: null, signal: error.signal, stdout, stderr });\n return;\n }\n // A start failure (ENOENT) or an output over the buffer.\n const failure: Error = error;\n reject(failure);\n },\n );\n });\n\nfunction isEnoent(err: unknown): boolean {\n return (\n typeof err === \"object\" &&\n err !== null &&\n \"code\" in err &&\n err.code === \"ENOENT\"\n );\n}\n\nfunction isMapping(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nasync function isFile(path: string): Promise<boolean> {\n try {\n return (await stat(path)).isFile();\n } catch {\n return false;\n }\n}\n\n/**\n * Whether a bare launcher name resolves to a file on `PATH`.\n *\n * Asked only after a failure, and only to choose the message. On Windows the\n * launcher is a `.bat` started through `cmd.exe`, so a missing one comes back\n * as cmd's own non-zero exit rather than as an `ENOENT` - and the advice a\n * reader needs is \"install DITA-OT\", not cmd's sentence about a command it did\n * not recognize.\n */\nasync function isOnPath(name: string): Promise<boolean> {\n for (const dir of (process.env[\"PATH\"] ?? \"\").split(delimiter)) {\n if (dir === \"\") continue;\n if (await isFile(join(dir, name))) return true;\n }\n return false;\n}\n\n/**\n * DITA-OT's `MessageBean.Type` onto the family's three-value scale, as\n * `foldValeSeverity` does for Vale's.\n *\n * `null` is \"not a finding\": `DEBUG` and `TRACE` are build chatter even when\n * they carry a code, and a level this does not know is dropped rather than\n * promoted to something it might not be.\n */\nexport function foldDitaOtSeverity(level: string): Severity | null {\n switch (level.toUpperCase()) {\n case \"FATAL\":\n case \"ERROR\":\n return \"error\";\n case \"WARN\":\n return \"warning\";\n case \"INFO\":\n return \"notice\";\n default:\n return null;\n }\n}\n\n/** One diagnostic DITA-OT reported, in the vocabulary the lint branch reads. */\nexport interface DitaOtMessage {\n /** DITA-OT's own message id, e.g. `DOTX010E`. Becomes the finding's `type`. */\n code: string;\n severity: Severity;\n message: string;\n /** The path its `location` URI named, absent when it named none. */\n file?: string;\n line?: number;\n /** The **column**. See `readMessage` for why the log calls it `row`. */\n column?: number;\n}\n\n/**\n * The path a `location` names.\n *\n * DITA-OT writes `file:/x`, one slash and no authority. `new URL` normalizes\n * that to the three-slash form, so the quirk costs nothing. What does cost\n * something is a POSIX-rooted URI read on Windows: `fileURLToPath` refuses\n * `file:///repo/a.dita` outright there, with `ERR_INVALID_FILE_URL_PATH`, and\n * a log written on a Linux CI runner is full of exactly those. The decoded\n * pathname is the answer in that case.\n */\nfunction pathFromFileUri(location: string): string {\n let url: URL;\n try {\n url = new URL(location);\n } catch {\n // Not a URI at all: DITA-OT named a bare path, so it is the path.\n return location;\n }\n if (url.protocol !== \"file:\") return location;\n try {\n return fileURLToPath(url);\n } catch {\n return decodeURIComponent(url.pathname);\n }\n}\n\n/**\n * One log object as a finding, or `null` when it is not one.\n *\n * `code` is the marker. DITA-OT writes hundreds of `INFO` lines that are\n * progress rather than diagnostics, and it is its own account of which is\n * which, so an object without a code is chatter whatever its level.\n */\nfunction readMessage(raw: unknown): DitaOtMessage | null {\n if (!isMapping(raw)) return null;\n const code = raw[\"code\"];\n if (typeof code !== \"string\" || code === \"\") return null;\n const level = raw[\"level\"];\n const severity =\n typeof level === \"string\" ? foldDitaOtSeverity(level) : null;\n if (severity === null) return null;\n\n const msg = raw[\"msg\"];\n const location = raw[\"location\"];\n const line = raw[\"line\"];\n // `row` is the column. The name is the logger's: its regex takes group 2 as\n // the line and group 3 as the column, then writes the column out under this\n // name. Read as a row it puts every finding on the wrong line, so do not\n // \"fix\" it to `line`.\n const row = raw[\"row\"];\n\n return {\n code,\n severity,\n // A coded message with no text is still a finding; the code says what it is.\n message: typeof msg === \"string\" && msg !== \"\" ? msg : code,\n ...(typeof location === \"string\" && location !== \"\"\n ? { file: pathFromFileUri(location) }\n : {}),\n ...(typeof line === \"number\" ? { line } : {}),\n ...(typeof row === \"number\" ? { column: row } : {}),\n };\n}\n\n/**\n * The findings in a `--logger=json` log, or `null` when the text is not one.\n *\n * Null rather than an empty list, because the caller treats the two\n * differently: no findings is a clean target, while no log at all is only a\n * failure when the launcher also exited non-zero.\n */\nexport function parseDitaOtLog(text: string): DitaOtMessage[] | null {\n let parsed: unknown;\n try {\n parsed = JSON.parse(text) as unknown;\n } catch {\n return null;\n }\n if (!Array.isArray(parsed)) return null;\n const messages: DitaOtMessage[] = [];\n for (const raw of parsed as unknown[]) {\n const message = readMessage(raw);\n if (message !== null) messages.push(message);\n }\n return messages;\n}\n\n/** The first version-shaped number in what the launcher printed. */\nexport function parseDitaOtVersion(output: string): string | null {\n const match = /\\b(\\d+(?:\\.\\d+)+(?:[-.][0-9A-Za-z]+)*)/.exec(output);\n return match?.[1] ?? null;\n}\n\n/** What one invocation of DITA-OT had to say about one target. */\nexport interface DitaOtTargetResult {\n /** The absolute path this invocation was given as `--input`. */\n target: string;\n messages: DitaOtMessage[];\n}\n\nexport interface DitaOtRunOptions {\n /** Absolute paths. One invocation each: DITA-OT takes one `--input`. */\n targets: string[];\n /** The directory the run resolves from, and where the launcher is started. */\n cwd: string;\n /** `tools.dita-ot.home`, already resolved to an absolute directory. */\n home?: string;\n spawn?: DitaOtSpawn;\n}\n\n/** The message a failure to run reports, which is the launcher's own. */\nfunction failureText(result: DitaOtProcessResult): string {\n const stderr = result.stderr.trim();\n if (stderr !== \"\") return stderr;\n // \"exit code null\" says nothing a reader can act on, and a signal is the one\n // ending that reliably leaves no message behind.\n if (result.signal != null) return `killed by ${result.signal}`;\n return `exit code ${String(result.code)}`;\n}\n\nasync function readLog(path: string): Promise<DitaOtMessage[] | null> {\n let text: string;\n try {\n text = await readFile(path, \"utf8\");\n } catch {\n return null;\n }\n return parseDitaOtLog(text);\n}\n\n/**\n * DITA-OT over each target, and what its log said.\n *\n * ## Why this is not `dita validate`\n *\n * Because `dita validate` does not answer the question this tool exists for.\n * Run against a map whose topic conrefs an id that is not there, it exits 0 and\n * prints nothing. It parses and checks grammar, and it resolves no references.\n * Its own `--help` lists neither `--logger` nor `--logfile` nor `--temp`, so\n * the obvious invocation is silently accepted and silently useless.\n *\n * `--format=dita` is the DITA-to-DITA transformation. It runs the whole\n * preprocessing chain, which is where conref, keyref and link resolution\n * happen, and it reports what those stages find. Measured against the fixtures\n * beside this file, it catches everything `validate` catches and the references\n * as well: a grammar error is `DOTJ088E` with a line and a column, a missing\n * conref target is `DOTX010E`, an unreadable link target is `DOTX008E`.\n *\n * The cost is that a transformation writes output. It goes to the scratch\n * directory with the logs and the temp trees, and the whole scratch is removed\n * however the run ends, so nothing of ours lands in the user's tree.\n *\n * ## Why verbose\n *\n * Because DITA-OT reports an undefined key reference (`DOTJ047I`) at `INFO`,\n * and the default verbosity drops it. Verbose turns one run of a four-file map\n * into roughly 135 log entries, of which one carries a `code`. That is what\n * makes the `code` filter in `parseDitaOtLog` load-bearing rather than tidy.\n */\nexport async function runDitaOtValidate(\n opts: DitaOtRunOptions,\n): Promise<DitaOtTargetResult[]> {\n const spawn = opts.spawn ?? spawnDitaOt;\n const launcher = ditaOtLauncher(opts.home);\n // A home that holds no launcher is a configuration mistake, and saying so\n // before anything is started names the thing the user can fix.\n if (opts.home !== undefined && !(await isFile(launcher))) {\n throw new LintError(noLauncher(opts.home));\n }\n\n const scratch = await mkdtemp(join(tmpdir(), \"manni-dita-ot-\"));\n try {\n const results: DitaOtTargetResult[] = [];\n for (const [index, target] of opts.targets.entries()) {\n const logfile = join(scratch, `${String(index)}.json`);\n const args = [\n `--input=${target}`,\n \"--format=dita\",\n `--output=${join(scratch, `out-${String(index)}`)}`,\n `--temp=${join(scratch, `temp-${String(index)}`)}`,\n \"--logger=json\",\n `--logfile=${logfile}`,\n \"--verbose\",\n ];\n\n let result: DitaOtProcessResult;\n try {\n result = await spawn(launcher, args, { cwd: opts.cwd });\n } catch (err) {\n if (isEnoent(err)) {\n throw new LintError(\n opts.home === undefined ? NOT_ON_PATH : noLauncher(opts.home),\n );\n }\n throw err;\n }\n\n const messages = await readLog(logfile);\n\n /**\n * A non-zero exit has to be accounted for by something we are going to\n * report. Otherwise the run failed for a reason this log does not hold,\n * and saying \"no findings\" would be inventing a clean bill of health.\n *\n * The asymmetry is DITA-OT's. It exits **0** while logging `DOTX010E`\n * for a broken conref, so a zero exit proves nothing and the log is the\n * verdict. It also exits **1** on a map that is not well-formed, having\n * already written a perfectly readable log whose only coded entries are\n * `DOTJ030I` at `INFO`, with the fatal parse error in neither the log\n * nor stdout nor stderr. Trusting the parse of that log reported the\n * file as passing, which is the false green this guard exists for.\n */\n // Only an `error` accounts for it. A warning or a notice is something\n // DITA-OT says while finishing the job, and it exits 0 having said it,\n // so a non-zero exit alongside nothing worse than `DOTJ047I` is still a\n // failure this log does not explain.\n const explained =\n messages !== null && messages.some((m) => m.severity === \"error\");\n\n if (result.code !== 0 && !explained) {\n if (opts.home === undefined && !(await isOnPath(launcher))) {\n throw new LintError(NOT_ON_PATH);\n }\n throw new LintError(\n `DITA Open Toolkit failed on ${target}: ${failureText(result)}. ` +\n `Run it directly on that file to see why.`,\n );\n }\n\n results.push({ target, messages: messages ?? [] });\n }\n return results;\n } finally {\n await rm(scratch, { recursive: true, force: true });\n }\n}\n\n/**\n * Whether DITA-OT can run here, and at what version.\n *\n * Never throws: reporting what cannot run is `manni lint tools`' job, and a\n * probe that threw would take the whole table down with it. So a launcher\n * that fails to start for any reason (`ENOENT`, but also `EACCES` or `EPERM`)\n * is unavailable. A non-zero exit counts as unavailable too, because on\n * Windows a missing `dita.bat` is cmd.exe's exit code rather than an `ENOENT`.\n */\nexport async function probeDitaOt(\n ctx: ToolProbeContext,\n spawn: DitaOtSpawn = spawnDitaOt,\n): Promise<ToolProbe> {\n const home =\n ctx.tools === undefined\n ? undefined\n : ditaOtHome(ctx.tools, ctx.configDir ?? ctx.cwd);\n const launcher = ditaOtLauncher(home);\n if (home !== undefined && !(await isFile(launcher))) {\n return { available: false, version: null };\n }\n\n let result: DitaOtProcessResult;\n try {\n result = await spawn(launcher, [\"--version\"], { cwd: ctx.cwd });\n } catch {\n return { available: false, version: null };\n }\n if (result.code !== 0) return { available: false, version: null };\n return {\n available: true,\n // Both channels, because which one carries the banner is not fixed: the\n // shell launcher prints it on stdout, and the Windows `.bat` run through\n // `cmd.exe` has been seen to put it on stderr. Reading one would report a\n // toolkit that is plainly there as versionless on the other platform.\n version: parseDitaOtVersion(`${result.stdout}\\n${result.stderr}`),\n };\n}\n\n/**\n * DITA's one format row.\n *\n * `kinds` is empty and that is correct: DITA-OT does not parse into manni's\n * content model, and the column exists to say what a template rule can ask\n * about. `.xml` is listed because a DITA topic is often named that way; the\n * walk set is narrower on purpose - see `walkExtensions`.\n */\nconst DITA_FORMAT: FormatInfo = {\n name: \"dita\",\n label: \"DITA\",\n extensions: [\".ditamap\", \".dita\", \".xml\"],\n kinds: [],\n};\n\nexport const ditaOt: StructureToolDescriptor = {\n name: \"dita-ot\",\n label: \"DITA Open Toolkit\",\n formats: () => [{ ...DITA_FORMAT }],\n // Maps only. DITA-OT takes one `--input` per invocation, so walking\n // every topic in a docset would pay a JVM start per topic. Naming a `.dita`\n // explicitly still works: a named file bypasses the extension filter.\n walkExtensions: () => [\".ditamap\"],\n probe: (ctx) => probeDitaOt(ctx),\n // None. Every option manni owns is refused under this tool, stdin included.\n ownedOptions: [],\n};\n","/**\n * The tools that can perform a lint job, one descriptor each.\n *\n * Deliberately **not** a unified `run()` interface. The tools take completely\n * different inputs: manni's engine needs the templates, the doctype index and\n * the parser registry, and a tool outside the package needs none of them. A\n * lowest-common-denominator `run(files, options)` would either lie about what\n * it accepts or grow a passthrough blob nobody can type. `src/shared/tools.ts`\n * records the same decision for `tools:`, and for the same reason.\n *\n * What the tools genuinely share is what the *command* has to know before it\n * dispatches: the formats to list, the extensions a directory walk collects,\n * whether the tool can run here, and which options belong to the tool rather\n * than to the job. That is this table, and nothing more. Running a tool stays\n * with the branch that runs it.\n */\nimport pkg from \"../../../package.json\" with { type: \"json\" };\nimport { listFormats, supportedExtensions } from \"../parsers/index.js\";\nimport type { FormatInfo } from \"../commands/tools.js\";\nimport { TOOLS_BY_JOB, type LintTool } from \"../core/config.js\";\nimport type { ToolsConfig } from \"../../shared/tools.js\";\nimport { LintError } from \"../types.js\";\nimport { ditaOt } from \"./dita-ot.js\";\n\n/** What a probe is allowed to look at. A tool outside the package shells out. */\nexport interface ToolProbeContext {\n /** The directory the run resolves from. */\n cwd: string;\n /**\n * The family's top-level `tools:`, when a config declared one.\n *\n * A tool outside the package is found where its own `tools.<tool>` says it\n * is, so a probe that could not read it would report \"not available\" over an\n * installation the run itself goes on to use. manni's own probe ignores it.\n */\n tools?: ToolsConfig;\n /** The directory the config that declared `tools:` sits in. */\n configDir?: string;\n}\n\n/** Whether a tool can run here, and at what version. */\nexport interface ToolProbe {\n available: boolean;\n /** The version the tool reported, or null when it reported none. */\n version: string | null;\n}\n\nexport interface StructureToolDescriptor {\n name: LintTool;\n label: string;\n /** Formats for `manni lint tools`' formats column. */\n formats: () => FormatInfo[];\n /** Extensions a directory walk collects when this tool runs. */\n walkExtensions: () => string[];\n /** Whether this tool can run here, and at what version. */\n probe: (ctx: ToolProbeContext) => Promise<ToolProbe>;\n /**\n * Options that belong to this tool alone, spelled as a user types them.\n *\n * `-` is in the list because stdin is one of them: a tool that reads a\n * document off a pipe is answering the same question as one that reads\n * `--template`, and deriving both from one list is what keeps the next tool\n * from having to remember to refuse either.\n */\n ownedOptions: readonly string[];\n}\n\n/**\n * manni's own engine, which ships in this package.\n *\n * `formats` and `walkExtensions` forward to the parser registry rather than\n * restating it: a format added there is listed and walked here the moment it\n * is registered, which is the property `parsers/index.ts` exists to have.\n */\nconst manni: StructureToolDescriptor = {\n name: \"manni\",\n label: \"manni's own structure engine\",\n formats: () => listFormats(),\n walkExtensions: () => supportedExtensions(),\n // Nothing to look for: the engine is this package, so it is available\n // wherever the CLI is. A tool that shells out answers this by looking.\n probe: () => Promise.resolve({ available: true, version: pkg.version }),\n // `-` is stdin, and it is in this list so the derivation in `lint.ts` has\n // one place to learn that manni owns it. The refusal itself is not shaped\n // like the others, because \"option\" is the wrong word for a positional:\n // `assertOptionsOwned` special-cases it to say \"cannot read stdin\" instead.\n // A tool that copies this list without reading that guard gets the right\n // ownership and the wrong sentence.\n ownedOptions: [\"--template\", \"--templates\", \"--explain\", \"--as\", \"-\"],\n};\n\n/**\n * Registered statically rather than through `registerStructureTool` at import\n * time, so the table and `LINT_TOOLS` agree whatever order the modules load\n * in: a name in `LINT_TOOLS` with no descriptor is a `--tool` value the config\n * validates and the run cannot dispatch.\n */\nconst descriptors = new Map<string, StructureToolDescriptor>([\n [manni.name, manni],\n [ditaOt.name, ditaOt],\n]);\n\n/**\n * Add a descriptor, and hand back the undo.\n *\n * The registry is mutable so a second tool can be stood up without a name\n * being added to `LINT_TOOLS` first. A name there is a `--tool` value the CLI\n * accepts and the config validates, so adding one for a tool that cannot run\n * is the silent green this seam exists to prevent.\n */\nexport function registerStructureTool(\n descriptor: StructureToolDescriptor,\n): () => void {\n const previous = descriptors.get(descriptor.name);\n descriptors.set(descriptor.name, descriptor);\n return () => {\n if (previous === undefined) descriptors.delete(descriptor.name);\n else descriptors.set(descriptor.name, previous);\n };\n}\n\n/** The descriptor registered under `name`, if there is one. */\nexport function structureTool(\n name: string,\n): StructureToolDescriptor | undefined {\n return descriptors.get(name);\n}\n\n/** Every registered descriptor, in registration order. */\nexport function structureTools(): StructureToolDescriptor[] {\n return [...descriptors.values()];\n}\n\n/**\n * The descriptor for a named tool, or the refusal a user reads.\n *\n * The message is the one the CLI's own `--tool` guard produced before the\n * registry existed, because `runLint` is exported from `src/index.ts` and\n * called in process: a caller that never touches commander owes the same\n * sentence.\n */\nexport function resolveStructureTool(name: string): StructureToolDescriptor {\n const descriptor = descriptors.get(name);\n if (descriptor) return descriptor;\n throw new LintError(\n `Unknown --tool \"${name}\" for structure. Use ${TOOLS_BY_JOB.structure.join(\", \")}.`,\n );\n}\n"],"mappings":"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","names":["readFile","resolve","firstLine","metadata","processor","ZERO","positionOf","childContent","span","toContentNode","documentEnd","ADMONITION_VARIANTS","firstLine","text","under","title","last","rawText","elementChildren","ADMONITION_VARIANTS","compiled","readMetadata","flattenInline","ADMONITION_VARIANTS","parse","lower","load","rebased","origin","dirname","isAbsolute","parseYaml","AjvNs","Ajv","isRecord","ajv","Ajv","compiled","describeError","parseYaml","dirname","isAbsolute","readFile","join","join","lower","readFile","origin","resolve","readFile"]}
|