@plebeiantech/lat.md 0.12.3-fork.17 → 0.12.3-fork.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (244) hide show
  1. package/README.md +1 -1
  2. package/dist/src/cli/agent-invocation.d.ts +6 -0
  3. package/dist/src/cli/agent-invocation.js +23 -0
  4. package/dist/src/cli/fork-instructions.js +1 -1
  5. package/dist/src/cli/fork-scaffold.js +2 -2
  6. package/dist/src/cli/graph.d.ts +1 -1
  7. package/dist/src/cli/hook.js +11 -11
  8. package/dist/src/cli/index.js +41 -59
  9. package/dist/src/cli/init-preferences.js +5 -4
  10. package/dist/src/cli/init.d.ts +1 -1
  11. package/dist/src/cli/init.js +54 -45
  12. package/dist/src/cli/reindex.d.ts +1 -1
  13. package/dist/src/cli/reindex.js +2 -2
  14. package/dist/src/cli/search.d.ts +4 -4
  15. package/dist/src/cli/search.js +41 -28
  16. package/dist/src/cli/ui-build-server.d.ts +1 -1
  17. package/dist/src/cli/ui-build.d.ts +1 -1
  18. package/dist/src/cli/ui.d.ts +1 -1
  19. package/dist/src/fork/antigravity-hook.js +6 -6
  20. package/dist/src/fork/antigravity-init.d.ts +2 -2
  21. package/dist/src/fork/antigravity-init.js +2 -2
  22. package/dist/src/graph-export.js +7 -7
  23. package/dist/src/knowledge/index.js +2 -2
  24. package/dist/src/mcp/server.js +8 -8
  25. package/dist/src/search/cache.d.ts +1 -1
  26. package/dist/src/search/cache.js +40 -7
  27. package/dist/src/search/chunks.d.ts +2 -2
  28. package/dist/src/search/db.d.ts +5 -4
  29. package/dist/src/search/db.js +36 -40
  30. package/dist/src/search/embedder.js +1 -1
  31. package/dist/src/search/index.d.ts +1 -1
  32. package/dist/src/search/index.js +2 -2
  33. package/dist/src/search/lock.d.ts +4 -1
  34. package/dist/src/search/lock.js +30 -8
  35. package/dist/src/search/query.d.ts +5 -2
  36. package/dist/src/search/query.js +55 -38
  37. package/dist/src/search/search.d.ts +3 -1
  38. package/dist/src/search/search.js +21 -12
  39. package/dist/src/search/types.d.ts +2 -18
  40. package/dist/src/view/client/assets/{GraphView-BWlRdQM4.js → GraphView-Dij8mAA_.js} +1 -1
  41. package/dist/src/view/client/assets/{MarkdownEditor-MW-Ck1O0.js → MarkdownEditor-88Wbt0M1.js} +1 -1
  42. package/dist/src/view/client/assets/{abnfDiagram-VCTEODGH-Bn3RshMV.js → abnfDiagram-VCTEODGH-y0DlYa8E.js} +1 -1
  43. package/dist/src/view/client/assets/{arc-En9tdFQF.js → arc-FlMu8dnO.js} +1 -1
  44. package/dist/src/view/client/assets/{architectureDiagram-5GKGNRK7-B-9J1VAM.js → architectureDiagram-5GKGNRK7-DA_uWZW1.js} +1 -1
  45. package/dist/src/view/client/assets/{blockDiagram-I7D4REHJ-QlznwalP.js → blockDiagram-I7D4REHJ-BHQ5LU85.js} +1 -1
  46. package/dist/src/view/client/assets/{c4Diagram-7LVT6UL2-Bp2y8B4_.js → c4Diagram-7LVT6UL2-BRucKCt2.js} +1 -1
  47. package/dist/src/view/client/assets/channel-BgDNA_Ay.js +1 -0
  48. package/dist/src/view/client/assets/{chunk-2Q5K7J3B-CnBKL-lm.js → chunk-2Q5K7J3B-BJPcFivt.js} +1 -1
  49. package/dist/src/view/client/assets/{chunk-5VM5RSS4-LLYMi_n6.js → chunk-5VM5RSS4-v2q99bGz.js} +1 -1
  50. package/dist/src/view/client/assets/{chunk-F27PBJKO-VIeO7VF0.js → chunk-F27PBJKO-CcHOuJCs.js} +1 -1
  51. package/dist/src/view/client/assets/{chunk-IMKFNOWR-D5i67DVD.js → chunk-IMKFNOWR-DNxYuJNq.js} +1 -1
  52. package/dist/src/view/client/assets/{chunk-JWPE2WC7-D4qAtoL3.js → chunk-JWPE2WC7-C0eHKvLW.js} +1 -1
  53. package/dist/src/view/client/assets/{chunk-POPQ4Y6H-BMzOyiW_.js → chunk-POPQ4Y6H-57CWp2Ve.js} +1 -1
  54. package/dist/src/view/client/assets/{chunk-SVP7TREG-DWy5nbfp.js → chunk-SVP7TREG-BqcoxIJw.js} +1 -1
  55. package/dist/src/view/client/assets/{chunk-TICWLB2K-CVqCANFB.js → chunk-TICWLB2K-DRUJR5zH.js} +1 -1
  56. package/dist/src/view/client/assets/{chunk-XXDRQBXY-Bp23h6Tf.js → chunk-XXDRQBXY-Dez0oRoM.js} +1 -1
  57. package/dist/src/view/client/assets/classDiagram-ZZMXUADV-CFZ_Sgh5.js +1 -0
  58. package/dist/src/view/client/assets/classDiagram-v2-VYDZK3BY-CFZ_Sgh5.js +1 -0
  59. package/dist/src/view/client/assets/{cose-bilkent-JH36ORCC-BCw7fCC2.js → cose-bilkent-JH36ORCC-BHtud6Hg.js} +1 -1
  60. package/dist/src/view/client/assets/{cynefin-OW5HDTMX--lYN4N9m.js → cynefin-OW5HDTMX-BjBW8VGk.js} +1 -1
  61. package/dist/src/view/client/assets/{cynefinDiagram-5FMLGOSQ-9sK5EV7v.js → cynefinDiagram-5FMLGOSQ-DwGuD7oF.js} +1 -1
  62. package/dist/src/view/client/assets/{dagre-GXQ25YYZ-CoMdEFCq.js → dagre-GXQ25YYZ-C5zSlGK9.js} +1 -1
  63. package/dist/src/view/client/assets/{diagram-S7CK7UJ4-D13dyWdd.js → diagram-S7CK7UJ4-C_NhA3bj.js} +1 -1
  64. package/dist/src/view/client/assets/{diagram-UQ7AKVKN-PdwLPPPA.js → diagram-UQ7AKVKN-az7QPYNb.js} +1 -1
  65. package/dist/src/view/client/assets/{diagram-VSXAHHWV-CtWWa_A7.js → diagram-VSXAHHWV-BRvDuM8_.js} +1 -1
  66. package/dist/src/view/client/assets/{diagram-VX7I27RA-BeCYcSU-.js → diagram-VX7I27RA-BWLgF6S-.js} +1 -1
  67. package/dist/src/view/client/assets/{diagram-Z3DM3KII-DiWabOBM.js → diagram-Z3DM3KII-DV3d6mL5.js} +1 -1
  68. package/dist/src/view/client/assets/{ebnfDiagram-PWID7BFC-CZQ3MD_K.js → ebnfDiagram-PWID7BFC-yUXrEAvK.js} +1 -1
  69. package/dist/src/view/client/assets/{erDiagram-RLTQ6QDP-B1AhXIrP.js → erDiagram-RLTQ6QDP-D35FN1Pt.js} +1 -1
  70. package/dist/src/view/client/assets/{flowDiagram-HODETNUW-Bhr0JM6P.js → flowDiagram-HODETNUW-BciZqsjT.js} +1 -1
  71. package/dist/src/view/client/assets/{ganttDiagram-EL5Y4UJY-CbP8iAkg.js → ganttDiagram-EL5Y4UJY-BysPGgXS.js} +1 -1
  72. package/dist/src/view/client/assets/{gitGraphDiagram-WWUBYQGX-B9uuGdLF.js → gitGraphDiagram-WWUBYQGX-C3DdJ5xG.js} +1 -1
  73. package/dist/src/view/client/assets/index-CJokoRSp.js +13 -0
  74. package/dist/src/view/client/assets/{infoDiagram-27XIBGKW-BrfwQ_Cq.js → infoDiagram-27XIBGKW-D3HZrDRb.js} +1 -1
  75. package/dist/src/view/client/assets/{ishikawaDiagram-5VMMS53U-CHtJ36re.js → ishikawaDiagram-5VMMS53U-BXyVIXTU.js} +1 -1
  76. package/dist/src/view/client/assets/{journeyDiagram-3NMN7TZE-BChcgX1s.js → journeyDiagram-3NMN7TZE-D4-1NxVU.js} +1 -1
  77. package/dist/src/view/client/assets/{kanban-definition-UXKFOSKX-BnwFsKiB.js → kanban-definition-UXKFOSKX-4Gu_5yBA.js} +1 -1
  78. package/dist/src/view/client/assets/{layout-Dnd0pLdb.js → layout-Jf1K3TMM.js} +1 -1
  79. package/dist/src/view/client/assets/{linear-CFhW2ozn.js → linear-DWfwzUT_.js} +1 -1
  80. package/dist/src/view/client/assets/{mermaid.core--OP6lXtW.js → mermaid.core-DMx_DAl8.js} +5 -5
  81. package/dist/src/view/client/assets/{mindmap-definition-YA3MSWOX-D51y2zbm.js → mindmap-definition-YA3MSWOX-8pxY_RWi.js} +1 -1
  82. package/dist/src/view/client/assets/{pegDiagram-XKGWAZYB--zyQJDvI.js → pegDiagram-XKGWAZYB-DNAw_O5t.js} +1 -1
  83. package/dist/src/view/client/assets/{pieDiagram-E7YTZNPT-Cj8mvpJy.js → pieDiagram-E7YTZNPT-uuvRCDkC.js} +1 -1
  84. package/dist/src/view/client/assets/{quadrantDiagram-AXDQQJYC-qvhJrnBf.js → quadrantDiagram-AXDQQJYC-BER2O4Aq.js} +1 -1
  85. package/dist/src/view/client/assets/{railroadDiagram-O6MQD6OU-CtWvxpSo.js → railroadDiagram-O6MQD6OU-CxEsJ_0n.js} +1 -1
  86. package/dist/src/view/client/assets/{requirementDiagram-BXWQKSXE-CBxen_KG.js → requirementDiagram-BXWQKSXE-yS9rspca.js} +1 -1
  87. package/dist/src/view/client/assets/{sankeyDiagram-P5KCCOFB-B_fUkmfc.js → sankeyDiagram-P5KCCOFB-Bqt70a2j.js} +1 -1
  88. package/dist/src/view/client/assets/{sequenceDiagram-WJ2MYXX4-Dclv4p68.js → sequenceDiagram-WJ2MYXX4-BvOOEJNr.js} +1 -1
  89. package/dist/src/view/client/assets/{sizeCapture-INFHLROL-GfG0sMTZ.js → sizeCapture-INFHLROL-CvO_Pjjo.js} +1 -1
  90. package/dist/src/view/client/assets/{stateDiagram-D77RDMKH-YQWPnzxU.js → stateDiagram-D77RDMKH-KLmVOZkq.js} +1 -1
  91. package/dist/src/view/client/assets/stateDiagram-v2-MP3YSRHH-KCS8Mdzu.js +1 -0
  92. package/dist/src/view/client/assets/{swimlanes-42K2YHIH-5yiCveVS.js → swimlanes-42K2YHIH-DC1r4_sq.js} +1 -1
  93. package/dist/src/view/client/assets/swimlanesDiagram-VR7AAH4N-B2TcAwis.js +8 -0
  94. package/dist/src/view/client/assets/{timeline-definition-24CTP7MA-BvAbB5Zs.js → timeline-definition-24CTP7MA-ChXLOuBL.js} +1 -1
  95. package/dist/src/view/client/assets/{vennDiagram-4TSXK5OY-guC-r60n.js → vennDiagram-4TSXK5OY-D9_h25-Y.js} +1 -1
  96. package/dist/src/view/client/assets/{wardleyDiagram-VM6X3IG4-C0yXcU2x.js → wardleyDiagram-VM6X3IG4-CsQJGGW0.js} +1 -1
  97. package/dist/src/view/client/assets/{xychartDiagram-S5SC5T6Z-RPmkPNfK.js → xychartDiagram-S5SC5T6Z-DGMuPMlm.js} +1 -1
  98. package/dist/src/view/client/index.html +1 -1
  99. package/dist/src/view/diagnostics.d.ts +2 -2
  100. package/dist/src/view/diagnostics.js +5 -5
  101. package/dist/src/view/external-document-tree.js +1 -1
  102. package/dist/src/view/git-diff.js +1 -1
  103. package/dist/src/view/git.js +1 -1
  104. package/dist/src/view/graph.d.ts +2 -2
  105. package/dist/src/view/graph.js +2 -2
  106. package/dist/src/view/markdown.js +1 -1
  107. package/dist/src/view/preindexed-search.d.ts +1 -1
  108. package/dist/src/view/protocol.d.ts +2 -18
  109. package/dist/src/view/publication.d.ts +2 -0
  110. package/dist/src/view/publication.js +78 -0
  111. package/dist/src/view/references.d.ts +3 -3
  112. package/dist/src/view/references.js +3 -3
  113. package/dist/src/view/repository.d.ts +6 -6
  114. package/dist/src/view/repository.js +28 -14
  115. package/dist/src/view/request-security.d.ts +5 -0
  116. package/dist/src/view/request-security.js +46 -0
  117. package/dist/src/view/search-result.d.ts +1 -1
  118. package/dist/src/view/search-result.js +1 -1
  119. package/dist/src/view/search.d.ts +1 -1
  120. package/dist/src/view/server-build.d.ts +2 -2
  121. package/dist/src/view/server-build.js +2 -2
  122. package/dist/src/view/server-deployment.d.ts +1 -2
  123. package/dist/src/view/server-deployment.js +6 -46
  124. package/dist/src/view/server-index-worker.d.ts +1 -1
  125. package/dist/src/view/server.d.ts +1 -1
  126. package/dist/src/view/server.js +13 -3
  127. package/dist/src/view/source-target.js +2 -2
  128. package/dist/src/view/static-build.d.ts +1 -1
  129. package/dist/src/view/static-build.js +49 -17
  130. package/dist/src/view/store.d.ts +4 -2
  131. package/dist/src/view/store.js +31 -19
  132. package/dist/src/view/table-of-contents.d.ts +1 -1
  133. package/dist/src/view/table-of-contents.js +1 -1
  134. package/dist/src/view/vercel-server-build.d.ts +1 -1
  135. package/package.json +19 -29
  136. package/templates/AGENTS.md +2 -2
  137. package/templates/cursor-rules.md +2 -2
  138. package/templates/opencode-plugin.ts +9 -9
  139. package/templates/pi-extension.ts +11 -11
  140. package/templates/skill/SKILL.md +2 -1
  141. package/dist/src/cli/check-context.d.ts +0 -56
  142. package/dist/src/cli/check-context.js +0 -215
  143. package/dist/src/cli/check-coverage.d.ts +0 -2
  144. package/dist/src/cli/check-coverage.js +0 -75
  145. package/dist/src/cli/check-frontmatter.d.ts +0 -12
  146. package/dist/src/cli/check-frontmatter.js +0 -44
  147. package/dist/src/cli/check-mode.d.ts +0 -21
  148. package/dist/src/cli/check-mode.js +0 -394
  149. package/dist/src/cli/check-status.d.ts +0 -74
  150. package/dist/src/cli/check-status.js +0 -217
  151. package/dist/src/cli/check.d.ts +0 -52
  152. package/dist/src/cli/check.js +0 -834
  153. package/dist/src/cli/context.d.ts +0 -11
  154. package/dist/src/cli/context.js +0 -58
  155. package/dist/src/cli/expand.d.ts +0 -7
  156. package/dist/src/cli/expand.js +0 -141
  157. package/dist/src/cli/external.d.ts +0 -11
  158. package/dist/src/cli/external.js +0 -185
  159. package/dist/src/cli/gen-index.d.ts +0 -45
  160. package/dist/src/cli/gen-index.js +0 -235
  161. package/dist/src/cli/link-scheme.d.ts +0 -54
  162. package/dist/src/cli/link-scheme.js +0 -101
  163. package/dist/src/cli/locate.d.ts +0 -2
  164. package/dist/src/cli/locate.js +0 -18
  165. package/dist/src/cli/refs.d.ts +0 -23
  166. package/dist/src/cli/refs.js +0 -274
  167. package/dist/src/cli/section.d.ts +0 -45
  168. package/dist/src/cli/section.js +0 -328
  169. package/dist/src/cli/select-menu.d.ts +0 -13
  170. package/dist/src/cli/select-menu.js +0 -100
  171. package/dist/src/code-refs.d.ts +0 -29
  172. package/dist/src/code-refs.js +0 -479
  173. package/dist/src/config.d.ts +0 -29
  174. package/dist/src/config.js +0 -83
  175. package/dist/src/context.d.ts +0 -26
  176. package/dist/src/context.js +0 -11
  177. package/dist/src/document-formats.d.ts +0 -7
  178. package/dist/src/document-formats.js +0 -39
  179. package/dist/src/extensions/alert-marker.d.ts +0 -25
  180. package/dist/src/extensions/alert-marker.js +0 -55
  181. package/dist/src/extensions/wiki-link/from-markdown.d.ts +0 -5
  182. package/dist/src/extensions/wiki-link/from-markdown.js +0 -34
  183. package/dist/src/extensions/wiki-link/index.d.ts +0 -4
  184. package/dist/src/extensions/wiki-link/index.js +0 -3
  185. package/dist/src/extensions/wiki-link/syntax.d.ts +0 -14
  186. package/dist/src/extensions/wiki-link/syntax.js +0 -121
  187. package/dist/src/extensions/wiki-link/to-markdown.d.ts +0 -5
  188. package/dist/src/extensions/wiki-link/to-markdown.js +0 -28
  189. package/dist/src/extensions/wiki-link/types.d.ts +0 -34
  190. package/dist/src/extensions/wiki-link/types.js +0 -1
  191. package/dist/src/external-documents.d.ts +0 -56
  192. package/dist/src/external-documents.js +0 -404
  193. package/dist/src/external-sources.d.ts +0 -136
  194. package/dist/src/external-sources.js +0 -1098
  195. package/dist/src/fork/frontmatter-fields.d.ts +0 -36
  196. package/dist/src/fork/frontmatter-fields.js +0 -23
  197. package/dist/src/format.d.ts +0 -16
  198. package/dist/src/format.js +0 -76
  199. package/dist/src/init-version.d.ts +0 -10
  200. package/dist/src/init-version.js +0 -49
  201. package/dist/src/lattice-model.d.ts +0 -84
  202. package/dist/src/lattice-model.js +0 -467
  203. package/dist/src/lattice.d.ts +0 -14
  204. package/dist/src/lattice.js +0 -353
  205. package/dist/src/markdown-analysis-cache.d.ts +0 -20
  206. package/dist/src/markdown-analysis-cache.js +0 -139
  207. package/dist/src/markdown-analysis-worker.d.ts +0 -16
  208. package/dist/src/markdown-analysis-worker.js +0 -33
  209. package/dist/src/markdown-analysis.d.ts +0 -61
  210. package/dist/src/markdown-analysis.js +0 -169
  211. package/dist/src/markdown-analyzer-loader.d.ts +0 -4
  212. package/dist/src/markdown-analyzer-loader.js +0 -13
  213. package/dist/src/markdown-validation.d.ts +0 -25
  214. package/dist/src/markdown-validation.js +0 -104
  215. package/dist/src/parser-cache.d.ts +0 -17
  216. package/dist/src/parser-cache.js +0 -65
  217. package/dist/src/parser-import.d.ts +0 -8
  218. package/dist/src/parser-import.js +0 -1
  219. package/dist/src/parser.d.ts +0 -3
  220. package/dist/src/parser.js +0 -93
  221. package/dist/src/path.d.ts +0 -2
  222. package/dist/src/path.js +0 -4
  223. package/dist/src/profiler.d.ts +0 -16
  224. package/dist/src/profiler.js +0 -81
  225. package/dist/src/project-analysis.d.ts +0 -59
  226. package/dist/src/project-analysis.js +0 -233
  227. package/dist/src/project-discovery.d.ts +0 -6
  228. package/dist/src/project-discovery.js +0 -30
  229. package/dist/src/repository-path.d.ts +0 -11
  230. package/dist/src/repository-path.js +0 -52
  231. package/dist/src/source-formats.d.ts +0 -7
  232. package/dist/src/source-formats.js +0 -30
  233. package/dist/src/source-parser.d.ts +0 -67
  234. package/dist/src/source-parser.js +0 -1749
  235. package/dist/src/untrusted.d.ts +0 -18
  236. package/dist/src/untrusted.js +0 -93
  237. package/dist/src/view/client/assets/channel-uy0fFvcW.js +0 -1
  238. package/dist/src/view/client/assets/classDiagram-ZZMXUADV-DbSEqjA5.js +0 -1
  239. package/dist/src/view/client/assets/classDiagram-v2-VYDZK3BY-DbSEqjA5.js +0 -1
  240. package/dist/src/view/client/assets/index-nBmbYfun.js +0 -13
  241. package/dist/src/view/client/assets/stateDiagram-v2-MP3YSRHH-gUj6Hzgl.js +0 -1
  242. package/dist/src/view/client/assets/swimlanesDiagram-VR7AAH4N-DR7JhrxL.js +0 -8
  243. package/dist/src/walk.d.ts +0 -20
  244. package/dist/src/walk.js +0 -121
