@plebeiantech/lat.md 0.12.3-fork.17 → 0.12.3-fork.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/src/cli/agent-invocation.d.ts +6 -0
- package/dist/src/cli/agent-invocation.js +23 -0
- package/dist/src/cli/fork-instructions.js +1 -1
- package/dist/src/cli/fork-scaffold.js +2 -2
- package/dist/src/cli/graph.d.ts +1 -1
- package/dist/src/cli/hook.js +11 -11
- package/dist/src/cli/index.js +41 -59
- package/dist/src/cli/init-preferences.js +5 -4
- package/dist/src/cli/init.d.ts +1 -1
- package/dist/src/cli/init.js +54 -45
- package/dist/src/cli/reindex.d.ts +1 -1
- package/dist/src/cli/reindex.js +2 -2
- package/dist/src/cli/search.d.ts +4 -4
- package/dist/src/cli/search.js +41 -28
- package/dist/src/cli/ui-build-server.d.ts +1 -1
- package/dist/src/cli/ui-build.d.ts +1 -1
- package/dist/src/cli/ui.d.ts +1 -1
- package/dist/src/fork/antigravity-hook.js +6 -6
- package/dist/src/fork/antigravity-init.d.ts +2 -2
- package/dist/src/fork/antigravity-init.js +2 -2
- package/dist/src/graph-export.js +7 -7
- package/dist/src/knowledge/index.js +2 -2
- package/dist/src/mcp/server.js +8 -8
- package/dist/src/search/cache.d.ts +1 -1
- package/dist/src/search/cache.js +40 -7
- package/dist/src/search/chunks.d.ts +2 -2
- package/dist/src/search/db.d.ts +5 -4
- package/dist/src/search/db.js +36 -40
- package/dist/src/search/embedder.js +1 -1
- package/dist/src/search/index.d.ts +1 -1
- package/dist/src/search/index.js +2 -2
- package/dist/src/search/lock.d.ts +4 -1
- package/dist/src/search/lock.js +30 -8
- package/dist/src/search/query.d.ts +5 -2
- package/dist/src/search/query.js +55 -38
- package/dist/src/search/search.d.ts +3 -1
- package/dist/src/search/search.js +21 -12
- package/dist/src/search/types.d.ts +2 -18
- package/dist/src/view/client/assets/{GraphView-BWlRdQM4.js → GraphView-Dij8mAA_.js} +1 -1
- package/dist/src/view/client/assets/{MarkdownEditor-MW-Ck1O0.js → MarkdownEditor-88Wbt0M1.js} +1 -1
- package/dist/src/view/client/assets/{abnfDiagram-VCTEODGH-Bn3RshMV.js → abnfDiagram-VCTEODGH-y0DlYa8E.js} +1 -1
- package/dist/src/view/client/assets/{arc-En9tdFQF.js → arc-FlMu8dnO.js} +1 -1
- package/dist/src/view/client/assets/{architectureDiagram-5GKGNRK7-B-9J1VAM.js → architectureDiagram-5GKGNRK7-DA_uWZW1.js} +1 -1
- package/dist/src/view/client/assets/{blockDiagram-I7D4REHJ-QlznwalP.js → blockDiagram-I7D4REHJ-BHQ5LU85.js} +1 -1
- package/dist/src/view/client/assets/{c4Diagram-7LVT6UL2-Bp2y8B4_.js → c4Diagram-7LVT6UL2-BRucKCt2.js} +1 -1
- package/dist/src/view/client/assets/channel-BgDNA_Ay.js +1 -0
- package/dist/src/view/client/assets/{chunk-2Q5K7J3B-CnBKL-lm.js → chunk-2Q5K7J3B-BJPcFivt.js} +1 -1
- package/dist/src/view/client/assets/{chunk-5VM5RSS4-LLYMi_n6.js → chunk-5VM5RSS4-v2q99bGz.js} +1 -1
- package/dist/src/view/client/assets/{chunk-F27PBJKO-VIeO7VF0.js → chunk-F27PBJKO-CcHOuJCs.js} +1 -1
- package/dist/src/view/client/assets/{chunk-IMKFNOWR-D5i67DVD.js → chunk-IMKFNOWR-DNxYuJNq.js} +1 -1
- package/dist/src/view/client/assets/{chunk-JWPE2WC7-D4qAtoL3.js → chunk-JWPE2WC7-C0eHKvLW.js} +1 -1
- package/dist/src/view/client/assets/{chunk-POPQ4Y6H-BMzOyiW_.js → chunk-POPQ4Y6H-57CWp2Ve.js} +1 -1
- package/dist/src/view/client/assets/{chunk-SVP7TREG-DWy5nbfp.js → chunk-SVP7TREG-BqcoxIJw.js} +1 -1
- package/dist/src/view/client/assets/{chunk-TICWLB2K-CVqCANFB.js → chunk-TICWLB2K-DRUJR5zH.js} +1 -1
- package/dist/src/view/client/assets/{chunk-XXDRQBXY-Bp23h6Tf.js → chunk-XXDRQBXY-Dez0oRoM.js} +1 -1
- package/dist/src/view/client/assets/classDiagram-ZZMXUADV-CFZ_Sgh5.js +1 -0
- package/dist/src/view/client/assets/classDiagram-v2-VYDZK3BY-CFZ_Sgh5.js +1 -0
- package/dist/src/view/client/assets/{cose-bilkent-JH36ORCC-BCw7fCC2.js → cose-bilkent-JH36ORCC-BHtud6Hg.js} +1 -1
- package/dist/src/view/client/assets/{cynefin-OW5HDTMX--lYN4N9m.js → cynefin-OW5HDTMX-BjBW8VGk.js} +1 -1
- package/dist/src/view/client/assets/{cynefinDiagram-5FMLGOSQ-9sK5EV7v.js → cynefinDiagram-5FMLGOSQ-DwGuD7oF.js} +1 -1
- package/dist/src/view/client/assets/{dagre-GXQ25YYZ-CoMdEFCq.js → dagre-GXQ25YYZ-C5zSlGK9.js} +1 -1
- package/dist/src/view/client/assets/{diagram-S7CK7UJ4-D13dyWdd.js → diagram-S7CK7UJ4-C_NhA3bj.js} +1 -1
- package/dist/src/view/client/assets/{diagram-UQ7AKVKN-PdwLPPPA.js → diagram-UQ7AKVKN-az7QPYNb.js} +1 -1
- package/dist/src/view/client/assets/{diagram-VSXAHHWV-CtWWa_A7.js → diagram-VSXAHHWV-BRvDuM8_.js} +1 -1
- package/dist/src/view/client/assets/{diagram-VX7I27RA-BeCYcSU-.js → diagram-VX7I27RA-BWLgF6S-.js} +1 -1
- package/dist/src/view/client/assets/{diagram-Z3DM3KII-DiWabOBM.js → diagram-Z3DM3KII-DV3d6mL5.js} +1 -1
- package/dist/src/view/client/assets/{ebnfDiagram-PWID7BFC-CZQ3MD_K.js → ebnfDiagram-PWID7BFC-yUXrEAvK.js} +1 -1
- package/dist/src/view/client/assets/{erDiagram-RLTQ6QDP-B1AhXIrP.js → erDiagram-RLTQ6QDP-D35FN1Pt.js} +1 -1
- package/dist/src/view/client/assets/{flowDiagram-HODETNUW-Bhr0JM6P.js → flowDiagram-HODETNUW-BciZqsjT.js} +1 -1
- package/dist/src/view/client/assets/{ganttDiagram-EL5Y4UJY-CbP8iAkg.js → ganttDiagram-EL5Y4UJY-BysPGgXS.js} +1 -1
- package/dist/src/view/client/assets/{gitGraphDiagram-WWUBYQGX-B9uuGdLF.js → gitGraphDiagram-WWUBYQGX-C3DdJ5xG.js} +1 -1
- package/dist/src/view/client/assets/index-CJokoRSp.js +13 -0
- package/dist/src/view/client/assets/{infoDiagram-27XIBGKW-BrfwQ_Cq.js → infoDiagram-27XIBGKW-D3HZrDRb.js} +1 -1
- package/dist/src/view/client/assets/{ishikawaDiagram-5VMMS53U-CHtJ36re.js → ishikawaDiagram-5VMMS53U-BXyVIXTU.js} +1 -1
- package/dist/src/view/client/assets/{journeyDiagram-3NMN7TZE-BChcgX1s.js → journeyDiagram-3NMN7TZE-D4-1NxVU.js} +1 -1
- package/dist/src/view/client/assets/{kanban-definition-UXKFOSKX-BnwFsKiB.js → kanban-definition-UXKFOSKX-4Gu_5yBA.js} +1 -1
- package/dist/src/view/client/assets/{layout-Dnd0pLdb.js → layout-Jf1K3TMM.js} +1 -1
- package/dist/src/view/client/assets/{linear-CFhW2ozn.js → linear-DWfwzUT_.js} +1 -1
- package/dist/src/view/client/assets/{mermaid.core--OP6lXtW.js → mermaid.core-DMx_DAl8.js} +5 -5
- package/dist/src/view/client/assets/{mindmap-definition-YA3MSWOX-D51y2zbm.js → mindmap-definition-YA3MSWOX-8pxY_RWi.js} +1 -1
- package/dist/src/view/client/assets/{pegDiagram-XKGWAZYB--zyQJDvI.js → pegDiagram-XKGWAZYB-DNAw_O5t.js} +1 -1
- package/dist/src/view/client/assets/{pieDiagram-E7YTZNPT-Cj8mvpJy.js → pieDiagram-E7YTZNPT-uuvRCDkC.js} +1 -1
- package/dist/src/view/client/assets/{quadrantDiagram-AXDQQJYC-qvhJrnBf.js → quadrantDiagram-AXDQQJYC-BER2O4Aq.js} +1 -1
- package/dist/src/view/client/assets/{railroadDiagram-O6MQD6OU-CtWvxpSo.js → railroadDiagram-O6MQD6OU-CxEsJ_0n.js} +1 -1
- package/dist/src/view/client/assets/{requirementDiagram-BXWQKSXE-CBxen_KG.js → requirementDiagram-BXWQKSXE-yS9rspca.js} +1 -1
- package/dist/src/view/client/assets/{sankeyDiagram-P5KCCOFB-B_fUkmfc.js → sankeyDiagram-P5KCCOFB-Bqt70a2j.js} +1 -1
- package/dist/src/view/client/assets/{sequenceDiagram-WJ2MYXX4-Dclv4p68.js → sequenceDiagram-WJ2MYXX4-BvOOEJNr.js} +1 -1
- package/dist/src/view/client/assets/{sizeCapture-INFHLROL-GfG0sMTZ.js → sizeCapture-INFHLROL-CvO_Pjjo.js} +1 -1
- package/dist/src/view/client/assets/{stateDiagram-D77RDMKH-YQWPnzxU.js → stateDiagram-D77RDMKH-KLmVOZkq.js} +1 -1
- package/dist/src/view/client/assets/stateDiagram-v2-MP3YSRHH-KCS8Mdzu.js +1 -0
- package/dist/src/view/client/assets/{swimlanes-42K2YHIH-5yiCveVS.js → swimlanes-42K2YHIH-DC1r4_sq.js} +1 -1
- package/dist/src/view/client/assets/swimlanesDiagram-VR7AAH4N-B2TcAwis.js +8 -0
- package/dist/src/view/client/assets/{timeline-definition-24CTP7MA-BvAbB5Zs.js → timeline-definition-24CTP7MA-ChXLOuBL.js} +1 -1
- package/dist/src/view/client/assets/{vennDiagram-4TSXK5OY-guC-r60n.js → vennDiagram-4TSXK5OY-D9_h25-Y.js} +1 -1
- package/dist/src/view/client/assets/{wardleyDiagram-VM6X3IG4-C0yXcU2x.js → wardleyDiagram-VM6X3IG4-CsQJGGW0.js} +1 -1
- package/dist/src/view/client/assets/{xychartDiagram-S5SC5T6Z-RPmkPNfK.js → xychartDiagram-S5SC5T6Z-DGMuPMlm.js} +1 -1
- package/dist/src/view/client/index.html +1 -1
- package/dist/src/view/diagnostics.d.ts +2 -2
- package/dist/src/view/diagnostics.js +5 -5
- package/dist/src/view/external-document-tree.js +1 -1
- package/dist/src/view/git-diff.js +1 -1
- package/dist/src/view/git.js +1 -1
- package/dist/src/view/graph.d.ts +2 -2
- package/dist/src/view/graph.js +2 -2
- package/dist/src/view/markdown.js +1 -1
- package/dist/src/view/preindexed-search.d.ts +1 -1
- package/dist/src/view/protocol.d.ts +2 -18
- package/dist/src/view/publication.d.ts +2 -0
- package/dist/src/view/publication.js +78 -0
- package/dist/src/view/references.d.ts +3 -3
- package/dist/src/view/references.js +3 -3
- package/dist/src/view/repository.d.ts +6 -6
- package/dist/src/view/repository.js +28 -14
- 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 +1 -1
- package/dist/src/view/search-result.js +1 -1
- package/dist/src/view/search.d.ts +1 -1
- package/dist/src/view/server-build.d.ts +2 -2
- package/dist/src/view/server-build.js +2 -2
- package/dist/src/view/server-deployment.d.ts +1 -2
- package/dist/src/view/server-deployment.js +6 -46
- package/dist/src/view/server-index-worker.d.ts +1 -1
- package/dist/src/view/server.d.ts +1 -1
- package/dist/src/view/server.js +13 -3
- package/dist/src/view/source-target.js +2 -2
- package/dist/src/view/static-build.d.ts +1 -1
- package/dist/src/view/static-build.js +49 -17
- package/dist/src/view/store.d.ts +4 -2
- package/dist/src/view/store.js +31 -19
- package/dist/src/view/table-of-contents.d.ts +1 -1
- package/dist/src/view/table-of-contents.js +1 -1
- package/dist/src/view/vercel-server-build.d.ts +1 -1
- package/package.json +19 -29
- package/templates/AGENTS.md +2 -2
- package/templates/cursor-rules.md +2 -2
- package/templates/opencode-plugin.ts +9 -9
- package/templates/pi-extension.ts +11 -11
- package/templates/skill/SKILL.md +2 -1
- package/dist/src/cli/check-context.d.ts +0 -56
- package/dist/src/cli/check-context.js +0 -215
- package/dist/src/cli/check-coverage.d.ts +0 -2
- package/dist/src/cli/check-coverage.js +0 -75
- 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 -394
- 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 -52
- package/dist/src/cli/check.js +0 -834
- 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 -7
- package/dist/src/cli/expand.js +0 -141
- package/dist/src/cli/external.d.ts +0 -11
- package/dist/src/cli/external.js +0 -185
- 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 -18
- package/dist/src/cli/refs.d.ts +0 -23
- package/dist/src/cli/refs.js +0 -274
- package/dist/src/cli/section.d.ts +0 -45
- package/dist/src/cli/section.js +0 -328
- 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 -29
- package/dist/src/code-refs.js +0 -479
- package/dist/src/config.d.ts +0 -29
- package/dist/src/config.js +0 -83
- package/dist/src/context.d.ts +0 -26
- package/dist/src/context.js +0 -11
- package/dist/src/document-formats.d.ts +0 -7
- package/dist/src/document-formats.js +0 -39
- package/dist/src/extensions/alert-marker.d.ts +0 -25
- package/dist/src/extensions/alert-marker.js +0 -55
- 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/extensions/wiki-link/types.js +0 -1
- package/dist/src/external-documents.d.ts +0 -56
- package/dist/src/external-documents.js +0 -404
- package/dist/src/external-sources.d.ts +0 -136
- package/dist/src/external-sources.js +0 -1098
- package/dist/src/fork/frontmatter-fields.d.ts +0 -36
- package/dist/src/fork/frontmatter-fields.js +0 -23
- package/dist/src/format.d.ts +0 -16
- package/dist/src/format.js +0 -76
- package/dist/src/init-version.d.ts +0 -10
- package/dist/src/init-version.js +0 -49
- package/dist/src/lattice-model.d.ts +0 -84
- package/dist/src/lattice-model.js +0 -467
- package/dist/src/lattice.d.ts +0 -14
- package/dist/src/lattice.js +0 -353
- package/dist/src/markdown-analysis-cache.d.ts +0 -20
- package/dist/src/markdown-analysis-cache.js +0 -139
- package/dist/src/markdown-analysis-worker.d.ts +0 -16
- package/dist/src/markdown-analysis-worker.js +0 -33
- package/dist/src/markdown-analysis.d.ts +0 -61
- package/dist/src/markdown-analysis.js +0 -169
- package/dist/src/markdown-analyzer-loader.d.ts +0 -4
- package/dist/src/markdown-analyzer-loader.js +0 -13
- package/dist/src/markdown-validation.d.ts +0 -25
- package/dist/src/markdown-validation.js +0 -104
- package/dist/src/parser-cache.d.ts +0 -17
- package/dist/src/parser-cache.js +0 -65
- package/dist/src/parser-import.d.ts +0 -8
- package/dist/src/parser-import.js +0 -1
- package/dist/src/parser.d.ts +0 -3
- package/dist/src/parser.js +0 -93
- package/dist/src/path.d.ts +0 -2
- package/dist/src/path.js +0 -4
- package/dist/src/profiler.d.ts +0 -16
- package/dist/src/profiler.js +0 -81
- package/dist/src/project-analysis.d.ts +0 -59
- package/dist/src/project-analysis.js +0 -233
- package/dist/src/project-discovery.d.ts +0 -6
- package/dist/src/project-discovery.js +0 -30
- package/dist/src/repository-path.d.ts +0 -11
- package/dist/src/repository-path.js +0 -52
- package/dist/src/source-formats.d.ts +0 -7
- package/dist/src/source-formats.js +0 -30
- package/dist/src/source-parser.d.ts +0 -67
- package/dist/src/source-parser.js +0 -1749
- package/dist/src/untrusted.d.ts +0 -18
- package/dist/src/untrusted.js +0 -93
- package/dist/src/view/client/assets/channel-uy0fFvcW.js +0 -1
- package/dist/src/view/client/assets/classDiagram-ZZMXUADV-DbSEqjA5.js +0 -1
- package/dist/src/view/client/assets/classDiagram-v2-VYDZK3BY-DbSEqjA5.js +0 -1
- package/dist/src/view/client/assets/index-nBmbYfun.js +0 -13
- package/dist/src/view/client/assets/stateDiagram-v2-MP3YSRHH-gUj6Hzgl.js +0 -1
- package/dist/src/view/client/assets/swimlanesDiagram-VR7AAH4N-DR7JhrxL.js +0 -8
- package/dist/src/walk.d.ts +0 -20
- package/dist/src/walk.js +0 -121
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { readFile, realpath } from 'node:fs/promises';
|
|
2
2
|
import { dirname, extname, isAbsolute, join, posix, relative, resolve, sep, } from 'node:path';
|
|
3
|
-
import { buildFileIndex, buildSectionSlugIndex, flattenSections, resolveRef, } from '
|
|
4
|
-
import { createExternalResolver, } from '
|
|
5
|
-
import { addExternalDocumentAliasAnchors, externalDocumentSections, } from '
|
|
6
|
-
import { resolveSourceSymbol, SourceParserRuntime, } from '
|
|
7
|
-
import { isSourceFileExtension } from '
|
|
8
|
-
import { toPosix } from '
|
|
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
9
|
import { renderExternalDocumentTree } from './external-document-tree.js';
|
|
10
10
|
import { visitDocumentElements } from './document-tree.js';
|
|
11
11
|
import { highlightSource } from './highlight.js';
|
|
@@ -73,7 +73,7 @@ function externalDocumentLink(href, current, external, available) {
|
|
|
73
73
|
href.startsWith('?') ||
|
|
74
74
|
href.startsWith('//') ||
|
|
75
75
|
/^[a-z][a-z\d+.-]*:/i.test(href) ||
|
|
76
|
-
/^\/
|
|
76
|
+
/^\/external(?:\/|$)/.test(href)) {
|
|
77
77
|
return undefined;
|
|
78
78
|
}
|
|
79
79
|
let destination;
|
|
@@ -168,7 +168,7 @@ function matchingSymbol(symbols, symbolPath) {
|
|
|
168
168
|
}
|
|
169
169
|
return undefined;
|
|
170
170
|
}
|
|
171
|
-
export async function createMarkdownWikiLinkResolver(latDir, requestedPath, loadedSections, referenceIndex, externalResolver) {
|
|
171
|
+
export async function createMarkdownWikiLinkResolver(latDir, requestedPath, loadedSections, referenceIndex, externalResolver, publishable) {
|
|
172
172
|
const external = externalResolver ?? (await createExternalResolver(latDir, dirname(latDir)));
|
|
173
173
|
const projectRoot = dirname(latDir);
|
|
174
174
|
const flat = flattenSections(loadedSections);
|
|
@@ -210,7 +210,7 @@ export async function createMarkdownWikiLinkResolver(latDir, requestedPath, load
|
|
|
210
210
|
};
|
|
211
211
|
}
|
|
212
212
|
const source = viewSourceTarget(target);
|
|
213
|
-
if (!source)
|
|
213
|
+
if (!source || (publishable && !(await publishable(source.path))))
|
|
214
214
|
return null;
|
|
215
215
|
try {
|
|
216
216
|
await readViewSource(latDir, projectRoot, source.path, source.symbol);
|
|
@@ -236,7 +236,7 @@ export async function createMarkdownWikiLinkResolver(latDir, requestedPath, load
|
|
|
236
236
|
};
|
|
237
237
|
}
|
|
238
238
|
/** Resolve and render one configured external file through the normal view models. */
|
|
239
|
-
export async function getViewExternal(latDir, projectRoot, targetValue, external, allSections, referenceIndex) {
|
|
239
|
+
export async function getViewExternal(latDir, projectRoot, targetValue, external, allSections, referenceIndex, publishable) {
|
|
240
240
|
let resolved;
|
|
241
241
|
try {
|
|
242
242
|
resolved = await external.resolve(targetValue);
|
|
@@ -244,12 +244,26 @@ export async function getViewExternal(latDir, projectRoot, targetValue, external
|
|
|
244
244
|
catch (error) {
|
|
245
245
|
throw new ViewExternalNotFoundError(error.message);
|
|
246
246
|
}
|
|
247
|
-
const createResolver = (path) => createMarkdownWikiLinkResolver(latDir, path, allSections, referenceIndex, external);
|
|
247
|
+
const createResolver = (path) => createMarkdownWikiLinkResolver(latDir, path, allSections, referenceIndex, external, publishable);
|
|
248
248
|
if (resolved.kind === 'document') {
|
|
249
249
|
const virtualPath = join(projectRoot, 'lat.md', '.external', resolved.target.handle, resolved.target.resolvedPath);
|
|
250
250
|
const analysis = resolved.document;
|
|
251
251
|
const sections = externalDocumentSections(virtualPath, analysis);
|
|
252
|
-
|
|
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
|
+
};
|
|
253
267
|
const rendered = analysis.format === 'markdown'
|
|
254
268
|
? await renderMarkdown(resolved.fullContent, resolved.target.resolvedPath, resolver, {})
|
|
255
269
|
: {
|
|
@@ -382,10 +396,10 @@ async function readViewSource(latDir, projectRoot, requestedPath, requestedSymbo
|
|
|
382
396
|
};
|
|
383
397
|
}
|
|
384
398
|
/** Read and highlight a source file after constraining it to the project root. */
|
|
385
|
-
export async function getViewSource(latDir, projectRoot, requestedPath, requestedSymbol = '', origin, requestedLine = 0, allSections = [], referenceIndex) {
|
|
399
|
+
export async function getViewSource(latDir, projectRoot, requestedPath, requestedSymbol = '', origin, requestedLine = 0, allSections = [], referenceIndex, publishable) {
|
|
386
400
|
const source = await readViewSource(latDir, projectRoot, requestedPath, requestedSymbol, requestedLine);
|
|
387
401
|
const references = referenceIndex
|
|
388
|
-
? 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))
|
|
389
403
|
: { context: null, otherReferences: [] };
|
|
390
404
|
return {
|
|
391
405
|
...source,
|
|
@@ -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'";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SectionMatch } from '
|
|
1
|
+
import type { SectionMatch } from '@plebeiantech/lat.md-core/lattice-model';
|
|
2
2
|
import type { ViewSearchResult } from './protocol.js';
|
|
3
3
|
/** Convert one graph section match into the browser search protocol. */
|
|
4
4
|
export declare function viewSearchResult(latDir: string, match: SectionMatch, documentPaths?: ReadonlyMap<string, string>): ViewSearchResult;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { dirname, relative, resolve } from 'node:path';
|
|
2
|
-
import { toPosix } from '
|
|
2
|
+
import { toPosix } from '@plebeiantech/lat.md-core/path';
|
|
3
3
|
import { documentUrl } from './document-route.js';
|
|
4
4
|
/** Convert one graph section match into the browser search protocol. */
|
|
5
5
|
export function viewSearchResult(latDir, match, documentPaths) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Section, 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 = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getLatServerVersion } from '../../vendor/lat.md-server/index.js';
|
|
2
|
-
import type { CmdContext } from '
|
|
3
|
-
import { analyzeMarkdownProject, type MarkdownProjectAnalysis } from '
|
|
2
|
+
import type { CmdContext } from '@plebeiantech/lat.md-core/context';
|
|
3
|
+
import { analyzeMarkdownProject, type MarkdownProjectAnalysis } from '@plebeiantech/lat.md-core/project-analysis';
|
|
4
4
|
import { getLocalVersion } from '../version.js';
|
|
5
5
|
import { buildStaticView, type StaticViewBuildOptions, type StaticViewBuildResult } from './static-build.js';
|
|
6
6
|
export type ServerViewBuildOptions = Omit<StaticViewBuildOptions, 'searchApi'>;
|
|
@@ -4,9 +4,9 @@ import { mkdtemp, mkdir, rm, writeFile } from 'node:fs/promises';
|
|
|
4
4
|
import { dirname, join, relative, resolve } from 'node:path';
|
|
5
5
|
import { fileURLToPath } from 'node:url';
|
|
6
6
|
import { getLatServerVersion } from '../../vendor/lat.md-server/index.js';
|
|
7
|
-
import { analyzeMarkdownProject, } from '
|
|
7
|
+
import { analyzeMarkdownProject, } from '@plebeiantech/lat.md-core/project-analysis';
|
|
8
8
|
import { getLocalVersion } from '../version.js';
|
|
9
|
-
import { toPosix } from '
|
|
9
|
+
import { toPosix } from '@plebeiantech/lat.md-core/path';
|
|
10
10
|
import { buildStaticView, moveViewBuildOutput, removeViewBuildStaging, normalizeStaticViewBasePath, validateViewBuildOutput, } from './static-build.js';
|
|
11
11
|
import { SERVER_VIEW_SCHEMA_VERSION, } from './server-deployment.js';
|
|
12
12
|
const defaultDependencies = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type LatServerApp } from '../../vendor/lat.md-server/index.js';
|
|
2
2
|
import type { Express } from 'express';
|
|
3
|
-
import type { Section } from '
|
|
3
|
+
import type { Section } from '@plebeiantech/lat.md-core/lattice-model';
|
|
4
4
|
import type { CreateSearchEngine } from '../search/embedder.js';
|
|
5
5
|
import type { ViewSearchResponse } from './protocol.js';
|
|
6
6
|
export declare const SERVER_VIEW_SCHEMA_VERSION = 1;
|
|
@@ -16,7 +16,6 @@ export type ServerViewAppOptions = {
|
|
|
16
16
|
app: Express;
|
|
17
17
|
manifestFile: string | URL;
|
|
18
18
|
indexFile: string | URL;
|
|
19
|
-
cacheDir?: string | URL;
|
|
20
19
|
createSearchEngine?: CreateSearchEngine;
|
|
21
20
|
search?: (query: string) => Promise<ViewSearchResponse>;
|
|
22
21
|
};
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { INDEX_FILE } from '../search/db.js';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { dirname, join, resolve } from 'node:path';
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
|
+
import { basename, dirname, resolve } from 'node:path';
|
|
5
4
|
import { fileURLToPath } from 'node:url';
|
|
6
5
|
import { createLatServerApp } from '../../vendor/lat.md-server/index.js';
|
|
7
6
|
import { createPreindexedViewSearch, } from './preindexed-search.js';
|
|
@@ -29,66 +28,27 @@ async function readManifest(path) {
|
|
|
29
28
|
}
|
|
30
29
|
return manifest;
|
|
31
30
|
}
|
|
32
|
-
/** Native SQLite handles may outlive close until the Windows process exits. */
|
|
33
|
-
async function removeRuntimeCache(path) {
|
|
34
|
-
try {
|
|
35
|
-
await rm(path, {
|
|
36
|
-
recursive: true,
|
|
37
|
-
force: true,
|
|
38
|
-
maxRetries: 10,
|
|
39
|
-
retryDelay: 150,
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
catch (error) {
|
|
43
|
-
const code = error.code;
|
|
44
|
-
if (process.platform !== 'win32' ||
|
|
45
|
-
(code !== 'EBUSY' && code !== 'EPERM' && code !== 'ENOTEMPTY')) {
|
|
46
|
-
throw error;
|
|
47
|
-
}
|
|
48
|
-
// This is an owned OS-temp copy, never the deployed index or user data.
|
|
49
|
-
// A lingering native lock must not fail otherwise successful shutdown.
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
31
|
async function prepareServerView(options, manifestFile, indexFile) {
|
|
53
32
|
const manifest = await readManifest(manifestFile);
|
|
54
|
-
let runtimeCacheDir = options.cacheDir ? localPath(options.cacheDir) : '';
|
|
55
|
-
let ownsCache = false;
|
|
56
33
|
let search = options.search;
|
|
57
34
|
let ownedSearch;
|
|
58
35
|
if (!search) {
|
|
59
|
-
if (
|
|
60
|
-
|
|
61
|
-
ownsCache = true;
|
|
62
|
-
}
|
|
63
|
-
await mkdir(runtimeCacheDir, { recursive: true });
|
|
64
|
-
try {
|
|
65
|
-
await copyFile(indexFile, join(runtimeCacheDir, INDEX_FILE));
|
|
66
|
-
}
|
|
67
|
-
catch (error) {
|
|
68
|
-
if (ownsCache) {
|
|
69
|
-
await removeRuntimeCache(runtimeCacheDir);
|
|
70
|
-
}
|
|
71
|
-
throw error;
|
|
36
|
+
if (basename(indexFile) !== INDEX_FILE) {
|
|
37
|
+
throw new Error(`Server search index must be named ${INDEX_FILE}: ${indexFile}`);
|
|
72
38
|
}
|
|
73
39
|
const documentPaths = new Map();
|
|
74
40
|
const sections = manifest.sections.map(({ documentPath, ...section }) => {
|
|
75
41
|
documentPaths.set(section.id.toLowerCase(), documentPath);
|
|
76
42
|
return { ...section, children: [] };
|
|
77
43
|
});
|
|
78
|
-
ownedSearch = await createPreindexedViewSearch(dirname(indexFile),
|
|
44
|
+
ownedSearch = await createPreindexedViewSearch(dirname(indexFile), dirname(indexFile), sections, documentPaths, undefined, options.createSearchEngine);
|
|
79
45
|
search = ownedSearch;
|
|
80
46
|
}
|
|
81
47
|
return {
|
|
82
48
|
manifest,
|
|
83
49
|
search,
|
|
84
50
|
close: async () => {
|
|
85
|
-
|
|
86
|
-
await ownedSearch?.close();
|
|
87
|
-
}
|
|
88
|
-
finally {
|
|
89
|
-
if (ownsCache)
|
|
90
|
-
await removeRuntimeCache(runtimeCacheDir);
|
|
91
|
-
}
|
|
51
|
+
await ownedSearch?.close();
|
|
92
52
|
},
|
|
93
53
|
};
|
|
94
54
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type Server } from 'node:http';
|
|
2
2
|
import { type LatServerApp } from '../../vendor/lat.md-server/index.js';
|
|
3
|
-
import { type CmdContext } from '
|
|
3
|
+
import { type CmdContext } from '@plebeiantech/lat.md-core/context';
|
|
4
4
|
import { type ViewSearch } from './search.js';
|
|
5
5
|
import { type ViewStore } from './store.js';
|
|
6
6
|
export declare const DEFAULT_VIEW_PORT = 4242;
|
package/dist/src/view/server.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { trustedLiveRequest, RESOURCE_CONTENT_SECURITY_POLICY, } from './request-security.js';
|
|
1
2
|
import { readFile } from 'node:fs/promises';
|
|
2
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
6
|
import { createLatServerApp, listenLatServer, } from '../../vendor/lat.md-server/index.js';
|
|
6
|
-
import { plainStyler } from '
|
|
7
|
-
import { sectionCommand } from '
|
|
7
|
+
import { plainStyler, } from '@plebeiantech/lat.md-core/context';
|
|
8
|
+
import { sectionCommand } from '@plebeiantech/lat.md-core/cli/section';
|
|
8
9
|
import { DEFAULT_VIEW_LOGO_TEXT, } from './protocol.js';
|
|
9
10
|
import { ViewDocumentConflictError } from './document-edit.js';
|
|
10
11
|
import { ViewExternalNotFoundError, ViewDocumentNotFoundError, ViewSourceNotFoundError, } from './repository.js';
|
|
@@ -149,9 +150,13 @@ export async function createViewApp(ctx, options = {}) {
|
|
|
149
150
|
heartbeat.unref();
|
|
150
151
|
const handleRequest = (req, res) => {
|
|
151
152
|
void (async () => {
|
|
153
|
+
if (!trustedLiveRequest(req, host)) {
|
|
154
|
+
send(res, 403, 'text/plain; charset=utf-8', 'Untrusted request origin or host');
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
152
157
|
const method = req.method ?? 'GET';
|
|
153
158
|
const headOnly = method === 'HEAD';
|
|
154
|
-
const url = new URL(req.url ?? '/', `http://${host}`);
|
|
159
|
+
const url = new URL(req.url ?? '/', `http://${req.headers.host}`);
|
|
155
160
|
const documentEdit = method === 'PATCH' && url.pathname === '/api/document';
|
|
156
161
|
if (method !== 'GET' && !headOnly && !documentEdit) {
|
|
157
162
|
res.setHeader('Allow', 'GET, HEAD');
|
|
@@ -358,6 +363,11 @@ export async function createViewApp(ctx, options = {}) {
|
|
|
358
363
|
try {
|
|
359
364
|
const body = await store.getDocumentResource(resourcePath);
|
|
360
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
|
+
}
|
|
361
371
|
send(res, 200, contentType(resourcePath), body, headOnly);
|
|
362
372
|
}
|
|
363
373
|
catch (error) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { extname } from 'node:path';
|
|
2
|
-
import { normalizeRepositoryPath } from '
|
|
3
|
-
import { isSourceFileExtension } from '
|
|
2
|
+
import { normalizeRepositoryPath } from '@plebeiantech/lat.md-core/repository-path';
|
|
3
|
+
import { isSourceFileExtension } from '@plebeiantech/lat.md-core/source-formats';
|
|
4
4
|
import { rewriteDocumentLink } from './document-route.js';
|
|
5
5
|
/** Resolve ordinary code links relative to their Markdown file, not the vault root. */
|
|
6
6
|
export function rewriteLocalFileLink(value, sourcePath) {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { createPublicationPolicy } from './publication.js';
|
|
1
2
|
import { createHash } from 'node:crypto';
|
|
2
3
|
import { cp, lstat, mkdir, mkdtemp, readFile, rename, rm, writeFile, } from 'node:fs/promises';
|
|
3
4
|
import { dirname, join, parse, relative, resolve, sep } from 'node:path';
|
|
4
5
|
import { fileURLToPath } from 'node:url';
|
|
5
|
-
import { isDocumentPath } from '
|
|
6
|
+
import { isDocumentPath } from '@plebeiantech/lat.md-core/document-formats';
|
|
6
7
|
import { DEFAULT_VIEW_LOGO_TEXT } from './protocol.js';
|
|
7
8
|
import { documentTreeUrls, rewriteDocumentTreeUrls } from './document-tree.js';
|
|
8
9
|
import { VIEW_STATIC_BOOTSTRAP_ID, viewStaticDocumentRequest, viewStaticSourceKey, } from './static-protocol.js';
|
|
@@ -182,8 +183,14 @@ function positiveInteger(value) {
|
|
|
182
183
|
return Number.isInteger(parsed) && parsed > 0 ? parsed : 0;
|
|
183
184
|
}
|
|
184
185
|
function sourceRequest(value) {
|
|
185
|
-
|
|
186
|
-
|
|
186
|
+
let url;
|
|
187
|
+
try {
|
|
188
|
+
url = new URL(decodeHtmlUrlAttribute(value), 'http://lat.local');
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
if (url.origin !== 'http://lat.local' || !url.pathname.startsWith('/code/'))
|
|
187
194
|
return null;
|
|
188
195
|
let path;
|
|
189
196
|
let symbol;
|
|
@@ -193,6 +200,14 @@ function sourceRequest(value) {
|
|
|
193
200
|
.split('/')
|
|
194
201
|
.map(decodeURIComponent)
|
|
195
202
|
.join('/');
|
|
203
|
+
if (path.split('/').some((part) => !part || part === '.' || part === '..') ||
|
|
204
|
+
path.includes('\\') ||
|
|
205
|
+
path.includes('\0') ||
|
|
206
|
+
/^[a-z]:/i.test(path))
|
|
207
|
+
return null;
|
|
208
|
+
// Encoded separators cannot create extra route components after decoding.
|
|
209
|
+
if (/%(?:2f|5c)/i.test(url.pathname))
|
|
210
|
+
return null;
|
|
196
211
|
symbol = decodeURIComponent(url.hash.slice(1));
|
|
197
212
|
}
|
|
198
213
|
catch {
|
|
@@ -214,7 +229,8 @@ function externalRequest(value, external) {
|
|
|
214
229
|
catch {
|
|
215
230
|
return null;
|
|
216
231
|
}
|
|
217
|
-
if (
|
|
232
|
+
if (url.origin !== 'http://lat.local' ||
|
|
233
|
+
!url.pathname.startsWith('/external/'))
|
|
218
234
|
return null;
|
|
219
235
|
try {
|
|
220
236
|
const parts = url.pathname
|
|
@@ -441,8 +457,24 @@ function redirectShell(target, basePath) {
|
|
|
441
457
|
</html>
|
|
442
458
|
`;
|
|
443
459
|
}
|
|
460
|
+
/** All authored route writes must remain strictly below the payload root. */
|
|
461
|
+
function publicationOutputPath(root, ...parts) {
|
|
462
|
+
if (parts.some((part) => part.includes('\\') ||
|
|
463
|
+
part.includes('\0') ||
|
|
464
|
+
part.split('/').some((segment) => segment === '..' || segment === '.')))
|
|
465
|
+
throw new Error('Unsafe export route');
|
|
466
|
+
const path = resolve(root, ...parts);
|
|
467
|
+
const rel = relative(root, path);
|
|
468
|
+
if (!rel ||
|
|
469
|
+
rel.startsWith(`..${sep}`) ||
|
|
470
|
+
rel === '..' ||
|
|
471
|
+
/^[a-z]:/i.test(rel) ||
|
|
472
|
+
rel.startsWith(sep))
|
|
473
|
+
throw new Error('Export route is outside the output directory');
|
|
474
|
+
return path;
|
|
475
|
+
}
|
|
444
476
|
async function writeRouteShell(outputDir, route, shell) {
|
|
445
|
-
const path =
|
|
477
|
+
const path = publicationOutputPath(outputDir, route, 'index.html');
|
|
446
478
|
await mkdir(dirname(path), { recursive: true });
|
|
447
479
|
await writeFile(path, shell);
|
|
448
480
|
}
|
|
@@ -455,14 +487,16 @@ export async function buildStaticView(ctx, requestedOutput, options = {}) {
|
|
|
455
487
|
await validateViewBuildOutput(outputDir, ctx.projectRoot, 'Static', options.force);
|
|
456
488
|
await mkdir(dirname(outputDir), { recursive: true });
|
|
457
489
|
const stagingDir = await mkdtemp(join(dirname(outputDir), '.lat-static-staging-'));
|
|
458
|
-
|
|
459
|
-
codeExcludePaths: [outputDir, ...(options.codeExcludePaths ?? [])],
|
|
460
|
-
git: false,
|
|
461
|
-
watch: false,
|
|
462
|
-
externalIgnoreLocal: true,
|
|
463
|
-
externalCa: options.externalCa,
|
|
464
|
-
});
|
|
490
|
+
let store;
|
|
465
491
|
try {
|
|
492
|
+
store = await createViewStore(ctx.latDir, ctx.projectRoot, {
|
|
493
|
+
codeExcludePaths: [outputDir, ...(options.codeExcludePaths ?? [])],
|
|
494
|
+
git: false,
|
|
495
|
+
watch: false,
|
|
496
|
+
externalIgnoreLocal: true,
|
|
497
|
+
externalCa: options.externalCa,
|
|
498
|
+
publishable: await createPublicationPolicy(ctx.projectRoot),
|
|
499
|
+
});
|
|
466
500
|
const clientHtml = await readFile(join(clientDir, 'index.html'), 'utf8');
|
|
467
501
|
const payloadDir = staticViewPayloadDir(stagingDir, basePath);
|
|
468
502
|
await mkdir(payloadDir, { recursive: true });
|
|
@@ -523,11 +557,9 @@ export async function buildStaticView(ctx, requestedOutput, options = {}) {
|
|
|
523
557
|
externals.set(target, external);
|
|
524
558
|
const before = externalRequests.size;
|
|
525
559
|
if (external.kind === 'markdown') {
|
|
526
|
-
sourceRequestsFromDocument(external.document, sourceRequests);
|
|
527
560
|
externalRequestsFromDocument(external.document, externalRequests, store.snapshot.external, external.document.path);
|
|
528
561
|
}
|
|
529
562
|
else {
|
|
530
|
-
sourceRequestsFromSource(external.source, sourceRequests);
|
|
531
563
|
externalRequestsFromSource(external.source, externalRequests, store.snapshot.external);
|
|
532
564
|
}
|
|
533
565
|
if (externalRequests.size > before) {
|
|
@@ -580,7 +612,7 @@ export async function buildStaticView(ctx, requestedOutput, options = {}) {
|
|
|
580
612
|
const rewritten = rewriteDocument(document, basePath, index.entry, sectionPaths, documentPaths);
|
|
581
613
|
manifest.documents[path] = await writeDataJson(payloadDir, 'documents', rewritten);
|
|
582
614
|
const source = await store.getDocumentSource(path);
|
|
583
|
-
const rawPath =
|
|
615
|
+
const rawPath = publicationOutputPath(payloadDir, path);
|
|
584
616
|
await mkdir(dirname(rawPath), { recursive: true });
|
|
585
617
|
await writeFile(rawPath, source.content);
|
|
586
618
|
const route = path.slice(0, -'.md'.length);
|
|
@@ -597,7 +629,7 @@ export async function buildStaticView(ctx, requestedOutput, options = {}) {
|
|
|
597
629
|
catch (error) {
|
|
598
630
|
throw new Error(`Could not export document resource ${path}: ${error.message}`);
|
|
599
631
|
}
|
|
600
|
-
const outputPath =
|
|
632
|
+
const outputPath = publicationOutputPath(payloadDir, 'resources', path);
|
|
601
633
|
await mkdir(dirname(outputPath), { recursive: true });
|
|
602
634
|
await writeFile(outputPath, content);
|
|
603
635
|
}
|
|
@@ -704,6 +736,6 @@ export async function buildStaticView(ctx, requestedOutput, options = {}) {
|
|
|
704
736
|
throw error;
|
|
705
737
|
}
|
|
706
738
|
finally {
|
|
707
|
-
await store
|
|
739
|
+
await store?.close();
|
|
708
740
|
}
|
|
709
741
|
}
|
package/dist/src/view/store.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type ExternalResolver } from '
|
|
2
|
-
import type { Section } from '
|
|
1
|
+
import { type ExternalResolver } from '@plebeiantech/lat.md-core/external-sources';
|
|
2
|
+
import type { Section } from '@plebeiantech/lat.md-core/lattice-model';
|
|
3
3
|
import { type ViewGitRepository, type ViewGitSnapshot } from './git.js';
|
|
4
4
|
import type { ViewDocument, ViewDocumentEditResponse, ViewDocumentError, ViewDocumentSource, ViewExternalDocument, ViewGraph, ViewIndex, ViewProjectGeneration, ViewDocumentTree, ViewSourceDocument } from './protocol.js';
|
|
5
5
|
import { type ViewCodeReferenceFile, type ViewParsedMarkdownFile, type ViewReferenceIndex } from './references.js';
|
|
@@ -16,6 +16,8 @@ export type ViewProjectSnapshot = {
|
|
|
16
16
|
external: ExternalResolver;
|
|
17
17
|
};
|
|
18
18
|
export type ViewStoreOptions = {
|
|
19
|
+
/** Export-only allowlist, applied before source/backlink/resource reads. */
|
|
20
|
+
publishable?: (path: string) => Promise<boolean>;
|
|
19
21
|
codeExcludePaths?: string[];
|
|
20
22
|
debounceMs?: number;
|
|
21
23
|
git?: boolean;
|