@plebeiantech/lat.md 0.12.3-fork.2 → 0.12.3-fork.21
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 +31 -2
- 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/comment-guard.d.ts +14 -0
- package/dist/src/cli/comment-guard.js +10 -33
- package/dist/src/cli/comment-reminder.d.ts +65 -6
- package/dist/src/cli/comment-reminder.js +164 -28
- package/dist/src/cli/fork-instructions.d.ts +20 -0
- package/dist/src/cli/fork-instructions.js +184 -0
- package/dist/src/cli/fork-scaffold.d.ts +106 -0
- package/dist/src/cli/fork-scaffold.js +490 -0
- 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 +166 -64
- 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 +107 -50
- 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 +116 -100
- 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 +4 -0
- package/dist/src/cli/ui-build.js +13 -0
- package/dist/src/cli/ui.d.ts +1 -1
- package/dist/src/cli/ui.js +18 -2
- 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-cli.js +2 -0
- package/dist/src/fork/upstream-drift.d.ts +26 -0
- package/dist/src/fork/upstream-drift.js +185 -0
- package/dist/src/fork/upstream-guard-cli.d.ts +1 -0
- package/dist/src/fork/upstream-guard-cli.js +2 -0
- package/dist/src/fork/upstream-guard.d.ts +72 -0
- package/dist/src/fork/upstream-guard.js +445 -0
- package/dist/src/graph-export.d.ts +2 -0
- package/dist/src/graph-export.js +38 -19
- package/dist/src/knowledge/claude-memory.d.ts +1 -0
- package/dist/src/knowledge/claude-memory.js +33 -4
- 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 +106 -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 -53
- 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 +17 -7
- package/dist/src/search/search.js +164 -14
- package/dist/src/search/types.d.ts +15 -0
- package/dist/src/search/types.js +1 -0
- package/dist/src/view/client/assets/GraphView-0bPe_Q5I.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-1_8mI7lO.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-BLIuikwY.js +1 -0
- package/dist/src/view/client/assets/arc-D4PzdKSA.js +1 -0
- package/dist/src/view/client/assets/architectureDiagram-5GKGNRK7-35Egww62.js +36 -0
- package/dist/src/view/client/assets/blockDiagram-I7D4REHJ-tqNy53-W.js +129 -0
- package/dist/src/view/client/assets/c4Diagram-7LVT6UL2-DZ_GcD9K.js +38 -0
- package/dist/src/view/client/assets/channel-DensupHE.js +1 -0
- package/dist/src/view/client/assets/chunk-2Q5K7J3B-BUjq4Q7b.js +1 -0
- package/dist/src/view/client/assets/chunk-5VM5RSS4-BsIix6I5.js +15 -0
- package/dist/src/view/client/assets/chunk-F27PBJKO-Dxo7UheG.js +1 -0
- package/dist/src/view/client/assets/chunk-IMKFNOWR-C5lzUDK5.js +231 -0
- package/dist/src/view/client/assets/chunk-JWPE2WC7-qCHQlKfY.js +1 -0
- package/dist/src/view/client/assets/chunk-POPQ4Y6H-CDPKw21I.js +1 -0
- package/dist/src/view/client/assets/chunk-SVP7TREG-CD_C-9M-.js +88 -0
- package/dist/src/view/client/assets/chunk-TICWLB2K-ZMatRvad.js +206 -0
- package/dist/src/view/client/assets/chunk-XXDRQBXY-dDs4quwg.js +1 -0
- package/dist/src/view/client/assets/classDiagram-ZZMXUADV-CV7ArHLW.js +1 -0
- package/dist/src/view/client/assets/classDiagram-v2-VYDZK3BY-CV7ArHLW.js +1 -0
- package/dist/src/view/client/assets/cose-bilkent-JH36ORCC-CwH3-T1N.js +1 -0
- package/dist/src/view/client/assets/cynefin-OW5HDTMX-DodS6r00.js +166 -0
- package/dist/src/view/client/assets/cynefinDiagram-5FMLGOSQ-D7WDoy0K.js +62 -0
- package/dist/src/view/client/assets/cytoscape.esm-DzSz-X2X.js +321 -0
- package/dist/src/view/client/assets/dagre-GXQ25YYZ-yc2GTi5h.js +4 -0
- package/dist/src/view/client/assets/defaultLocale-DX6XiGOO.js +1 -0
- package/dist/src/view/client/assets/diagram-S7CK7UJ4-CEP0FGL8.js +30 -0
- package/dist/src/view/client/assets/diagram-UQ7AKVKN-BZIEojBf.js +41 -0
- package/dist/src/view/client/assets/diagram-VSXAHHWV-BSB6COmM.js +3 -0
- package/dist/src/view/client/assets/diagram-VX7I27RA-DqfR3psV.js +24 -0
- package/dist/src/view/client/assets/diagram-Z3DM3KII-B79t0s5P.js +24 -0
- package/dist/src/view/client/assets/ebnfDiagram-PWID7BFC-CqbCQhE1.js +1 -0
- package/dist/src/view/client/assets/erDiagram-RLTQ6QDP-BVfoYIhJ.js +99 -0
- package/dist/src/view/client/assets/flowDiagram-HODETNUW-Dfyjm6ib.js +168 -0
- package/dist/src/view/client/assets/ganttDiagram-EL5Y4UJY-Da9ta_k3.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-BDqlQ6LG.js +106 -0
- package/dist/src/view/client/assets/index-BnENo9bV.js +1 -0
- package/dist/src/view/client/assets/index-DG0Ez15D.css +1 -0
- package/dist/src/view/client/assets/index-heNSjszK.js +13 -0
- package/dist/src/view/client/assets/infoDiagram-27XIBGKW-CozIUYm1.js +2 -0
- package/dist/src/view/client/assets/init-Gi6I4Gst.js +1 -0
- package/dist/src/view/client/assets/ishikawaDiagram-5VMMS53U-tkBLr-Tn.js +70 -0
- package/dist/src/view/client/assets/journeyDiagram-3NMN7TZE-Dcd_Ofwc.js +139 -0
- package/dist/src/view/client/assets/kanban-definition-UXKFOSKX-CQvZmdAf.js +89 -0
- package/dist/src/view/client/assets/katex-HP8lGamR.js +257 -0
- package/dist/src/view/client/assets/layout-BxuGL0Ip.js +1 -0
- package/dist/src/view/client/assets/linear-D8tR6G5K.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-BlHZooLK.js +310 -0
- package/dist/src/view/client/assets/mindmap-definition-YA3MSWOX-BqvVz5lC.js +96 -0
- package/dist/src/view/client/assets/ordinal-Cboi1Yqb.js +1 -0
- package/dist/src/view/client/assets/pegDiagram-XKGWAZYB-BkbOOTxX.js +1 -0
- package/dist/src/view/client/assets/pieDiagram-E7YTZNPT-BToTpG0m.js +39 -0
- package/dist/src/view/client/assets/quadrantDiagram-AXDQQJYC-CerD2TfT.js +7 -0
- package/dist/src/view/client/assets/railroadDiagram-O6MQD6OU-B2oElPYD.js +1 -0
- package/dist/src/view/client/assets/requirementDiagram-BXWQKSXE-BCL8RGFd.js +84 -0
- package/dist/src/view/client/assets/sankeyDiagram-P5KCCOFB-BqnkNRPm.js +40 -0
- package/dist/src/view/client/assets/sequenceDiagram-WJ2MYXX4-DKSKYknp.js +162 -0
- package/dist/src/view/client/assets/sizeCapture-INFHLROL-D8reQ7IM.js +1 -0
- package/dist/src/view/client/assets/stateDiagram-D77RDMKH-B-Eme-BN.js +1 -0
- package/dist/src/view/client/assets/stateDiagram-v2-MP3YSRHH-yXL-Y-Ym.js +1 -0
- package/dist/src/view/client/assets/swimlanes-42K2YHIH-lK0158X4.js +1 -0
- package/dist/src/view/client/assets/swimlanesDiagram-VR7AAH4N-CGn5WOGw.js +8 -0
- package/dist/src/view/client/assets/three.module-PDSP0dbZ.js +4108 -0
- package/dist/src/view/client/assets/timeline-definition-24CTP7MA-imh-edhJ.js +120 -0
- package/dist/src/view/client/assets/vennDiagram-4TSXK5OY-Ixwhcd6r.js +34 -0
- package/dist/src/view/client/assets/wardleyDiagram-VM6X3IG4-Cvr_zzKI.js +78 -0
- package/dist/src/view/client/assets/xychartDiagram-S5SC5T6Z-BvcmHKlQ.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 +126 -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 +205 -1
- package/dist/src/view/git.js +1 -1
- package/dist/src/view/graph.d.ts +7 -0
- package/dist/src/view/graph.js +267 -0
- package/dist/src/view/highlight.d.ts +10 -2
- package/dist/src/view/highlight.js +50648 -3166
- package/dist/src/view/markdown.d.ts +8 -3
- package/dist/src/view/markdown.js +311 -41
- 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 +95 -6
- package/dist/src/view/protocol.js +1 -1
- package/dist/src/view/publication.d.ts +2 -0
- package/dist/src/view/publication.js +78 -0
- package/dist/src/view/references.d.ts +13 -26
- package/dist/src/view/references.js +150 -119
- package/dist/src/view/repository.d.ts +18 -5
- package/dist/src/view/repository.js +269 -27
- 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 -33
- 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 +94 -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 +14 -2
- package/dist/src/view/server.js +254 -51
- package/dist/src/view/source-target.d.ts +10 -0
- package/dist/src/view/source-target.js +43 -0
- package/dist/src/view/static-build.d.ts +32 -0
- package/dist/src/view/static-build.js +741 -0
- package/dist/src/view/static-protocol.d.ts +47 -0
- package/dist/src/view/static-protocol.js +15 -0
- package/dist/src/view/store.d.ts +26 -3
- package/dist/src/view/store.js +325 -44
- package/dist/src/view/table-of-contents.d.ts +9 -0
- package/dist/src/view/table-of-contents.js +83 -0
- package/dist/src/view/vercel-build.d.ts +24 -0
- package/dist/src/view/vercel-build.js +140 -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 +72 -25
- 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 +118 -0
- package/plugins/lat-md/skills/lat-md/SKILL.md +178 -0
- package/plugins/lat-md/skills/lat-md-conventions/SKILL.md +182 -0
- package/templates/AGENTS.md +19 -20
- package/templates/cursor-rules.md +14 -7
- package/templates/fork/conventions.md +173 -0
- package/templates/opencode-plugin.ts +9 -9
- package/templates/pi-extension.ts +11 -11
- package/templates/skill/SKILL.md +28 -17
- 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 -6
- package/dist/src/cli/check-mode.js +0 -303
- 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 -777
- 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 -277
- 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 -108
- package/dist/src/lattice.js +0 -816
- 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 -24
- package/dist/src/untrusted.js +0 -97
- package/dist/src/view/client/assets/index-B0n0u03y.css +0 -1
- package/dist/src/view/client/assets/index-xm2_px4q.js +0 -23
- package/dist/src/walk.d.ts +0 -18
- package/dist/src/walk.js +0 -27
- /package/dist/src/{extensions/wiki-link/types.js → fork/upstream-drift-cli.d.ts} +0 -0
package/dist/src/view/store.js
CHANGED
|
@@ -1,17 +1,30 @@
|
|
|
1
|
+
import { repositoryFilePath } from '@plebeiantech/lat.md-core/repository-path';
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
1
3
|
import { watch as watchFiles } from 'node:fs';
|
|
2
|
-
import { readFile, realpath } from 'node:fs/promises';
|
|
4
|
+
import { readFile, realpath, rename, rm, stat, writeFile, } from 'node:fs/promises';
|
|
3
5
|
import { basename, extname, isAbsolute, relative, resolve, sep, } from 'node:path';
|
|
4
|
-
import { LAT_REF_RE,
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { createCodeReferenceDiscovery, LAT_REF_RE, } from '@plebeiantech/lat.md-core/code-refs';
|
|
7
|
+
import { createExternalResolver, } from '@plebeiantech/lat.md-core/external-sources';
|
|
8
|
+
import { listLatticeFiles } from '@plebeiantech/lat.md-core/project-discovery';
|
|
9
|
+
import { analyzeMarkdownPath } from '@plebeiantech/lat.md-core/markdown-analysis-cache';
|
|
10
|
+
import { isSourceFileExtension } from '@plebeiantech/lat.md-core/source-formats';
|
|
11
|
+
import { toPosix } from '@plebeiantech/lat.md-core/path';
|
|
8
12
|
import { renderMarkdown } from './markdown.js';
|
|
9
13
|
import { buildViewDiagnostics } from './diagnostics.js';
|
|
14
|
+
import { applyDocumentEdit, ViewDocumentConflictError, } from './document-edit.js';
|
|
10
15
|
import { buildGitDiffTree } from './git-diff.js';
|
|
16
|
+
import { buildViewGraph } from './graph.js';
|
|
17
|
+
import { buildViewTableOfContents } from './table-of-contents.js';
|
|
11
18
|
import { emptyViewGitSnapshot, findViewGitRepository, readViewGitSnapshot, sameViewGitSnapshot, } from './git.js';
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
19
|
+
import { DEFAULT_VIEW_LOGO_TEXT } from './protocol.js';
|
|
20
|
+
import { createMarkdownWikiLinkResolver, getViewExternal, getViewSource, ViewDocumentNotFoundError, ViewSourceNotFoundError, } from './repository.js';
|
|
21
|
+
import { buildViewReferenceIndex, renderSectionBackReferences, } from './references.js';
|
|
22
|
+
import { rewriteLocalFileLink } from './source-target.js';
|
|
14
23
|
const DEFAULT_DEBOUNCE_MS = 75;
|
|
24
|
+
const DEFAULT_GIT_POLL_MS = 2_000;
|
|
25
|
+
const EXTERNAL_REFRESH_PATH = '@lat-external-refresh';
|
|
26
|
+
const DOCUMENT_EDIT_WRITE_ATTEMPTS = 3;
|
|
27
|
+
const DOCUMENT_EDIT_TEMP_PREFIX = '.lat-edit-';
|
|
15
28
|
function isInside(root, candidate) {
|
|
16
29
|
const rel = relative(root, candidate);
|
|
17
30
|
return (rel === '' ||
|
|
@@ -21,8 +34,16 @@ function projectPath(projectRoot, path) {
|
|
|
21
34
|
const normalized = isAbsolute(path) ? relative(projectRoot, path) : path;
|
|
22
35
|
return toPosix(normalized).replace(/^\.\//, '');
|
|
23
36
|
}
|
|
37
|
+
function isInternalLatCachePath(path, latPath) {
|
|
38
|
+
const cachePath = latPath ? `${latPath}/.cache` : '.cache';
|
|
39
|
+
return path === cachePath || path.startsWith(`${cachePath}/`);
|
|
40
|
+
}
|
|
41
|
+
function excludedCodePath(projectRoot, path, excludedPaths) {
|
|
42
|
+
const absolutePath = resolve(projectRoot, path);
|
|
43
|
+
return excludedPaths.some((root) => isInside(resolve(root), absolutePath));
|
|
44
|
+
}
|
|
24
45
|
function sourcePath(path) {
|
|
25
|
-
return
|
|
46
|
+
return isSourceFileExtension(extname(path).toLowerCase());
|
|
26
47
|
}
|
|
27
48
|
function obviouslyIgnoredCodePath(path, latPath) {
|
|
28
49
|
const parts = path.split('/');
|
|
@@ -55,7 +76,10 @@ async function loadCodeReferenceFiles(projectRoot, refs) {
|
|
|
55
76
|
const files = new Map();
|
|
56
77
|
await Promise.all([...refsByFile].map(async ([path, fileRefs]) => {
|
|
57
78
|
try {
|
|
58
|
-
const
|
|
79
|
+
const safePath = await repositoryFilePath(projectRoot, path);
|
|
80
|
+
if (!safePath)
|
|
81
|
+
return;
|
|
82
|
+
const content = await readFile(safePath, 'utf8');
|
|
59
83
|
files.set(path, { path, lines: content.split('\n'), refs: fileRefs });
|
|
60
84
|
}
|
|
61
85
|
catch {
|
|
@@ -64,22 +88,61 @@ async function loadCodeReferenceFiles(projectRoot, refs) {
|
|
|
64
88
|
}));
|
|
65
89
|
return files;
|
|
66
90
|
}
|
|
67
|
-
async function scanCodeState(projectRoot) {
|
|
68
|
-
const
|
|
69
|
-
const
|
|
91
|
+
async function scanCodeState(projectRoot, excludedPaths = [], publishable) {
|
|
92
|
+
const discovery = createCodeReferenceDiscovery(projectRoot);
|
|
93
|
+
const [scan, sourceFiles] = await Promise.all([
|
|
94
|
+
discovery.scan(),
|
|
95
|
+
discovery.listSourceFiles(),
|
|
96
|
+
]);
|
|
97
|
+
const allowed = (path) => !excludedCodePath(projectRoot, path, excludedPaths);
|
|
98
|
+
const candidates = sourceFiles.filter(allowed);
|
|
99
|
+
const decisions = await Promise.all(candidates.map((path) => publishable?.(projectPath(projectRoot, path)) ?? true));
|
|
100
|
+
const files = candidates.filter((_, index) => decisions[index]);
|
|
101
|
+
const scope = new Set(files.map((path) => projectPath(projectRoot, path)));
|
|
102
|
+
const refs = scan.refs.filter((ref) => allowed(ref.file) && scope.has(ref.file));
|
|
70
103
|
return {
|
|
71
|
-
files: await loadCodeReferenceFiles(projectRoot,
|
|
104
|
+
files: await loadCodeReferenceFiles(projectRoot, refs),
|
|
72
105
|
scope,
|
|
73
106
|
};
|
|
74
107
|
}
|
|
75
|
-
function viewIndex(latDir,
|
|
76
|
-
const files = [...
|
|
108
|
+
function viewIndex(latDir, markdownFiles, diagnostics, git, references, external) {
|
|
109
|
+
const files = [...markdownFiles.keys()].sort();
|
|
110
|
+
const externalFiles = new Map();
|
|
111
|
+
for (const target of references.externalByTarget.keys()) {
|
|
112
|
+
try {
|
|
113
|
+
const parsed = external.parse(target);
|
|
114
|
+
if (!parsed)
|
|
115
|
+
continue;
|
|
116
|
+
const hash = parsed.identity.indexOf('#');
|
|
117
|
+
const baseTarget = hash === -1 ? parsed.identity : parsed.identity.slice(0, hash);
|
|
118
|
+
externalFiles.set(baseTarget, {
|
|
119
|
+
handle: parsed.handle,
|
|
120
|
+
path: parsed.resolvedPath,
|
|
121
|
+
target: baseTarget,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
// Invalid external targets remain diagnostics, not sidebar entries.
|
|
126
|
+
}
|
|
127
|
+
}
|
|
77
128
|
const directoryName = basename(latDir);
|
|
78
129
|
const indexName = directoryName.endsWith('.md')
|
|
79
130
|
? directoryName
|
|
80
131
|
: `${directoryName}.md`;
|
|
132
|
+
const directoryOrder = Object.fromEntries([...markdownFiles].flatMap(([path, file]) => {
|
|
133
|
+
const separator = path.lastIndexOf('/');
|
|
134
|
+
const directory = separator === -1 ? '' : path.slice(0, separator);
|
|
135
|
+
const name = directory ? basename(directory) : directoryName;
|
|
136
|
+
const filename = name.endsWith('.md') ? name : `${name}.md`;
|
|
137
|
+
if (path.slice(separator + 1) !== filename)
|
|
138
|
+
return [];
|
|
139
|
+
return [[directory, file.indexEntries]];
|
|
140
|
+
}));
|
|
81
141
|
return {
|
|
82
142
|
files,
|
|
143
|
+
directoryOrder,
|
|
144
|
+
externalFiles: [...externalFiles.values()].sort((left, right) => left.handle.localeCompare(right.handle) ||
|
|
145
|
+
left.path.localeCompare(right.path)),
|
|
83
146
|
entry: files.includes(indexName) ? indexName : (files[0] ?? ''),
|
|
84
147
|
errorCounts: Object.fromEntries([...diagnostics]
|
|
85
148
|
.filter(([, errors]) => errors.length > 0)
|
|
@@ -89,21 +152,37 @@ function viewIndex(latDir, paths, diagnostics, git) {
|
|
|
89
152
|
files: Object.fromEntries([...git.files].map(([path, file]) => [path, file.status])),
|
|
90
153
|
}
|
|
91
154
|
: null,
|
|
155
|
+
logoText: DEFAULT_VIEW_LOGO_TEXT,
|
|
92
156
|
};
|
|
93
157
|
}
|
|
94
|
-
async function buildSnapshot(latDir, projectRoot, markdownFiles, codeFiles, git, generation, markdownGeneration) {
|
|
158
|
+
async function buildSnapshot(latDir, projectRoot, markdownFiles, codeFiles, git, generation, markdownGeneration, options) {
|
|
95
159
|
const files = new Map([...markdownFiles].sort(([left], [right]) => left.localeCompare(right)));
|
|
96
160
|
const allSections = [...files.values()].flatMap((file) => file.sections);
|
|
97
|
-
const
|
|
161
|
+
const external = await createExternalResolver(latDir, projectRoot, {
|
|
162
|
+
ignoreLocal: options.externalIgnoreLocal,
|
|
163
|
+
ca: options.externalCa,
|
|
164
|
+
});
|
|
165
|
+
await external.reconcile();
|
|
166
|
+
const diagnostics = await buildViewDiagnostics(files.values(), codeFiles.values(), allSections, projectRoot, external, latDir);
|
|
167
|
+
const references = buildViewReferenceIndex(files.values(), codeFiles.values(), allSections, (target) => {
|
|
168
|
+
try {
|
|
169
|
+
return external.parse(target)?.identity ?? null;
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
return target;
|
|
173
|
+
}
|
|
174
|
+
});
|
|
98
175
|
return {
|
|
99
176
|
generation,
|
|
100
177
|
markdownGeneration,
|
|
101
178
|
files,
|
|
102
179
|
allSections,
|
|
103
|
-
references
|
|
180
|
+
references,
|
|
181
|
+
graph: buildViewGraph(files.values(), codeFiles.values(), allSections, diagnostics, git, generation, references, external),
|
|
104
182
|
diagnostics,
|
|
105
183
|
git,
|
|
106
|
-
index: viewIndex(latDir,
|
|
184
|
+
index: viewIndex(latDir, files, diagnostics, git, references, external),
|
|
185
|
+
external,
|
|
107
186
|
};
|
|
108
187
|
}
|
|
109
188
|
/** Own the immutable, incrementally refreshed project snapshot for `lat ui`. */
|
|
@@ -119,9 +198,13 @@ export class ViewStore {
|
|
|
119
198
|
ignoredCodePaths = new Set();
|
|
120
199
|
listeners = new Set();
|
|
121
200
|
watcher = null;
|
|
201
|
+
externalWatchers = [];
|
|
122
202
|
pendingPaths = new Set();
|
|
123
203
|
debounceTimer = null;
|
|
204
|
+
gitPollTimer = null;
|
|
205
|
+
gitPollQueued = false;
|
|
124
206
|
refreshTail = Promise.resolve();
|
|
207
|
+
editTail = Promise.resolve();
|
|
125
208
|
closed = false;
|
|
126
209
|
constructor(latDir, projectRoot, realLatDir, snapshot, codeFiles, codeScope, gitRepository, options) {
|
|
127
210
|
this.latDir = latDir;
|
|
@@ -140,6 +223,7 @@ export class ViewStore {
|
|
|
140
223
|
return this.snapshotValue.markdownGeneration;
|
|
141
224
|
}
|
|
142
225
|
startWatching() {
|
|
226
|
+
this.startGitPolling();
|
|
143
227
|
if (this.options.watch === false || this.watcher)
|
|
144
228
|
return;
|
|
145
229
|
try {
|
|
@@ -151,6 +235,29 @@ export class ViewStore {
|
|
|
151
235
|
catch (error) {
|
|
152
236
|
process.stderr.write(`lat ui watcher: ${error.message}\n`);
|
|
153
237
|
}
|
|
238
|
+
this.refreshExternalWatchers();
|
|
239
|
+
}
|
|
240
|
+
refreshExternalWatchers() {
|
|
241
|
+
for (const watcher of this.externalWatchers)
|
|
242
|
+
watcher.close();
|
|
243
|
+
this.externalWatchers = [];
|
|
244
|
+
if (this.options.watch === false)
|
|
245
|
+
return;
|
|
246
|
+
const paths = new Set([...this.snapshotValue.external.snapshot.sources.values()]
|
|
247
|
+
.map((source) => source.localPath)
|
|
248
|
+
.filter((path) => Boolean(path)));
|
|
249
|
+
for (const path of paths) {
|
|
250
|
+
try {
|
|
251
|
+
const watcher = watchFiles(path, { recursive: true }, () => this.scheduleRefresh(EXTERNAL_REFRESH_PATH));
|
|
252
|
+
watcher.on('error', (error) => {
|
|
253
|
+
process.stderr.write(`lat ui external watcher: ${error.message}\n`);
|
|
254
|
+
});
|
|
255
|
+
this.externalWatchers.push(watcher);
|
|
256
|
+
}
|
|
257
|
+
catch (error) {
|
|
258
|
+
process.stderr.write(`lat ui external watcher: ${error.message}\n`);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
154
261
|
}
|
|
155
262
|
subscribe(listener) {
|
|
156
263
|
this.listeners.add(listener);
|
|
@@ -159,6 +266,18 @@ export class ViewStore {
|
|
|
159
266
|
getIndex() {
|
|
160
267
|
return this.snapshotValue.index;
|
|
161
268
|
}
|
|
269
|
+
getGraph() {
|
|
270
|
+
return this.snapshotValue.graph;
|
|
271
|
+
}
|
|
272
|
+
async renderSectionOutput(markdown, sectionId) {
|
|
273
|
+
const snapshot = this.snapshotValue;
|
|
274
|
+
const section = snapshot.allSections.find((candidate) => candidate.id.toLowerCase() === sectionId.toLowerCase());
|
|
275
|
+
const requestedPath = section
|
|
276
|
+
? toPosix(relative(this.latDir, resolve(this.projectRoot, section.filePath)))
|
|
277
|
+
: 'section-output.md';
|
|
278
|
+
const resolver = await createMarkdownWikiLinkResolver(this.latDir, requestedPath, snapshot.allSections, snapshot.references, snapshot.external, this.options.publishable);
|
|
279
|
+
return (await renderMarkdown(markdown, requestedPath, resolver)).tree;
|
|
280
|
+
}
|
|
162
281
|
async getDocument(requestedPath) {
|
|
163
282
|
if (!requestedPath ||
|
|
164
283
|
requestedPath.includes('\\') ||
|
|
@@ -171,33 +290,152 @@ export class ViewStore {
|
|
|
171
290
|
if (!file) {
|
|
172
291
|
throw new ViewDocumentNotFoundError('Markdown document not found');
|
|
173
292
|
}
|
|
174
|
-
const resolver = await createMarkdownWikiLinkResolver(this.latDir, requestedPath, snapshot.allSections);
|
|
175
|
-
const rendered = await renderMarkdown(file.content, requestedPath, resolver, {
|
|
293
|
+
const resolver = await createMarkdownWikiLinkResolver(this.latDir, requestedPath, snapshot.allSections, snapshot.references, snapshot.external, this.options.publishable);
|
|
294
|
+
const rendered = await renderMarkdown(file.content, requestedPath, resolver, {
|
|
295
|
+
errors: [...(snapshot.diagnostics.get(requestedPath) ?? [])],
|
|
296
|
+
rewriteMarkdownLink: (url) => rewriteLocalFileLink(url, requestedPath),
|
|
297
|
+
});
|
|
298
|
+
const errors = [...(snapshot.diagnostics.get(requestedPath) ?? [])];
|
|
176
299
|
const gitFile = snapshot.git.files.get(requestedPath);
|
|
177
|
-
const
|
|
178
|
-
?
|
|
300
|
+
const gitTree = gitFile
|
|
301
|
+
? buildGitDiffTree(gitFile.baseContent, file.content)
|
|
302
|
+
: null;
|
|
303
|
+
const gitRendered = gitTree
|
|
304
|
+
? await renderMarkdown(file.content, requestedPath, resolver, {
|
|
305
|
+
errors,
|
|
306
|
+
rewriteMarkdownLink: (url) => rewriteLocalFileLink(url, requestedPath),
|
|
307
|
+
}, gitTree)
|
|
179
308
|
: null;
|
|
180
|
-
const errors = [...(snapshot.diagnostics.get(requestedPath) ?? [])];
|
|
181
309
|
return {
|
|
182
310
|
path: requestedPath,
|
|
183
311
|
...rendered,
|
|
184
|
-
|
|
312
|
+
gitTree: gitRendered?.tree ?? null,
|
|
313
|
+
tableOfContents: buildViewTableOfContents(file.sections, file.headingTitles, { errors, gitTree }),
|
|
314
|
+
graphNodeIds: Object.fromEntries(snapshot.graph.nodes
|
|
315
|
+
.filter((node) => node.documentPath === requestedPath && node.kind === 'document')
|
|
316
|
+
.map((node) => {
|
|
317
|
+
const hash = new URL(node.url, 'http://lat.local').hash.slice(1);
|
|
318
|
+
let headingId = hash;
|
|
319
|
+
try {
|
|
320
|
+
headingId = decodeURIComponent(hash);
|
|
321
|
+
}
|
|
322
|
+
catch {
|
|
323
|
+
// Keep malformed fragments as-is; they cannot collide with valid ids.
|
|
324
|
+
}
|
|
325
|
+
return [headingId, node.id];
|
|
326
|
+
})),
|
|
185
327
|
errors,
|
|
186
|
-
backReferences: await renderSectionBackReferences(snapshot.references, file.sections, this.latDir, this.projectRoot, (path) => createMarkdownWikiLinkResolver(this.latDir, path, snapshot.allSections)),
|
|
328
|
+
backReferences: await renderSectionBackReferences(snapshot.references, file.sections, this.latDir, this.projectRoot, (path) => createMarkdownWikiLinkResolver(this.latDir, path, snapshot.allSections, snapshot.references, snapshot.external, this.options.publishable)),
|
|
187
329
|
frontmatter: {
|
|
188
|
-
requireCodeMention:
|
|
330
|
+
requireCodeMention: file.frontmatter.requireCodeMention === true,
|
|
189
331
|
},
|
|
190
332
|
};
|
|
191
333
|
}
|
|
192
|
-
|
|
334
|
+
async editableDocumentPath(requestedPath) {
|
|
335
|
+
if (!requestedPath ||
|
|
336
|
+
requestedPath.includes('\\') ||
|
|
337
|
+
isAbsolute(requestedPath) ||
|
|
338
|
+
!requestedPath.toLowerCase().endsWith('.md') ||
|
|
339
|
+
!this.snapshotValue.files.has(requestedPath)) {
|
|
340
|
+
throw new ViewDocumentNotFoundError('Markdown document not found');
|
|
341
|
+
}
|
|
342
|
+
let realFile;
|
|
343
|
+
try {
|
|
344
|
+
realFile = await realpath(resolve(this.latDir, requestedPath));
|
|
345
|
+
}
|
|
346
|
+
catch {
|
|
347
|
+
throw new ViewDocumentNotFoundError('Markdown document not found');
|
|
348
|
+
}
|
|
349
|
+
if (!isInside(this.realLatDir, realFile)) {
|
|
350
|
+
throw new ViewDocumentNotFoundError('Markdown document not found');
|
|
351
|
+
}
|
|
352
|
+
return realFile;
|
|
353
|
+
}
|
|
354
|
+
async getDocumentSource(requestedPath) {
|
|
355
|
+
const path = await this.editableDocumentPath(requestedPath);
|
|
356
|
+
return { path: requestedPath, content: await readFile(path, 'utf8') };
|
|
357
|
+
}
|
|
358
|
+
async getDocumentResource(requestedPath) {
|
|
359
|
+
if (this.options.publishable &&
|
|
360
|
+
!(await this.options.publishable(projectPath(this.projectRoot, resolve(this.latDir, requestedPath)))))
|
|
361
|
+
throw new ViewDocumentNotFoundError(`Resource is excluded from publication: ${requestedPath}`);
|
|
362
|
+
if (!requestedPath ||
|
|
363
|
+
requestedPath.includes('\\') ||
|
|
364
|
+
isAbsolute(requestedPath) ||
|
|
365
|
+
requestedPath.toLowerCase().endsWith('.md')) {
|
|
366
|
+
throw new ViewDocumentNotFoundError('Document resource not found');
|
|
367
|
+
}
|
|
368
|
+
let path;
|
|
369
|
+
try {
|
|
370
|
+
path = await realpath(resolve(this.latDir, requestedPath));
|
|
371
|
+
if (!isInside(this.realLatDir, path) || !(await stat(path)).isFile()) {
|
|
372
|
+
throw new ViewDocumentNotFoundError('Document resource not found');
|
|
373
|
+
}
|
|
374
|
+
return await readFile(path);
|
|
375
|
+
}
|
|
376
|
+
catch (error) {
|
|
377
|
+
if (error instanceof ViewDocumentNotFoundError)
|
|
378
|
+
throw error;
|
|
379
|
+
throw new ViewDocumentNotFoundError('Document resource not found');
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
editDocument(requestedPath, baseContent, editedContent) {
|
|
383
|
+
const operation = this.editTail.then(async () => {
|
|
384
|
+
const path = await this.editableDocumentPath(requestedPath);
|
|
385
|
+
for (let attempt = 0; attempt < DOCUMENT_EDIT_WRITE_ATTEMPTS; attempt++) {
|
|
386
|
+
const currentContent = await readFile(path, 'utf8');
|
|
387
|
+
const edit = applyDocumentEdit(baseContent, editedContent, currentContent);
|
|
388
|
+
if (edit.content === currentContent) {
|
|
389
|
+
return { path: requestedPath, ...edit };
|
|
390
|
+
}
|
|
391
|
+
const currentStat = await stat(path);
|
|
392
|
+
const temporaryPath = resolve(this.latDir, `${DOCUMENT_EDIT_TEMP_PREFIX}${process.pid}-${randomUUID()}.tmp`);
|
|
393
|
+
try {
|
|
394
|
+
await writeFile(temporaryPath, edit.content, {
|
|
395
|
+
encoding: 'utf8',
|
|
396
|
+
flag: 'wx',
|
|
397
|
+
mode: currentStat.mode,
|
|
398
|
+
});
|
|
399
|
+
if ((await readFile(path, 'utf8')) !== currentContent)
|
|
400
|
+
continue;
|
|
401
|
+
await rename(temporaryPath, path);
|
|
402
|
+
}
|
|
403
|
+
finally {
|
|
404
|
+
await rm(temporaryPath, { force: true });
|
|
405
|
+
}
|
|
406
|
+
await this.refresh([resolve(this.latDir, requestedPath)]);
|
|
407
|
+
return { path: requestedPath, ...edit };
|
|
408
|
+
}
|
|
409
|
+
throw new ViewDocumentConflictError('Could not save because this file kept changing. Your edits are still in the editor.');
|
|
410
|
+
});
|
|
411
|
+
this.editTail = operation.then(() => undefined, () => undefined);
|
|
412
|
+
return operation;
|
|
413
|
+
}
|
|
414
|
+
async getSource(requestedPath, requestedSymbol = '', origin, requestedLine = 0) {
|
|
415
|
+
if (this.options.publishable &&
|
|
416
|
+
!(await this.options.publishable(requestedPath)))
|
|
417
|
+
throw new ViewSourceNotFoundError(`Source is excluded from publication: ${requestedPath}`);
|
|
193
418
|
const snapshot = this.snapshotValue;
|
|
194
|
-
return getViewSource(this.latDir, this.projectRoot, requestedPath, requestedSymbol, origin, requestedLine, snapshot.allSections, snapshot.references);
|
|
419
|
+
return getViewSource(this.latDir, this.projectRoot, requestedPath, requestedSymbol, origin, requestedLine, snapshot.allSections, snapshot.references, this.options.publishable);
|
|
420
|
+
}
|
|
421
|
+
getExternal(target) {
|
|
422
|
+
const snapshot = this.snapshotValue;
|
|
423
|
+
return getViewExternal(this.latDir, this.projectRoot, target, snapshot.external, snapshot.allSections, snapshot.references, this.options.publishable);
|
|
195
424
|
}
|
|
196
425
|
refresh(paths) {
|
|
197
426
|
if (this.closed)
|
|
198
427
|
return Promise.resolve();
|
|
199
|
-
const
|
|
200
|
-
const
|
|
428
|
+
const latPath = projectPath(this.projectRoot, this.latDir);
|
|
429
|
+
const normalized = paths
|
|
430
|
+
.map((path) => (path ? projectPath(this.projectRoot, path) : ''))
|
|
431
|
+
.filter((path) => !isInternalLatCachePath(path, latPath));
|
|
432
|
+
if (paths.length > 0 && normalized.length === 0) {
|
|
433
|
+
return Promise.resolve();
|
|
434
|
+
}
|
|
435
|
+
return this.queueRefresh(normalized, false);
|
|
436
|
+
}
|
|
437
|
+
queueRefresh(paths, pollGit) {
|
|
438
|
+
const refresh = this.refreshTail.then(() => this.applyRefresh(paths, pollGit));
|
|
201
439
|
this.refreshTail = refresh.catch(() => { });
|
|
202
440
|
return refresh;
|
|
203
441
|
}
|
|
@@ -206,15 +444,35 @@ export class ViewStore {
|
|
|
206
444
|
if (this.debounceTimer)
|
|
207
445
|
clearTimeout(this.debounceTimer);
|
|
208
446
|
this.debounceTimer = null;
|
|
447
|
+
if (this.gitPollTimer)
|
|
448
|
+
clearInterval(this.gitPollTimer);
|
|
449
|
+
this.gitPollTimer = null;
|
|
209
450
|
this.watcher?.close();
|
|
210
451
|
this.watcher = null;
|
|
452
|
+
for (const watcher of this.externalWatchers)
|
|
453
|
+
watcher.close();
|
|
454
|
+
this.externalWatchers = [];
|
|
455
|
+
await this.editTail;
|
|
211
456
|
await this.refreshTail;
|
|
212
457
|
this.listeners.clear();
|
|
213
458
|
}
|
|
214
459
|
scheduleRefresh(path) {
|
|
215
460
|
if (this.closed)
|
|
216
461
|
return;
|
|
217
|
-
|
|
462
|
+
if (path !== EXTERNAL_REFRESH_PATH &&
|
|
463
|
+
basename(path).startsWith(DOCUMENT_EDIT_TEMP_PREFIX) &&
|
|
464
|
+
path.endsWith('.tmp')) {
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
467
|
+
const normalizedPath = path === EXTERNAL_REFRESH_PATH
|
|
468
|
+
? path
|
|
469
|
+
: path
|
|
470
|
+
? projectPath(this.projectRoot, path)
|
|
471
|
+
: '';
|
|
472
|
+
const latPath = projectPath(this.projectRoot, this.latDir);
|
|
473
|
+
if (isInternalLatCachePath(normalizedPath, latPath))
|
|
474
|
+
return;
|
|
475
|
+
this.pendingPaths.add(normalizedPath);
|
|
218
476
|
if (this.debounceTimer)
|
|
219
477
|
clearTimeout(this.debounceTimer);
|
|
220
478
|
this.debounceTimer = setTimeout(() => {
|
|
@@ -226,6 +484,24 @@ export class ViewStore {
|
|
|
226
484
|
});
|
|
227
485
|
}, this.options.debounceMs ?? DEFAULT_DEBOUNCE_MS);
|
|
228
486
|
}
|
|
487
|
+
startGitPolling() {
|
|
488
|
+
const interval = this.options.gitPollMs ?? DEFAULT_GIT_POLL_MS;
|
|
489
|
+
if (!this.gitRepository || interval <= 0 || this.gitPollTimer)
|
|
490
|
+
return;
|
|
491
|
+
this.gitPollTimer = setInterval(() => {
|
|
492
|
+
if (this.closed || this.gitPollQueued)
|
|
493
|
+
return;
|
|
494
|
+
this.gitPollQueued = true;
|
|
495
|
+
void this.queueRefresh([], true)
|
|
496
|
+
.catch((error) => {
|
|
497
|
+
process.stderr.write(`lat ui git: ${error.message}\n`);
|
|
498
|
+
})
|
|
499
|
+
.finally(() => {
|
|
500
|
+
this.gitPollQueued = false;
|
|
501
|
+
});
|
|
502
|
+
}, interval);
|
|
503
|
+
this.gitPollTimer.unref();
|
|
504
|
+
}
|
|
229
505
|
async readMarkdownFile(absolutePath) {
|
|
230
506
|
let realFile;
|
|
231
507
|
try {
|
|
@@ -236,12 +512,13 @@ export class ViewStore {
|
|
|
236
512
|
}
|
|
237
513
|
if (!isInside(this.realLatDir, realFile))
|
|
238
514
|
return null;
|
|
239
|
-
|
|
240
|
-
return parseViewMarkdownFile(absolutePath, content, this.latDir, this.projectRoot);
|
|
515
|
+
return analyzeMarkdownPath(absolutePath, this.latDir, this.projectRoot);
|
|
241
516
|
}
|
|
242
|
-
async applyRefresh(paths) {
|
|
517
|
+
async applyRefresh(paths, pollGit) {
|
|
243
518
|
const fullRefresh = paths.includes('');
|
|
244
519
|
const latPath = projectPath(this.projectRoot, this.latDir);
|
|
520
|
+
const externalChanged = paths.includes(EXTERNAL_REFRESH_PATH) ||
|
|
521
|
+
paths.includes(`${latPath}/config.local.yaml`);
|
|
245
522
|
const touchesMarkdown = fullRefresh ||
|
|
246
523
|
paths.some((path) => path === latPath || path.startsWith(`${latPath}/`));
|
|
247
524
|
let markdownFiles = new Map(this.snapshotValue.files);
|
|
@@ -298,7 +575,7 @@ export class ViewStore {
|
|
|
298
575
|
}
|
|
299
576
|
linkedResourceChanged = paths.some((path) => path.startsWith(`${latPath}/`) && !path.toLowerCase().endsWith('.md'));
|
|
300
577
|
}
|
|
301
|
-
if (touchesMarkdown && this.gitRepository) {
|
|
578
|
+
if ((touchesMarkdown || pollGit) && this.gitRepository) {
|
|
302
579
|
try {
|
|
303
580
|
const nextGit = await readViewGitSnapshot(this.gitRepository, markdownFiles);
|
|
304
581
|
gitChanged = !sameViewGitSnapshot(git, nextGit);
|
|
@@ -308,12 +585,15 @@ export class ViewStore {
|
|
|
308
585
|
process.stderr.write(`lat ui git: ${error.message}\n`);
|
|
309
586
|
}
|
|
310
587
|
}
|
|
311
|
-
const codePaths = paths.filter((path) => path &&
|
|
588
|
+
const codePaths = paths.filter((path) => path &&
|
|
589
|
+
sourcePath(path) &&
|
|
590
|
+
!obviouslyIgnoredCodePath(path, latPath) &&
|
|
591
|
+
!excludedCodePath(this.projectRoot, path, this.options.codeExcludePaths ?? []));
|
|
312
592
|
const refreshCodeScope = fullRefresh ||
|
|
313
593
|
paths.some((path) => path === '.gitignore' || path.endsWith('/.gitignore')) ||
|
|
314
594
|
codePaths.some((path) => !this.codeScope.has(path) && !this.ignoredCodePaths.has(path));
|
|
315
595
|
if (refreshCodeScope) {
|
|
316
|
-
const nextCode = await scanCodeState(this.projectRoot);
|
|
596
|
+
const nextCode = await scanCodeState(this.projectRoot, this.options.codeExcludePaths, this.options.publishable);
|
|
317
597
|
codeFiles = nextCode.files;
|
|
318
598
|
this.codeScope = nextCode.scope;
|
|
319
599
|
this.ignoredCodePaths.clear();
|
|
@@ -352,10 +632,12 @@ export class ViewStore {
|
|
|
352
632
|
if (!markdownChanged &&
|
|
353
633
|
!codeChanged &&
|
|
354
634
|
!gitChanged &&
|
|
355
|
-
!linkedResourceChanged
|
|
635
|
+
!linkedResourceChanged &&
|
|
636
|
+
!externalChanged)
|
|
356
637
|
return;
|
|
357
638
|
this.codeFiles = codeFiles;
|
|
358
|
-
this.snapshotValue = await buildSnapshot(this.latDir, this.projectRoot, markdownFiles, codeFiles, git, this.snapshotValue.generation + 1, this.snapshotValue.markdownGeneration + (markdownChanged ? 1 : 0));
|
|
639
|
+
this.snapshotValue = await buildSnapshot(this.latDir, this.projectRoot, markdownFiles, codeFiles, git, this.snapshotValue.generation + 1, this.snapshotValue.markdownGeneration + (markdownChanged ? 1 : 0), this.options);
|
|
640
|
+
this.refreshExternalWatchers();
|
|
359
641
|
const change = {
|
|
360
642
|
generation: this.snapshotValue.generation,
|
|
361
643
|
markdownGeneration: this.snapshotValue.markdownGeneration,
|
|
@@ -369,7 +651,7 @@ export async function createViewStore(latDir, projectRoot, options = {}) {
|
|
|
369
651
|
const [realLatDir, markdownPaths, codeState, gitRepository] = await Promise.all([
|
|
370
652
|
realpath(latDir),
|
|
371
653
|
listLatticeFiles(latDir),
|
|
372
|
-
scanCodeState(projectRoot),
|
|
654
|
+
scanCodeState(projectRoot, options.codeExcludePaths, options.publishable),
|
|
373
655
|
options.git === false
|
|
374
656
|
? Promise.resolve(null)
|
|
375
657
|
: findViewGitRepository(projectRoot, latDir),
|
|
@@ -382,8 +664,7 @@ export async function createViewStore(latDir, projectRoot, options = {}) {
|
|
|
382
664
|
const realFile = await realpath(absolutePath);
|
|
383
665
|
if (!isInside(realLatDir, realFile))
|
|
384
666
|
return;
|
|
385
|
-
const
|
|
386
|
-
const parsed = parseViewMarkdownFile(absolutePath, content, latDir, projectRoot);
|
|
667
|
+
const parsed = await analyzeMarkdownPath(absolutePath, latDir, projectRoot);
|
|
387
668
|
markdownFiles.set(parsed.path, parsed);
|
|
388
669
|
}));
|
|
389
670
|
if (markdownFiles.size === 0) {
|
|
@@ -398,7 +679,7 @@ export async function createViewStore(latDir, projectRoot, options = {}) {
|
|
|
398
679
|
process.stderr.write(`lat ui git: ${error.message}\n`);
|
|
399
680
|
}
|
|
400
681
|
}
|
|
401
|
-
const store = new ViewStore(latDir, projectRoot, realLatDir, await buildSnapshot(latDir, projectRoot, markdownFiles, codeState.files, git, 0, 0), codeState.files, codeState.scope, gitRepository, options);
|
|
682
|
+
const store = new ViewStore(latDir, projectRoot, realLatDir, await buildSnapshot(latDir, projectRoot, markdownFiles, codeState.files, git, 0, 0, options), codeState.files, codeState.scope, gitRepository, options);
|
|
402
683
|
store.startWatching();
|
|
403
684
|
return store;
|
|
404
685
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Root } from 'mdast';
|
|
2
|
+
import { type Section } from '@plebeiantech/lat.md-core/lattice-model';
|
|
3
|
+
import type { ViewDocumentError, ViewDocumentTocItem } from './protocol.js';
|
|
4
|
+
export type ViewTableOfContentsOptions = {
|
|
5
|
+
errors?: readonly ViewDocumentError[];
|
|
6
|
+
gitTree?: Root | null;
|
|
7
|
+
};
|
|
8
|
+
/** Project rendered headings into the document's local navigation. */
|
|
9
|
+
export declare function buildViewTableOfContents(sections: Section[], titles: readonly string[], options?: ViewTableOfContentsOptions): ViewDocumentTocItem[];
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { flattenSections, } from '@plebeiantech/lat.md-core/lattice-model';
|
|
2
|
+
function sectionAtLine(sections, line) {
|
|
3
|
+
let owner = null;
|
|
4
|
+
for (const section of sections) {
|
|
5
|
+
if (line < section.startLine || line > section.endLine)
|
|
6
|
+
continue;
|
|
7
|
+
if (!owner || section.depth >= owner.depth)
|
|
8
|
+
owner = section;
|
|
9
|
+
}
|
|
10
|
+
return owner;
|
|
11
|
+
}
|
|
12
|
+
function classNames(node) {
|
|
13
|
+
const value = node.data?.hProperties?.className;
|
|
14
|
+
if (Array.isArray(value))
|
|
15
|
+
return value.map(String);
|
|
16
|
+
return value ? [String(value)] : [];
|
|
17
|
+
}
|
|
18
|
+
function hasGitChanges(node) {
|
|
19
|
+
if (classNames(node).some((name) => name.startsWith('git-'))) {
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
if (!('children' in node) || !Array.isArray(node.children))
|
|
23
|
+
return false;
|
|
24
|
+
return node.children.some((child) => hasGitChanges(child));
|
|
25
|
+
}
|
|
26
|
+
function gitChangedSections(sections, tree) {
|
|
27
|
+
const changed = new Set();
|
|
28
|
+
if (!tree)
|
|
29
|
+
return changed;
|
|
30
|
+
const headingStack = [];
|
|
31
|
+
const rootSection = sections[0] ?? null;
|
|
32
|
+
for (const node of tree.children) {
|
|
33
|
+
if (node.type === 'heading') {
|
|
34
|
+
while (headingStack.length > 0 &&
|
|
35
|
+
headingStack[headingStack.length - 1].depth >= node.depth) {
|
|
36
|
+
headingStack.pop();
|
|
37
|
+
}
|
|
38
|
+
const line = node.position?.start.line;
|
|
39
|
+
const section = line
|
|
40
|
+
? (sections.find((candidate) => candidate.startLine === line && candidate.depth === node.depth) ?? null)
|
|
41
|
+
: null;
|
|
42
|
+
if (section)
|
|
43
|
+
headingStack.push(section);
|
|
44
|
+
if (hasGitChanges(node)) {
|
|
45
|
+
const owner = section ?? headingStack[headingStack.length - 1] ?? rootSection;
|
|
46
|
+
if (owner)
|
|
47
|
+
changed.add(owner.id);
|
|
48
|
+
}
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (!hasGitChanges(node))
|
|
52
|
+
continue;
|
|
53
|
+
const line = node.position?.start.line;
|
|
54
|
+
const owner = (line ? sectionAtLine(sections, line) : null) ??
|
|
55
|
+
headingStack[headingStack.length - 1] ??
|
|
56
|
+
rootSection;
|
|
57
|
+
if (owner)
|
|
58
|
+
changed.add(owner.id);
|
|
59
|
+
}
|
|
60
|
+
return changed;
|
|
61
|
+
}
|
|
62
|
+
/** Project rendered headings into the document's local navigation. */
|
|
63
|
+
export function buildViewTableOfContents(sections, titles, options = {}) {
|
|
64
|
+
const flatSections = flattenSections(sections);
|
|
65
|
+
const errorCounts = new Map();
|
|
66
|
+
for (const error of options.errors ?? []) {
|
|
67
|
+
const owner = sectionAtLine(flatSections, error.line);
|
|
68
|
+
if (owner)
|
|
69
|
+
errorCounts.set(owner.id, (errorCounts.get(owner.id) ?? 0) + 1);
|
|
70
|
+
}
|
|
71
|
+
const gitChanges = gitChangedSections(flatSections, options.gitTree);
|
|
72
|
+
return flatSections.flatMap((section, index) => section.githubSlug
|
|
73
|
+
? [
|
|
74
|
+
{
|
|
75
|
+
id: section.githubSlug,
|
|
76
|
+
title: titles[index] || section.heading,
|
|
77
|
+
depth: section.depth,
|
|
78
|
+
errorCount: errorCounts.get(section.id) ?? 0,
|
|
79
|
+
hasGitChanges: gitChanges.has(section.id),
|
|
80
|
+
},
|
|
81
|
+
]
|
|
82
|
+
: []);
|
|
83
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
type FileTraceResult = {
|
|
2
|
+
fileList: Set<string>;
|
|
3
|
+
warnings: Set<Error>;
|
|
4
|
+
};
|
|
5
|
+
export type VercelBuildDependencies = {
|
|
6
|
+
traceFiles: (files: string[], options: {
|
|
7
|
+
base: string;
|
|
8
|
+
conditions: string[];
|
|
9
|
+
exportsOnly: boolean;
|
|
10
|
+
processCwd: string;
|
|
11
|
+
}) => Promise<FileTraceResult>;
|
|
12
|
+
};
|
|
13
|
+
export type VercelBuildOptions = {
|
|
14
|
+
force?: boolean;
|
|
15
|
+
warn?: (message: string) => void;
|
|
16
|
+
};
|
|
17
|
+
export type VercelBuildResult = {
|
|
18
|
+
files: number;
|
|
19
|
+
functionPath: string;
|
|
20
|
+
outputDir: string;
|
|
21
|
+
};
|
|
22
|
+
/** Convert an installed portable Lat UI server into Vercel Build Output API v3. */
|
|
23
|
+
export declare function buildVercelOutput(requestedArtifact: string, requestedOutput?: string, options?: VercelBuildOptions, dependencies?: VercelBuildDependencies): Promise<VercelBuildResult>;
|
|
24
|
+
export {};
|