@plebeiantech/lat.md 0.12.3-fork.9 → 0.13.4-fork.1
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 +27 -3
- package/dist/src/cli/agent-invocation.d.ts +6 -0
- package/dist/src/cli/agent-invocation.js +23 -0
- package/dist/src/cli/checklist-menu.d.ts +2 -1
- package/dist/src/cli/checklist-menu.js +3 -2
- package/dist/src/cli/fork-instructions.d.ts +1 -0
- package/dist/src/cli/fork-instructions.js +8 -32
- package/dist/src/cli/fork-scaffold.js +2 -2
- package/dist/src/cli/graph.d.ts +1 -1
- package/dist/src/cli/hook.d.ts +26 -0
- package/dist/src/cli/hook.js +115 -64
- package/dist/src/cli/index.js +147 -70
- package/dist/src/cli/init-preferences.d.ts +4 -0
- package/dist/src/cli/init-preferences.js +36 -0
- package/dist/src/cli/init.d.ts +2 -1
- package/dist/src/cli/init.js +100 -60
- package/dist/src/cli/reindex.d.ts +1 -1
- package/dist/src/cli/reindex.js +7 -10
- package/dist/src/cli/search.d.ts +14 -4
- package/dist/src/cli/search.js +115 -101
- package/dist/src/cli/ui-build-server.d.ts +12 -0
- package/dist/src/cli/ui-build-server.js +26 -0
- package/dist/src/cli/ui-build.d.ts +1 -1
- package/dist/src/cli/ui-build.js +1 -1
- package/dist/src/cli/ui.d.ts +1 -1
- package/dist/src/cli/ui.js +1 -1
- package/dist/src/fork/antigravity-hook.d.ts +47 -0
- package/dist/src/fork/antigravity-hook.js +424 -0
- package/dist/src/fork/antigravity-init.d.ts +17 -0
- package/dist/src/fork/antigravity-init.js +124 -0
- package/dist/src/fork/upstream-drift.js +1 -1
- package/dist/src/fork/upstream-guard.d.ts +1 -1
- package/dist/src/fork/upstream-guard.js +8 -7
- package/dist/src/graph-export.js +7 -7
- package/dist/src/knowledge/index.js +2 -2
- package/dist/src/mcp/server.js +34 -18
- package/dist/src/search/cache.d.ts +3 -0
- package/dist/src/search/cache.js +104 -0
- package/dist/src/search/chunks.d.ts +23 -0
- package/dist/src/search/chunks.js +200 -0
- package/dist/src/search/db.d.ts +28 -16
- package/dist/src/search/db.js +100 -40
- package/dist/src/search/embedder.d.ts +2 -1
- package/dist/src/search/embedder.js +7 -6
- package/dist/src/search/index.d.ts +6 -2
- package/dist/src/search/index.js +176 -70
- package/dist/src/search/lexical.d.ts +6 -0
- package/dist/src/search/lexical.js +36 -0
- package/dist/src/search/lock.d.ts +5 -0
- package/dist/src/search/lock.js +45 -0
- package/dist/src/search/query.d.ts +26 -0
- package/dist/src/search/query.js +103 -0
- package/dist/src/search/search.d.ts +16 -7
- package/dist/src/search/search.js +165 -21
- package/dist/src/search/types.d.ts +15 -0
- package/dist/src/view/client/assets/GraphView-D_xnk0bP.js +456 -0
- package/dist/src/view/client/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- package/dist/src/view/client/assets/MarkdownEditor-bjqt_FoF.js +28 -0
- package/dist/src/view/client/assets/OrbitControls-DwcpQNja.js +1 -0
- package/dist/src/view/client/assets/STLLoader-CLWTKt5i.js +1 -0
- package/dist/src/view/client/assets/_commonjsHelpers-CqkleIqs.js +1 -0
- package/dist/src/view/client/assets/abnfDiagram-VCTEODGH-kWGvtRnL.js +1 -0
- package/dist/src/view/client/assets/arc-BPAFd7cP.js +1 -0
- package/dist/src/view/client/assets/architectureDiagram-5GKGNRK7-CsY39oIR.js +36 -0
- package/dist/src/view/client/assets/blockDiagram-I7D4REHJ-DHGBG7BJ.js +129 -0
- package/dist/src/view/client/assets/c4Diagram-7LVT6UL2-vywK4eb7.js +38 -0
- package/dist/src/view/client/assets/channel-CX71L_qV.js +1 -0
- package/dist/src/view/client/assets/chunk-2Q5K7J3B-Do3Hz_ci.js +1 -0
- package/dist/src/view/client/assets/chunk-5VM5RSS4-B5R1lSeY.js +15 -0
- package/dist/src/view/client/assets/chunk-F27PBJKO-Dm55FM_W.js +1 -0
- package/dist/src/view/client/assets/chunk-IMKFNOWR-ChptrvvM.js +231 -0
- package/dist/src/view/client/assets/chunk-JWPE2WC7-BRQBjrKS.js +1 -0
- package/dist/src/view/client/assets/chunk-POPQ4Y6H-CainVZIL.js +1 -0
- package/dist/src/view/client/assets/chunk-SVP7TREG-DsKsNGmM.js +88 -0
- package/dist/src/view/client/assets/chunk-TICWLB2K-BctkMcJc.js +206 -0
- package/dist/src/view/client/assets/chunk-XXDRQBXY-BN7SgOUT.js +1 -0
- package/dist/src/view/client/assets/classDiagram-ZZMXUADV-B1VyU6zO.js +1 -0
- package/dist/src/view/client/assets/classDiagram-v2-VYDZK3BY-B1VyU6zO.js +1 -0
- package/dist/src/view/client/assets/cose-bilkent-JH36ORCC-BszzwrMe.js +1 -0
- package/dist/src/view/client/assets/cynefin-OW5HDTMX-CdRyAkPs.js +166 -0
- package/dist/src/view/client/assets/cynefinDiagram-5FMLGOSQ-BLvKPZ1u.js +62 -0
- package/dist/src/view/client/assets/cytoscape.esm-DzSz-X2X.js +321 -0
- package/dist/src/view/client/assets/dagre-GXQ25YYZ-V68w_l65.js +4 -0
- package/dist/src/view/client/assets/defaultLocale-DX6XiGOO.js +1 -0
- package/dist/src/view/client/assets/diagram-S7CK7UJ4-C2i4eEMg.js +30 -0
- package/dist/src/view/client/assets/diagram-UQ7AKVKN-BiwWh5jC.js +41 -0
- package/dist/src/view/client/assets/diagram-VSXAHHWV-hkKR_vyS.js +3 -0
- package/dist/src/view/client/assets/diagram-VX7I27RA-DzRCSMAc.js +24 -0
- package/dist/src/view/client/assets/diagram-Z3DM3KII-fhSFPxyK.js +24 -0
- package/dist/src/view/client/assets/ebnfDiagram-PWID7BFC-CCEUDKSA.js +1 -0
- package/dist/src/view/client/assets/erDiagram-RLTQ6QDP-FJ2IMyTi.js +99 -0
- package/dist/src/view/client/assets/flowDiagram-HODETNUW-BvasdLeK.js +168 -0
- package/dist/src/view/client/assets/ganttDiagram-EL5Y4UJY-CiwkBZvY.js +292 -0
- package/dist/src/view/client/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
- package/dist/src/view/client/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
- package/dist/src/view/client/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
- package/dist/src/view/client/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
- package/dist/src/view/client/assets/geist-mono-cyrillic-ext-wght-normal-X_5orZeX.woff2 +0 -0
- package/dist/src/view/client/assets/geist-mono-cyrillic-wght-normal-DiZS0aHC.woff2 +0 -0
- package/dist/src/view/client/assets/geist-mono-latin-ext-wght-normal-Bwz-egvJ.woff2 +0 -0
- package/dist/src/view/client/assets/geist-mono-latin-wght-normal-XN7g48iV.woff2 +0 -0
- package/dist/src/view/client/assets/geist-mono-symbols2-wght-normal-CO5SzqOn.woff2 +0 -0
- package/dist/src/view/client/assets/geist-mono-vietnamese-wght-normal-DadHysG0.woff2 +0 -0
- package/dist/src/view/client/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
- package/dist/src/view/client/assets/gitGraphDiagram-WWUBYQGX-DYlP2_js.js +106 -0
- package/dist/src/view/client/assets/index-BnENo9bV.js +1 -0
- package/dist/src/view/client/assets/index-CQ7EOox7.css +1 -0
- package/dist/src/view/client/assets/index-CynNDkxt.js +13 -0
- package/dist/src/view/client/assets/infoDiagram-27XIBGKW-DRPB2c48.js +2 -0
- package/dist/src/view/client/assets/init-Gi6I4Gst.js +1 -0
- package/dist/src/view/client/assets/ishikawaDiagram-5VMMS53U-8VV429Cv.js +70 -0
- package/dist/src/view/client/assets/journeyDiagram-3NMN7TZE-Dzmwnf83.js +139 -0
- package/dist/src/view/client/assets/kanban-definition-UXKFOSKX-pYyZZ1i-.js +89 -0
- package/dist/src/view/client/assets/katex-HP8lGamR.js +257 -0
- package/dist/src/view/client/assets/layout-GF9k6yGo.js +1 -0
- package/dist/src/view/client/assets/linear-Yt2sSOYV.js +1 -0
- package/dist/src/view/client/assets/logo-RR_KBOAT.svg +149 -0
- package/dist/src/view/client/assets/maplibre-gl-CDX6Zuow.js +800 -0
- package/dist/src/view/client/assets/mermaid.core-ChWYCHN0.js +310 -0
- package/dist/src/view/client/assets/mindmap-definition-YA3MSWOX-Cc4fQvf1.js +96 -0
- package/dist/src/view/client/assets/ordinal-Cboi1Yqb.js +1 -0
- package/dist/src/view/client/assets/pegDiagram-XKGWAZYB-C0SsB8bZ.js +1 -0
- package/dist/src/view/client/assets/pieDiagram-E7YTZNPT-DIJpqERZ.js +39 -0
- package/dist/src/view/client/assets/quadrantDiagram-AXDQQJYC--d-gl6j-.js +7 -0
- package/dist/src/view/client/assets/railroadDiagram-O6MQD6OU-BQxwTt7z.js +1 -0
- package/dist/src/view/client/assets/requirementDiagram-BXWQKSXE-B_oTeD2A.js +84 -0
- package/dist/src/view/client/assets/sankeyDiagram-P5KCCOFB-DLukmE8X.js +40 -0
- package/dist/src/view/client/assets/sequenceDiagram-WJ2MYXX4-BNjVB2sc.js +162 -0
- package/dist/src/view/client/assets/sizeCapture-INFHLROL-BZecQTOw.js +1 -0
- package/dist/src/view/client/assets/stateDiagram-D77RDMKH-Bu1urvXC.js +1 -0
- package/dist/src/view/client/assets/stateDiagram-v2-MP3YSRHH-5pc_697G.js +1 -0
- package/dist/src/view/client/assets/swimlanes-42K2YHIH-bLAlcepB.js +1 -0
- package/dist/src/view/client/assets/swimlanesDiagram-VR7AAH4N-BbOpZjpp.js +8 -0
- package/dist/src/view/client/assets/three.module-PDSP0dbZ.js +4108 -0
- package/dist/src/view/client/assets/timeline-definition-24CTP7MA-tbwCNvcA.js +120 -0
- package/dist/src/view/client/assets/vennDiagram-4TSXK5OY-D8U8Fk0N.js +34 -0
- package/dist/src/view/client/assets/wardleyDiagram-VM6X3IG4-LHBVIeNb.js +78 -0
- package/dist/src/view/client/assets/xychartDiagram-S5SC5T6Z-CN4tfaFV.js +7 -0
- package/dist/src/view/client/index.html +2 -2
- package/dist/src/view/client-shell.d.ts +2 -0
- package/dist/src/view/client-shell.js +5 -0
- package/dist/src/view/diagnostics.d.ts +3 -2
- package/dist/src/view/diagnostics.js +49 -58
- package/dist/src/view/document-edit.d.ts +8 -0
- package/dist/src/view/document-edit.js +25 -0
- package/dist/src/view/document-route.d.ts +14 -0
- package/dist/src/view/document-route.js +137 -0
- package/dist/src/view/document-tree.d.ts +18 -0
- package/dist/src/view/document-tree.js +139 -0
- package/dist/src/view/external-document-tree.d.ts +3 -0
- package/dist/src/view/external-document-tree.js +674 -0
- package/dist/src/view/git-diff.js +202 -2
- package/dist/src/view/git.js +1 -1
- package/dist/src/view/graph.d.ts +4 -3
- package/dist/src/view/graph.js +100 -9
- package/dist/src/view/highlight.d.ts +10 -2
- package/dist/src/view/highlight.js +50648 -3166
- package/dist/src/view/markdown.d.ts +3 -2
- package/dist/src/view/markdown.js +256 -54
- package/dist/src/view/preindexed-search.d.ts +15 -0
- package/dist/src/view/preindexed-search.js +25 -0
- package/dist/src/view/protocol.d.ts +53 -7
- package/dist/src/view/publication.d.ts +2 -0
- package/dist/src/view/publication.js +78 -0
- package/dist/src/view/references.d.ts +11 -26
- package/dist/src/view/references.js +121 -112
- package/dist/src/view/repository.d.ts +14 -4
- package/dist/src/view/repository.js +260 -19
- package/dist/src/view/request-security.d.ts +5 -0
- package/dist/src/view/request-security.js +46 -0
- package/dist/src/view/search-result.d.ts +4 -0
- package/dist/src/view/search-result.js +25 -0
- package/dist/src/view/search.d.ts +7 -2
- package/dist/src/view/search.js +23 -34
- package/dist/src/view/server-build.d.ts +21 -0
- package/dist/src/view/server-build.js +145 -0
- package/dist/src/view/server-deployment.d.ts +31 -0
- package/dist/src/view/server-deployment.js +123 -0
- package/dist/src/view/server-index-worker.d.ts +6 -0
- package/dist/src/view/server-index-worker.js +14 -0
- package/dist/src/view/server.d.ts +11 -2
- package/dist/src/view/server.js +245 -73
- package/dist/src/view/source-target.d.ts +2 -0
- package/dist/src/view/source-target.js +49 -8
- package/dist/src/view/static-build.d.ts +18 -2
- package/dist/src/view/static-build.js +449 -110
- package/dist/src/view/static-protocol.d.ts +26 -2
- package/dist/src/view/static-protocol.js +5 -0
- package/dist/src/view/store.d.ts +20 -3
- package/dist/src/view/store.js +304 -48
- package/dist/src/view/table-of-contents.d.ts +2 -2
- package/dist/src/view/table-of-contents.js +2 -22
- package/dist/src/view/vercel-build.d.ts +24 -0
- package/dist/src/view/vercel-build.js +152 -0
- package/dist/src/view/vercel-server-build.d.ts +10 -0
- package/dist/src/view/vercel-server-build.js +61 -0
- package/dist/vendor/lat.md-server/cli.d.ts +2 -0
- package/dist/vendor/lat.md-server/cli.js +12 -0
- package/dist/vendor/lat.md-server/index.d.ts +38 -0
- package/dist/vendor/lat.md-server/index.js +128 -0
- package/package.json +68 -22
- package/plugins/lat-md/README.md +61 -0
- package/plugins/lat-md/hooks.json +38 -0
- package/plugins/lat-md/plugin.json +9 -0
- package/plugins/lat-md/rules/AGENTS.md +344 -0
- package/plugins/lat-md/skills/lat-md/SKILL.md +210 -0
- package/plugins/lat-md/skills/lat-md-conventions/SKILL.md +226 -0
- package/templates/AGENTS.md +26 -7
- package/templates/cursor-rules.md +23 -7
- package/templates/fork/conventions.md +133 -11
- package/templates/opencode-plugin.ts +9 -9
- package/templates/pi-extension.ts +11 -11
- package/templates/skill/SKILL.md +35 -3
- package/dist/src/cli/check-coverage.d.ts +0 -2
- package/dist/src/cli/check-coverage.js +0 -71
- package/dist/src/cli/check-frontmatter.d.ts +0 -12
- package/dist/src/cli/check-frontmatter.js +0 -44
- package/dist/src/cli/check-mode.d.ts +0 -21
- package/dist/src/cli/check-mode.js +0 -364
- package/dist/src/cli/check-status.d.ts +0 -74
- package/dist/src/cli/check-status.js +0 -217
- package/dist/src/cli/check.d.ts +0 -45
- package/dist/src/cli/check.js +0 -781
- package/dist/src/cli/context.d.ts +0 -11
- package/dist/src/cli/context.js +0 -58
- package/dist/src/cli/expand.d.ts +0 -8
- package/dist/src/cli/expand.js +0 -94
- package/dist/src/cli/gen-index.d.ts +0 -45
- package/dist/src/cli/gen-index.js +0 -235
- package/dist/src/cli/link-scheme.d.ts +0 -54
- package/dist/src/cli/link-scheme.js +0 -101
- package/dist/src/cli/locate.d.ts +0 -2
- package/dist/src/cli/locate.js +0 -17
- package/dist/src/cli/refs.d.ts +0 -22
- package/dist/src/cli/refs.js +0 -229
- package/dist/src/cli/section.d.ts +0 -43
- package/dist/src/cli/section.js +0 -252
- package/dist/src/cli/select-menu.d.ts +0 -13
- package/dist/src/cli/select-menu.js +0 -100
- package/dist/src/code-refs.d.ts +0 -17
- package/dist/src/code-refs.js +0 -298
- package/dist/src/config.d.ts +0 -29
- package/dist/src/config.js +0 -83
- package/dist/src/context.d.ts +0 -23
- package/dist/src/context.js +0 -11
- package/dist/src/extensions/wiki-link/from-markdown.d.ts +0 -5
- package/dist/src/extensions/wiki-link/from-markdown.js +0 -34
- package/dist/src/extensions/wiki-link/index.d.ts +0 -4
- package/dist/src/extensions/wiki-link/index.js +0 -3
- package/dist/src/extensions/wiki-link/syntax.d.ts +0 -14
- package/dist/src/extensions/wiki-link/syntax.js +0 -121
- package/dist/src/extensions/wiki-link/to-markdown.d.ts +0 -5
- package/dist/src/extensions/wiki-link/to-markdown.js +0 -28
- package/dist/src/extensions/wiki-link/types.d.ts +0 -34
- package/dist/src/format.d.ts +0 -8
- package/dist/src/format.js +0 -43
- package/dist/src/init-version.d.ts +0 -10
- package/dist/src/init-version.js +0 -49
- package/dist/src/lattice.d.ts +0 -109
- package/dist/src/lattice.js +0 -817
- package/dist/src/parser.d.ts +0 -3
- package/dist/src/parser.js +0 -18
- package/dist/src/source-parser.d.ts +0 -27
- package/dist/src/source-parser.js +0 -916
- package/dist/src/untrusted.d.ts +0 -18
- package/dist/src/untrusted.js +0 -93
- package/dist/src/view/client/assets/index-C3iaZyYT.css +0 -1
- package/dist/src/view/client/assets/index-KWi67IMz.js +0 -334
- package/dist/src/view/client/assets/logo-CNF8zs47.svg +0 -182
- package/dist/src/walk.d.ts +0 -18
- package/dist/src/walk.js +0 -27
- /package/dist/src/{extensions/wiki-link → search}/types.js +0 -0
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { CmdContext, Styler } from '../context.js';
|
|
2
|
-
export type { CmdContext };
|
|
3
|
-
export declare function makeStyler(): Styler;
|
|
4
|
-
export declare function resolveContext(opts: {
|
|
5
|
-
dir?: string;
|
|
6
|
-
color?: boolean;
|
|
7
|
-
}): CmdContext;
|
|
8
|
-
export declare function resolveCheckContext(opts: {
|
|
9
|
-
dir?: string;
|
|
10
|
-
color?: boolean;
|
|
11
|
-
}, target?: string): CmdContext;
|
package/dist/src/cli/context.js
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { statSync } from 'node:fs';
|
|
2
|
-
import { dirname, resolve } from 'node:path';
|
|
3
|
-
import { styleText } from 'node:util';
|
|
4
|
-
import { findLatticeDir } from '../lattice.js';
|
|
5
|
-
export function makeStyler() {
|
|
6
|
-
return {
|
|
7
|
-
bold: (s) => styleText('bold', s),
|
|
8
|
-
dim: (s) => styleText('dim', s),
|
|
9
|
-
red: (s) => styleText('red', s),
|
|
10
|
-
cyan: (s) => styleText('cyan', s),
|
|
11
|
-
white: (s) => styleText('white', s),
|
|
12
|
-
green: (s) => styleText('green', s),
|
|
13
|
-
yellow: (s) => styleText('yellow', s),
|
|
14
|
-
boldWhite: (s) => styleText(['bold', 'white'], s),
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
export function resolveContext(opts) {
|
|
18
|
-
const color = opts.color !== false;
|
|
19
|
-
if (!color) {
|
|
20
|
-
process.env.NO_COLOR = '1';
|
|
21
|
-
}
|
|
22
|
-
const latDir = findLatticeDir(opts.dir) ?? '';
|
|
23
|
-
if (!latDir) {
|
|
24
|
-
console.error(styleText('red', 'No lat.md directory found'));
|
|
25
|
-
console.error(styleText('dim', 'Run `lat init` to create one.'));
|
|
26
|
-
process.exit(1);
|
|
27
|
-
}
|
|
28
|
-
const projectRoot = dirname(latDir);
|
|
29
|
-
return { latDir, projectRoot, styler: makeStyler(), mode: 'cli' };
|
|
30
|
-
}
|
|
31
|
-
export function resolveCheckContext(opts, target) {
|
|
32
|
-
if (target === undefined)
|
|
33
|
-
return resolveContext(opts);
|
|
34
|
-
if (opts.color === false) {
|
|
35
|
-
process.env.NO_COLOR = '1';
|
|
36
|
-
}
|
|
37
|
-
const projectRoot = resolve(opts.dir ?? process.cwd());
|
|
38
|
-
const latDir = resolve(projectRoot, target);
|
|
39
|
-
try {
|
|
40
|
-
if (!statSync(latDir).isDirectory()) {
|
|
41
|
-
console.error(styleText('red', `Check target is not a directory: ${target}`));
|
|
42
|
-
process.exit(1);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
catch (error) {
|
|
46
|
-
if (error.code !== 'ENOENT')
|
|
47
|
-
throw error;
|
|
48
|
-
console.error(styleText('red', `Check directory not found: ${target}`));
|
|
49
|
-
process.exit(1);
|
|
50
|
-
}
|
|
51
|
-
return {
|
|
52
|
-
latDir,
|
|
53
|
-
projectRoot,
|
|
54
|
-
styler: makeStyler(),
|
|
55
|
-
mode: 'cli',
|
|
56
|
-
headless: true,
|
|
57
|
-
};
|
|
58
|
-
}
|
package/dist/src/cli/expand.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { type Section } from '../lattice.js';
|
|
2
|
-
import type { CmdContext, CmdResult } from '../context.js';
|
|
3
|
-
/**
|
|
4
|
-
* Resolve [[refs]] in text and return the expanded output.
|
|
5
|
-
* Returns null if there are no wiki links, or if resolution fails.
|
|
6
|
-
*/
|
|
7
|
-
export declare function expandPrompt(ctx: CmdContext, text: string, preloadedSections?: Section[]): Promise<string | null>;
|
|
8
|
-
export declare function expandCommand(ctx: CmdContext, text: string): Promise<CmdResult>;
|
package/dist/src/cli/expand.js
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import { join, relative } from 'node:path';
|
|
2
|
-
import { loadAllSections, findSections, } from '../lattice.js';
|
|
3
|
-
import { UNTRUSTED_NOTICE, quoteUntrusted, cleanUntrustedId, } from '../untrusted.js';
|
|
4
|
-
const WIKI_LINK_RE = /\[\[([^\]]+)\]\]/g;
|
|
5
|
-
function formatLocation(section, projectRoot) {
|
|
6
|
-
const relPath = relative(process.cwd(), join(projectRoot, section.filePath));
|
|
7
|
-
return `${cleanUntrustedId(relPath)}:${section.startLine}-${section.endLine}`;
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* Resolve [[refs]] in text and return the expanded output.
|
|
11
|
-
* Returns null if there are no wiki links, or if resolution fails.
|
|
12
|
-
*/
|
|
13
|
-
export async function expandPrompt(ctx, text, preloadedSections) {
|
|
14
|
-
const refs = [...text.matchAll(WIKI_LINK_RE)];
|
|
15
|
-
if (refs.length === 0)
|
|
16
|
-
return null;
|
|
17
|
-
const allSections = preloadedSections ?? (await loadAllSections(ctx.latDir));
|
|
18
|
-
const resolved = new Map();
|
|
19
|
-
const errors = [];
|
|
20
|
-
for (const match of refs) {
|
|
21
|
-
const target = match[1];
|
|
22
|
-
if (resolved.has(target))
|
|
23
|
-
continue;
|
|
24
|
-
const matches = findSections(allSections, target);
|
|
25
|
-
if (matches.length >= 1) {
|
|
26
|
-
resolved.set(target, {
|
|
27
|
-
target,
|
|
28
|
-
best: matches[0],
|
|
29
|
-
alternatives: matches.slice(1),
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
errors.push(`No section found for [[${target}]]`);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
if (errors.length > 0)
|
|
37
|
-
return null;
|
|
38
|
-
// Replace [[refs]] inline
|
|
39
|
-
let output = text.replace(WIKI_LINK_RE, (_match, target) => {
|
|
40
|
-
const ref = resolved.get(target);
|
|
41
|
-
return `[[${cleanUntrustedId(ref.best.section.id)}]]`;
|
|
42
|
-
});
|
|
43
|
-
// Append context block as nested outliner
|
|
44
|
-
output += '\n\n<lat-context>\n';
|
|
45
|
-
output += UNTRUSTED_NOTICE + '\n';
|
|
46
|
-
for (const ref of resolved.values()) {
|
|
47
|
-
const isExact = ref.best.reason === 'exact match' ||
|
|
48
|
-
ref.best.reason.startsWith('file stem expanded');
|
|
49
|
-
const all = isExact ? [ref.best] : [ref.best, ...ref.alternatives];
|
|
50
|
-
if (isExact) {
|
|
51
|
-
output += `* \`[[${ref.target}]]\` is referring to:\n`;
|
|
52
|
-
}
|
|
53
|
-
else {
|
|
54
|
-
output += `* \`[[${ref.target}]]\` might be referring to either of the following:\n`;
|
|
55
|
-
}
|
|
56
|
-
for (const m of all) {
|
|
57
|
-
const reason = isExact ? '' : ` (${cleanUntrustedId(m.reason)})`;
|
|
58
|
-
output += ` * [[${cleanUntrustedId(m.section.id)}]]${reason}\n`;
|
|
59
|
-
output += ` * ${formatLocation(m.section, ctx.projectRoot)}\n`;
|
|
60
|
-
if (m.section.firstParagraph) {
|
|
61
|
-
output += ` * ${quoteUntrusted(m.section.firstParagraph)}\n`;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
output += '</lat-context>\n';
|
|
66
|
-
return output;
|
|
67
|
-
}
|
|
68
|
-
export async function expandCommand(ctx, text) {
|
|
69
|
-
const result = await expandPrompt(ctx, text);
|
|
70
|
-
if (result === null) {
|
|
71
|
-
const refs = [...text.matchAll(WIKI_LINK_RE)];
|
|
72
|
-
if (refs.length === 0) {
|
|
73
|
-
return { output: text };
|
|
74
|
-
}
|
|
75
|
-
// Resolution failed — find which ref is broken
|
|
76
|
-
const allSections = await loadAllSections(ctx.latDir);
|
|
77
|
-
for (const match of refs) {
|
|
78
|
-
const target = match[1];
|
|
79
|
-
const matches = findSections(allSections, target);
|
|
80
|
-
if (matches.length === 0) {
|
|
81
|
-
const s = ctx.styler;
|
|
82
|
-
return {
|
|
83
|
-
output: s.red(`No section found for [[${target}]]`) +
|
|
84
|
-
' (no exact, substring, or fuzzy matches).\n' +
|
|
85
|
-
s.dim('Ask the user to correct the reference.'),
|
|
86
|
-
isError: true,
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
// All refs matched individually but expansion still failed — shouldn't happen
|
|
91
|
-
return { output: text };
|
|
92
|
-
}
|
|
93
|
-
return { output: result };
|
|
94
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
export declare function mdEscapeLabel(value: string): string;
|
|
2
|
-
export declare function mdEscapeDest(value: string): string;
|
|
3
|
-
export type IndexEntrySource = {
|
|
4
|
-
/** Filesystem entry name: "notes.md" for a file, "guides" for a directory. */
|
|
5
|
-
name: string;
|
|
6
|
-
/**
|
|
7
|
-
* Link destination relative to the index file being written: the child's
|
|
8
|
-
* own filename ("notes.md"), or its own index file for a directory
|
|
9
|
-
* ("guides/guides.md"). This is what actually resolves on disk — unlike
|
|
10
|
-
* the wiki-link stem, it keeps the .md extension.
|
|
11
|
-
*/
|
|
12
|
-
dest: string;
|
|
13
|
-
/** Absolute path to read the title/summary from (the file itself, or a directory's own index file). */
|
|
14
|
-
readFrom: string;
|
|
15
|
-
};
|
|
16
|
-
/**
|
|
17
|
-
* Render the generated bullet list for a directory index, one entry per
|
|
18
|
-
* child, sorted by title. Each entry links through the wiki-link stem
|
|
19
|
-
* (`entryToStem`-compatible) using a real Markdown link so the title can
|
|
20
|
-
* carry a human-written summary — which is exactly why it must be escaped:
|
|
21
|
-
* the title is repository text landing inside `[...]`.
|
|
22
|
-
*/
|
|
23
|
-
export declare function renderIndexEntries(entries: IndexEntrySource[]): Promise<string>;
|
|
24
|
-
/**
|
|
25
|
-
* Compute, for each line, whether it lies inside a fenced code block.
|
|
26
|
-
* Marker and bullet-run detection must skip fenced lines — otherwise a
|
|
27
|
-
* documentation example that shows the marker syntax (or a sample bullet
|
|
28
|
-
* list) inside a ``` block gets mistaken for the real thing and rewritten.
|
|
29
|
-
*/
|
|
30
|
-
export declare function fencedLineMask(lines: string[]): boolean[];
|
|
31
|
-
export type SpliceResult = {
|
|
32
|
-
ok: true;
|
|
33
|
-
content: string;
|
|
34
|
-
} | {
|
|
35
|
-
ok: false;
|
|
36
|
-
message: string;
|
|
37
|
-
};
|
|
38
|
-
/**
|
|
39
|
-
* Splice a freshly rendered entry list into an index file's content inside
|
|
40
|
-
* `<!-- lat:index:begin -->` / `<!-- lat:index:end -->` markers, preserving
|
|
41
|
-
* everything outside that region byte for byte. An unmarked file is
|
|
42
|
-
* migrated by wrapping the first contiguous run of local index entry
|
|
43
|
-
* bullets; a malformed marker pair is refused rather than guessed at.
|
|
44
|
-
*/
|
|
45
|
-
export declare function spliceIndexContent(existingContent: string | null, dirLabel: string, renderedList: string): SpliceResult;
|
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
import { readFile } from 'node:fs/promises';
|
|
2
|
-
import { cleanUntrusted } from '../untrusted.js';
|
|
3
|
-
import { isLatticeLocalDest } from './link-scheme.js';
|
|
4
|
-
// Mirrors the two escaping rules in hooks/generate_docs_index.rb (see
|
|
5
|
-
// lat-t1y.5). Both were found by a working exploit against that generator,
|
|
6
|
-
// and the same exploit applies here: an index entry's title is repository
|
|
7
|
-
// text (an H1 heading or a leading paragraph) placed into a generated
|
|
8
|
-
// Markdown link, so it must be treated as untrusted the moment it is quoted.
|
|
9
|
-
/**
|
|
10
|
-
* Escape a link LABEL. Without this, a title of `Real](https://evil/)
|
|
11
|
-
* [ignore` closes the generated link early and reopens it against an
|
|
12
|
-
* attacker's URL, leaving the real target as the label of a second,
|
|
13
|
-
* harmless-looking link. Backslash-escaping is CommonMark's own answer: each
|
|
14
|
-
* of these renders as the literal character.
|
|
15
|
-
*/
|
|
16
|
-
const MD_LABEL_SPECIALS = /([\\[\]()`])/g;
|
|
17
|
-
export function mdEscapeLabel(value) {
|
|
18
|
-
return value.replace(MD_LABEL_SPECIALS, '\\$1');
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Escape a link DESTINATION. A destination does not escape the same way a
|
|
22
|
-
* label does: a `)` anywhere ends the destination there, and CommonMark reads
|
|
23
|
-
* a bare `\` in a destination as an escape for the punctuation after it.
|
|
24
|
-
* Percent-encoding survives the round trip; backslash-escaping does not,
|
|
25
|
-
* because a renderer that decodes `%5C` back to `\` does not then treat it as
|
|
26
|
-
* an escape character again.
|
|
27
|
-
*
|
|
28
|
-
* `%` itself must be in the class too, or the encoding is not injective: a
|
|
29
|
-
* file genuinely named `a%28b.md` would be emitted verbatim and then decoded
|
|
30
|
-
* by the renderer to `a(b.md` — a link to a path that does not exist.
|
|
31
|
-
*/
|
|
32
|
-
const MD_DEST_SPECIALS = /[()<>\s%\\]/g;
|
|
33
|
-
export function mdEscapeDest(value) {
|
|
34
|
-
return value.replace(MD_DEST_SPECIALS, (c) => '%' + c.charCodeAt(0).toString(16).toUpperCase().padStart(2, '0'));
|
|
35
|
-
}
|
|
36
|
-
function fallbackTitle(name) {
|
|
37
|
-
const stem = name.endsWith('.md') ? name.slice(0, -3) : name;
|
|
38
|
-
return stem.replace(/[-_]/g, ' ');
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Pull a title (first `# ` heading) and a summary (the paragraph that
|
|
42
|
-
* follows it, or the document's own leading paragraph when it has no
|
|
43
|
-
* heading) out of a document's raw text. Deliberately simple line scanning
|
|
44
|
-
* rather than a full parse — good enough for index generation, and it avoids
|
|
45
|
-
* depending on parseSections' heading-to-id machinery here.
|
|
46
|
-
*/
|
|
47
|
-
async function titleAndSummary(readFrom, fallback) {
|
|
48
|
-
let content;
|
|
49
|
-
try {
|
|
50
|
-
content = await readFile(readFrom, 'utf-8');
|
|
51
|
-
}
|
|
52
|
-
catch {
|
|
53
|
-
return { title: fallback, summary: '(no summary yet)' };
|
|
54
|
-
}
|
|
55
|
-
const stripped = content.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/, '');
|
|
56
|
-
const lines = stripped.split(/\r?\n/);
|
|
57
|
-
let idx = 0;
|
|
58
|
-
while (idx < lines.length && lines[idx].trim() === '')
|
|
59
|
-
idx++;
|
|
60
|
-
let title = fallback;
|
|
61
|
-
if (idx < lines.length && /^#\s+\S/.test(lines[idx])) {
|
|
62
|
-
title = lines[idx].replace(/^#\s+/, '').trim();
|
|
63
|
-
idx++;
|
|
64
|
-
}
|
|
65
|
-
while (idx < lines.length && lines[idx].trim() === '')
|
|
66
|
-
idx++;
|
|
67
|
-
const paraLines = [];
|
|
68
|
-
while (idx < lines.length &&
|
|
69
|
-
lines[idx].trim() !== '' &&
|
|
70
|
-
!/^#{1,6}\s/.test(lines[idx]) &&
|
|
71
|
-
!/^- /.test(lines[idx])) {
|
|
72
|
-
paraLines.push(lines[idx]);
|
|
73
|
-
idx++;
|
|
74
|
-
}
|
|
75
|
-
const summary = paraLines.join(' ').trim();
|
|
76
|
-
return {
|
|
77
|
-
title: cleanUntrusted(title || fallback, 120),
|
|
78
|
-
summary: summary ? cleanUntrusted(summary, 300) : '(no summary yet)',
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Render the generated bullet list for a directory index, one entry per
|
|
83
|
-
* child, sorted by title. Each entry links through the wiki-link stem
|
|
84
|
-
* (`entryToStem`-compatible) using a real Markdown link so the title can
|
|
85
|
-
* carry a human-written summary — which is exactly why it must be escaped:
|
|
86
|
-
* the title is repository text landing inside `[...]`.
|
|
87
|
-
*/
|
|
88
|
-
export async function renderIndexEntries(entries) {
|
|
89
|
-
const rendered = await Promise.all(entries.map(async (entry) => {
|
|
90
|
-
const { title, summary } = await titleAndSummary(entry.readFrom, fallbackTitle(entry.name));
|
|
91
|
-
return {
|
|
92
|
-
title,
|
|
93
|
-
line: `- [${mdEscapeLabel(title)}](${mdEscapeDest(entry.dest)}) — ${mdEscapeLabel(summary)}`,
|
|
94
|
-
};
|
|
95
|
-
}));
|
|
96
|
-
rendered.sort((a, b) => a.title.toLowerCase().localeCompare(b.title.toLowerCase()));
|
|
97
|
-
return rendered.map((r) => r.line).join('\n');
|
|
98
|
-
}
|
|
99
|
-
/** HTML comment markers delimiting the region `--fix` is allowed to rewrite. */
|
|
100
|
-
const BEGIN_MARKER = '<!-- lat:index:begin -->';
|
|
101
|
-
const END_MARKER = '<!-- lat:index:end -->';
|
|
102
|
-
// Tolerant of a trailing \r so a CRLF file's marker lines still match —
|
|
103
|
-
// `existingContent` is otherwise split on plain '\n' (see the module doc).
|
|
104
|
-
const BEGIN_RE = /^<!-- lat:index:begin -->\r?$/;
|
|
105
|
-
const END_RE = /^<!-- lat:index:end -->\r?$/;
|
|
106
|
-
/**
|
|
107
|
-
* True when `line` is a "local index entry bullet" per the shared predicate
|
|
108
|
-
* documented in link-scheme.ts: the legacy wiki form, or a Markdown link
|
|
109
|
-
* bullet whose destination names a child of this directory. This MUST agree
|
|
110
|
-
* with `parseIndexEntries` in check.ts — both read the same bullets, and a
|
|
111
|
-
* second, differently-behaved copy of the rule is exactly how they drift.
|
|
112
|
-
*/
|
|
113
|
-
function isIndexEntryBulletLine(line) {
|
|
114
|
-
const trimmed = line.replace(/\r$/, '');
|
|
115
|
-
if (/^- \[\[/.test(trimmed))
|
|
116
|
-
return true;
|
|
117
|
-
const m = /^- \[(?:\\.|[^\]])*\]\(([^)]*)\)/.exec(trimmed);
|
|
118
|
-
if (!m)
|
|
119
|
-
return false;
|
|
120
|
-
return isLatticeLocalDest(m[1]);
|
|
121
|
-
}
|
|
122
|
-
/** A fenced code block delimiter line (opening or closing ``` or ~~~). */
|
|
123
|
-
const FENCE_RE = /^ {0,3}(`{3,}|~{3,})/;
|
|
124
|
-
/**
|
|
125
|
-
* Compute, for each line, whether it lies inside a fenced code block.
|
|
126
|
-
* Marker and bullet-run detection must skip fenced lines — otherwise a
|
|
127
|
-
* documentation example that shows the marker syntax (or a sample bullet
|
|
128
|
-
* list) inside a ``` block gets mistaken for the real thing and rewritten.
|
|
129
|
-
*/
|
|
130
|
-
export function fencedLineMask(lines) {
|
|
131
|
-
const mask = new Array(lines.length).fill(false);
|
|
132
|
-
let inFence = false;
|
|
133
|
-
for (let i = 0; i < lines.length; i++) {
|
|
134
|
-
const isFenceDelim = FENCE_RE.test(lines[i].replace(/\r$/, ''));
|
|
135
|
-
if (isFenceDelim) {
|
|
136
|
-
// The delimiter line itself counts as "inside" so it can never be
|
|
137
|
-
// mistaken for a marker or entry bullet either.
|
|
138
|
-
mask[i] = true;
|
|
139
|
-
inFence = !inFence;
|
|
140
|
-
}
|
|
141
|
-
else {
|
|
142
|
-
mask[i] = inFence;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
return mask;
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* Splice a freshly rendered entry list into an index file's content inside
|
|
149
|
-
* `<!-- lat:index:begin -->` / `<!-- lat:index:end -->` markers, preserving
|
|
150
|
-
* everything outside that region byte for byte. An unmarked file is
|
|
151
|
-
* migrated by wrapping the first contiguous run of local index entry
|
|
152
|
-
* bullets; a malformed marker pair is refused rather than guessed at.
|
|
153
|
-
*/
|
|
154
|
-
export function spliceIndexContent(existingContent, dirLabel, renderedList) {
|
|
155
|
-
const block = `${BEGIN_MARKER}\n${renderedList}\n${END_MARKER}`;
|
|
156
|
-
if (existingContent === null) {
|
|
157
|
-
return { ok: true, content: `${dirLabel} directory index.\n\n${block}\n` };
|
|
158
|
-
}
|
|
159
|
-
const lines = existingContent.replace(/\n$/, '').split('\n');
|
|
160
|
-
const fenced = fencedLineMask(lines);
|
|
161
|
-
const beginIdx = lines.findIndex((l, i) => !fenced[i] && BEGIN_RE.test(l));
|
|
162
|
-
// The end marker that matters is the first one AFTER begin (per the
|
|
163
|
-
// design contract). Fall back to the first end anywhere so an end marker
|
|
164
|
-
// with no begin at all is still detected and reported.
|
|
165
|
-
let endIdx = -1;
|
|
166
|
-
if (beginIdx !== -1) {
|
|
167
|
-
for (let i = beginIdx + 1; i < lines.length; i++) {
|
|
168
|
-
if (!fenced[i] && END_RE.test(lines[i])) {
|
|
169
|
-
endIdx = i;
|
|
170
|
-
break;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
else {
|
|
175
|
-
endIdx = lines.findIndex((l, i) => !fenced[i] && END_RE.test(l));
|
|
176
|
-
}
|
|
177
|
-
if (beginIdx !== -1 || endIdx !== -1) {
|
|
178
|
-
if (beginIdx === -1) {
|
|
179
|
-
return {
|
|
180
|
-
ok: false,
|
|
181
|
-
message: 'found a "lat:index:end" marker with no matching "lat:index:begin" marker — fix the markers by hand before running --fix again',
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
if (endIdx === -1) {
|
|
185
|
-
return {
|
|
186
|
-
ok: false,
|
|
187
|
-
message: 'found a "lat:index:begin" marker with no matching "lat:index:end" marker — fix the markers by hand before running --fix again',
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
if (endIdx < beginIdx) {
|
|
191
|
-
return {
|
|
192
|
-
ok: false,
|
|
193
|
-
message: 'found a "lat:index:end" marker before the "lat:index:begin" marker — fix the markers by hand before running --fix again',
|
|
194
|
-
};
|
|
195
|
-
}
|
|
196
|
-
const before = lines.slice(0, beginIdx);
|
|
197
|
-
const after = lines.slice(endIdx + 1);
|
|
198
|
-
const rebuilt = [...before, block, ...after].join('\n');
|
|
199
|
-
return { ok: true, content: `${rebuilt}\n` };
|
|
200
|
-
}
|
|
201
|
-
// No markers at all: migrate. Find the first contiguous run of local index
|
|
202
|
-
// entry bullets and replace exactly that run with the marked block.
|
|
203
|
-
let runStart = -1;
|
|
204
|
-
let runEnd = -1;
|
|
205
|
-
for (let i = 0; i < lines.length; i++) {
|
|
206
|
-
if (!fenced[i] && isIndexEntryBulletLine(lines[i])) {
|
|
207
|
-
if (runStart === -1)
|
|
208
|
-
runStart = i;
|
|
209
|
-
runEnd = i;
|
|
210
|
-
}
|
|
211
|
-
else if (runStart !== -1) {
|
|
212
|
-
break;
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
if (runStart !== -1) {
|
|
216
|
-
const before = lines.slice(0, runStart);
|
|
217
|
-
const after = lines.slice(runEnd + 1);
|
|
218
|
-
const rebuilt = [...before, block, ...after].join('\n');
|
|
219
|
-
return { ok: true, content: `${rebuilt}\n` };
|
|
220
|
-
}
|
|
221
|
-
// No entry-bullet run: insert before the first heading, or append at the end.
|
|
222
|
-
const headingIdx = lines.findIndex((l, i) => !fenced[i] && /^#{2,6}\s/.test(l));
|
|
223
|
-
if (headingIdx !== -1) {
|
|
224
|
-
const before = lines.slice(0, headingIdx);
|
|
225
|
-
while (before.length > 0 && before[before.length - 1].trim() === '') {
|
|
226
|
-
before.pop();
|
|
227
|
-
}
|
|
228
|
-
const after = lines.slice(headingIdx);
|
|
229
|
-
const rebuilt = [...before, '', block, '', ...after].join('\n');
|
|
230
|
-
return { ok: true, content: `${rebuilt}\n` };
|
|
231
|
-
}
|
|
232
|
-
const trimmedExisting = lines.join('\n').replace(/\s+$/, '');
|
|
233
|
-
const rebuilt = trimmedExisting.length > 0 ? `${trimmedExisting}\n\n${block}` : block;
|
|
234
|
-
return { ok: true, content: `${rebuilt}\n` };
|
|
235
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Decide whether a Markdown link destination points inside the lattice or
|
|
3
|
-
* out at the wider world.
|
|
4
|
-
*
|
|
5
|
-
* This exists as its own module because two callers need the same answer and
|
|
6
|
-
* a second, differently-behaved copy of the rule is exactly how the two
|
|
7
|
-
* drift: `parseIndexEntries` in check.ts decides which index bullets are
|
|
8
|
-
* generated entries, and `spliceIndexContent` in gen-index.ts decides which
|
|
9
|
-
* bullets belong to the region `--fix` is allowed to rewrite. If those two
|
|
10
|
-
* ever disagree about a line, `--fix` rewrites a bullet the checker does not
|
|
11
|
-
* track, or leaves one it does.
|
|
12
|
-
*
|
|
13
|
-
* `localLinkTarget` in check.ts applies the same rule inline for
|
|
14
|
-
* relative-link validation. It is upstream code and is deliberately left
|
|
15
|
-
* alone here; if this ever moves upstream, that is the call site to fold in.
|
|
16
|
-
*/
|
|
17
|
-
/**
|
|
18
|
-
* True when `url` carries a URL scheme (`https:`, `mailto:`, `file:`) and is
|
|
19
|
-
* therefore not a path inside the lattice.
|
|
20
|
-
*
|
|
21
|
-
* A Windows drive letter is the one case that looks like a scheme and is not
|
|
22
|
-
* — `C:\docs\a.md` matches the scheme grammar because a drive letter is a
|
|
23
|
-
* single ASCII letter followed by a colon. Treat it as a path, the same way
|
|
24
|
-
* `localLinkTarget` does, so the two agree.
|
|
25
|
-
*/
|
|
26
|
-
export declare function hasUrlScheme(url: string): boolean;
|
|
27
|
-
/**
|
|
28
|
-
* True when `url` is a destination the lattice can own: no scheme, and not
|
|
29
|
-
* rooted at the filesystem root. A root-absolute path is excluded for the
|
|
30
|
-
* same reason `localLinkTarget` excludes it — it names a location outside
|
|
31
|
-
* the lattice tree, so it is never a child entry of a directory index.
|
|
32
|
-
*/
|
|
33
|
-
export declare function isLatticeLocalDest(url: string): boolean;
|
|
34
|
-
/**
|
|
35
|
-
* Reduce a Markdown link destination to the name of the directory child it
|
|
36
|
-
* refers to, or null when it refers to no child of this directory at all.
|
|
37
|
-
*
|
|
38
|
-
* The naive reading — take the first `/`-separated segment — is wrong in
|
|
39
|
-
* four distinct ways, and each one was observed producing a bogus entry
|
|
40
|
-
* name that `lat check` then reported as a stale entry that "does not
|
|
41
|
-
* exist":
|
|
42
|
-
*
|
|
43
|
-
* https://example.com/docs -> "https:" a scheme is not a path segment
|
|
44
|
-
* ./notes.md -> "." a no-op prefix is not a child
|
|
45
|
-
* ../siblings/x.md -> ".." this escapes the directory
|
|
46
|
-
* notes.md#intro -> "notes.md#intro" fragments are not names
|
|
47
|
-
*
|
|
48
|
-
* Order is load-bearing. The fragment and query are split off BEFORE
|
|
49
|
-
* percent-decoding, and the path is split on `/` BEFORE decoding too, for
|
|
50
|
-
* the same reason `localLinkTarget` does it: `%23` and `%2F` decode to `#`
|
|
51
|
-
* and `/`, and decoding first would let a filename that legitimately
|
|
52
|
-
* contains either one truncate or split itself.
|
|
53
|
-
*/
|
|
54
|
-
export declare function indexEntryNameFromDest(dest: string): string | null;
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Decide whether a Markdown link destination points inside the lattice or
|
|
3
|
-
* out at the wider world.
|
|
4
|
-
*
|
|
5
|
-
* This exists as its own module because two callers need the same answer and
|
|
6
|
-
* a second, differently-behaved copy of the rule is exactly how the two
|
|
7
|
-
* drift: `parseIndexEntries` in check.ts decides which index bullets are
|
|
8
|
-
* generated entries, and `spliceIndexContent` in gen-index.ts decides which
|
|
9
|
-
* bullets belong to the region `--fix` is allowed to rewrite. If those two
|
|
10
|
-
* ever disagree about a line, `--fix` rewrites a bullet the checker does not
|
|
11
|
-
* track, or leaves one it does.
|
|
12
|
-
*
|
|
13
|
-
* `localLinkTarget` in check.ts applies the same rule inline for
|
|
14
|
-
* relative-link validation. It is upstream code and is deliberately left
|
|
15
|
-
* alone here; if this ever moves upstream, that is the call site to fold in.
|
|
16
|
-
*/
|
|
17
|
-
/**
|
|
18
|
-
* True when `url` carries a URL scheme (`https:`, `mailto:`, `file:`) and is
|
|
19
|
-
* therefore not a path inside the lattice.
|
|
20
|
-
*
|
|
21
|
-
* A Windows drive letter is the one case that looks like a scheme and is not
|
|
22
|
-
* — `C:\docs\a.md` matches the scheme grammar because a drive letter is a
|
|
23
|
-
* single ASCII letter followed by a colon. Treat it as a path, the same way
|
|
24
|
-
* `localLinkTarget` does, so the two agree.
|
|
25
|
-
*/
|
|
26
|
-
export function hasUrlScheme(url) {
|
|
27
|
-
const u = url.trim();
|
|
28
|
-
if (/^[a-zA-Z]:\\/.test(u))
|
|
29
|
-
return false;
|
|
30
|
-
return /^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(u);
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* True when `url` is a destination the lattice can own: no scheme, and not
|
|
34
|
-
* rooted at the filesystem root. A root-absolute path is excluded for the
|
|
35
|
-
* same reason `localLinkTarget` excludes it — it names a location outside
|
|
36
|
-
* the lattice tree, so it is never a child entry of a directory index.
|
|
37
|
-
*/
|
|
38
|
-
export function isLatticeLocalDest(url) {
|
|
39
|
-
const u = url.trim();
|
|
40
|
-
if (u === '')
|
|
41
|
-
return false;
|
|
42
|
-
if (u.startsWith('/'))
|
|
43
|
-
return false;
|
|
44
|
-
return !hasUrlScheme(u);
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Reduce a Markdown link destination to the name of the directory child it
|
|
48
|
-
* refers to, or null when it refers to no child of this directory at all.
|
|
49
|
-
*
|
|
50
|
-
* The naive reading — take the first `/`-separated segment — is wrong in
|
|
51
|
-
* four distinct ways, and each one was observed producing a bogus entry
|
|
52
|
-
* name that `lat check` then reported as a stale entry that "does not
|
|
53
|
-
* exist":
|
|
54
|
-
*
|
|
55
|
-
* https://example.com/docs -> "https:" a scheme is not a path segment
|
|
56
|
-
* ./notes.md -> "." a no-op prefix is not a child
|
|
57
|
-
* ../siblings/x.md -> ".." this escapes the directory
|
|
58
|
-
* notes.md#intro -> "notes.md#intro" fragments are not names
|
|
59
|
-
*
|
|
60
|
-
* Order is load-bearing. The fragment and query are split off BEFORE
|
|
61
|
-
* percent-decoding, and the path is split on `/` BEFORE decoding too, for
|
|
62
|
-
* the same reason `localLinkTarget` does it: `%23` and `%2F` decode to `#`
|
|
63
|
-
* and `/`, and decoding first would let a filename that legitimately
|
|
64
|
-
* contains either one truncate or split itself.
|
|
65
|
-
*/
|
|
66
|
-
export function indexEntryNameFromDest(dest) {
|
|
67
|
-
if (!isLatticeLocalDest(dest))
|
|
68
|
-
return null;
|
|
69
|
-
const u = dest.trim();
|
|
70
|
-
const queryAt = u.indexOf('?');
|
|
71
|
-
const fragmentAt = u.indexOf('#');
|
|
72
|
-
const pathEnd = Math.min(queryAt === -1 ? u.length : queryAt, fragmentAt === -1 ? u.length : fragmentAt);
|
|
73
|
-
let path = u.slice(0, pathEnd);
|
|
74
|
-
// `./` contributes nothing to the path, and may be repeated.
|
|
75
|
-
while (path.startsWith('./'))
|
|
76
|
-
path = path.slice(2);
|
|
77
|
-
// `..` leaves the directory whose index this is, so whatever it names is
|
|
78
|
-
// by definition not a child of it.
|
|
79
|
-
if (path === '..' || path.startsWith('../'))
|
|
80
|
-
return null;
|
|
81
|
-
if (path === '' || path === '.')
|
|
82
|
-
return null;
|
|
83
|
-
const segment = path.split('/')[0];
|
|
84
|
-
if (segment === '')
|
|
85
|
-
return null;
|
|
86
|
-
let decoded;
|
|
87
|
-
try {
|
|
88
|
-
decoded = decodeURIComponent(segment);
|
|
89
|
-
}
|
|
90
|
-
catch {
|
|
91
|
-
decoded = segment;
|
|
92
|
-
}
|
|
93
|
-
// A percent-encoded `.` or `..` (e.g. `%2e%2e`) decodes to the same
|
|
94
|
-
// traversal segment the raw check above already rejects. Re-check after
|
|
95
|
-
// decoding so both spellings agree — this is a consistency fix, not a
|
|
96
|
-
// security one: parseIndexEntries only compares names, it never builds a
|
|
97
|
-
// filesystem path from one.
|
|
98
|
-
if (decoded === '.' || decoded === '..')
|
|
99
|
-
return null;
|
|
100
|
-
return decoded;
|
|
101
|
-
}
|
package/dist/src/cli/locate.d.ts
DELETED
package/dist/src/cli/locate.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { loadAllSections, findSections } from '../lattice.js';
|
|
2
|
-
import { formatResultList } from '../format.js';
|
|
3
|
-
export async function locateCommand(ctx, query) {
|
|
4
|
-
const stripped = query.replace(/^\[\[|\]\]$/g, '');
|
|
5
|
-
const sections = await loadAllSections(ctx.latDir);
|
|
6
|
-
const matches = findSections(sections, stripped);
|
|
7
|
-
if (matches.length === 0) {
|
|
8
|
-
const s = ctx.styler;
|
|
9
|
-
return {
|
|
10
|
-
output: s.red(`No sections matching "${stripped}" (no exact, substring, or fuzzy matches)`),
|
|
11
|
-
isError: true,
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
|
-
return {
|
|
15
|
-
output: formatResultList(ctx, `Sections matching "${stripped}":`, matches),
|
|
16
|
-
};
|
|
17
|
-
}
|
package/dist/src/cli/refs.d.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { type Section, type SectionMatch } from '../lattice.js';
|
|
2
|
-
import type { CmdContext, CmdResult } from '../context.js';
|
|
3
|
-
export type Scope = 'md' | 'code' | 'md+code';
|
|
4
|
-
export type RefsFound = {
|
|
5
|
-
kind: 'found';
|
|
6
|
-
target: Section;
|
|
7
|
-
mdRefs: SectionMatch[];
|
|
8
|
-
codeRefs: string[];
|
|
9
|
-
};
|
|
10
|
-
export type RefsError = {
|
|
11
|
-
kind: 'no-match';
|
|
12
|
-
suggestions: SectionMatch[];
|
|
13
|
-
};
|
|
14
|
-
export type RefsResult = RefsFound | RefsError;
|
|
15
|
-
/**
|
|
16
|
-
* Find all sections and code locations that reference a given section or
|
|
17
|
-
* source file. Accepts section ids (full-path, short-form) and source file
|
|
18
|
-
* paths (e.g. src/app.rs#foo). Source file queries match wiki links directly
|
|
19
|
-
* without section resolution.
|
|
20
|
-
*/
|
|
21
|
-
export declare function findRefs(ctx: CmdContext, query: string, scope: Scope): Promise<RefsResult>;
|
|
22
|
-
export declare function refsCommand(ctx: CmdContext, query: string, scope: Scope): Promise<CmdResult>;
|