@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/server.js
CHANGED
|
@@ -1,20 +1,23 @@
|
|
|
1
|
+
import { trustedLiveRequest, RESOURCE_CONTENT_SECURITY_POLICY, } from './request-security.js';
|
|
1
2
|
import { readFile } from 'node:fs/promises';
|
|
2
|
-
import {
|
|
3
|
+
import { randomUUID } from 'node:crypto';
|
|
3
4
|
import { extname, join, relative, resolve, sep } from 'node:path';
|
|
4
5
|
import { fileURLToPath } from 'node:url';
|
|
5
|
-
import {
|
|
6
|
+
import { createLatServerApp, listenLatServer, } from '../../vendor/lat.md-server/index.js';
|
|
7
|
+
import { plainStyler, } from '@plebeiantech/lat.md-core/context';
|
|
8
|
+
import { sectionCommand } from '@plebeiantech/lat.md-core/cli/section';
|
|
9
|
+
import { DEFAULT_VIEW_LOGO_TEXT, } from './protocol.js';
|
|
10
|
+
import { ViewDocumentConflictError } from './document-edit.js';
|
|
11
|
+
import { ViewExternalNotFoundError, ViewDocumentNotFoundError, ViewSourceNotFoundError, } from './repository.js';
|
|
6
12
|
import { createViewSearch } from './search.js';
|
|
7
13
|
import { createViewStore } from './store.js';
|
|
14
|
+
import { rewriteClientAssetUrls } from './client-shell.js';
|
|
15
|
+
import { documentResourcePath, documentPath, rawDocumentPath, validateDocumentRoutes, } from './document-route.js';
|
|
8
16
|
const DEFAULT_HOST = '127.0.0.1';
|
|
17
|
+
export const DEFAULT_VIEW_PORT = 4242;
|
|
18
|
+
const MAX_DOCUMENT_EDIT_BODY_BYTES = 16 * 1024 * 1024;
|
|
19
|
+
const MAX_DOCUMENT_CONTENT_LENGTH = 8 * 1024 * 1024;
|
|
9
20
|
const defaultClientDir = fileURLToPath(new URL('./client/', import.meta.url));
|
|
10
|
-
function documentUrl(path) {
|
|
11
|
-
return `/docs/${path.split('/').map(encodeURIComponent).join('/')}`;
|
|
12
|
-
}
|
|
13
|
-
function setSecurityHeaders(res) {
|
|
14
|
-
res.setHeader('Content-Security-Policy', "default-src 'self'; img-src 'self' data:; object-src 'none'; base-uri 'none'; frame-ancestors 'none'");
|
|
15
|
-
res.setHeader('Referrer-Policy', 'no-referrer');
|
|
16
|
-
res.setHeader('X-Content-Type-Options', 'nosniff');
|
|
17
|
-
}
|
|
18
21
|
function send(res, status, contentType, body, headOnly = false) {
|
|
19
22
|
res.statusCode = status;
|
|
20
23
|
res.setHeader('Content-Type', contentType);
|
|
@@ -25,6 +28,24 @@ function sendJson(res, status, value, headOnly) {
|
|
|
25
28
|
res.setHeader('Cache-Control', 'no-store');
|
|
26
29
|
send(res, status, 'application/json; charset=utf-8', JSON.stringify(value), headOnly);
|
|
27
30
|
}
|
|
31
|
+
async function readJsonBody(req) {
|
|
32
|
+
const chunks = [];
|
|
33
|
+
let size = 0;
|
|
34
|
+
for await (const value of req) {
|
|
35
|
+
const chunk = Buffer.isBuffer(value) ? value : Buffer.from(value);
|
|
36
|
+
size += chunk.byteLength;
|
|
37
|
+
if (size > MAX_DOCUMENT_EDIT_BODY_BYTES) {
|
|
38
|
+
throw new RangeError('Document edit is too large');
|
|
39
|
+
}
|
|
40
|
+
chunks.push(chunk);
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
return JSON.parse(Buffer.concat(chunks).toString('utf8'));
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
throw new SyntaxError('Document edit must be valid JSON');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
28
49
|
function contentType(path) {
|
|
29
50
|
switch (extname(path)) {
|
|
30
51
|
case '.css':
|
|
@@ -35,8 +56,17 @@ function contentType(path) {
|
|
|
35
56
|
return 'text/javascript; charset=utf-8';
|
|
36
57
|
case '.json':
|
|
37
58
|
return 'application/json; charset=utf-8';
|
|
59
|
+
case '.gif':
|
|
60
|
+
return 'image/gif';
|
|
61
|
+
case '.jpeg':
|
|
62
|
+
case '.jpg':
|
|
63
|
+
return 'image/jpeg';
|
|
64
|
+
case '.png':
|
|
65
|
+
return 'image/png';
|
|
38
66
|
case '.svg':
|
|
39
67
|
return 'image/svg+xml';
|
|
68
|
+
case '.webp':
|
|
69
|
+
return 'image/webp';
|
|
40
70
|
case '.woff2':
|
|
41
71
|
return 'font/woff2';
|
|
42
72
|
default:
|
|
@@ -69,47 +99,94 @@ async function sendClientFile(res, path, headOnly, immutable = false) {
|
|
|
69
99
|
send(res, 404, 'text/plain; charset=utf-8', 'Not found', headOnly);
|
|
70
100
|
}
|
|
71
101
|
}
|
|
72
|
-
|
|
73
|
-
|
|
102
|
+
async function sendClientShell(res, path, headOnly, entry) {
|
|
103
|
+
try {
|
|
104
|
+
const html = rewriteClientAssetUrls(await readFile(path, 'utf8'), '/');
|
|
105
|
+
const config = `<meta name="lat-live-entry" content="${encodeURIComponent(entry)}">`;
|
|
106
|
+
const body = html.includes('</head>')
|
|
107
|
+
? html.replace('</head>', `${config}</head>`)
|
|
108
|
+
: `${config}${html}`;
|
|
109
|
+
res.setHeader('Cache-Control', 'no-cache');
|
|
110
|
+
send(res, 200, 'text/html; charset=utf-8', body, headOnly);
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
if (error.code !== 'ENOENT')
|
|
114
|
+
throw error;
|
|
115
|
+
send(res, 404, 'text/plain; charset=utf-8', 'Not found', headOnly);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/** Create the portable Express application used by live Lat UI servers. */
|
|
119
|
+
export async function createViewApp(ctx, options = {}) {
|
|
74
120
|
const host = options.host ?? DEFAULT_HOST;
|
|
75
121
|
const clientDir = options.clientDir ?? defaultClientDir;
|
|
122
|
+
const logoText = options.logoText ?? DEFAULT_VIEW_LOGO_TEXT;
|
|
76
123
|
const store = await createViewStore(ctx.latDir, ctx.projectRoot, {
|
|
77
124
|
git: options.git,
|
|
125
|
+
gitPollMs: options.gitPollMs,
|
|
78
126
|
watch: options.watch,
|
|
127
|
+
externalCa: options.externalCa,
|
|
79
128
|
});
|
|
129
|
+
try {
|
|
130
|
+
validateDocumentRoutes(store.getIndex().files);
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
await store.close();
|
|
134
|
+
throw error;
|
|
135
|
+
}
|
|
80
136
|
const search = options.search ??
|
|
81
137
|
createViewSearch(ctx.latDir, undefined, () => store.markdownGeneration);
|
|
82
138
|
const eventClients = new Set();
|
|
139
|
+
const instanceId = randomUUID();
|
|
83
140
|
const broadcastChange = (change) => {
|
|
84
|
-
const message = `event: change\ndata: ${JSON.stringify(change)}\n\n`;
|
|
141
|
+
const message = `event: change\ndata: ${JSON.stringify({ ...change, instanceId })}\n\n`;
|
|
85
142
|
for (const client of eventClients)
|
|
86
143
|
client.write(message);
|
|
87
144
|
};
|
|
88
145
|
const unsubscribeStore = store.subscribe(broadcastChange);
|
|
89
|
-
const
|
|
146
|
+
const heartbeat = setInterval(() => {
|
|
147
|
+
for (const client of eventClients)
|
|
148
|
+
client.write(': heartbeat\n\n');
|
|
149
|
+
}, 15_000);
|
|
150
|
+
heartbeat.unref();
|
|
151
|
+
const handleRequest = (req, res) => {
|
|
90
152
|
void (async () => {
|
|
91
|
-
|
|
153
|
+
if (!trustedLiveRequest(req, host)) {
|
|
154
|
+
send(res, 403, 'text/plain; charset=utf-8', 'Untrusted request origin or host');
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
92
157
|
const method = req.method ?? 'GET';
|
|
93
158
|
const headOnly = method === 'HEAD';
|
|
94
|
-
|
|
159
|
+
const url = new URL(req.url ?? '/', `http://${req.headers.host}`);
|
|
160
|
+
const documentEdit = method === 'PATCH' && url.pathname === '/api/document';
|
|
161
|
+
if (method !== 'GET' && !headOnly && !documentEdit) {
|
|
95
162
|
res.setHeader('Allow', 'GET, HEAD');
|
|
96
163
|
send(res, 405, 'text/plain; charset=utf-8', 'Method not allowed');
|
|
97
164
|
return;
|
|
98
165
|
}
|
|
99
|
-
const url = new URL(req.url ?? '/', `http://${host}`);
|
|
100
166
|
if (url.pathname === '/') {
|
|
101
167
|
const entry = store.getIndex().entry;
|
|
102
168
|
if (!entry) {
|
|
103
169
|
send(res, 404, 'text/plain; charset=utf-8', 'No Markdown files found');
|
|
104
170
|
return;
|
|
105
171
|
}
|
|
106
|
-
res.
|
|
107
|
-
|
|
172
|
+
await sendClientShell(res, join(clientDir, 'index.html'), headOnly, entry);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
const index = store.getIndex();
|
|
176
|
+
const routePath = url.pathname.replace(/\/$/, '');
|
|
177
|
+
const markdownPath = documentPath(routePath);
|
|
178
|
+
if (markdownPath === index.entry) {
|
|
179
|
+
res.statusCode = 308;
|
|
180
|
+
res.setHeader('Location', `/${url.search}`);
|
|
108
181
|
res.end();
|
|
109
182
|
return;
|
|
110
183
|
}
|
|
111
184
|
if (url.pathname === '/api/index') {
|
|
112
|
-
sendJson(res, 200, store.getIndex(), headOnly);
|
|
185
|
+
sendJson(res, 200, { ...store.getIndex(), logoText }, headOnly);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
if (url.pathname === '/api/graph') {
|
|
189
|
+
sendJson(res, 200, store.getGraph(), headOnly);
|
|
113
190
|
return;
|
|
114
191
|
}
|
|
115
192
|
if (url.pathname === '/api/events') {
|
|
@@ -123,12 +200,52 @@ export async function startViewServer(ctx, options = {}) {
|
|
|
123
200
|
return;
|
|
124
201
|
}
|
|
125
202
|
eventClients.add(res);
|
|
126
|
-
res.write(`
|
|
203
|
+
res.write(`retry: 1000\nevent: ready\ndata: ${JSON.stringify({ instanceId, generation: store.snapshot.generation, markdownGeneration: store.markdownGeneration })}\n\n`);
|
|
127
204
|
req.once('close', () => eventClients.delete(res));
|
|
128
205
|
return;
|
|
129
206
|
}
|
|
130
207
|
if (url.pathname === '/api/document') {
|
|
131
208
|
const path = url.searchParams.get('path') ?? '';
|
|
209
|
+
if (documentEdit) {
|
|
210
|
+
let body;
|
|
211
|
+
try {
|
|
212
|
+
body = await readJsonBody(req);
|
|
213
|
+
}
|
|
214
|
+
catch (error) {
|
|
215
|
+
sendJson(res, error instanceof RangeError ? 413 : 400, { error: error.message }, false);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
if (!body ||
|
|
219
|
+
typeof body !== 'object' ||
|
|
220
|
+
typeof body.baseContent !==
|
|
221
|
+
'string' ||
|
|
222
|
+
typeof body.content !==
|
|
223
|
+
'string') {
|
|
224
|
+
sendJson(res, 400, {
|
|
225
|
+
error: 'Document edit content is required',
|
|
226
|
+
}, false);
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
const edit = body;
|
|
230
|
+
if (edit.baseContent.length > MAX_DOCUMENT_CONTENT_LENGTH ||
|
|
231
|
+
edit.content.length > MAX_DOCUMENT_CONTENT_LENGTH) {
|
|
232
|
+
sendJson(res, 413, { error: 'Document edit is too large' }, false);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
try {
|
|
236
|
+
sendJson(res, 200, await store.editDocument(path, edit.baseContent, edit.content), false);
|
|
237
|
+
}
|
|
238
|
+
catch (error) {
|
|
239
|
+
if (error instanceof ViewDocumentConflictError) {
|
|
240
|
+
sendJson(res, 409, { error: error.message }, false);
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
if (!(error instanceof ViewDocumentNotFoundError))
|
|
244
|
+
throw error;
|
|
245
|
+
sendJson(res, 404, { error: error.message }, false);
|
|
246
|
+
}
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
132
249
|
try {
|
|
133
250
|
sendJson(res, 200, await store.getDocument(path), headOnly);
|
|
134
251
|
}
|
|
@@ -139,6 +256,18 @@ export async function startViewServer(ctx, options = {}) {
|
|
|
139
256
|
}
|
|
140
257
|
return;
|
|
141
258
|
}
|
|
259
|
+
if (url.pathname === '/api/document-source') {
|
|
260
|
+
const path = url.searchParams.get('path') ?? '';
|
|
261
|
+
try {
|
|
262
|
+
sendJson(res, 200, await store.getDocumentSource(path), headOnly);
|
|
263
|
+
}
|
|
264
|
+
catch (error) {
|
|
265
|
+
if (!(error instanceof ViewDocumentNotFoundError))
|
|
266
|
+
throw error;
|
|
267
|
+
sendJson(res, 404, { error: error.message }, headOnly);
|
|
268
|
+
}
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
142
271
|
if (url.pathname === '/api/search') {
|
|
143
272
|
const query = (url.searchParams.get('query') ?? '').trim();
|
|
144
273
|
if (query.length > 500) {
|
|
@@ -148,6 +277,30 @@ export async function startViewServer(ctx, options = {}) {
|
|
|
148
277
|
sendJson(res, 200, await search(query), headOnly);
|
|
149
278
|
return;
|
|
150
279
|
}
|
|
280
|
+
if (url.pathname === '/api/section') {
|
|
281
|
+
const query = (url.searchParams.get('query') ?? '').trim();
|
|
282
|
+
if (!query) {
|
|
283
|
+
sendJson(res, 400, { error: 'Section ID is required' }, headOnly);
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
if (query.length > 1_000) {
|
|
287
|
+
sendJson(res, 400, { error: 'Section ID is too long' }, headOnly);
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
const result = await sectionCommand({
|
|
291
|
+
latDir: ctx.latDir,
|
|
292
|
+
projectRoot: ctx.projectRoot,
|
|
293
|
+
styler: plainStyler,
|
|
294
|
+
mode: 'cli',
|
|
295
|
+
}, query);
|
|
296
|
+
const tree = await store.renderSectionOutput(result.output, query);
|
|
297
|
+
sendJson(res, 200, {
|
|
298
|
+
output: result.output,
|
|
299
|
+
tree,
|
|
300
|
+
isError: result.isError === true,
|
|
301
|
+
}, headOnly);
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
151
304
|
if (url.pathname === '/api/source') {
|
|
152
305
|
const path = url.searchParams.get('path') ?? '';
|
|
153
306
|
const symbol = url.searchParams.get('symbol') ?? '';
|
|
@@ -170,6 +323,18 @@ export async function startViewServer(ctx, options = {}) {
|
|
|
170
323
|
}
|
|
171
324
|
return;
|
|
172
325
|
}
|
|
326
|
+
if (url.pathname === '/api/external') {
|
|
327
|
+
const target = url.searchParams.get('target') ?? '';
|
|
328
|
+
try {
|
|
329
|
+
sendJson(res, 200, await store.getExternal(target), headOnly);
|
|
330
|
+
}
|
|
331
|
+
catch (error) {
|
|
332
|
+
if (!(error instanceof ViewExternalNotFoundError))
|
|
333
|
+
throw error;
|
|
334
|
+
sendJson(res, 404, { error: error.message }, headOnly);
|
|
335
|
+
}
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
173
338
|
if (url.pathname.startsWith('/assets/')) {
|
|
174
339
|
const path = clientPath(clientDir, url.pathname);
|
|
175
340
|
if (!path) {
|
|
@@ -179,10 +344,45 @@ export async function startViewServer(ctx, options = {}) {
|
|
|
179
344
|
await sendClientFile(res, path, headOnly, true);
|
|
180
345
|
return;
|
|
181
346
|
}
|
|
347
|
+
const rawMarkdownPath = rawDocumentPath(url.pathname);
|
|
348
|
+
if (rawMarkdownPath) {
|
|
349
|
+
try {
|
|
350
|
+
const source = await store.getDocumentSource(rawMarkdownPath);
|
|
351
|
+
res.setHeader('Cache-Control', 'no-cache');
|
|
352
|
+
send(res, 200, 'text/markdown; charset=utf-8', source.content, headOnly);
|
|
353
|
+
}
|
|
354
|
+
catch (error) {
|
|
355
|
+
if (!(error instanceof ViewDocumentNotFoundError))
|
|
356
|
+
throw error;
|
|
357
|
+
send(res, 404, 'text/plain; charset=utf-8', error.message, headOnly);
|
|
358
|
+
}
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
const resourcePath = documentResourcePath(url.pathname);
|
|
362
|
+
if (resourcePath) {
|
|
363
|
+
try {
|
|
364
|
+
const body = await store.getDocumentResource(resourcePath);
|
|
365
|
+
res.setHeader('Cache-Control', 'no-cache');
|
|
366
|
+
res.setHeader('Content-Security-Policy', RESOURCE_CONTENT_SECURITY_POLICY);
|
|
367
|
+
res.setHeader('Cross-Origin-Resource-Policy', 'same-origin');
|
|
368
|
+
if (/\.(?:html?|xhtml|xml|[cm]?js)$/i.test(resourcePath)) {
|
|
369
|
+
res.setHeader('Content-Disposition', 'attachment');
|
|
370
|
+
}
|
|
371
|
+
send(res, 200, contentType(resourcePath), body, headOnly);
|
|
372
|
+
}
|
|
373
|
+
catch (error) {
|
|
374
|
+
if (!(error instanceof ViewDocumentNotFoundError))
|
|
375
|
+
throw error;
|
|
376
|
+
send(res, 404, 'text/plain; charset=utf-8', error.message, headOnly);
|
|
377
|
+
}
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
182
380
|
if (url.pathname === '/search' ||
|
|
183
|
-
url.pathname
|
|
184
|
-
|
|
185
|
-
|
|
381
|
+
url.pathname === '/graph' ||
|
|
382
|
+
(markdownPath !== null && index.files.includes(markdownPath)) ||
|
|
383
|
+
url.pathname.startsWith('/code/') ||
|
|
384
|
+
url.pathname.startsWith('/external/')) {
|
|
385
|
+
await sendClientShell(res, join(clientDir, 'index.html'), headOnly, index.entry);
|
|
186
386
|
return;
|
|
187
387
|
}
|
|
188
388
|
send(res, 404, 'text/plain; charset=utf-8', 'Not found', headOnly);
|
|
@@ -193,41 +393,44 @@ export async function startViewServer(ctx, options = {}) {
|
|
|
193
393
|
}
|
|
194
394
|
sendJson(res, 500, { error: error.message }, false);
|
|
195
395
|
});
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
await new Promise((resolveListen, reject) => {
|
|
199
|
-
server.once('error', reject);
|
|
200
|
-
server.listen(options.port ?? 0, host, () => {
|
|
201
|
-
server.off('error', reject);
|
|
202
|
-
resolveListen();
|
|
203
|
-
});
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
catch (error) {
|
|
207
|
-
unsubscribeStore();
|
|
208
|
-
await store.close();
|
|
209
|
-
throw error;
|
|
210
|
-
}
|
|
211
|
-
const address = server.address();
|
|
212
|
-
if (!address || typeof address === 'string') {
|
|
213
|
-
await new Promise((resolveClose) => server.close(() => resolveClose()));
|
|
214
|
-
unsubscribeStore();
|
|
215
|
-
await store.close();
|
|
216
|
-
throw new Error('Could not determine lat ui server address');
|
|
217
|
-
}
|
|
396
|
+
};
|
|
397
|
+
const app = createLatServerApp({ handle: handleRequest });
|
|
218
398
|
return {
|
|
219
|
-
|
|
399
|
+
app,
|
|
220
400
|
store,
|
|
221
|
-
url: `http://${host}:${address.port}/`,
|
|
222
401
|
close: async () => {
|
|
402
|
+
clearInterval(heartbeat);
|
|
223
403
|
unsubscribeStore();
|
|
224
404
|
for (const client of eventClients)
|
|
225
405
|
client.end();
|
|
226
406
|
eventClients.clear();
|
|
227
407
|
await store.close();
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
408
|
+
},
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
/** Start the loopback server used by `lat ui`. */
|
|
412
|
+
export async function startViewServer(ctx, options = {}) {
|
|
413
|
+
const host = options.host ?? DEFAULT_HOST;
|
|
414
|
+
const view = await createViewApp(ctx, options);
|
|
415
|
+
let running;
|
|
416
|
+
try {
|
|
417
|
+
const requestedPort = options.port;
|
|
418
|
+
running = await listenLatServer(view.app, {
|
|
419
|
+
host,
|
|
420
|
+
port: requestedPort ?? DEFAULT_VIEW_PORT,
|
|
421
|
+
findAvailablePort: requestedPort === undefined,
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
catch (error) {
|
|
425
|
+
await view.close();
|
|
426
|
+
throw error;
|
|
427
|
+
}
|
|
428
|
+
return {
|
|
429
|
+
server: running.server,
|
|
430
|
+
store: view.store,
|
|
431
|
+
url: running.url,
|
|
432
|
+
close: async () => {
|
|
433
|
+
await Promise.all([running.close(), view.close()]);
|
|
231
434
|
},
|
|
232
435
|
};
|
|
233
436
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Resolve ordinary code links relative to their Markdown file, not the vault root. */
|
|
2
|
+
export declare function rewriteLocalFileLink(value: string, sourcePath: string): string;
|
|
3
|
+
export type ViewSourceTarget = {
|
|
4
|
+
path: string;
|
|
5
|
+
symbol: string;
|
|
6
|
+
key: string;
|
|
7
|
+
fileKey: string;
|
|
8
|
+
};
|
|
9
|
+
/** Normalize a supported source wiki-link target for view indexes and routes. */
|
|
10
|
+
export declare function viewSourceTarget(target: string): ViewSourceTarget | null;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { extname } from 'node:path';
|
|
2
|
+
import { normalizeRepositoryPath } from '@plebeiantech/lat.md-core/repository-path';
|
|
3
|
+
import { isSourceFileExtension } from '@plebeiantech/lat.md-core/source-formats';
|
|
4
|
+
import { rewriteDocumentLink } from './document-route.js';
|
|
5
|
+
/** Resolve ordinary code links relative to their Markdown file, not the vault root. */
|
|
6
|
+
export function rewriteLocalFileLink(value, sourcePath) {
|
|
7
|
+
if (value && !/^(?:[#/]|[a-z][a-z\d+.-]*:)/i.test(value)) {
|
|
8
|
+
try {
|
|
9
|
+
// Keep a project prefix so URL normalization cannot silently clamp an
|
|
10
|
+
// escaping relative path back into the project.
|
|
11
|
+
const base = sourcePath.split('/').map(encodeURIComponent).join('/');
|
|
12
|
+
const url = new URL(value, `http://lat.local/project/lat.md/${base}`);
|
|
13
|
+
if (url.origin === 'http://lat.local' &&
|
|
14
|
+
url.pathname.startsWith('/project/')) {
|
|
15
|
+
const path = decodeURIComponent(url.pathname.slice('/project/'.length));
|
|
16
|
+
if (normalizeRepositoryPath(path) &&
|
|
17
|
+
(!path.startsWith('lat.md/') || isSourceFileExtension(extname(path)))) {
|
|
18
|
+
return `/code/${path.split('/').map(encodeURIComponent).join('/')}${url.search}${url.hash}`;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
// Malformed URLs retain the ordinary document/resource fallback.
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return rewriteDocumentLink(value, sourcePath);
|
|
27
|
+
}
|
|
28
|
+
/** Normalize a supported source wiki-link target for view indexes and routes. */
|
|
29
|
+
export function viewSourceTarget(target) {
|
|
30
|
+
const hash = target.indexOf('#');
|
|
31
|
+
const authoredPath = hash === -1 ? target : target.slice(0, hash);
|
|
32
|
+
const path = normalizeRepositoryPath(authoredPath);
|
|
33
|
+
if (!path || !isSourceFileExtension(extname(path)))
|
|
34
|
+
return null;
|
|
35
|
+
const symbol = hash === -1 ? '' : target.slice(hash + 1);
|
|
36
|
+
const fileKey = path.toLowerCase();
|
|
37
|
+
return {
|
|
38
|
+
path,
|
|
39
|
+
symbol,
|
|
40
|
+
key: `${fileKey}${symbol ? `#${symbol.toLowerCase()}` : ''}`,
|
|
41
|
+
fileKey,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { rename } from 'node:fs/promises';
|
|
2
|
+
import type { CmdContext } from '@plebeiantech/lat.md-core/context';
|
|
3
|
+
export type StaticViewBuildOptions = {
|
|
4
|
+
basePath?: string;
|
|
5
|
+
clientDir?: string;
|
|
6
|
+
codeExcludePaths?: string[];
|
|
7
|
+
force?: boolean;
|
|
8
|
+
logoText?: string;
|
|
9
|
+
externalCa?: string | Buffer;
|
|
10
|
+
searchApi?: string;
|
|
11
|
+
};
|
|
12
|
+
export type StaticViewBuildResult = {
|
|
13
|
+
documents: number;
|
|
14
|
+
outputDir: string;
|
|
15
|
+
sources: number;
|
|
16
|
+
};
|
|
17
|
+
export declare function normalizeStaticViewBasePath(value: string): string;
|
|
18
|
+
/** Convert a live view route to its physical static-directory URL. */
|
|
19
|
+
export declare function staticViewUrl(value: string, basePath: string, entryPath?: string): string;
|
|
20
|
+
/** Refuse build targets that exist or could replace the project itself. */
|
|
21
|
+
export declare function validateViewBuildOutput(outputDir: string, projectRoot: string, kind?: string, force?: boolean): Promise<void>;
|
|
22
|
+
type ViewBuildMoveDependencies = {
|
|
23
|
+
move: typeof rename;
|
|
24
|
+
wait: (milliseconds: number) => Promise<void>;
|
|
25
|
+
};
|
|
26
|
+
/** Commit a staged build after transient filesystem locks have cleared. */
|
|
27
|
+
export declare function moveViewBuildOutput(stagingDir: string, outputDir: string, dependencies?: ViewBuildMoveDependencies): Promise<void>;
|
|
28
|
+
/** Remove abandoned staging after transient filesystem locks have cleared. */
|
|
29
|
+
export declare function removeViewBuildStaging(stagingDir: string): Promise<void>;
|
|
30
|
+
/** Build a serverless snapshot of the current read-only Lat UI. */
|
|
31
|
+
export declare function buildStaticView(ctx: CmdContext, requestedOutput: string, options?: StaticViewBuildOptions): Promise<StaticViewBuildResult>;
|
|
32
|
+
export {};
|