@plebeiantech/lat.md 0.12.3-fork.8 → 0.13.4-fork.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -3
- package/dist/src/cli/agent-invocation.d.ts +6 -0
- package/dist/src/cli/agent-invocation.js +23 -0
- package/dist/src/cli/checklist-menu.d.ts +2 -1
- package/dist/src/cli/checklist-menu.js +3 -2
- package/dist/src/cli/fork-instructions.d.ts +1 -0
- package/dist/src/cli/fork-instructions.js +8 -32
- package/dist/src/cli/fork-scaffold.js +2 -2
- package/dist/src/cli/graph.d.ts +1 -1
- package/dist/src/cli/hook.d.ts +26 -0
- package/dist/src/cli/hook.js +115 -64
- package/dist/src/cli/index.js +147 -70
- package/dist/src/cli/init-preferences.d.ts +4 -0
- package/dist/src/cli/init-preferences.js +36 -0
- package/dist/src/cli/init.d.ts +2 -1
- package/dist/src/cli/init.js +100 -60
- package/dist/src/cli/reindex.d.ts +1 -1
- package/dist/src/cli/reindex.js +7 -10
- package/dist/src/cli/search.d.ts +14 -4
- package/dist/src/cli/search.js +115 -101
- package/dist/src/cli/ui-build-server.d.ts +12 -0
- package/dist/src/cli/ui-build-server.js +26 -0
- package/dist/src/cli/ui-build.d.ts +1 -1
- package/dist/src/cli/ui-build.js +1 -1
- package/dist/src/cli/ui.d.ts +1 -1
- package/dist/src/cli/ui.js +1 -1
- package/dist/src/fork/antigravity-hook.d.ts +47 -0
- package/dist/src/fork/antigravity-hook.js +424 -0
- package/dist/src/fork/antigravity-init.d.ts +17 -0
- package/dist/src/fork/antigravity-init.js +124 -0
- package/dist/src/fork/upstream-drift.js +1 -1
- package/dist/src/fork/upstream-guard.d.ts +1 -1
- package/dist/src/fork/upstream-guard.js +8 -7
- package/dist/src/graph-export.js +7 -7
- package/dist/src/knowledge/index.js +2 -2
- package/dist/src/mcp/server.js +34 -18
- package/dist/src/search/cache.d.ts +3 -0
- package/dist/src/search/cache.js +104 -0
- package/dist/src/search/chunks.d.ts +23 -0
- package/dist/src/search/chunks.js +200 -0
- package/dist/src/search/db.d.ts +28 -16
- package/dist/src/search/db.js +100 -40
- package/dist/src/search/embedder.d.ts +2 -1
- package/dist/src/search/embedder.js +7 -6
- package/dist/src/search/index.d.ts +6 -2
- package/dist/src/search/index.js +176 -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 +16 -7
- package/dist/src/search/search.js +165 -21
- package/dist/src/search/types.d.ts +15 -0
- package/dist/src/view/client/assets/GraphView-D_xnk0bP.js +456 -0
- package/dist/src/view/client/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- package/dist/src/view/client/assets/MarkdownEditor-bjqt_FoF.js +28 -0
- package/dist/src/view/client/assets/OrbitControls-DwcpQNja.js +1 -0
- package/dist/src/view/client/assets/STLLoader-CLWTKt5i.js +1 -0
- package/dist/src/view/client/assets/_commonjsHelpers-CqkleIqs.js +1 -0
- package/dist/src/view/client/assets/abnfDiagram-VCTEODGH-kWGvtRnL.js +1 -0
- package/dist/src/view/client/assets/arc-BPAFd7cP.js +1 -0
- package/dist/src/view/client/assets/architectureDiagram-5GKGNRK7-CsY39oIR.js +36 -0
- package/dist/src/view/client/assets/blockDiagram-I7D4REHJ-DHGBG7BJ.js +129 -0
- package/dist/src/view/client/assets/c4Diagram-7LVT6UL2-vywK4eb7.js +38 -0
- package/dist/src/view/client/assets/channel-CX71L_qV.js +1 -0
- package/dist/src/view/client/assets/chunk-2Q5K7J3B-Do3Hz_ci.js +1 -0
- package/dist/src/view/client/assets/chunk-5VM5RSS4-B5R1lSeY.js +15 -0
- package/dist/src/view/client/assets/chunk-F27PBJKO-Dm55FM_W.js +1 -0
- package/dist/src/view/client/assets/chunk-IMKFNOWR-ChptrvvM.js +231 -0
- package/dist/src/view/client/assets/chunk-JWPE2WC7-BRQBjrKS.js +1 -0
- package/dist/src/view/client/assets/chunk-POPQ4Y6H-CainVZIL.js +1 -0
- package/dist/src/view/client/assets/chunk-SVP7TREG-DsKsNGmM.js +88 -0
- package/dist/src/view/client/assets/chunk-TICWLB2K-BctkMcJc.js +206 -0
- package/dist/src/view/client/assets/chunk-XXDRQBXY-BN7SgOUT.js +1 -0
- package/dist/src/view/client/assets/classDiagram-ZZMXUADV-B1VyU6zO.js +1 -0
- package/dist/src/view/client/assets/classDiagram-v2-VYDZK3BY-B1VyU6zO.js +1 -0
- package/dist/src/view/client/assets/cose-bilkent-JH36ORCC-BszzwrMe.js +1 -0
- package/dist/src/view/client/assets/cynefin-OW5HDTMX-CdRyAkPs.js +166 -0
- package/dist/src/view/client/assets/cynefinDiagram-5FMLGOSQ-BLvKPZ1u.js +62 -0
- package/dist/src/view/client/assets/cytoscape.esm-DzSz-X2X.js +321 -0
- package/dist/src/view/client/assets/dagre-GXQ25YYZ-V68w_l65.js +4 -0
- package/dist/src/view/client/assets/defaultLocale-DX6XiGOO.js +1 -0
- package/dist/src/view/client/assets/diagram-S7CK7UJ4-C2i4eEMg.js +30 -0
- package/dist/src/view/client/assets/diagram-UQ7AKVKN-BiwWh5jC.js +41 -0
- package/dist/src/view/client/assets/diagram-VSXAHHWV-hkKR_vyS.js +3 -0
- package/dist/src/view/client/assets/diagram-VX7I27RA-DzRCSMAc.js +24 -0
- package/dist/src/view/client/assets/diagram-Z3DM3KII-fhSFPxyK.js +24 -0
- package/dist/src/view/client/assets/ebnfDiagram-PWID7BFC-CCEUDKSA.js +1 -0
- package/dist/src/view/client/assets/erDiagram-RLTQ6QDP-FJ2IMyTi.js +99 -0
- package/dist/src/view/client/assets/flowDiagram-HODETNUW-BvasdLeK.js +168 -0
- package/dist/src/view/client/assets/ganttDiagram-EL5Y4UJY-CiwkBZvY.js +292 -0
- package/dist/src/view/client/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
- package/dist/src/view/client/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
- package/dist/src/view/client/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
- package/dist/src/view/client/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
- package/dist/src/view/client/assets/geist-mono-cyrillic-ext-wght-normal-X_5orZeX.woff2 +0 -0
- package/dist/src/view/client/assets/geist-mono-cyrillic-wght-normal-DiZS0aHC.woff2 +0 -0
- package/dist/src/view/client/assets/geist-mono-latin-ext-wght-normal-Bwz-egvJ.woff2 +0 -0
- package/dist/src/view/client/assets/geist-mono-latin-wght-normal-XN7g48iV.woff2 +0 -0
- package/dist/src/view/client/assets/geist-mono-symbols2-wght-normal-CO5SzqOn.woff2 +0 -0
- package/dist/src/view/client/assets/geist-mono-vietnamese-wght-normal-DadHysG0.woff2 +0 -0
- package/dist/src/view/client/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
- package/dist/src/view/client/assets/gitGraphDiagram-WWUBYQGX-DYlP2_js.js +106 -0
- package/dist/src/view/client/assets/index-BnENo9bV.js +1 -0
- package/dist/src/view/client/assets/index-CQ7EOox7.css +1 -0
- package/dist/src/view/client/assets/index-CynNDkxt.js +13 -0
- package/dist/src/view/client/assets/infoDiagram-27XIBGKW-DRPB2c48.js +2 -0
- package/dist/src/view/client/assets/init-Gi6I4Gst.js +1 -0
- package/dist/src/view/client/assets/ishikawaDiagram-5VMMS53U-8VV429Cv.js +70 -0
- package/dist/src/view/client/assets/journeyDiagram-3NMN7TZE-Dzmwnf83.js +139 -0
- package/dist/src/view/client/assets/kanban-definition-UXKFOSKX-pYyZZ1i-.js +89 -0
- package/dist/src/view/client/assets/katex-HP8lGamR.js +257 -0
- package/dist/src/view/client/assets/layout-GF9k6yGo.js +1 -0
- package/dist/src/view/client/assets/linear-Yt2sSOYV.js +1 -0
- package/dist/src/view/client/assets/logo-RR_KBOAT.svg +149 -0
- package/dist/src/view/client/assets/maplibre-gl-CDX6Zuow.js +800 -0
- package/dist/src/view/client/assets/mermaid.core-ChWYCHN0.js +310 -0
- package/dist/src/view/client/assets/mindmap-definition-YA3MSWOX-Cc4fQvf1.js +96 -0
- package/dist/src/view/client/assets/ordinal-Cboi1Yqb.js +1 -0
- package/dist/src/view/client/assets/pegDiagram-XKGWAZYB-C0SsB8bZ.js +1 -0
- package/dist/src/view/client/assets/pieDiagram-E7YTZNPT-DIJpqERZ.js +39 -0
- package/dist/src/view/client/assets/quadrantDiagram-AXDQQJYC--d-gl6j-.js +7 -0
- package/dist/src/view/client/assets/railroadDiagram-O6MQD6OU-BQxwTt7z.js +1 -0
- package/dist/src/view/client/assets/requirementDiagram-BXWQKSXE-B_oTeD2A.js +84 -0
- package/dist/src/view/client/assets/sankeyDiagram-P5KCCOFB-DLukmE8X.js +40 -0
- package/dist/src/view/client/assets/sequenceDiagram-WJ2MYXX4-BNjVB2sc.js +162 -0
- package/dist/src/view/client/assets/sizeCapture-INFHLROL-BZecQTOw.js +1 -0
- package/dist/src/view/client/assets/stateDiagram-D77RDMKH-Bu1urvXC.js +1 -0
- package/dist/src/view/client/assets/stateDiagram-v2-MP3YSRHH-5pc_697G.js +1 -0
- package/dist/src/view/client/assets/swimlanes-42K2YHIH-bLAlcepB.js +1 -0
- package/dist/src/view/client/assets/swimlanesDiagram-VR7AAH4N-BbOpZjpp.js +8 -0
- package/dist/src/view/client/assets/three.module-PDSP0dbZ.js +4108 -0
- package/dist/src/view/client/assets/timeline-definition-24CTP7MA-tbwCNvcA.js +120 -0
- package/dist/src/view/client/assets/vennDiagram-4TSXK5OY-D8U8Fk0N.js +34 -0
- package/dist/src/view/client/assets/wardleyDiagram-VM6X3IG4-LHBVIeNb.js +78 -0
- package/dist/src/view/client/assets/xychartDiagram-S5SC5T6Z-CN4tfaFV.js +7 -0
- package/dist/src/view/client/index.html +2 -2
- package/dist/src/view/client-shell.d.ts +2 -0
- package/dist/src/view/client-shell.js +5 -0
- package/dist/src/view/diagnostics.d.ts +3 -2
- package/dist/src/view/diagnostics.js +49 -58
- package/dist/src/view/document-edit.d.ts +8 -0
- package/dist/src/view/document-edit.js +25 -0
- package/dist/src/view/document-route.d.ts +14 -0
- package/dist/src/view/document-route.js +137 -0
- package/dist/src/view/document-tree.d.ts +18 -0
- package/dist/src/view/document-tree.js +139 -0
- package/dist/src/view/external-document-tree.d.ts +3 -0
- package/dist/src/view/external-document-tree.js +674 -0
- package/dist/src/view/git-diff.js +202 -2
- package/dist/src/view/git.js +1 -1
- package/dist/src/view/graph.d.ts +4 -3
- package/dist/src/view/graph.js +100 -9
- package/dist/src/view/highlight.d.ts +10 -2
- package/dist/src/view/highlight.js +50648 -3166
- package/dist/src/view/markdown.d.ts +3 -2
- package/dist/src/view/markdown.js +256 -54
- package/dist/src/view/preindexed-search.d.ts +15 -0
- package/dist/src/view/preindexed-search.js +25 -0
- package/dist/src/view/protocol.d.ts +53 -7
- package/dist/src/view/publication.d.ts +2 -0
- package/dist/src/view/publication.js +78 -0
- package/dist/src/view/references.d.ts +11 -26
- package/dist/src/view/references.js +121 -112
- package/dist/src/view/repository.d.ts +14 -4
- package/dist/src/view/repository.js +260 -19
- package/dist/src/view/request-security.d.ts +5 -0
- package/dist/src/view/request-security.js +46 -0
- package/dist/src/view/search-result.d.ts +4 -0
- package/dist/src/view/search-result.js +25 -0
- package/dist/src/view/search.d.ts +7 -2
- package/dist/src/view/search.js +23 -34
- package/dist/src/view/server-build.d.ts +21 -0
- package/dist/src/view/server-build.js +145 -0
- package/dist/src/view/server-deployment.d.ts +31 -0
- package/dist/src/view/server-deployment.js +123 -0
- package/dist/src/view/server-index-worker.d.ts +6 -0
- package/dist/src/view/server-index-worker.js +14 -0
- package/dist/src/view/server.d.ts +11 -2
- package/dist/src/view/server.js +245 -73
- package/dist/src/view/source-target.d.ts +2 -0
- package/dist/src/view/source-target.js +49 -8
- package/dist/src/view/static-build.d.ts +18 -2
- package/dist/src/view/static-build.js +449 -110
- package/dist/src/view/static-protocol.d.ts +26 -2
- package/dist/src/view/static-protocol.js +5 -0
- package/dist/src/view/store.d.ts +20 -3
- package/dist/src/view/store.js +304 -48
- package/dist/src/view/table-of-contents.d.ts +2 -2
- package/dist/src/view/table-of-contents.js +2 -22
- package/dist/src/view/vercel-build.d.ts +24 -0
- package/dist/src/view/vercel-build.js +152 -0
- package/dist/src/view/vercel-server-build.d.ts +10 -0
- package/dist/src/view/vercel-server-build.js +61 -0
- package/dist/vendor/lat.md-server/cli.d.ts +2 -0
- package/dist/vendor/lat.md-server/cli.js +12 -0
- package/dist/vendor/lat.md-server/index.d.ts +38 -0
- package/dist/vendor/lat.md-server/index.js +128 -0
- package/package.json +68 -22
- package/plugins/lat-md/README.md +61 -0
- package/plugins/lat-md/hooks.json +38 -0
- package/plugins/lat-md/plugin.json +9 -0
- package/plugins/lat-md/rules/AGENTS.md +344 -0
- package/plugins/lat-md/skills/lat-md/SKILL.md +210 -0
- package/plugins/lat-md/skills/lat-md-conventions/SKILL.md +226 -0
- package/templates/AGENTS.md +26 -7
- package/templates/cursor-rules.md +23 -7
- package/templates/fork/conventions.md +133 -11
- package/templates/opencode-plugin.ts +9 -9
- package/templates/pi-extension.ts +11 -11
- package/templates/skill/SKILL.md +35 -3
- package/dist/src/cli/check-coverage.d.ts +0 -2
- package/dist/src/cli/check-coverage.js +0 -71
- package/dist/src/cli/check-frontmatter.d.ts +0 -12
- package/dist/src/cli/check-frontmatter.js +0 -44
- package/dist/src/cli/check-mode.d.ts +0 -21
- package/dist/src/cli/check-mode.js +0 -364
- package/dist/src/cli/check-status.d.ts +0 -74
- package/dist/src/cli/check-status.js +0 -217
- package/dist/src/cli/check.d.ts +0 -45
- package/dist/src/cli/check.js +0 -781
- package/dist/src/cli/context.d.ts +0 -11
- package/dist/src/cli/context.js +0 -58
- package/dist/src/cli/expand.d.ts +0 -8
- package/dist/src/cli/expand.js +0 -94
- package/dist/src/cli/gen-index.d.ts +0 -45
- package/dist/src/cli/gen-index.js +0 -235
- package/dist/src/cli/link-scheme.d.ts +0 -54
- package/dist/src/cli/link-scheme.js +0 -101
- package/dist/src/cli/locate.d.ts +0 -2
- package/dist/src/cli/locate.js +0 -17
- package/dist/src/cli/refs.d.ts +0 -22
- package/dist/src/cli/refs.js +0 -229
- package/dist/src/cli/section.d.ts +0 -43
- package/dist/src/cli/section.js +0 -252
- package/dist/src/cli/select-menu.d.ts +0 -13
- package/dist/src/cli/select-menu.js +0 -100
- package/dist/src/code-refs.d.ts +0 -17
- package/dist/src/code-refs.js +0 -298
- package/dist/src/config.d.ts +0 -29
- package/dist/src/config.js +0 -83
- package/dist/src/context.d.ts +0 -23
- package/dist/src/context.js +0 -11
- package/dist/src/extensions/wiki-link/from-markdown.d.ts +0 -5
- package/dist/src/extensions/wiki-link/from-markdown.js +0 -34
- package/dist/src/extensions/wiki-link/index.d.ts +0 -4
- package/dist/src/extensions/wiki-link/index.js +0 -3
- package/dist/src/extensions/wiki-link/syntax.d.ts +0 -14
- package/dist/src/extensions/wiki-link/syntax.js +0 -121
- package/dist/src/extensions/wiki-link/to-markdown.d.ts +0 -5
- package/dist/src/extensions/wiki-link/to-markdown.js +0 -28
- package/dist/src/extensions/wiki-link/types.d.ts +0 -34
- package/dist/src/format.d.ts +0 -8
- package/dist/src/format.js +0 -43
- package/dist/src/init-version.d.ts +0 -10
- package/dist/src/init-version.js +0 -49
- package/dist/src/lattice.d.ts +0 -109
- package/dist/src/lattice.js +0 -817
- package/dist/src/parser.d.ts +0 -3
- package/dist/src/parser.js +0 -18
- package/dist/src/source-parser.d.ts +0 -27
- package/dist/src/source-parser.js +0 -916
- package/dist/src/untrusted.d.ts +0 -18
- package/dist/src/untrusted.js +0 -93
- package/dist/src/view/client/assets/index-VZwPPiFE.js +0 -334
- package/dist/src/view/client/assets/index-W8ktvNj9.css +0 -1
- package/dist/src/view/client/assets/logo-CNF8zs47.svg +0 -182
- package/dist/src/walk.d.ts +0 -18
- package/dist/src/walk.js +0 -27
- /package/dist/src/{extensions/wiki-link → search}/types.js +0 -0
|
@@ -1,23 +1,30 @@
|
|
|
1
1
|
import { readFile, realpath } from 'node:fs/promises';
|
|
2
|
-
import { dirname, extname, isAbsolute, relative, resolve, sep, } from 'node:path';
|
|
3
|
-
import { buildFileIndex, buildSectionSlugIndex, flattenSections, resolveRef, } from '
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import { dirname, extname, isAbsolute, join, posix, relative, resolve, sep, } from 'node:path';
|
|
3
|
+
import { buildFileIndex, buildSectionSlugIndex, flattenSections, resolveRef, } from '@plebeiantech/lat.md-core/lattice-model';
|
|
4
|
+
import { createExternalResolver, } from '@plebeiantech/lat.md-core/external-sources';
|
|
5
|
+
import { addExternalDocumentAliasAnchors, externalDocumentSections, } from '@plebeiantech/lat.md-core/external-documents';
|
|
6
|
+
import { resolveSourceSymbol, SourceParserRuntime, } from '@plebeiantech/lat.md-core/source-parser';
|
|
7
|
+
import { isSourceFileExtension } from '@plebeiantech/lat.md-core/source-formats';
|
|
8
|
+
import { toPosix } from '@plebeiantech/lat.md-core/path';
|
|
9
|
+
import { renderExternalDocumentTree } from './external-document-tree.js';
|
|
10
|
+
import { visitDocumentElements } from './document-tree.js';
|
|
6
11
|
import { highlightSource } from './highlight.js';
|
|
7
|
-
import {
|
|
12
|
+
import { renderMarkdown } from './markdown.js';
|
|
13
|
+
import { renderExternalSectionBackReferences, renderExternalSourceReferences, renderSourceReferenceContext, } from './references.js';
|
|
14
|
+
import { buildViewTableOfContents } from './table-of-contents.js';
|
|
8
15
|
import { viewSourceTarget } from './source-target.js';
|
|
16
|
+
import { documentUrl } from './document-route.js';
|
|
9
17
|
export class ViewDocumentNotFoundError extends Error {
|
|
10
18
|
}
|
|
11
19
|
export class ViewSourceNotFoundError extends Error {
|
|
12
20
|
}
|
|
21
|
+
export class ViewExternalNotFoundError extends Error {
|
|
22
|
+
}
|
|
13
23
|
function isInside(root, candidate) {
|
|
14
24
|
const rel = relative(root, candidate);
|
|
15
25
|
return (rel === '' ||
|
|
16
26
|
(!isAbsolute(rel) && rel !== '..' && !rel.startsWith(`..${sep}`)));
|
|
17
27
|
}
|
|
18
|
-
function documentUrl(path) {
|
|
19
|
-
return `/docs/${path.split('/').map(encodeURIComponent).join('/')}`;
|
|
20
|
-
}
|
|
21
28
|
function sourceUrl(path, symbol, origin) {
|
|
22
29
|
const encodedPath = path.split('/').map(encodeURIComponent).join('/');
|
|
23
30
|
const query = new URLSearchParams();
|
|
@@ -29,6 +36,128 @@ function sourceUrl(path, symbol, origin) {
|
|
|
29
36
|
const fragment = symbol ? `#${encodeURIComponent(symbol)}` : '';
|
|
30
37
|
return `/code/${encodedPath}${search}${fragment}`;
|
|
31
38
|
}
|
|
39
|
+
export function externalUrl(target) {
|
|
40
|
+
const colon = target.indexOf(':');
|
|
41
|
+
const hash = target.indexOf('#', colon + 1);
|
|
42
|
+
const handle = target.slice(0, colon);
|
|
43
|
+
const path = hash === -1 ? target.slice(colon + 1) : target.slice(colon + 1, hash);
|
|
44
|
+
const fragment = hash === -1 ? '' : target.slice(hash + 1);
|
|
45
|
+
const encodedPath = path.split('/').map(encodeURIComponent).join('/');
|
|
46
|
+
return `/external/${encodeURIComponent(handle)}/${encodedPath}${fragment ? `#${encodeURIComponent(fragment)}` : ''}`;
|
|
47
|
+
}
|
|
48
|
+
function baseExternalTarget(identity) {
|
|
49
|
+
const hash = identity.indexOf('#');
|
|
50
|
+
return hash === -1 ? identity : identity.slice(0, hash);
|
|
51
|
+
}
|
|
52
|
+
function externalFileKey(handle, path) {
|
|
53
|
+
return `${handle}\0${path}`;
|
|
54
|
+
}
|
|
55
|
+
function availableExternalFiles(external, referenceIndex, current) {
|
|
56
|
+
const files = new Map();
|
|
57
|
+
for (const target of referenceIndex.externalByTarget.keys()) {
|
|
58
|
+
try {
|
|
59
|
+
const parsed = external.parse(target);
|
|
60
|
+
if (!parsed)
|
|
61
|
+
continue;
|
|
62
|
+
files.set(externalFileKey(parsed.handle, parsed.resolvedPath), baseExternalTarget(parsed.identity));
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
// Invalid external references remain diagnostics and are not navigable.
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
files.set(externalFileKey(current.handle, current.resolvedPath), baseExternalTarget(current.identity));
|
|
69
|
+
return files;
|
|
70
|
+
}
|
|
71
|
+
function externalDocumentLink(href, current, external, available) {
|
|
72
|
+
if (href.startsWith('#') ||
|
|
73
|
+
href.startsWith('?') ||
|
|
74
|
+
href.startsWith('//') ||
|
|
75
|
+
/^[a-z][a-z\d+.-]*:/i.test(href) ||
|
|
76
|
+
/^\/external(?:\/|$)/.test(href)) {
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
let destination;
|
|
80
|
+
try {
|
|
81
|
+
const encodedPath = current.resolvedPath
|
|
82
|
+
.split('/')
|
|
83
|
+
.map(encodeURIComponent)
|
|
84
|
+
.join('/');
|
|
85
|
+
destination = new URL(href, `http://lat.external/${encodedPath}`);
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
if (destination.origin !== 'http://lat.external')
|
|
91
|
+
return undefined;
|
|
92
|
+
let path;
|
|
93
|
+
let fragment;
|
|
94
|
+
try {
|
|
95
|
+
path = destination.pathname
|
|
96
|
+
.slice(1)
|
|
97
|
+
.split('/')
|
|
98
|
+
.map(decodeURIComponent)
|
|
99
|
+
.join('/');
|
|
100
|
+
fragment = decodeURIComponent(destination.hash.slice(1));
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
path = posix.normalize(path);
|
|
106
|
+
if (!path || path === '.' || path === '..' || path.startsWith('../')) {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
let parsed;
|
|
110
|
+
try {
|
|
111
|
+
parsed = external.parse(`${current.handle}:${path}${fragment ? `#${fragment}` : ''}`);
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
if (!parsed)
|
|
117
|
+
return null;
|
|
118
|
+
const availableTarget = available.get(externalFileKey(parsed.handle, parsed.resolvedPath));
|
|
119
|
+
if (!availableTarget)
|
|
120
|
+
return null;
|
|
121
|
+
const route = externalUrl(`${availableTarget}${fragment ? `#${fragment}` : ''}`);
|
|
122
|
+
if (!destination.search)
|
|
123
|
+
return route;
|
|
124
|
+
const hash = route.indexOf('#');
|
|
125
|
+
return hash === -1
|
|
126
|
+
? `${route}${destination.search}`
|
|
127
|
+
: `${route.slice(0, hash)}${destination.search}${route.slice(hash)}`;
|
|
128
|
+
}
|
|
129
|
+
/** Make repository-relative external-document links reflect pulled files. */
|
|
130
|
+
export function resolveExternalDocumentLinks(tree, current, external, referenceIndex) {
|
|
131
|
+
const available = availableExternalFiles(external, referenceIndex, current);
|
|
132
|
+
visitDocumentElements(tree, (element) => {
|
|
133
|
+
if (element.tagName !== 'a')
|
|
134
|
+
return;
|
|
135
|
+
const href = element.properties.href;
|
|
136
|
+
if (typeof href !== 'string')
|
|
137
|
+
return;
|
|
138
|
+
const resolved = externalDocumentLink(href, current, external, available);
|
|
139
|
+
if (resolved === undefined)
|
|
140
|
+
return;
|
|
141
|
+
if (resolved !== null) {
|
|
142
|
+
element.properties.href = resolved;
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
const currentClasses = element.properties.className;
|
|
146
|
+
const classes = Array.isArray(currentClasses)
|
|
147
|
+
? currentClasses.map(String)
|
|
148
|
+
: typeof currentClasses === 'string'
|
|
149
|
+
? currentClasses.split(/\s+/).filter(Boolean)
|
|
150
|
+
: [];
|
|
151
|
+
element.tagName = 'span';
|
|
152
|
+
element.properties = {
|
|
153
|
+
...element.properties,
|
|
154
|
+
className: [...classes, 'external-source-link-unavailable'],
|
|
155
|
+
title: 'Linked file is not included in this Lat project',
|
|
156
|
+
};
|
|
157
|
+
delete element.properties.href;
|
|
158
|
+
});
|
|
159
|
+
return tree;
|
|
160
|
+
}
|
|
32
161
|
function matchingSymbol(symbols, symbolPath) {
|
|
33
162
|
const parts = symbolPath.split('#');
|
|
34
163
|
if (parts.length === 1) {
|
|
@@ -39,7 +168,8 @@ function matchingSymbol(symbols, symbolPath) {
|
|
|
39
168
|
}
|
|
40
169
|
return undefined;
|
|
41
170
|
}
|
|
42
|
-
export async function createMarkdownWikiLinkResolver(latDir, requestedPath, loadedSections, referenceIndex) {
|
|
171
|
+
export async function createMarkdownWikiLinkResolver(latDir, requestedPath, loadedSections, referenceIndex, externalResolver, publishable) {
|
|
172
|
+
const external = externalResolver ?? (await createExternalResolver(latDir, dirname(latDir)));
|
|
43
173
|
const projectRoot = dirname(latDir);
|
|
44
174
|
const flat = flattenSections(loadedSections);
|
|
45
175
|
const sectionIds = new Set(flat.map((section) => section.id.toLowerCase()));
|
|
@@ -51,6 +181,18 @@ export async function createMarkdownWikiLinkResolver(latDir, requestedPath, load
|
|
|
51
181
|
.filter((section) => section.filePath === currentFile)
|
|
52
182
|
.sort((a, b) => a.startLine - b.startLine);
|
|
53
183
|
return async (target, context) => {
|
|
184
|
+
try {
|
|
185
|
+
const parsed = external.parse(target);
|
|
186
|
+
if (parsed) {
|
|
187
|
+
return {
|
|
188
|
+
href: externalUrl(parsed.identity),
|
|
189
|
+
referenceCount: referenceIndex?.externalByTarget.get(parsed.identity)?.length ?? 0,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
54
196
|
const result = resolveRef(target, sectionIds, fileIndex, slugIndex);
|
|
55
197
|
if (result.ambiguous)
|
|
56
198
|
return null;
|
|
@@ -68,10 +210,10 @@ export async function createMarkdownWikiLinkResolver(latDir, requestedPath, load
|
|
|
68
210
|
};
|
|
69
211
|
}
|
|
70
212
|
const source = viewSourceTarget(target);
|
|
71
|
-
if (!source)
|
|
213
|
+
if (!source || (publishable && !(await publishable(source.path))))
|
|
72
214
|
return null;
|
|
73
215
|
try {
|
|
74
|
-
await readViewSource(projectRoot, source.path, source.symbol);
|
|
216
|
+
await readViewSource(latDir, projectRoot, source.path, source.symbol);
|
|
75
217
|
let section;
|
|
76
218
|
for (const candidate of currentSections) {
|
|
77
219
|
if (candidate.startLine > context.line)
|
|
@@ -93,11 +235,102 @@ export async function createMarkdownWikiLinkResolver(latDir, requestedPath, load
|
|
|
93
235
|
}
|
|
94
236
|
};
|
|
95
237
|
}
|
|
96
|
-
|
|
238
|
+
/** Resolve and render one configured external file through the normal view models. */
|
|
239
|
+
export async function getViewExternal(latDir, projectRoot, targetValue, external, allSections, referenceIndex, publishable) {
|
|
240
|
+
let resolved;
|
|
241
|
+
try {
|
|
242
|
+
resolved = await external.resolve(targetValue);
|
|
243
|
+
}
|
|
244
|
+
catch (error) {
|
|
245
|
+
throw new ViewExternalNotFoundError(error.message);
|
|
246
|
+
}
|
|
247
|
+
const createResolver = (path) => createMarkdownWikiLinkResolver(latDir, path, allSections, referenceIndex, external, publishable);
|
|
248
|
+
if (resolved.kind === 'document') {
|
|
249
|
+
const virtualPath = join(projectRoot, 'lat.md', '.external', resolved.target.handle, resolved.target.resolvedPath);
|
|
250
|
+
const analysis = resolved.document;
|
|
251
|
+
const sections = externalDocumentSections(virtualPath, analysis);
|
|
252
|
+
// Remote-authored wiki links may resolve only to configured external files.
|
|
253
|
+
// Do not call the local resolver before rewriting their URLs.
|
|
254
|
+
const available = availableExternalFiles(external, referenceIndex, resolved.target);
|
|
255
|
+
const resolver = async (target) => {
|
|
256
|
+
try {
|
|
257
|
+
const parsed = external.parse(target);
|
|
258
|
+
if (parsed)
|
|
259
|
+
return { href: externalUrl(parsed.identity), referenceCount: 0 };
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
return null;
|
|
263
|
+
}
|
|
264
|
+
const href = externalDocumentLink(target, resolved.target, external, available);
|
|
265
|
+
return typeof href === 'string' ? { href, referenceCount: 0 } : null;
|
|
266
|
+
};
|
|
267
|
+
const rendered = analysis.format === 'markdown'
|
|
268
|
+
? await renderMarkdown(resolved.fullContent, resolved.target.resolvedPath, resolver, {})
|
|
269
|
+
: {
|
|
270
|
+
title: analysis.title,
|
|
271
|
+
tree: await renderExternalDocumentTree(analysis.format, resolved.fullContent),
|
|
272
|
+
};
|
|
273
|
+
resolveExternalDocumentLinks(rendered.tree, resolved.target, external, referenceIndex);
|
|
274
|
+
const fragmentIndex = resolved.target.identity.indexOf('#');
|
|
275
|
+
const baseTarget = fragmentIndex === -1
|
|
276
|
+
? resolved.target.identity
|
|
277
|
+
: resolved.target.identity.slice(0, fragmentIndex);
|
|
278
|
+
const targetHeadings = new Map();
|
|
279
|
+
targetHeadings.set(baseTarget, analysis.sections[0]?.anchor ?? '');
|
|
280
|
+
for (const section of analysis.sections) {
|
|
281
|
+
for (const alias of section.aliases) {
|
|
282
|
+
const target = `${baseTarget}#${alias}`;
|
|
283
|
+
if (!targetHeadings.has(target)) {
|
|
284
|
+
targetHeadings.set(target, section.anchor);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return {
|
|
289
|
+
kind: 'markdown',
|
|
290
|
+
target: resolved.target.identity,
|
|
291
|
+
document: {
|
|
292
|
+
path: baseTarget,
|
|
293
|
+
...rendered,
|
|
294
|
+
tree: addExternalDocumentAliasAnchors(rendered.tree, analysis),
|
|
295
|
+
gitTree: null,
|
|
296
|
+
graphNodeIds: {},
|
|
297
|
+
tableOfContents: buildViewTableOfContents(sections, analysis.sections.map((section) => section.title), {
|
|
298
|
+
errors: [],
|
|
299
|
+
gitTree: null,
|
|
300
|
+
}),
|
|
301
|
+
errors: [],
|
|
302
|
+
backReferences: await renderExternalSectionBackReferences(referenceIndex, targetHeadings, latDir, projectRoot, createResolver),
|
|
303
|
+
frontmatter: { requireCodeMention: false },
|
|
304
|
+
},
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
const references = await renderExternalSourceReferences(referenceIndex, resolved.target.identity, latDir, projectRoot, createResolver);
|
|
308
|
+
return {
|
|
309
|
+
kind: 'source',
|
|
310
|
+
target: resolved.target.identity,
|
|
311
|
+
source: {
|
|
312
|
+
path: `${resolved.target.handle}:${resolved.target.authoredPath}`,
|
|
313
|
+
content: resolved.fullContent,
|
|
314
|
+
highlightedLines: highlightSource(resolved.target.resolvedPath, resolved.fullContent),
|
|
315
|
+
focus: resolved.target.fragment
|
|
316
|
+
? {
|
|
317
|
+
symbol: resolved.target.fragment,
|
|
318
|
+
kind: 'external',
|
|
319
|
+
signature: resolved.signature ?? resolved.target.fragment,
|
|
320
|
+
startLine: resolved.startLine,
|
|
321
|
+
endLine: resolved.endLine,
|
|
322
|
+
}
|
|
323
|
+
: null,
|
|
324
|
+
context: null,
|
|
325
|
+
otherReferences: references,
|
|
326
|
+
},
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
async function readViewSource(latDir, projectRoot, requestedPath, requestedSymbol = '', requestedLine = 0) {
|
|
97
330
|
if (!requestedPath ||
|
|
98
331
|
requestedPath.includes('\\') ||
|
|
99
332
|
isAbsolute(requestedPath) ||
|
|
100
|
-
!
|
|
333
|
+
(requestedSymbol && !isSourceFileExtension(extname(requestedPath)))) {
|
|
101
334
|
throw new ViewSourceNotFoundError('Source document not found');
|
|
102
335
|
}
|
|
103
336
|
const candidate = resolve(projectRoot, requestedPath);
|
|
@@ -115,7 +348,15 @@ async function readViewSource(projectRoot, requestedPath, requestedSymbol = '',
|
|
|
115
348
|
if (!isInside(realRoot, realFile)) {
|
|
116
349
|
throw new ViewSourceNotFoundError('Source document not found');
|
|
117
350
|
}
|
|
118
|
-
|
|
351
|
+
let content;
|
|
352
|
+
try {
|
|
353
|
+
content = new TextDecoder('utf-8', { fatal: true }).decode(await readFile(realFile));
|
|
354
|
+
if (content.includes('\0'))
|
|
355
|
+
throw new Error('Binary file');
|
|
356
|
+
}
|
|
357
|
+
catch {
|
|
358
|
+
throw new ViewSourceNotFoundError('Source file is not readable UTF-8 text');
|
|
359
|
+
}
|
|
119
360
|
if (!requestedSymbol) {
|
|
120
361
|
if (!requestedLine)
|
|
121
362
|
return { path: requestedPath, content, focus: null };
|
|
@@ -135,7 +376,7 @@ async function readViewSource(projectRoot, requestedPath, requestedSymbol = '',
|
|
|
135
376
|
},
|
|
136
377
|
};
|
|
137
378
|
}
|
|
138
|
-
const resolved = await resolveSourceSymbol(requestedPath, requestedSymbol, projectRoot);
|
|
379
|
+
const resolved = await resolveSourceSymbol(requestedPath, requestedSymbol, projectRoot, { latDir, runtime: new SourceParserRuntime() });
|
|
139
380
|
const symbol = resolved.found
|
|
140
381
|
? matchingSymbol(resolved.symbols, requestedSymbol)
|
|
141
382
|
: undefined;
|
|
@@ -155,14 +396,14 @@ async function readViewSource(projectRoot, requestedPath, requestedSymbol = '',
|
|
|
155
396
|
};
|
|
156
397
|
}
|
|
157
398
|
/** Read and highlight a source file after constraining it to the project root. */
|
|
158
|
-
export async function getViewSource(latDir, projectRoot, requestedPath, requestedSymbol = '', origin, requestedLine = 0, allSections = [], referenceIndex) {
|
|
159
|
-
const source = await readViewSource(projectRoot, requestedPath, requestedSymbol, requestedLine);
|
|
399
|
+
export async function getViewSource(latDir, projectRoot, requestedPath, requestedSymbol = '', origin, requestedLine = 0, allSections = [], referenceIndex, publishable) {
|
|
400
|
+
const source = await readViewSource(latDir, projectRoot, requestedPath, requestedSymbol, requestedLine);
|
|
160
401
|
const references = referenceIndex
|
|
161
|
-
? await renderSourceReferenceContext(referenceIndex, `${source.path}${requestedSymbol ? `#${requestedSymbol}` : ''}`, origin, latDir, projectRoot, (path) => createMarkdownWikiLinkResolver(latDir, path, allSections, referenceIndex))
|
|
402
|
+
? await renderSourceReferenceContext(referenceIndex, `${source.path}${requestedSymbol ? `#${requestedSymbol}` : ''}`, origin, latDir, projectRoot, (path) => createMarkdownWikiLinkResolver(latDir, path, allSections, referenceIndex, undefined, publishable))
|
|
162
403
|
: { context: null, otherReferences: [] };
|
|
163
404
|
return {
|
|
164
405
|
...source,
|
|
165
|
-
|
|
406
|
+
highlightedLines: highlightSource(source.path, source.content),
|
|
166
407
|
...references,
|
|
167
408
|
};
|
|
168
409
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { IncomingMessage } from 'node:http';
|
|
2
|
+
/** Check the actual listener authority; forwarding headers are not trusted. */
|
|
3
|
+
export declare function trustedLiveRequest(req: IncomingMessage, configuredHost: string): boolean;
|
|
4
|
+
/** Untrusted repository resources cannot execute with the editor's origin. */
|
|
5
|
+
export declare const RESOURCE_CONTENT_SECURITY_POLICY = "sandbox; default-src 'none'; img-src 'self' data:; style-src 'unsafe-inline'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'";
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const LOOPBACK_HOSTS = new Set(['localhost', '127.0.0.1', '[::1]']);
|
|
2
|
+
const urlHost = (host) => host.includes(':') && !host.startsWith('[')
|
|
3
|
+
? `[${host}]`
|
|
4
|
+
: host.toLowerCase();
|
|
5
|
+
/** Check the actual listener authority; forwarding headers are not trusted. */
|
|
6
|
+
export function trustedLiveRequest(req, configuredHost) {
|
|
7
|
+
const authority = req.headers.host;
|
|
8
|
+
if (!authority || !/^[a-z\d.\-:[\]]+$/i.test(authority))
|
|
9
|
+
return false;
|
|
10
|
+
let url;
|
|
11
|
+
try {
|
|
12
|
+
url = new URL(`http://${authority}`);
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
if (Number(url.port || 80) !== req.socket.localPort)
|
|
18
|
+
return false;
|
|
19
|
+
const host = urlHost(configuredHost);
|
|
20
|
+
const allowed = new Set([host]);
|
|
21
|
+
if (LOOPBACK_HOSTS.has(host) || host === '0.0.0.0' || host === '[::]') {
|
|
22
|
+
for (const name of LOOPBACK_HOSTS)
|
|
23
|
+
allowed.add(name);
|
|
24
|
+
if (req.socket.localAddress)
|
|
25
|
+
allowed.add(urlHost(req.socket.localAddress));
|
|
26
|
+
}
|
|
27
|
+
if (!allowed.has(url.hostname))
|
|
28
|
+
return false;
|
|
29
|
+
const origin = req.headers.origin;
|
|
30
|
+
if (origin !== undefined && origin !== url.origin)
|
|
31
|
+
return false;
|
|
32
|
+
if (!['GET', 'HEAD'].includes(req.method ?? 'GET') &&
|
|
33
|
+
req.headers['sec-fetch-site'] === 'cross-site')
|
|
34
|
+
return false;
|
|
35
|
+
// Do not accept an absolute-form URL for a different authority.
|
|
36
|
+
try {
|
|
37
|
+
if (new URL(req.url ?? '/', url).origin !== url.origin)
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
/** Untrusted repository resources cannot execute with the editor's origin. */
|
|
46
|
+
export const RESOURCE_CONTENT_SECURITY_POLICY = "sandbox; default-src 'none'; img-src 'self' data:; style-src 'unsafe-inline'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'";
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { SectionMatch } from '@plebeiantech/lat.md-core/lattice-model';
|
|
2
|
+
import type { ViewSearchResult } from './protocol.js';
|
|
3
|
+
/** Convert one graph section match into the browser search protocol. */
|
|
4
|
+
export declare function viewSearchResult(latDir: string, match: SectionMatch, documentPaths?: ReadonlyMap<string, string>): ViewSearchResult;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { dirname, relative, resolve } from 'node:path';
|
|
2
|
+
import { toPosix } from '@plebeiantech/lat.md-core/path';
|
|
3
|
+
import { documentUrl } from './document-route.js';
|
|
4
|
+
/** Convert one graph section match into the browser search protocol. */
|
|
5
|
+
export function viewSearchResult(latDir, match, documentPaths) {
|
|
6
|
+
const section = match.section;
|
|
7
|
+
const projectRoot = dirname(latDir);
|
|
8
|
+
const path = documentPaths?.get(section.id.toLowerCase()) ??
|
|
9
|
+
toPosix(relative(latDir, resolve(projectRoot, section.filePath)));
|
|
10
|
+
const fileBreadcrumbs = path.replace(/\.md$/i, '').split('/');
|
|
11
|
+
return {
|
|
12
|
+
sectionId: section.id,
|
|
13
|
+
title: section.heading,
|
|
14
|
+
path,
|
|
15
|
+
breadcrumbs: [...fileBreadcrumbs, ...section.id.split('#').slice(1)],
|
|
16
|
+
description: match.evidence?.[0]?.text ?? section.firstParagraph,
|
|
17
|
+
introduction: section.firstParagraph,
|
|
18
|
+
evidence: match.evidence ?? [],
|
|
19
|
+
semanticSimilarity: match.semanticSimilarity,
|
|
20
|
+
semanticRank: match.semanticRank,
|
|
21
|
+
lexicalRank: match.lexicalRank,
|
|
22
|
+
url: documentUrl(path, section.githubSlug ?? ''),
|
|
23
|
+
rankScore: match.rankScore ?? 0,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SectionMatch } from '
|
|
1
|
+
import type { Section, SectionMatch } from '@plebeiantech/lat.md-core/lattice-model';
|
|
2
2
|
import type { ViewSearchResponse } from './protocol.js';
|
|
3
3
|
export type ViewSearch = (query: string) => Promise<ViewSearchResponse>;
|
|
4
4
|
export type ViewSearchDependencies = {
|
|
@@ -11,4 +11,9 @@ export type ViewSearchDependencies = {
|
|
|
11
11
|
}>;
|
|
12
12
|
};
|
|
13
13
|
/** Create the lazily indexed semantic search service used by `lat ui`. */
|
|
14
|
-
export declare function createViewSearch(latDir: string, dependencies?: ViewSearchDependencies, getGeneration?: () => number
|
|
14
|
+
export declare function createViewSearch(latDir: string, dependencies?: ViewSearchDependencies, getGeneration?: () => number, options?: {
|
|
15
|
+
cacheDir?: string;
|
|
16
|
+
preindexed?: boolean;
|
|
17
|
+
sections?: readonly Section[];
|
|
18
|
+
documentPaths?: ReadonlyMap<string, string>;
|
|
19
|
+
}): ViewSearch;
|
package/dist/src/view/search.js
CHANGED
|
@@ -1,45 +1,34 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { toPosix } from '../walk.js';
|
|
1
|
+
import { viewSearchResult } from './search-result.js';
|
|
3
2
|
const VIEW_SEARCH_LIMIT = 10;
|
|
4
|
-
|
|
5
|
-
async runIndex(latDir) {
|
|
6
|
-
const { runIndex } = await import('../cli/search.js');
|
|
7
|
-
await runIndex(latDir);
|
|
8
|
-
},
|
|
9
|
-
async runSearch(latDir, query, limit, options) {
|
|
10
|
-
const { runSearch } = await import('../cli/search.js');
|
|
11
|
-
return runSearch(latDir, query, limit, undefined, options);
|
|
12
|
-
},
|
|
13
|
-
};
|
|
14
|
-
function documentUrl(path, headingId) {
|
|
15
|
-
const encodedPath = path.split('/').map(encodeURIComponent).join('/');
|
|
16
|
-
const fragment = headingId ? `#${encodeURIComponent(headingId)}` : '';
|
|
17
|
-
return `/docs/${encodedPath}${fragment}`;
|
|
18
|
-
}
|
|
19
|
-
function viewSearchResult(latDir, match) {
|
|
20
|
-
const section = match.section;
|
|
21
|
-
const projectRoot = dirname(latDir);
|
|
22
|
-
const path = toPosix(relative(latDir, resolve(projectRoot, section.filePath)));
|
|
23
|
-
const fileBreadcrumbs = path.replace(/\.md$/i, '').split('/');
|
|
3
|
+
function defaultDependencies(cacheDir, sectionById) {
|
|
24
4
|
return {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
5
|
+
async runIndex(latDir) {
|
|
6
|
+
const { runIndex } = await import('../cli/search.js');
|
|
7
|
+
await runIndex(latDir, undefined, undefined, { cacheDir });
|
|
8
|
+
},
|
|
9
|
+
async runSearch(latDir, query, limit, options) {
|
|
10
|
+
const { runSearch } = await import('../cli/search.js');
|
|
11
|
+
return runSearch(latDir, query, limit, undefined, {
|
|
12
|
+
...options,
|
|
13
|
+
cacheDir,
|
|
14
|
+
sectionById,
|
|
15
|
+
});
|
|
16
|
+
},
|
|
32
17
|
};
|
|
33
18
|
}
|
|
34
19
|
/** Create the lazily indexed semantic search service used by `lat ui`. */
|
|
35
|
-
export function createViewSearch(latDir, dependencies
|
|
20
|
+
export function createViewSearch(latDir, dependencies, getGeneration = () => 0, options = {}) {
|
|
21
|
+
const sectionById = options.sections
|
|
22
|
+
? new Map(options.sections.map((section) => [section.id.toLowerCase(), section]))
|
|
23
|
+
: undefined;
|
|
24
|
+
const resolvedDependencies = dependencies ?? defaultDependencies(options.cacheDir, sectionById);
|
|
36
25
|
let indexReady = null;
|
|
37
|
-
let indexedGeneration = -1;
|
|
26
|
+
let indexedGeneration = options.preindexed ? getGeneration() : -1;
|
|
38
27
|
const prepareIndex = async () => {
|
|
39
28
|
while (indexedGeneration < getGeneration() || indexedGeneration < 0) {
|
|
40
29
|
if (!indexReady) {
|
|
41
30
|
const generation = getGeneration();
|
|
42
|
-
indexReady =
|
|
31
|
+
indexReady = resolvedDependencies
|
|
43
32
|
.runIndex(latDir)
|
|
44
33
|
.then(() => {
|
|
45
34
|
indexedGeneration = Math.max(indexedGeneration, generation);
|
|
@@ -56,10 +45,10 @@ export function createViewSearch(latDir, dependencies = defaultDependencies, get
|
|
|
56
45
|
if (!query)
|
|
57
46
|
return { query: '', results: [] };
|
|
58
47
|
await prepareIndex();
|
|
59
|
-
const search = await
|
|
48
|
+
const search = await resolvedDependencies.runSearch(latDir, query, VIEW_SEARCH_LIMIT, { buildIndex: false });
|
|
60
49
|
return {
|
|
61
50
|
query: search.query,
|
|
62
|
-
results: search.matches.map((match) => viewSearchResult(latDir, match)),
|
|
51
|
+
results: search.matches.map((match) => viewSearchResult(latDir, match, options.documentPaths)),
|
|
63
52
|
};
|
|
64
53
|
};
|
|
65
54
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { getLatServerVersion } from '../../vendor/lat.md-server/index.js';
|
|
2
|
+
import type { CmdContext } from '@plebeiantech/lat.md-core/context';
|
|
3
|
+
import { analyzeMarkdownProject, type MarkdownProjectAnalysis } from '@plebeiantech/lat.md-core/project-analysis';
|
|
4
|
+
import { getLocalVersion } from '../version.js';
|
|
5
|
+
import { buildStaticView, type StaticViewBuildOptions, type StaticViewBuildResult } from './static-build.js';
|
|
6
|
+
export type ServerViewBuildOptions = Omit<StaticViewBuildOptions, 'searchApi'>;
|
|
7
|
+
export type ServerViewBuildResult = StaticViewBuildResult;
|
|
8
|
+
export type ServerViewBuildDependencies = {
|
|
9
|
+
analyzeMarkdownProject: typeof analyzeMarkdownProject;
|
|
10
|
+
buildStaticView: typeof buildStaticView;
|
|
11
|
+
getLocalVersion: typeof getLocalVersion;
|
|
12
|
+
getLatServerVersion: typeof getLatServerVersion;
|
|
13
|
+
getPackageVersion: typeof getPackageVersion;
|
|
14
|
+
buildSearchIndex: typeof buildServerSearchIndex;
|
|
15
|
+
};
|
|
16
|
+
/** Wait for the index process to exit so native handles cannot lock staging. */
|
|
17
|
+
export declare function buildServerSearchIndex(latDir: string, project: MarkdownProjectAnalysis, cacheDir: string): Promise<void>;
|
|
18
|
+
declare function getPackageVersion(name: string): string;
|
|
19
|
+
/** Build immutable UI data plus the small portable Express search service. */
|
|
20
|
+
export declare function buildServerView(ctx: CmdContext, requestedOutput: string, options?: ServerViewBuildOptions, dependencies?: ServerViewBuildDependencies): Promise<ServerViewBuildResult>;
|
|
21
|
+
export {};
|