@@ -1,353 +0,0 @@
1
- import { readFile } from 'node:fs/promises';
2
- import { dirname, basename, relative } from 'node:path';
3
- import GithubSlugger from 'github-slugger';
4
- import { parse as parseYaml } from 'yaml';
5
- import { parse } from './parser.js';
6
- import { toPosix } from './path.js';
7
- import { visit } from 'unist-util-visit';
8
- import { listLatticeFiles } from './project-discovery.js';
9
- import { flattenSections, } from './lattice-model.js';
10
- import { LAT_FIELDS, } from './fork/frontmatter-fields.js';
11
- export { buildFileIndex, buildSectionSlugIndex, findSections, flattenSections, resolveRef, } from './lattice-model.js';
12
- export { findLatticeDir, findProjectRoot, listLatticeFiles, } from './project-discovery.js';
13
- export { LAT_FIELDS } from './fork/frontmatter-fields.js';
14
- export function parseFrontmatter(content) {
15
- const match = content.match(/^---\n([\s\S]*?)\n---/);
16
- if (!match)
17
- return { raw: {} };
18
- let raw = {};
19
- const problems = [];
20
- try {
21
- const parsed = parseYaml(match[1]);
22
- if (parsed !== null &&
23
- typeof parsed === 'object' &&
24
- !Array.isArray(parsed)) {
25
- const root = parsed;
26
- const lat = root['lat'];
27
- const hasLatMapping = lat !== null && typeof lat === 'object' && !Array.isArray(lat);
28
- if (hasLatMapping) {
29
- raw = lat;
30
- }
31
- // A field written at the document root was accepted by the regex reader
32
- // this parser replaced. Staying quiet about it is what makes the change
33
- // dangerous: the field simply stops being read.
34
- for (const field of LAT_FIELDS) {
35
- if (Object.hasOwn(root, field) && !Object.hasOwn(raw, field)) {
36
- problems.push({ kind: 'root-level-field', field });
37
- }
38
- }
39
- }
40
- }
41
- catch (err) {
42
- // One malformed line anywhere in the block used to be harmless, because
43
- // the old reader pattern-matched the raw text. A strict parse throws away
44
- // every field instead, so the failure has to be reported rather than
45
- // swallowed.
46
- raw = {};
47
- problems.push({
48
- kind: 'parse-error',
49
- message: err.message.split('\n')[0],
50
- });
51
- }
52
- const result = { raw };
53
- if (raw['require-code-mention'] === true) {
54
- result.requireCodeMention = true;
55
- }
56
- if (problems.length > 0)
57
- result.problems = problems;
58
- return result;
59
- }
60
- /** Extract the rendered text GitHub uses as input to its heading slugger. */
61
- function headingText(node) {
62
- if (!node || typeof node !== 'object')
63
- return '';
64
- const value = node;
65
- if (value.type === 'text' || value.type === 'inlineCode') {
66
- return value.value ?? '';
67
- }
68
- if (value.type === 'image' || value.type === 'imageReference') {
69
- return value.alt ?? '';
70
- }
71
- if (value.type === 'wikiLink') {
72
- return value.data?.alias ?? value.value ?? '';
73
- }
74
- if (value.children) {
75
- return value.children.map(headingText).join('');
76
- }
77
- return '';
78
- }
79
- function inlineText(node) {
80
- return node.children
81
- .map((c) => {
82
- if (c.type === 'text')
83
- return c.value;
84
- if (c.type === 'inlineCode')
85
- return '`' + c.value + '`';
86
- if (c.type === 'wikiLink')
87
- return '[[' + c.value + ']]';
88
- if ('children' in c)
89
- return inlineText(c);
90
- return '';
91
- })
92
- .join('');
93
- }
94
- function lastLine(content) {
95
- const lines = content.split('\n');
96
- // If trailing newline, count doesn't include empty last line
97
- return lines[lines.length - 1] === '' ? lines.length - 1 : lines.length;
98
- }
99
- export function parseSections(filePath, content, projectRoot, tree = parse(content)) {
100
- const file = projectRoot
101
- ? toPosix(relative(projectRoot, filePath)).replace(/\.md$/, '')
102
- : basename(filePath, '.md');
103
- const sectionFilePath = projectRoot
104
- ? toPosix(relative(projectRoot, filePath))
105
- : basename(filePath);
106
- const roots = [];
107
- const stack = [];
108
- const flat = [];
109
- const slugger = new GithubSlugger();
110
- const usedIds = new Set();
111
- const nextSuffix = new Map();
112
- visit(tree, 'heading', (node) => {
113
- const heading = headingText(node);
114
- const depth = node.depth;
115
- const startLine = node.position.start.line;
116
- // Pop stack until we find a parent with smaller depth
117
- while (stack.length > 0 && stack[stack.length - 1].depth >= depth) {
118
- stack.pop();
119
- }
120
- const parent = stack.length > 0 ? stack[stack.length - 1] : null;
121
- const baseId = parent ? `${parent.id}#${heading}` : `${file}#${heading}`;
122
- let id = baseId;
123
- const key = baseId.toLowerCase();
124
- let suffix = nextSuffix.get(key) ?? 1;
125
- while (usedIds.has(id.toLowerCase()))
126
- id = `${baseId}-${suffix++}`;
127
- nextSuffix.set(key, suffix);
128
- usedIds.add(id.toLowerCase());
129
- const section = {
130
- id,
131
- heading,
132
- depth,
133
- file,
134
- filePath: sectionFilePath,
135
- children: [],
136
- startLine,
137
- endLine: 0,
138
- firstParagraph: '',
139
- githubSlug: slugger.slug(headingText(node)),
140
- };
141
- if (parent) {
142
- parent.children.push(section);
143
- }
144
- else {
145
- roots.push(section);
146
- }
147
- stack.push(section);
148
- flat.push(section);
149
- });
150
- // Compute endLine: line before next heading or last line of file
151
- const fileLastLine = lastLine(content);
152
- for (let i = 0; i < flat.length; i++) {
153
- if (i + 1 < flat.length) {
154
- flat[i].endLine = flat[i + 1].startLine - 1;
155
- }
156
- else {
157
- flat[i].endLine = fileLastLine;
158
- }
159
- }
160
- // Extract firstParagraph: first paragraph after each heading
161
- const children = tree.children;
162
- let headingIdx = 0;
163
- for (let i = 0; i < children.length; i++) {
164
- const node = children[i];
165
- if (node.type === 'heading') {
166
- // Find the first paragraph after this heading, before the next heading
167
- for (let j = i + 1; j < children.length; j++) {
168
- if (children[j].type === 'heading')
169
- break;
170
- if (children[j].type === 'paragraph') {
171
- flat[headingIdx].firstParagraph = inlineText(children[j]);
172
- break;
173
- }
174
- }
175
- headingIdx++;
176
- }
177
- }
178
- return roots;
179
- }
180
- export async function loadAllSections(latticeDir, projectRoot = dirname(latticeDir), profile) {
181
- const files = profile
182
- ? await profile.time('list Markdown files', () => listLatticeFiles(latticeDir))
183
- : await listLatticeFiles(latticeDir);
184
- const all = [];
185
- for (const file of files) {
186
- const detail = toPosix(relative(latticeDir, file));
187
- const content = profile
188
- ? await profile.time('read Markdown file', () => readFile(file, 'utf-8'), detail)
189
- : await readFile(file, 'utf-8');
190
- const sections = profile
191
- ? profile.timeSync('parse Markdown sections', () => parseSections(file, content, projectRoot), detail)
192
- : parseSections(file, content, projectRoot);
193
- all.push(...sections);
194
- }
195
- return all;
196
- }
197
- export function extractRefs(filePath, content, projectRoot, tree = parse(content), sections = parseSections(filePath, content, projectRoot, tree)) {
198
- const file = projectRoot
199
- ? toPosix(relative(projectRoot, filePath)).replace(/\.md$/, '')
200
- : basename(filePath, '.md');
201
- const refs = [];
202
- // Reuse canonical identities, including duplicate suffixes and formatted text.
203
- const flat = flattenSections(sections);
204
- visit(tree, 'wikiLink', (node) => {
205
- const line = node.position.start.line;
206
- // Find enclosing section: last heading with startLine <= link line
207
- let fromSection = '';
208
- for (const s of flat) {
209
- if (s.startLine <= line) {
210
- fromSection = s.id;
211
- }
212
- else {
213
- break;
214
- }
215
- }
216
- refs.push({
217
- target: node.value,
218
- fromSection,
219
- file,
220
- line,
221
- });
222
- });
223
- return refs;
224
- }
225
- function isEscapedAt(value, index) {
226
- let slashes = 0;
227
- for (let i = index - 1; i >= 0 && value[i] === '\\'; i--)
228
- slashes++;
229
- return slashes % 2 === 1;
230
- }
231
- function closingBracket(value, open) {
232
- let depth = 0;
233
- for (let i = open; i < value.length; i++) {
234
- if (isEscapedAt(value, i))
235
- continue;
236
- if (value[i] === '[') {
237
- depth++;
238
- }
239
- else if (value[i] === ']') {
240
- depth--;
241
- if (depth === 0)
242
- return i;
243
- }
244
- }
245
- return -1;
246
- }
247
- /** Extract link destinations and undefined reference syntax. */
248
- export function extractLinks(content, tree = parse(content)) {
249
- const links = [];
250
- visit(tree, ['link', 'image', 'definition'], (node) => {
251
- const { url, type, position } = node;
252
- links.push({ url, kind: type, line: position.start.line });
253
- });
254
- // CommonMark parses a reference with no matching definition as plain text,
255
- // so it has no linkReference node to visit. Scan the authored syntax while
256
- // excluding AST ranges where bracket text is data rather than prose.
257
- const excluded = [];
258
- visit(tree, [
259
- 'code',
260
- 'inlineCode',
261
- 'html',
262
- 'math',
263
- 'inlineMath',
264
- 'yaml',
265
- 'link',
266
- 'image',
267
- 'definition',
268
- 'linkReference',
269
- 'imageReference',
270
- 'footnoteReference',
271
- 'alertMarker',
272
- 'wikiLink',
273
- ], (node) => {
274
- const start = node.position?.start.offset;
275
- const end = node.position?.end.offset;
276
- if (start !== undefined && end !== undefined) {
277
- excluded.push({ start, end });
278
- }
279
- });
280
- // GFM removes task-list markers from the paragraph AST. Exclude just the
281
- // marker prefix so strict shortcut checks still apply to the item body.
282
- visit(tree, 'listItem', (node) => {
283
- if (typeof node.checked !== 'boolean')
284
- return;
285
- const start = node.position?.start.offset;
286
- const bodyStart = node.children[0]?.position?.start.offset;
287
- if (start === undefined || bodyStart === undefined)
288
- return;
289
- const marker = /\[[ xX]\]/.exec(content.slice(start, bodyStart));
290
- if (marker) {
291
- excluded.push({
292
- start: start + marker.index,
293
- end: start + marker.index + marker[0].length,
294
- });
295
- }
296
- });
297
- // Likewise, exclude only a footnote definition's label and delimiter. Its
298
- // body remains prose and must still obey strict shortcut validation.
299
- visit(tree, 'footnoteDefinition', (node) => {
300
- const start = node.position?.start.offset;
301
- const bodyStart = node.children[0]?.position?.start.offset;
302
- if (start !== undefined && bodyStart !== undefined) {
303
- excluded.push({ start, end: bodyStart });
304
- }
305
- });
306
- const overlapsExcluded = (start, end) => excluded.some((range) => start < range.end && end > range.start);
307
- for (let open = 0; open < content.length; open++) {
308
- if (content[open] !== '[' || isEscapedAt(content, open))
309
- continue;
310
- const labelEnd = closingBracket(content, open);
311
- if (labelEnd === -1)
312
- continue;
313
- const identifierStart = labelEnd + 1;
314
- const hasSecondLabel = content[identifierStart] === '[' &&
315
- !isEscapedAt(content, identifierStart);
316
- const identifierEnd = hasSecondLabel
317
- ? closingBracket(content, identifierStart)
318
- : labelEnd;
319
- if (identifierEnd === -1)
320
- continue;
321
- const isImage = open > 0 && content[open - 1] === '!' && !isEscapedAt(content, open - 1);
322
- const isMalformedDefinition = !isImage && !hasSecondLabel && content[labelEnd + 1] === ':';
323
- const start = isImage ? open - 1 : open;
324
- const end = identifierEnd + 1 + (isMalformedDefinition ? 1 : 0);
325
- if (overlapsExcluded(start, end)) {
326
- open = identifierEnd;
327
- continue;
328
- }
329
- const explicitIdentifier = hasSecondLabel
330
- ? content.slice(identifierStart + 1, identifierEnd)
331
- : '';
332
- const identifier = explicitIdentifier || content.slice(open + 1, labelEnd);
333
- if (identifier.trim() === '') {
334
- open = identifierEnd;
335
- continue;
336
- }
337
- links.push({
338
- identifier: identifier.trim(),
339
- source: content.slice(start, end),
340
- kind: isImage ? 'imageReference' : 'linkReference',
341
- style: !hasSecondLabel
342
- ? isMalformedDefinition
343
- ? 'definition'
344
- : 'shortcut'
345
- : explicitIdentifier
346
- ? 'full'
347
- : 'collapsed',
348
- line: content.slice(0, start).split('\n').length,
349
- });
350
- open = identifierEnd;
351
- }
352
- return links.sort((a, b) => a.line - b.line);
353
- }
@@ -1,20 +0,0 @@
1
- import type { MarkdownAnalysisTimings, MarkdownFileAnalysis } from './markdown-analysis.js';
2
- import type { ParserImportObserver } from './parser-import.js';
3
- export { PARSER_CACHE_VERSION } from './parser-cache.js';
4
- export type MarkdownAnalysisCacheStatus = 'disabled' | 'hit' | 'miss';
5
- export type PreparedMarkdownAnalysis = {
6
- absolutePath: string;
7
- cachePath: string;
8
- content: string;
9
- contentHash: string;
10
- analysis?: MarkdownFileAnalysis;
11
- timings: Pick<MarkdownAnalysisTimings, 'readMs' | 'hashMs' | 'cacheReadMs' | 'cacheStatus'>;
12
- };
13
- /** Return the collision-safe, sharded cache path for one Markdown file. */
14
- export declare function markdownAnalysisCachePath(latDir: string, projectRoot: string, absolutePath: string): string;
15
- /** Read, hash, and attempt to hydrate one Markdown file from persistent cache. */
16
- export declare function prepareMarkdownAnalysis(absolutePath: string, latDir: string, projectRoot: string, cache?: boolean): Promise<PreparedMarkdownAnalysis>;
17
- /** Attach I/O timings and best-effort publish one newly parsed analysis. */
18
- export declare function publishMarkdownAnalysis(prepared: PreparedMarkdownAnalysis, analysis: MarkdownFileAnalysis): Promise<MarkdownFileAnalysis>;
19
- /** Analyze one path through the same persistent cache used by project runs. */
20
- export declare function analyzeMarkdownPath(absolutePath: string, latDir: string, projectRoot: string, cache?: boolean, onParserImport?: ParserImportObserver): Promise<MarkdownFileAnalysis>;
@@ -1,139 +0,0 @@
1
- import { readFile } from 'node:fs/promises';
2
- import { relative } from 'node:path';
3
- import { performance } from 'node:perf_hooks';
4
- import { PARSER_CACHE_VERSION, hashParserContent, parsedCachePath, parserCacheIdentity, readParsedCache, writeParsedCache, } from './parser-cache.js';
5
- import { toPosix } from './path.js';
6
- import { loadMarkdownAnalyzer } from './markdown-analyzer-loader.js';
7
- export { PARSER_CACHE_VERSION } from './parser-cache.js';
8
- /** Return the collision-safe, sharded cache path for one Markdown file. */
9
- export function markdownAnalysisCachePath(latDir, projectRoot, absolutePath) {
10
- return parsedCachePath(latDir, parserCacheIdentity(absolutePath, projectRoot));
11
- }
12
- function emptyTimings(values) {
13
- return {
14
- ...values,
15
- cacheWriteMs: 0,
16
- parseMs: 0,
17
- sectionsMs: 0,
18
- refsMs: 0,
19
- linksMs: 0,
20
- paragraphsMs: 0,
21
- frontmatterMs: 0,
22
- indexEntriesMs: 0,
23
- diagnosticsMs: 0,
24
- };
25
- }
26
- function isRecord(value) {
27
- return typeof value === 'object' && value !== null && !Array.isArray(value);
28
- }
29
- function cachedAnalysis(entry, contentHash, content, absolutePath, latDir, projectRoot) {
30
- if (!entry ||
31
- entry.version !== PARSER_CACHE_VERSION ||
32
- entry.contentHash !== contentHash) {
33
- return null;
34
- }
35
- try {
36
- const analysis = entry.value;
37
- const expectedPath = toPosix(relative(latDir, absolutePath));
38
- const expectedProjectPath = toPosix(relative(projectRoot, absolutePath));
39
- if (!isRecord(analysis) ||
40
- analysis.content !== content ||
41
- analysis.path !== expectedPath ||
42
- analysis.projectPath !== expectedProjectPath ||
43
- !isRecord(analysis.frontmatter) ||
44
- !Array.isArray(analysis.sections) ||
45
- !Array.isArray(analysis.headingTitles) ||
46
- !Array.isArray(analysis.wikiRefs) ||
47
- !Array.isArray(analysis.paragraphs) ||
48
- !Array.isArray(analysis.markdownLinks) ||
49
- !Array.isArray(analysis.validationLinks) ||
50
- !Array.isArray(analysis.indexEntries) ||
51
- !Array.isArray(analysis.diagnostics)) {
52
- return null;
53
- }
54
- return { ...analysis, absolutePath };
55
- }
56
- catch {
57
- return null;
58
- }
59
- }
60
- /** Read, hash, and attempt to hydrate one Markdown file from persistent cache. */
61
- export async function prepareMarkdownAnalysis(absolutePath, latDir, projectRoot, cache = true) {
62
- const cachePath = markdownAnalysisCachePath(latDir, projectRoot, absolutePath);
63
- const readStarted = performance.now();
64
- const contentPromise = readFile(absolutePath, 'utf8').then((content) => ({
65
- content,
66
- readMs: performance.now() - readStarted,
67
- }));
68
- const cacheStarted = performance.now();
69
- const cachePromise = cache
70
- ? readParsedCache(cachePath).then((entry) => ({
71
- entry,
72
- cacheReadMs: performance.now() - cacheStarted,
73
- }))
74
- : Promise.resolve({ entry: null, cacheReadMs: 0 });
75
- const [{ content, readMs }, { entry, cacheReadMs }] = await Promise.all([
76
- contentPromise,
77
- cachePromise,
78
- ]);
79
- const hashStarted = performance.now();
80
- const contentHash = hashParserContent(content);
81
- const hashMs = performance.now() - hashStarted;
82
- const analysis = cache
83
- ? cachedAnalysis(entry, contentHash, content, absolutePath, latDir, projectRoot)
84
- : null;
85
- const timings = {
86
- readMs,
87
- hashMs,
88
- cacheReadMs,
89
- cacheStatus: cache ? (analysis ? 'hit' : 'miss') : 'disabled',
90
- };
91
- return {
92
- absolutePath,
93
- cachePath,
94
- content,
95
- contentHash,
96
- analysis: analysis
97
- ? { ...analysis, timings: emptyTimings(timings) }
98
- : undefined,
99
- timings,
100
- };
101
- }
102
- /** Attach I/O timings and best-effort publish one newly parsed analysis. */
103
- export async function publishMarkdownAnalysis(prepared, analysis) {
104
- const base = {
105
- ...analysis,
106
- timings: {
107
- ...analysis.timings,
108
- ...prepared.timings,
109
- cacheWriteMs: 0,
110
- },
111
- };
112
- if (prepared.timings.cacheStatus === 'disabled')
113
- return base;
114
- const started = performance.now();
115
- try {
116
- await writeParsedCache(prepared.cachePath, prepared.contentHash, base);
117
- }
118
- catch {
119
- // The cache is a disposable optimization; analysis must work read-only.
120
- }
121
- base.timings.cacheWriteMs = performance.now() - started;
122
- return base;
123
- }
124
- /** Analyze one path through the same persistent cache used by project runs. */
125
- export async function analyzeMarkdownPath(absolutePath, latDir, projectRoot, cache = true, onParserImport) {
126
- const prepared = await prepareMarkdownAnalysis(absolutePath, latDir, projectRoot, cache);
127
- const detail = toPosix(relative(latDir, absolutePath));
128
- if (prepared.analysis) {
129
- onParserImport?.({
130
- parser: 'Markdown analyzer',
131
- imported: false,
132
- durationMs: 0,
133
- detail: `${detail} cached`,
134
- });
135
- return prepared.analysis;
136
- }
137
- const analyzeMarkdownFile = await loadMarkdownAnalyzer(onParserImport, detail);
138
- return publishMarkdownAnalysis(prepared, analyzeMarkdownFile(absolutePath, prepared.content, latDir, projectRoot));
139
- }
@@ -1,16 +0,0 @@
1
- import type { MarkdownFileAnalysis } from './markdown-analysis.js';
2
- export type MarkdownWorkerTask = {
3
- id: number;
4
- absolutePath: string;
5
- content: string;
6
- latDir: string;
7
- projectRoot: string;
8
- };
9
- export type MarkdownWorkerResponse = {
10
- id: number;
11
- analysis: MarkdownFileAnalysis;
12
- importMs?: number;
13
- } | {
14
- id: number;
15
- error: string;
16
- };
@@ -1,33 +0,0 @@
1
- import { parentPort } from 'node:worker_threads';
2
- import { performance } from 'node:perf_hooks';
3
- if (!parentPort)
4
- throw new Error('Markdown analysis worker needs a parent port');
5
- async function loadAnalyzer() {
6
- const started = performance.now();
7
- const sourceRuntime = import.meta.url.endsWith('.ts');
8
- const moduleUrl = new URL(sourceRuntime ? './markdown-analysis.ts' : './markdown-analysis.js', import.meta.url).href;
9
- const module = sourceRuntime
10
- ? await import('tsx/esm/api').then(({ tsImport }) => tsImport(moduleUrl, import.meta.url))
11
- : await import(moduleUrl);
12
- return {
13
- analyzeMarkdownFile: module.analyzeMarkdownFile,
14
- importMs: performance.now() - started,
15
- };
16
- }
17
- const analyzerPromise = loadAnalyzer();
18
- let importReported = false;
19
- parentPort.on('message', async (task) => {
20
- try {
21
- const loaded = await analyzerPromise;
22
- const importMs = importReported ? undefined : loaded.importMs;
23
- importReported = true;
24
- const analysis = loaded.analyzeMarkdownFile(task.absolutePath, task.content, task.latDir, task.projectRoot);
25
- parentPort.postMessage({ id: task.id, analysis, importMs });
26
- }
27
- catch (error) {
28
- parentPort.postMessage({
29
- id: task.id,
30
- error: error instanceof Error ? error.message : String(error),
31
- });
32
- }
33
- });
@@ -1,61 +0,0 @@
1
- import type { LatFrontmatter, MdLink, Ref, Section } from './lattice-model.js';
2
- import { type LocalMarkdownDiagnostic } from './markdown-validation.js';
3
- export type MarkdownParagraph = {
4
- markdown: string;
5
- startLine: number;
6
- endLine: number;
7
- text: string;
8
- };
9
- /** Source-positioned block facts; never retains the parser AST. */
10
- export type MarkdownBlock = {
11
- type: string;
12
- start: number;
13
- end: number;
14
- startLine: number;
15
- endLine: number;
16
- language?: string;
17
- children: MarkdownBlock[];
18
- };
19
- export type MarkdownDestinationLink = {
20
- kind: 'image' | 'link';
21
- line: number;
22
- url: string;
23
- };
24
- export type MarkdownAnalysisTimings = {
25
- readMs: number;
26
- hashMs: number;
27
- cacheReadMs: number;
28
- cacheWriteMs: number;
29
- cacheStatus: 'disabled' | 'hit' | 'miss';
30
- parseMs: number;
31
- sectionsMs: number;
32
- refsMs: number;
33
- linksMs: number;
34
- paragraphsMs: number;
35
- frontmatterMs: number;
36
- indexEntriesMs: number;
37
- diagnosticsMs: number;
38
- };
39
- /** Serializable semantic facts extracted from one Markdown file. */
40
- export type MarkdownFileAnalysis = {
41
- absolutePath: string;
42
- content: string;
43
- path: string;
44
- projectPath: string;
45
- frontmatter: LatFrontmatter;
46
- sections: Section[];
47
- headingTitles: string[];
48
- wikiRefs: Ref[];
49
- paragraphs: MarkdownParagraph[];
50
- blocks: MarkdownBlock[];
51
- markdownLinks: MarkdownDestinationLink[];
52
- validationLinks: MdLink[];
53
- indexEntries: string[];
54
- diagnostics: LocalMarkdownDiagnostic[];
55
- timings: MarkdownAnalysisTimings;
56
- };
57
- /**
58
- * Parse and analyze one Markdown document. The syntax tree is deliberately
59
- * confined to this call so callers and workers only exchange serializable facts.
60
- */
61
- export declare function analyzeMarkdownFile(absolutePath: string, content: string, latDir: string, projectRoot: string): MarkdownFileAnalysis;