@hawkeyexl/manni 4.10.0 → 4.12.0
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/batch-EFSFG6GC.js +46 -0
- package/dist/build-NIO3UIWJ.js +36 -0
- package/dist/calibrate-6VO7URRV.js +41 -0
- package/dist/capture-NMBVJO3C.js +38 -0
- package/dist/check-SHOYX2B5.js +30 -0
- package/dist/check-XMJKH3KV.js +34 -0
- package/dist/{check-NLL4NRYA.js → check-Y62BJNC4.js} +35 -31
- package/dist/{check-NLL4NRYA.js.map → check-Y62BJNC4.js.map} +1 -1
- package/dist/{check-7B77ZD2N.js → check-ZMO3ZLMW.js} +19 -15
- package/dist/{chunk-PK7EKJ5T.js → chunk-24AJK2RG.js} +5 -10
- package/dist/chunk-24AJK2RG.js.map +1 -0
- package/dist/chunk-2OZF2VUB.js +164 -0
- package/dist/chunk-2OZF2VUB.js.map +1 -0
- package/dist/chunk-2UJZXVHR.js +1868 -0
- package/dist/chunk-2UJZXVHR.js.map +1 -0
- package/dist/{chunk-DNZUBCGZ.js → chunk-3BRJCQPY.js} +36 -7
- package/dist/chunk-3BRJCQPY.js.map +1 -0
- package/dist/{chunk-D2UW3ZCK.js → chunk-42VFJOAF.js} +13 -11
- package/dist/{chunk-D2UW3ZCK.js.map → chunk-42VFJOAF.js.map} +1 -1
- package/dist/{chunk-LQZQ5KGG.js → chunk-4Q24OYI3.js} +7 -7
- package/dist/{chunk-XU73V5XT.js → chunk-4WJTURRO.js} +15 -15
- package/dist/{chunk-WN47MNSK.js → chunk-5SID2SVL.js} +4 -4
- package/dist/{chunk-5REEVKGH.js → chunk-AANUY4BH.js} +2 -2
- package/dist/chunk-ANPIIYRH.js +2272 -0
- package/dist/chunk-ANPIIYRH.js.map +1 -0
- package/dist/{chunk-RZVCWX5R.js → chunk-AYVKN3PG.js} +4 -4
- package/dist/{chunk-2UCC26MO.js → chunk-CH6IOGXV.js} +9 -9
- package/dist/{chunk-RODZ7MB7.js → chunk-D5Z6B4M7.js} +6 -6
- package/dist/{chunk-IJ62BB2T.js → chunk-D6SELXQ2.js} +7 -7
- package/dist/{chunk-2JV7C4YV.js → chunk-DDILEF5F.js} +890 -1399
- package/dist/chunk-DDILEF5F.js.map +1 -0
- package/dist/{chunk-3E2X2RBU.js → chunk-DGRLHDM4.js} +9 -9
- package/dist/{chunk-2BV4FBC7.js → chunk-DHGB4JBG.js} +4 -3
- package/dist/chunk-DHGB4JBG.js.map +1 -0
- package/dist/{chunk-6LR73NMO.js → chunk-DLU5FCFT.js} +30 -28
- package/dist/chunk-DLU5FCFT.js.map +1 -0
- package/dist/chunk-DSWKBZWW.js +16 -0
- package/dist/chunk-DSWKBZWW.js.map +1 -0
- package/dist/{chunk-BD7IXBWE.js → chunk-F564FHMQ.js} +8 -8
- package/dist/{chunk-ABHG6I3G.js → chunk-FKAZUZQU.js} +469 -85
- package/dist/chunk-FKAZUZQU.js.map +1 -0
- package/dist/{chunk-DFCQ6BMI.js → chunk-G3MBUL5M.js} +4 -4
- package/dist/{chunk-SUTMSDQ2.js → chunk-GQ3KRY3B.js} +3 -3
- package/dist/chunk-HDPN46JP.js +393 -0
- package/dist/chunk-HDPN46JP.js.map +1 -0
- package/dist/{chunk-EAUIQADY.js → chunk-IQQAJROD.js} +6 -6
- package/dist/{chunk-ZHRPH52H.js → chunk-IZXN3WI6.js} +2 -2
- package/dist/{chunk-NCPWXHDO.js → chunk-JEUFYSFQ.js} +4 -4
- package/dist/{chunk-G6FNWRAI.js → chunk-JSSM7VVV.js} +4 -4
- package/dist/{chunk-CCWMACJL.js → chunk-KFGZPVFA.js} +229 -821
- package/dist/chunk-KFGZPVFA.js.map +1 -0
- package/dist/{chunk-H26VDFDS.js → chunk-KGFSPJLD.js} +2 -2
- package/dist/{chunk-AO5TSDKT.js → chunk-KMORGMCW.js} +7 -7
- package/dist/{chunk-WQWKYAAK.js → chunk-NUQF5F5J.js} +2 -2
- package/dist/{chunk-2YJ5H5E6.js → chunk-NZ6KSHFD.js} +23 -21
- package/dist/{chunk-2YJ5H5E6.js.map → chunk-NZ6KSHFD.js.map} +1 -1
- package/dist/{chunk-7Y3N4Y72.js → chunk-OHUDZRLK.js} +3 -3
- package/dist/{chunk-GCKHSBEN.js → chunk-OKMTUAWO.js} +4 -4
- package/dist/{chunk-6M5VJOC2.js → chunk-OTJOBZJ5.js} +167 -166
- package/dist/chunk-OTJOBZJ5.js.map +1 -0
- package/dist/{chunk-2W34HX2U.js → chunk-PS257NIU.js} +288 -373
- package/dist/chunk-PS257NIU.js.map +1 -0
- package/dist/chunk-QDC7JPFG.js +685 -0
- package/dist/chunk-QDC7JPFG.js.map +1 -0
- package/dist/chunk-QEAGL4V5.js +3185 -0
- package/dist/chunk-QEAGL4V5.js.map +1 -0
- package/dist/{chunk-GB2XPITA.js → chunk-QMY57PVW.js} +2 -2
- package/dist/{chunk-55GMOVKW.js → chunk-QNDDPXFR.js} +2 -2
- package/dist/{chunk-GXN7RRHR.js → chunk-QSIXNTRV.js} +4 -4
- package/dist/{chunk-G7XD4QH5.js → chunk-RGLFV4KO.js} +11372 -10218
- package/dist/chunk-RGLFV4KO.js.map +1 -0
- package/dist/{chunk-QBVP3SQP.js → chunk-SGR7ZAVE.js} +13 -7
- package/dist/chunk-SGR7ZAVE.js.map +1 -0
- package/dist/{chunk-KBG463UK.js → chunk-SMHAYK6I.js} +2409 -5243
- package/dist/chunk-SMHAYK6I.js.map +1 -0
- package/dist/{chunk-XG6PVB5S.js → chunk-SSQZB5SQ.js} +1 -11
- package/dist/chunk-SSQZB5SQ.js.map +1 -0
- package/dist/{chunk-GDLHTI5R.js → chunk-STPGIKPY.js} +8 -2
- package/dist/chunk-STPGIKPY.js.map +1 -0
- package/dist/{chunk-QJRQ4BRC.js → chunk-U22TOL5Y.js} +17 -17
- package/dist/{chunk-NGTVREIH.js → chunk-U6IHLEWT.js} +2 -2
- package/dist/{chunk-Z5YHMRLF.js → chunk-UUCCV3SI.js} +2 -2
- package/dist/{chunk-ZXXFP2LA.js → chunk-UXMCHBOJ.js} +2 -2
- package/dist/{chunk-VZVEP2OZ.js → chunk-VFAKGIDG.js} +2 -2
- package/dist/{chunk-QCHVR4ZM.js → chunk-VM7VAFJW.js} +33 -7
- package/dist/chunk-VM7VAFJW.js.map +1 -0
- package/dist/{chunk-VQK4VHLF.js → chunk-YQV75FIL.js} +2 -2
- package/dist/chunk-YUTVAMWW.js +2 -0
- package/dist/chunk-ZPLVANY2.js +15 -0
- package/dist/chunk-ZPLVANY2.js.map +1 -0
- package/dist/{cli-BIIUKPTE.js → cli-4CR7QIOK.js} +26 -22
- package/dist/{cli-BIIUKPTE.js.map → cli-4CR7QIOK.js.map} +1 -1
- package/dist/{cli-V2DI3K2R.js → cli-6R4W3HAH.js} +37 -33
- package/dist/{cli-V2DI3K2R.js.map → cli-6R4W3HAH.js.map} +1 -1
- package/dist/{cli-HO62TOM2.js → cli-BOMA2FMP.js} +14 -11
- package/dist/{cli-EH3I4IUX.js → cli-EDQPQOCE.js} +47 -41
- package/dist/cli-EDQPQOCE.js.map +1 -0
- package/dist/{cli-P2X7PNY6.js → cli-GBF76EXT.js} +25 -20
- package/dist/{cli-P2X7PNY6.js.map → cli-GBF76EXT.js.map} +1 -1
- package/dist/{cli-4YYC6LCY.js → cli-MQYCF3SR.js} +27 -23
- package/dist/{cli-4YYC6LCY.js.map → cli-MQYCF3SR.js.map} +1 -1
- package/dist/{cli-UETKXHJN.js → cli-OJKFXQOM.js} +9 -9
- package/dist/{cli-LWST5FQH.js → cli-PHZAO4LZ.js} +4 -4
- package/dist/{cli-TELPAMJO.js → cli-PTKFFNOW.js} +59 -35
- package/dist/cli-PTKFFNOW.js.map +1 -0
- package/dist/{cli-SGVFZOAW.js → cli-UW2K5Z5J.js} +34 -29
- package/dist/{cli-SGVFZOAW.js.map → cli-UW2K5Z5J.js.map} +1 -1
- package/dist/cli-XXTNPPKB.js +83 -0
- package/dist/cli-XXTNPPKB.js.map +1 -0
- package/dist/cli.js +24 -12
- package/dist/cli.js.map +1 -1
- package/dist/{config-TYXYQK3I.js → config-JJW75SBX.js} +5 -5
- package/dist/docmeta.js +13 -10
- package/dist/docmeta.js.map +1 -1
- package/dist/github-6VQKSB67.js +35 -0
- package/dist/github-RBSEM7ZK.js +30 -0
- package/dist/graph/runtime.d.ts +4 -1
- package/dist/graph/runtime.js +20 -9
- package/dist/graph/runtime.js.map +1 -1
- package/dist/{host-6GURH5HE.js → host-YSTYO5DX.js} +3 -3
- package/dist/index.d.ts +1214 -940
- package/dist/index.js +190 -160
- package/dist/index.js.map +1 -1
- package/dist/{json-QR4G35KA.js → json-PU2HLHDQ.js} +18 -14
- package/dist/labels-SJNSOPBI.js +73 -0
- package/dist/labels-SJNSOPBI.js.map +1 -0
- package/dist/lint-KIVTHLGU.js +34 -0
- package/dist/list-RDEJDDJF.js +32 -0
- package/dist/list-SUTDWL2J.js +35 -0
- package/dist/{page-FSXDXCDD.js → page-UMAA3NCM.js} +18 -13
- package/dist/{prepare-UPIBTFNS.js → prepare-3I3LOXXD.js} +24 -20
- package/dist/{prepare-UPIBTFNS.js.map → prepare-3I3LOXXD.js.map} +1 -1
- package/dist/{pretty-4IONWSEP.js → pretty-ANLRHU4O.js} +18 -14
- package/dist/{pretty-R4BQD2VH.js → pretty-Q3ZFKOR7.js} +18 -14
- package/dist/{provider-527CO4DM.js → provider-LBX4IXGX.js} +3 -3
- package/dist/{release-3D5PK6M7.js → release-VV3UTKE5.js} +3 -3
- package/dist/{reporters-M6LJ2IYU.js → reporters-26H3N2KW.js} +3 -3
- package/dist/{reporters-DHO2BXAD.js → reporters-ILT36CIH.js} +7 -7
- package/dist/{reporters-FPP6JNDP.js → reporters-PNDLWT6K.js} +16 -12
- package/dist/run-QXCK33Z4.js +37 -0
- package/dist/{term-ASM4LVYC.js → term-D2N7UN4P.js} +981 -138
- package/dist/term-D2N7UN4P.js.map +1 -0
- package/dist/validate-BRUCOT2O.js +19 -0
- package/dist/validate-BRUCOT2O.js.map +1 -0
- package/package.json +3 -2
- package/plugin/manni/.claude-plugin/plugin.json +1 -1
- package/shapes/graph/shapes-1.1.0.ttl +785 -0
- package/dist/batch-6NICDKRE.js +0 -41
- package/dist/build-3KP2K3XN.js +0 -32
- package/dist/calibrate-LUA3DWKD.js +0 -36
- package/dist/capture-NETOHCB4.js +0 -34
- package/dist/check-E4QCB7LS.js +0 -20
- package/dist/check-PTECPIIB.js +0 -26
- package/dist/chunk-2BV4FBC7.js.map +0 -1
- package/dist/chunk-2JV7C4YV.js.map +0 -1
- package/dist/chunk-2W34HX2U.js.map +0 -1
- package/dist/chunk-4DLF5SA4.js +0 -392
- package/dist/chunk-4DLF5SA4.js.map +0 -1
- package/dist/chunk-6AGESHHM.js +0 -387
- package/dist/chunk-6AGESHHM.js.map +0 -1
- package/dist/chunk-6LR73NMO.js.map +0 -1
- package/dist/chunk-6M5VJOC2.js.map +0 -1
- package/dist/chunk-ABHG6I3G.js.map +0 -1
- package/dist/chunk-CCWMACJL.js.map +0 -1
- package/dist/chunk-DNZUBCGZ.js.map +0 -1
- package/dist/chunk-G7XD4QH5.js.map +0 -1
- package/dist/chunk-GDLHTI5R.js.map +0 -1
- package/dist/chunk-KBG463UK.js.map +0 -1
- package/dist/chunk-PK7EKJ5T.js.map +0 -1
- package/dist/chunk-QBVP3SQP.js.map +0 -1
- package/dist/chunk-QCHVR4ZM.js.map +0 -1
- package/dist/chunk-VVVKBUBO.js +0 -818
- package/dist/chunk-VVVKBUBO.js.map +0 -1
- package/dist/chunk-XG6PVB5S.js.map +0 -1
- package/dist/cli-EH3I4IUX.js.map +0 -1
- package/dist/cli-TELPAMJO.js.map +0 -1
- package/dist/github-ESK45CEZ.js +0 -26
- package/dist/github-WER7JUTN.js +0 -31
- package/dist/lint-QTI7XK2A.js +0 -30
- package/dist/list-JO4G3TS3.js +0 -30
- package/dist/list-O2MJUP5V.js +0 -28
- package/dist/run-YH5Z7RJ7.js +0 -32
- package/dist/term-ASM4LVYC.js.map +0 -1
- package/dist/validate-7JI3H57P.js +0 -17
- /package/dist/{batch-6NICDKRE.js.map → batch-EFSFG6GC.js.map} +0 -0
- /package/dist/{build-3KP2K3XN.js.map → build-NIO3UIWJ.js.map} +0 -0
- /package/dist/{calibrate-LUA3DWKD.js.map → calibrate-6VO7URRV.js.map} +0 -0
- /package/dist/{capture-NETOHCB4.js.map → capture-NMBVJO3C.js.map} +0 -0
- /package/dist/{check-7B77ZD2N.js.map → check-SHOYX2B5.js.map} +0 -0
- /package/dist/{check-E4QCB7LS.js.map → check-XMJKH3KV.js.map} +0 -0
- /package/dist/{check-PTECPIIB.js.map → check-ZMO3ZLMW.js.map} +0 -0
- /package/dist/{chunk-LQZQ5KGG.js.map → chunk-4Q24OYI3.js.map} +0 -0
- /package/dist/{chunk-XU73V5XT.js.map → chunk-4WJTURRO.js.map} +0 -0
- /package/dist/{chunk-WN47MNSK.js.map → chunk-5SID2SVL.js.map} +0 -0
- /package/dist/{chunk-5REEVKGH.js.map → chunk-AANUY4BH.js.map} +0 -0
- /package/dist/{chunk-RZVCWX5R.js.map → chunk-AYVKN3PG.js.map} +0 -0
- /package/dist/{chunk-2UCC26MO.js.map → chunk-CH6IOGXV.js.map} +0 -0
- /package/dist/{chunk-RODZ7MB7.js.map → chunk-D5Z6B4M7.js.map} +0 -0
- /package/dist/{chunk-IJ62BB2T.js.map → chunk-D6SELXQ2.js.map} +0 -0
- /package/dist/{chunk-3E2X2RBU.js.map → chunk-DGRLHDM4.js.map} +0 -0
- /package/dist/{chunk-BD7IXBWE.js.map → chunk-F564FHMQ.js.map} +0 -0
- /package/dist/{chunk-DFCQ6BMI.js.map → chunk-G3MBUL5M.js.map} +0 -0
- /package/dist/{chunk-SUTMSDQ2.js.map → chunk-GQ3KRY3B.js.map} +0 -0
- /package/dist/{chunk-EAUIQADY.js.map → chunk-IQQAJROD.js.map} +0 -0
- /package/dist/{chunk-ZHRPH52H.js.map → chunk-IZXN3WI6.js.map} +0 -0
- /package/dist/{chunk-NCPWXHDO.js.map → chunk-JEUFYSFQ.js.map} +0 -0
- /package/dist/{chunk-G6FNWRAI.js.map → chunk-JSSM7VVV.js.map} +0 -0
- /package/dist/{chunk-H26VDFDS.js.map → chunk-KGFSPJLD.js.map} +0 -0
- /package/dist/{chunk-AO5TSDKT.js.map → chunk-KMORGMCW.js.map} +0 -0
- /package/dist/{chunk-WQWKYAAK.js.map → chunk-NUQF5F5J.js.map} +0 -0
- /package/dist/{chunk-7Y3N4Y72.js.map → chunk-OHUDZRLK.js.map} +0 -0
- /package/dist/{chunk-GCKHSBEN.js.map → chunk-OKMTUAWO.js.map} +0 -0
- /package/dist/{chunk-GB2XPITA.js.map → chunk-QMY57PVW.js.map} +0 -0
- /package/dist/{chunk-55GMOVKW.js.map → chunk-QNDDPXFR.js.map} +0 -0
- /package/dist/{chunk-GXN7RRHR.js.map → chunk-QSIXNTRV.js.map} +0 -0
- /package/dist/{chunk-QJRQ4BRC.js.map → chunk-U22TOL5Y.js.map} +0 -0
- /package/dist/{chunk-NGTVREIH.js.map → chunk-U6IHLEWT.js.map} +0 -0
- /package/dist/{chunk-Z5YHMRLF.js.map → chunk-UUCCV3SI.js.map} +0 -0
- /package/dist/{chunk-ZXXFP2LA.js.map → chunk-UXMCHBOJ.js.map} +0 -0
- /package/dist/{chunk-VZVEP2OZ.js.map → chunk-VFAKGIDG.js.map} +0 -0
- /package/dist/{chunk-VQK4VHLF.js.map → chunk-YQV75FIL.js.map} +0 -0
- /package/dist/{cli-HO62TOM2.js.map → chunk-YUTVAMWW.js.map} +0 -0
- /package/dist/{config-TYXYQK3I.js.map → cli-BOMA2FMP.js.map} +0 -0
- /package/dist/{cli-UETKXHJN.js.map → cli-OJKFXQOM.js.map} +0 -0
- /package/dist/{cli-LWST5FQH.js.map → cli-PHZAO4LZ.js.map} +0 -0
- /package/dist/{github-ESK45CEZ.js.map → config-JJW75SBX.js.map} +0 -0
- /package/dist/{github-WER7JUTN.js.map → github-6VQKSB67.js.map} +0 -0
- /package/dist/{host-6GURH5HE.js.map → github-RBSEM7ZK.js.map} +0 -0
- /package/dist/{json-QR4G35KA.js.map → host-YSTYO5DX.js.map} +0 -0
- /package/dist/{lint-QTI7XK2A.js.map → json-PU2HLHDQ.js.map} +0 -0
- /package/dist/{list-JO4G3TS3.js.map → lint-KIVTHLGU.js.map} +0 -0
- /package/dist/{list-O2MJUP5V.js.map → list-RDEJDDJF.js.map} +0 -0
- /package/dist/{page-FSXDXCDD.js.map → list-SUTDWL2J.js.map} +0 -0
- /package/dist/{pretty-4IONWSEP.js.map → page-UMAA3NCM.js.map} +0 -0
- /package/dist/{pretty-R4BQD2VH.js.map → pretty-ANLRHU4O.js.map} +0 -0
- /package/dist/{provider-527CO4DM.js.map → pretty-Q3ZFKOR7.js.map} +0 -0
- /package/dist/{reporters-DHO2BXAD.js.map → provider-LBX4IXGX.js.map} +0 -0
- /package/dist/{release-3D5PK6M7.js.map → release-VV3UTKE5.js.map} +0 -0
- /package/dist/{reporters-FPP6JNDP.js.map → reporters-26H3N2KW.js.map} +0 -0
- /package/dist/{reporters-M6LJ2IYU.js.map → reporters-ILT36CIH.js.map} +0 -0
- /package/dist/{run-YH5Z7RJ7.js.map → reporters-PNDLWT6K.js.map} +0 -0
- /package/dist/{validate-7JI3H57P.js.map → run-QXCK33Z4.js.map} +0 -0
|
@@ -0,0 +1,1868 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
parserByName,
|
|
4
|
+
parserForExtension,
|
|
5
|
+
supportedExtensions,
|
|
6
|
+
unsupportedFormatMessage
|
|
7
|
+
} from "./chunk-IZXN3WI6.js";
|
|
8
|
+
import {
|
|
9
|
+
metaPageView
|
|
10
|
+
} from "./chunk-JSSM7VVV.js";
|
|
11
|
+
import {
|
|
12
|
+
DEFAULT_CHUNK_CHARS
|
|
13
|
+
} from "./chunk-PS257NIU.js";
|
|
14
|
+
import {
|
|
15
|
+
STDIN_REQUIRES_AS,
|
|
16
|
+
parseLines
|
|
17
|
+
} from "./chunk-SMHAYK6I.js";
|
|
18
|
+
import {
|
|
19
|
+
extractFrontmatter,
|
|
20
|
+
extractorForExtension
|
|
21
|
+
} from "./chunk-RGLFV4KO.js";
|
|
22
|
+
import {
|
|
23
|
+
findConfigFileSync,
|
|
24
|
+
parseCollections,
|
|
25
|
+
readConfigFileSync,
|
|
26
|
+
selectCollections
|
|
27
|
+
} from "./chunk-OTJOBZJ5.js";
|
|
28
|
+
import {
|
|
29
|
+
warn
|
|
30
|
+
} from "./chunk-HX44GB4Z.js";
|
|
31
|
+
import {
|
|
32
|
+
PROVIDERS_KEY,
|
|
33
|
+
assertKnownProvider,
|
|
34
|
+
parseProviders
|
|
35
|
+
} from "./chunk-VM7VAFJW.js";
|
|
36
|
+
import {
|
|
37
|
+
ToolError,
|
|
38
|
+
errorMessage
|
|
39
|
+
} from "./chunk-G3T47CFV.js";
|
|
40
|
+
|
|
41
|
+
// src/graph/types.ts
|
|
42
|
+
var GraphError = class extends ToolError {
|
|
43
|
+
constructor(message) {
|
|
44
|
+
super(message);
|
|
45
|
+
this.name = "GraphError";
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// src/graph/core/iri.ts
|
|
50
|
+
import { slug as githubSlug } from "github-slugger";
|
|
51
|
+
var DEFAULT_BASE_IRI = "urn:manni:graph:";
|
|
52
|
+
function resolveBaseIri(base) {
|
|
53
|
+
if (!base) return DEFAULT_BASE_IRI;
|
|
54
|
+
if (base.endsWith("/") || base.endsWith(":")) return base;
|
|
55
|
+
return `${base}/`;
|
|
56
|
+
}
|
|
57
|
+
function normalizeDocPath(p) {
|
|
58
|
+
let out = p.replace(/\\/g, "/");
|
|
59
|
+
while (out.startsWith("./")) out = out.slice(2);
|
|
60
|
+
return out;
|
|
61
|
+
}
|
|
62
|
+
function encodeSegment(segment) {
|
|
63
|
+
return encodeURIComponent(segment).replace(
|
|
64
|
+
/[!'()*]/g,
|
|
65
|
+
(c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
var STDIN_PATH = "<stdin>";
|
|
69
|
+
function mintDocIri(base, relPath) {
|
|
70
|
+
if (relPath === STDIN_PATH) return `${base}stdin`;
|
|
71
|
+
const path = normalizeDocPath(relPath).split("/").map(encodeSegment).join("/");
|
|
72
|
+
return `${base}doc/${path}`;
|
|
73
|
+
}
|
|
74
|
+
function mintSectionIri(docIri, slugValue) {
|
|
75
|
+
return `${docIri}#${slugValue}`;
|
|
76
|
+
}
|
|
77
|
+
function conceptSlug(label) {
|
|
78
|
+
return githubSlug(label);
|
|
79
|
+
}
|
|
80
|
+
function mintConceptIri(base, label) {
|
|
81
|
+
return `${base}concept/${encodeSegment(conceptSlug(label))}`;
|
|
82
|
+
}
|
|
83
|
+
function mintTermConceptIri(base, id) {
|
|
84
|
+
return `${base}concept/${encodeSegment(id)}`;
|
|
85
|
+
}
|
|
86
|
+
function mintProductIri(base, label) {
|
|
87
|
+
return `${base}product/${encodeSegment(conceptSlug(label))}`;
|
|
88
|
+
}
|
|
89
|
+
function mintSchemeIri(base) {
|
|
90
|
+
return `${base}scheme`;
|
|
91
|
+
}
|
|
92
|
+
function mintAgentIri(base, kind, name) {
|
|
93
|
+
return `${base}agent/${kind}/${encodeSegment(conceptSlug(name))}`;
|
|
94
|
+
}
|
|
95
|
+
function mintGraphIri(base) {
|
|
96
|
+
return `${base}graph`;
|
|
97
|
+
}
|
|
98
|
+
function mintBuildActivityIri(base) {
|
|
99
|
+
return `${base}activity/build`;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// src/graph/core/vocab.ts
|
|
103
|
+
var NS = {
|
|
104
|
+
dcterms: "http://purl.org/dc/terms/",
|
|
105
|
+
foaf: "http://xmlns.com/foaf/0.1/",
|
|
106
|
+
graph: "https://hawkeyexl.github.io/manni/graph/ns#",
|
|
107
|
+
iirds: "http://iirds.tekom.de/iirds#",
|
|
108
|
+
iirdsSft: "http://iirds.tekom.de/iirds/domain/software#",
|
|
109
|
+
prov: "http://www.w3.org/ns/prov#",
|
|
110
|
+
rdf: "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
|
|
111
|
+
schema: "https://schema.org/",
|
|
112
|
+
skos: "http://www.w3.org/2004/02/skos/core#",
|
|
113
|
+
xsd: "http://www.w3.org/2001/XMLSchema#"
|
|
114
|
+
};
|
|
115
|
+
var PREFIXES = Object.entries(NS).sort(([a], [b]) => a < b ? -1 : 1);
|
|
116
|
+
var RDF_TYPE = `${NS.rdf}type`;
|
|
117
|
+
var ROLE = {
|
|
118
|
+
author: `${NS.graph}authorRole`,
|
|
119
|
+
generator: `${NS.graph}generatorRole`,
|
|
120
|
+
tool: `${NS.graph}toolRole`
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
// src/graph/core/config.ts
|
|
124
|
+
import { dirname, resolve } from "node:path";
|
|
125
|
+
import { parse as parseYaml } from "yaml";
|
|
126
|
+
import { Ajv2020 } from "ajv/dist/2020.js";
|
|
127
|
+
|
|
128
|
+
// src/graph/core/config-schema.json
|
|
129
|
+
var config_schema_default = {
|
|
130
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
131
|
+
$id: "manni:graph:config",
|
|
132
|
+
title: "manni graph configuration",
|
|
133
|
+
type: "object",
|
|
134
|
+
additionalProperties: false,
|
|
135
|
+
properties: {
|
|
136
|
+
provider: {
|
|
137
|
+
type: "string",
|
|
138
|
+
minLength: 1,
|
|
139
|
+
description: "Which provider `manni graph fill` sends pages to: auto | anthropic | openai | claude-cli | llama-cpp. Unset, the family's top-level providers.provider decides, then auto, detected exactly as manni meta fill detects: an Anthropic key, then an OpenAI key, then the Claude CLI, then a local model. --provider wins over it, and --local overrides both. Connection settings live in the family's top-level providers: map."
|
|
140
|
+
},
|
|
141
|
+
model: {
|
|
142
|
+
type: "string",
|
|
143
|
+
minLength: 1,
|
|
144
|
+
description: "The model, within the provider named beside it. A model is carried only to the provider its own level names: a differing --provider or providers.provider takes its own default instead. With no provider here, it goes to whichever provider is in force, which must not be auto, because a model name does not say which provider owns it. Unset (the default) takes the provider's default model from the inference library; manni pins none. --model wins over it. This is not `embed.model`, which is a local embedding model id."
|
|
145
|
+
},
|
|
146
|
+
baseIri: {
|
|
147
|
+
type: "string",
|
|
148
|
+
minLength: 1
|
|
149
|
+
},
|
|
150
|
+
out: {
|
|
151
|
+
type: "string",
|
|
152
|
+
minLength: 1
|
|
153
|
+
},
|
|
154
|
+
questionFiles: {
|
|
155
|
+
type: "array",
|
|
156
|
+
items: {
|
|
157
|
+
type: "string",
|
|
158
|
+
minLength: 1
|
|
159
|
+
},
|
|
160
|
+
description: "Golden-set files, relative to the config file. They hold questions that span pages or that the docs don't answer, and `check` asks them beside each page's sample-questions. Default none."
|
|
161
|
+
},
|
|
162
|
+
routes: {
|
|
163
|
+
type: "array",
|
|
164
|
+
items: {
|
|
165
|
+
type: "object",
|
|
166
|
+
additionalProperties: false,
|
|
167
|
+
required: ["root"],
|
|
168
|
+
properties: {
|
|
169
|
+
basePath: {
|
|
170
|
+
type: "string"
|
|
171
|
+
},
|
|
172
|
+
root: {
|
|
173
|
+
type: "string"
|
|
174
|
+
},
|
|
175
|
+
extensions: {
|
|
176
|
+
type: "array",
|
|
177
|
+
items: {
|
|
178
|
+
type: "string",
|
|
179
|
+
pattern: "^\\."
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
language: {
|
|
183
|
+
type: "string",
|
|
184
|
+
pattern: "^[A-Za-z]{2,3}(-[A-Za-z]{4})?(-([A-Za-z]{2}|[0-9]{3}))?(-([A-Za-z0-9]{5,8}|[0-9][A-Za-z0-9]{3}))*$"
|
|
185
|
+
},
|
|
186
|
+
indexFiles: {
|
|
187
|
+
type: "array",
|
|
188
|
+
items: {
|
|
189
|
+
type: "string",
|
|
190
|
+
minLength: 1
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
build: {
|
|
197
|
+
type: "object",
|
|
198
|
+
additionalProperties: false,
|
|
199
|
+
properties: {
|
|
200
|
+
derive: {
|
|
201
|
+
type: "array",
|
|
202
|
+
uniqueItems: true,
|
|
203
|
+
items: {
|
|
204
|
+
enum: [
|
|
205
|
+
"frontmatter",
|
|
206
|
+
"sections",
|
|
207
|
+
"links",
|
|
208
|
+
"tags",
|
|
209
|
+
"images",
|
|
210
|
+
"code",
|
|
211
|
+
"provenance",
|
|
212
|
+
"terms"
|
|
213
|
+
]
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
check: {
|
|
219
|
+
type: "object",
|
|
220
|
+
additionalProperties: false,
|
|
221
|
+
properties: {
|
|
222
|
+
shapes: {
|
|
223
|
+
type: "array",
|
|
224
|
+
items: {
|
|
225
|
+
type: "string",
|
|
226
|
+
minLength: 1
|
|
227
|
+
}
|
|
228
|
+
},
|
|
229
|
+
questions: {
|
|
230
|
+
type: "object",
|
|
231
|
+
additionalProperties: false,
|
|
232
|
+
properties: {
|
|
233
|
+
top: {
|
|
234
|
+
type: "integer",
|
|
235
|
+
minimum: 1
|
|
236
|
+
},
|
|
237
|
+
severity: {
|
|
238
|
+
enum: ["notice", "warning", "error", "off"]
|
|
239
|
+
},
|
|
240
|
+
foundThreshold: {
|
|
241
|
+
anyOf: [
|
|
242
|
+
{ type: "number", minimum: 0, maximum: 100 },
|
|
243
|
+
{ type: "null" }
|
|
244
|
+
],
|
|
245
|
+
description: "`check` exits 1 when the percentage of reviewed questions found in the top `top` falls below this, 0-100. The same scale as stats.coverageThreshold. Null (the default) sets no rate gate. questions.severity does not touch it."
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
provenance: {
|
|
252
|
+
type: "object",
|
|
253
|
+
additionalProperties: false,
|
|
254
|
+
properties: {
|
|
255
|
+
qualified: {
|
|
256
|
+
type: "boolean"
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
},
|
|
260
|
+
stats: {
|
|
261
|
+
type: "object",
|
|
262
|
+
additionalProperties: false,
|
|
263
|
+
properties: {
|
|
264
|
+
coverageThreshold: {
|
|
265
|
+
anyOf: [
|
|
266
|
+
{
|
|
267
|
+
type: "number",
|
|
268
|
+
minimum: 0,
|
|
269
|
+
maximum: 100
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
type: "object",
|
|
273
|
+
additionalProperties: false,
|
|
274
|
+
properties: {
|
|
275
|
+
title: {
|
|
276
|
+
type: "number",
|
|
277
|
+
minimum: 0,
|
|
278
|
+
maximum: 100
|
|
279
|
+
},
|
|
280
|
+
description: {
|
|
281
|
+
type: "number",
|
|
282
|
+
minimum: 0,
|
|
283
|
+
maximum: 100
|
|
284
|
+
},
|
|
285
|
+
creator: {
|
|
286
|
+
type: "number",
|
|
287
|
+
minimum: 0,
|
|
288
|
+
maximum: 100
|
|
289
|
+
},
|
|
290
|
+
created: {
|
|
291
|
+
type: "number",
|
|
292
|
+
minimum: 0,
|
|
293
|
+
maximum: 100
|
|
294
|
+
},
|
|
295
|
+
modified: {
|
|
296
|
+
type: "number",
|
|
297
|
+
minimum: 0,
|
|
298
|
+
maximum: 100
|
|
299
|
+
},
|
|
300
|
+
subject: {
|
|
301
|
+
type: "number",
|
|
302
|
+
minimum: 0,
|
|
303
|
+
maximum: 100
|
|
304
|
+
},
|
|
305
|
+
label: {
|
|
306
|
+
type: "number",
|
|
307
|
+
minimum: 0,
|
|
308
|
+
maximum: 100
|
|
309
|
+
},
|
|
310
|
+
language: {
|
|
311
|
+
type: "number",
|
|
312
|
+
minimum: 0,
|
|
313
|
+
maximum: 100
|
|
314
|
+
},
|
|
315
|
+
type: {
|
|
316
|
+
type: "number",
|
|
317
|
+
minimum: 0,
|
|
318
|
+
maximum: 100
|
|
319
|
+
},
|
|
320
|
+
"applies-to": {
|
|
321
|
+
type: "number",
|
|
322
|
+
minimum: 0,
|
|
323
|
+
maximum: 100
|
|
324
|
+
},
|
|
325
|
+
"about-product-lifecycle": {
|
|
326
|
+
type: "number",
|
|
327
|
+
minimum: 0,
|
|
328
|
+
maximum: 100
|
|
329
|
+
},
|
|
330
|
+
"about-product-aspect": {
|
|
331
|
+
type: "number",
|
|
332
|
+
minimum: 0,
|
|
333
|
+
maximum: 100
|
|
334
|
+
},
|
|
335
|
+
"sample-questions": {
|
|
336
|
+
type: "number",
|
|
337
|
+
minimum: 0,
|
|
338
|
+
maximum: 100
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
]
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
},
|
|
346
|
+
fill: {
|
|
347
|
+
type: "object",
|
|
348
|
+
additionalProperties: false,
|
|
349
|
+
properties: {
|
|
350
|
+
temperature: {
|
|
351
|
+
type: "number",
|
|
352
|
+
minimum: 0,
|
|
353
|
+
maximum: 2
|
|
354
|
+
},
|
|
355
|
+
maxTurns: {
|
|
356
|
+
type: ["integer", "null"],
|
|
357
|
+
minimum: 1,
|
|
358
|
+
description: "Stop after this many inference calls. One page is one turn, and a cached proposal spends none. Null (the default) is unbounded. Replaces the maxCostUsd ceiling, which read as zero for every model outside the library's price table \u2014 see graph ADR 01027 and docevals ADR 01019."
|
|
359
|
+
},
|
|
360
|
+
cacheDir: {
|
|
361
|
+
type: "string",
|
|
362
|
+
minLength: 1
|
|
363
|
+
},
|
|
364
|
+
confidenceThreshold: {
|
|
365
|
+
type: "number",
|
|
366
|
+
minimum: 0,
|
|
367
|
+
maximum: 1,
|
|
368
|
+
description: "Minimum model self-confidence (0..1) to write a proposed field; below it the field is reported and not written. Default 0.7. `--confidence` wins over it."
|
|
369
|
+
},
|
|
370
|
+
writeProvenance: {
|
|
371
|
+
type: "boolean"
|
|
372
|
+
},
|
|
373
|
+
validateGraph: {
|
|
374
|
+
type: "boolean"
|
|
375
|
+
},
|
|
376
|
+
fields: {
|
|
377
|
+
type: "array",
|
|
378
|
+
uniqueItems: true,
|
|
379
|
+
items: {
|
|
380
|
+
enum: [
|
|
381
|
+
"label",
|
|
382
|
+
"alt-labels",
|
|
383
|
+
"broader",
|
|
384
|
+
"narrower",
|
|
385
|
+
"related-concepts",
|
|
386
|
+
"concepts",
|
|
387
|
+
"type",
|
|
388
|
+
"applies-to",
|
|
389
|
+
"about-product-lifecycle",
|
|
390
|
+
"about-product-aspect",
|
|
391
|
+
"not-applicable-to",
|
|
392
|
+
"not-about-product-aspect",
|
|
393
|
+
"sample-questions"
|
|
394
|
+
]
|
|
395
|
+
}
|
|
396
|
+
},
|
|
397
|
+
sections: {
|
|
398
|
+
type: "boolean"
|
|
399
|
+
},
|
|
400
|
+
chunkChars: {
|
|
401
|
+
type: "integer",
|
|
402
|
+
minimum: 1,
|
|
403
|
+
description: "The largest body piece one question request sends. Default 12000, as meta fill's. `--chunk-chars` wins over it."
|
|
404
|
+
},
|
|
405
|
+
offline: {
|
|
406
|
+
type: "boolean",
|
|
407
|
+
description: "Send nothing off this machine: use only a local model that is already downloaded. Default false. `--offline` wins over it."
|
|
408
|
+
},
|
|
409
|
+
questions: {
|
|
410
|
+
type: "object",
|
|
411
|
+
additionalProperties: false,
|
|
412
|
+
properties: {
|
|
413
|
+
perPage: {
|
|
414
|
+
type: "integer",
|
|
415
|
+
minimum: 1,
|
|
416
|
+
description: "Draft until a page has this many sample questions, reviewed or drafted. Default 3."
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
},
|
|
422
|
+
embed: {
|
|
423
|
+
type: "object",
|
|
424
|
+
additionalProperties: false,
|
|
425
|
+
properties: {
|
|
426
|
+
model: {
|
|
427
|
+
type: "string",
|
|
428
|
+
minLength: 1
|
|
429
|
+
},
|
|
430
|
+
dtype: {
|
|
431
|
+
type: "string",
|
|
432
|
+
minLength: 1
|
|
433
|
+
},
|
|
434
|
+
out: {
|
|
435
|
+
type: "string",
|
|
436
|
+
minLength: 1
|
|
437
|
+
},
|
|
438
|
+
cacheDir: {
|
|
439
|
+
type: "string",
|
|
440
|
+
minLength: 1
|
|
441
|
+
},
|
|
442
|
+
byLanguage: {
|
|
443
|
+
type: "object",
|
|
444
|
+
additionalProperties: false,
|
|
445
|
+
patternProperties: {
|
|
446
|
+
"^[A-Za-z]{2,3}(-[A-Za-z]{4})?(-([A-Za-z]{2}|[0-9]{3}))?(-([A-Za-z0-9]{5,8}|[0-9][A-Za-z0-9]{3}))*$": {
|
|
447
|
+
type: "object",
|
|
448
|
+
additionalProperties: false,
|
|
449
|
+
properties: {
|
|
450
|
+
model: {
|
|
451
|
+
type: "string",
|
|
452
|
+
minLength: 1
|
|
453
|
+
},
|
|
454
|
+
dtype: {
|
|
455
|
+
type: "string",
|
|
456
|
+
minLength: 1
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
},
|
|
464
|
+
export: {
|
|
465
|
+
type: "object",
|
|
466
|
+
additionalProperties: false,
|
|
467
|
+
properties: {
|
|
468
|
+
iirds: {
|
|
469
|
+
type: "object",
|
|
470
|
+
additionalProperties: false,
|
|
471
|
+
properties: {
|
|
472
|
+
title: {
|
|
473
|
+
type: "string",
|
|
474
|
+
minLength: 1
|
|
475
|
+
},
|
|
476
|
+
creator: {
|
|
477
|
+
type: "string",
|
|
478
|
+
minLength: 1
|
|
479
|
+
},
|
|
480
|
+
version: {
|
|
481
|
+
enum: ["1.2", "1.3"]
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
};
|
|
489
|
+
|
|
490
|
+
// src/graph/core/iirds.ts
|
|
491
|
+
var IIRDS_HAS_TOPIC_TYPE = `${NS.iirds}has-topic-type`;
|
|
492
|
+
var IIRDS_RELATES_TO_PRODUCT_VARIANT = `${NS.iirds}relates-to-product-variant`;
|
|
493
|
+
var IIRDS_RELATES_TO_LIFECYCLE_PHASE = `${NS.iirds}relates-to-product-lifecycle-phase`;
|
|
494
|
+
var IIRDS_HAS_SUBJECT = `${NS.iirds}has-subject`;
|
|
495
|
+
var IIRDS_PRODUCT_VARIANT = `${NS.iirds}ProductVariant`;
|
|
496
|
+
var IIRDS_PACKAGE = `${NS.iirds}Package`;
|
|
497
|
+
var IIRDS_IIRDS_VERSION = `${NS.iirds}iiRDSVersion`;
|
|
498
|
+
var IIRDS_TOPIC = `${NS.iirds}Topic`;
|
|
499
|
+
var IIRDS_IS_PART_OF_PACKAGE = `${NS.iirds}is-part-of-package`;
|
|
500
|
+
var IIRDS_HAS_RENDITION = `${NS.iirds}has-rendition`;
|
|
501
|
+
var IIRDS_RENDITION = `${NS.iirds}Rendition`;
|
|
502
|
+
var IIRDS_SOURCE = `${NS.iirds}source`;
|
|
503
|
+
var IIRDS_FORMAT = `${NS.iirds}format`;
|
|
504
|
+
var IIRDS_TITLE = `${NS.iirds}title`;
|
|
505
|
+
var IIRDS_LANGUAGE = `${NS.iirds}language`;
|
|
506
|
+
var IIRDS_PARTY = `${NS.iirds}Party`;
|
|
507
|
+
var IIRDS_HAS_PARTY_ROLE = `${NS.iirds}has-party-role`;
|
|
508
|
+
var IIRDS_CREATOR = `${NS.iirds}Creator`;
|
|
509
|
+
var IIRDS_RELATES_TO_PARTY = `${NS.iirds}relates-to-party`;
|
|
510
|
+
var IIRDS_RELATES_TO_VCARD = `${NS.iirds}relates-to-vcard`;
|
|
511
|
+
var VCARD_NS = "http://www.w3.org/2006/vcard/ns#";
|
|
512
|
+
var VCARD_ORGANIZATION = `${VCARD_NS}Organization`;
|
|
513
|
+
var VCARD_ORGANIZATION_NAME = `${VCARD_NS}organization-name`;
|
|
514
|
+
var GRAPH_NOT_APPLICABLE_TO_VARIANT = `${NS.graph}notApplicableToVariant`;
|
|
515
|
+
var GRAPH_NOT_SOFTWARE_SUBJECT = `${NS.graph}notSoftwareSubject`;
|
|
516
|
+
var PAGE_TYPE_TO_TOPIC_TYPE = {
|
|
517
|
+
"how-to": "task",
|
|
518
|
+
tutorial: "learning",
|
|
519
|
+
explanation: "concept",
|
|
520
|
+
reference: "reference",
|
|
521
|
+
troubleshooting: "troubleshooting"
|
|
522
|
+
};
|
|
523
|
+
var TOPIC_TYPE_IRIS = {
|
|
524
|
+
task: `${NS.iirds}GenericTask`,
|
|
525
|
+
concept: `${NS.iirds}GenericConcept`,
|
|
526
|
+
reference: `${NS.iirds}GenericReference`,
|
|
527
|
+
learning: `${NS.iirds}GenericLearning`,
|
|
528
|
+
troubleshooting: `${NS.iirds}GenericTroubleshooting`,
|
|
529
|
+
form: `${NS.iirds}GenericForm`
|
|
530
|
+
};
|
|
531
|
+
var SOFTWARE_LIFECYCLE_IRIS = {
|
|
532
|
+
administration: `${NS.iirdsSft}Administration`,
|
|
533
|
+
customization: `${NS.iirdsSft}Customization`,
|
|
534
|
+
update: `${NS.iirdsSft}Update`,
|
|
535
|
+
deployment: `${NS.iirdsSft}Deployment`,
|
|
536
|
+
integration: `${NS.iirdsSft}Integration`,
|
|
537
|
+
deinstallation: `${NS.iirdsSft}Deinstallation`
|
|
538
|
+
};
|
|
539
|
+
var SOFTWARE_SUBJECT_IRIS = {
|
|
540
|
+
architecture: `${NS.iirdsSft}Architecture`,
|
|
541
|
+
interface: `${NS.iirdsSft}Interface`,
|
|
542
|
+
"system-requirement": `${NS.iirdsSft}SystemRequirement`
|
|
543
|
+
};
|
|
544
|
+
|
|
545
|
+
// src/graph/core/coverage.ts
|
|
546
|
+
var COVERAGE_FIELDS = [
|
|
547
|
+
{ field: "title", iri: `${NS.dcterms}title` },
|
|
548
|
+
{ field: "description", iri: `${NS.dcterms}description` },
|
|
549
|
+
{ field: "creator", iri: `${NS.dcterms}creator` },
|
|
550
|
+
{ field: "created", iri: `${NS.dcterms}created` },
|
|
551
|
+
{ field: "modified", iri: `${NS.dcterms}modified` },
|
|
552
|
+
{ field: "subject", iri: `${NS.dcterms}subject` },
|
|
553
|
+
{ field: "label", iri: `${NS.foaf}primaryTopic` },
|
|
554
|
+
// Dropped by ADR 01011 as "near-universally 0% noise", which was true on the
|
|
555
|
+
// monolingual corpora it was measured against and false the moment language
|
|
556
|
+
// means something. Restored by ADR 01037, which made it a scope dimension:
|
|
557
|
+
// an unlabelled document in a translated corpus cannot be filtered, indexed
|
|
558
|
+
// per locale, or counted against the right audience.
|
|
559
|
+
{ field: "language", iri: `${NS.dcterms}language` },
|
|
560
|
+
// The iiRDS typing added in Phases 2–4. Coverage predates all of it, so the
|
|
561
|
+
// measure of "what a graph-side consumer can see" was silent about the
|
|
562
|
+
// vocabulary the project spent four phases adding (ADR 01029).
|
|
563
|
+
{ field: "type", iri: IIRDS_HAS_TOPIC_TYPE },
|
|
564
|
+
{ field: "applies-to", iri: IIRDS_RELATES_TO_PRODUCT_VARIANT },
|
|
565
|
+
{
|
|
566
|
+
field: "about-product-lifecycle",
|
|
567
|
+
iri: IIRDS_RELATES_TO_LIFECYCLE_PHASE
|
|
568
|
+
},
|
|
569
|
+
{ field: "about-product-aspect", iri: IIRDS_HAS_SUBJECT },
|
|
570
|
+
// Pages with a reader question (proposal 0087). Gated only by name.
|
|
571
|
+
{ field: "sample-questions", iri: `${NS.graph}sampleQuestion`, namedOnly: true }
|
|
572
|
+
];
|
|
573
|
+
var SECTION_FIELD_NAMES = [
|
|
574
|
+
"type",
|
|
575
|
+
"applies-to",
|
|
576
|
+
"about-product-lifecycle",
|
|
577
|
+
"about-product-aspect",
|
|
578
|
+
"subject"
|
|
579
|
+
];
|
|
580
|
+
var SECTION_COVERAGE_FIELDS = SECTION_FIELD_NAMES.map((name) => {
|
|
581
|
+
const field = COVERAGE_FIELDS.find((f) => f.field === name);
|
|
582
|
+
if (field === void 0) {
|
|
583
|
+
throw new Error(
|
|
584
|
+
`SECTION_FIELD_NAMES names ${name}, which COVERAGE_FIELDS does not define`
|
|
585
|
+
);
|
|
586
|
+
}
|
|
587
|
+
return field;
|
|
588
|
+
});
|
|
589
|
+
var COVERAGE_FIELD_NAMES = COVERAGE_FIELDS.map(
|
|
590
|
+
(f) => f.field
|
|
591
|
+
);
|
|
592
|
+
var UNIFORM_COVERAGE_FIELD_NAMES = COVERAGE_FIELDS.flatMap(
|
|
593
|
+
(f) => f.namedOnly ? [] : [f.field]
|
|
594
|
+
);
|
|
595
|
+
|
|
596
|
+
// src/graph/embed/types.ts
|
|
597
|
+
var DEFAULT_PROFILE = {
|
|
598
|
+
id: "onnx-community/granite-embedding-small-english-r2-ONNX",
|
|
599
|
+
note: "Default. 384-d, 8192-token context so sections are never truncated; no prefixes."
|
|
600
|
+
};
|
|
601
|
+
var MODEL_PROFILES = [
|
|
602
|
+
DEFAULT_PROFILE,
|
|
603
|
+
{
|
|
604
|
+
id: "Xenova/gte-small",
|
|
605
|
+
note: "Lighter (~34 MB). 384-d, 512-token context; no prefixes."
|
|
606
|
+
},
|
|
607
|
+
{
|
|
608
|
+
id: "Xenova/bge-small-en-v1.5",
|
|
609
|
+
queryPrefix: "Represent this sentence for searching relevant passages: ",
|
|
610
|
+
note: "384-d. Needs a query prefix \u2014 applied automatically here, since omitting it degrades retrieval silently."
|
|
611
|
+
},
|
|
612
|
+
{
|
|
613
|
+
id: "Xenova/all-MiniLM-L6-v2",
|
|
614
|
+
note: "Smallest (~23 MB) but truncates at 256 wordpieces (~190 words), so long sections lose their tail."
|
|
615
|
+
}
|
|
616
|
+
];
|
|
617
|
+
var DEFAULT_MODEL = DEFAULT_PROFILE.id;
|
|
618
|
+
function profileFor(id) {
|
|
619
|
+
return MODEL_PROFILES.find((p) => p.id === id) ?? { id };
|
|
620
|
+
}
|
|
621
|
+
function withPrefix(profile, role, text) {
|
|
622
|
+
const prefix = role === "query" ? profile.queryPrefix : profile.passagePrefix;
|
|
623
|
+
return prefix ? `${prefix}${text}` : text;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
// src/graph/core/config.ts
|
|
627
|
+
var ALL_FILL_FIELDS = [
|
|
628
|
+
"label",
|
|
629
|
+
"alt-labels",
|
|
630
|
+
"broader",
|
|
631
|
+
"narrower",
|
|
632
|
+
"related-concepts",
|
|
633
|
+
"concepts",
|
|
634
|
+
"type",
|
|
635
|
+
"applies-to",
|
|
636
|
+
"about-product-lifecycle",
|
|
637
|
+
"about-product-aspect",
|
|
638
|
+
"not-applicable-to",
|
|
639
|
+
"not-about-product-aspect",
|
|
640
|
+
"sample-questions"
|
|
641
|
+
];
|
|
642
|
+
var DEFAULT_CONFIG_FILENAME = "manni.config.yaml";
|
|
643
|
+
var CONFIG_SECTION = "graph";
|
|
644
|
+
var COLLECTIONS_KEY = "collections";
|
|
645
|
+
var CONFIG_REF = "https://hawkeyexl.github.io/manni/meta/reference/configuration/";
|
|
646
|
+
var MOVED_KEYS = ["inputs", "exclude"];
|
|
647
|
+
var ALL_DERIVE_SOURCES = [
|
|
648
|
+
"frontmatter",
|
|
649
|
+
"sections",
|
|
650
|
+
"links",
|
|
651
|
+
"tags",
|
|
652
|
+
"images",
|
|
653
|
+
"code",
|
|
654
|
+
"provenance",
|
|
655
|
+
"terms"
|
|
656
|
+
];
|
|
657
|
+
var DEFAULT_LINK_EXTENSIONS = [
|
|
658
|
+
".md",
|
|
659
|
+
".mdx",
|
|
660
|
+
".markdown",
|
|
661
|
+
".html",
|
|
662
|
+
".htm",
|
|
663
|
+
".adoc",
|
|
664
|
+
".asciidoc",
|
|
665
|
+
".rst",
|
|
666
|
+
".dita",
|
|
667
|
+
".ditamap"
|
|
668
|
+
];
|
|
669
|
+
var DEFAULT_INDEX_FILES = ["index", "README"];
|
|
670
|
+
function normalizeBasePath(basePath) {
|
|
671
|
+
let out = basePath.trim();
|
|
672
|
+
if (!out.startsWith("/")) out = `/${out}`;
|
|
673
|
+
out = out.replace(/\/+$/, "");
|
|
674
|
+
return out;
|
|
675
|
+
}
|
|
676
|
+
var ajv = new Ajv2020({ allErrors: true, allowUnionTypes: true });
|
|
677
|
+
var validateConfig = ajv.compile(config_schema_default);
|
|
678
|
+
function configErrorLine(e) {
|
|
679
|
+
const extra = e.keyword === "additionalProperties" ? e.params.additionalProperty : void 0;
|
|
680
|
+
const where = `/${CONFIG_SECTION}${e.instancePath}`;
|
|
681
|
+
return extra === void 0 ? ` ${where}: ${e.message ?? "is invalid"}` : ` ${where}: unknown key "${extra}"`;
|
|
682
|
+
}
|
|
683
|
+
function resolveCoverageThreshold(raw) {
|
|
684
|
+
if (raw == null) return {};
|
|
685
|
+
if (typeof raw === "number")
|
|
686
|
+
return Object.fromEntries(UNIFORM_COVERAGE_FIELD_NAMES.map((f) => [f, raw]));
|
|
687
|
+
return { ...raw };
|
|
688
|
+
}
|
|
689
|
+
function parseConfig(text, configPath) {
|
|
690
|
+
let raw;
|
|
691
|
+
try {
|
|
692
|
+
raw = parseYaml(text);
|
|
693
|
+
} catch (e) {
|
|
694
|
+
throw new GraphError(
|
|
695
|
+
`Invalid YAML in ${configPath}: ${errorMessage(e)}`
|
|
696
|
+
);
|
|
697
|
+
}
|
|
698
|
+
if (raw == null) return parseConfigSection(null, configPath);
|
|
699
|
+
if (typeof raw !== "object" || Array.isArray(raw)) {
|
|
700
|
+
throw new GraphError(`Invalid config in ${configPath}: root must be an object`);
|
|
701
|
+
}
|
|
702
|
+
const doc = raw;
|
|
703
|
+
const wrapped = Object.hasOwn(doc, CONFIG_SECTION);
|
|
704
|
+
const toError = (message) => new GraphError(message);
|
|
705
|
+
const collections = Object.hasOwn(doc, COLLECTIONS_KEY) ? parseCollections(doc[COLLECTIONS_KEY], configPath, toError) : [];
|
|
706
|
+
const providers = Object.hasOwn(doc, PROVIDERS_KEY) ? parseProviders(
|
|
707
|
+
doc[PROVIDERS_KEY],
|
|
708
|
+
configPath,
|
|
709
|
+
dirname(resolve(configPath)),
|
|
710
|
+
toError
|
|
711
|
+
) : {};
|
|
712
|
+
return parseConfigSection(wrapped ? doc[CONFIG_SECTION] : doc, configPath, {
|
|
713
|
+
source: configPath,
|
|
714
|
+
collections,
|
|
715
|
+
providers
|
|
716
|
+
});
|
|
717
|
+
}
|
|
718
|
+
function parseConfigSection(raw, configPath, file = { source: configPath, collections: [] }) {
|
|
719
|
+
if (raw == null) raw = {};
|
|
720
|
+
if (typeof raw !== "object" || Array.isArray(raw)) {
|
|
721
|
+
throw new GraphError(
|
|
722
|
+
`Invalid config in ${configPath}: root must be an object`
|
|
723
|
+
);
|
|
724
|
+
}
|
|
725
|
+
for (const key of MOVED_KEYS) {
|
|
726
|
+
if (Object.hasOwn(raw, key)) {
|
|
727
|
+
throw new GraphError(
|
|
728
|
+
`${file.source}: "${key}" is no longer a graph key. Document sets are declared once for every tool, under a top-level collections: list. See ${CONFIG_REF}#${COLLECTIONS_KEY}`
|
|
729
|
+
);
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
if (!validateConfig(raw)) {
|
|
733
|
+
const details = (validateConfig.errors ?? []).map((e) => configErrorLine(e)).join("\n");
|
|
734
|
+
throw new GraphError(`Invalid config in ${configPath}:
|
|
735
|
+
${details}`);
|
|
736
|
+
}
|
|
737
|
+
const r = raw;
|
|
738
|
+
const abs = resolve(configPath);
|
|
739
|
+
const dir = dirname(abs);
|
|
740
|
+
const provider = r.provider ?? null;
|
|
741
|
+
if (provider !== null) {
|
|
742
|
+
assertKnownProvider(provider, (message) => new GraphError(message));
|
|
743
|
+
}
|
|
744
|
+
return {
|
|
745
|
+
collections: file.collections,
|
|
746
|
+
configSource: file.source,
|
|
747
|
+
provider,
|
|
748
|
+
model: r.model ?? null,
|
|
749
|
+
providers: file.providers ?? {},
|
|
750
|
+
baseIri: resolveBaseIri(r.baseIri),
|
|
751
|
+
out: r.out ?? "graph/graph.ttl",
|
|
752
|
+
routes: (r.routes ?? []).map((m) => ({
|
|
753
|
+
basePath: normalizeBasePath(m.basePath ?? "/"),
|
|
754
|
+
root: m.root.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+$/, ""),
|
|
755
|
+
extensions: m.extensions ?? [...DEFAULT_LINK_EXTENSIONS],
|
|
756
|
+
indexFiles: m.indexFiles ?? [...DEFAULT_INDEX_FILES],
|
|
757
|
+
...m.language === void 0 ? {} : { language: m.language }
|
|
758
|
+
})),
|
|
759
|
+
questionFiles: r.questionFiles ?? [],
|
|
760
|
+
build: {
|
|
761
|
+
derive: r.build?.derive ?? [...ALL_DERIVE_SOURCES]
|
|
762
|
+
},
|
|
763
|
+
check: {
|
|
764
|
+
// Empty means: use the shapes bundled with manni (see bundledShapesPath).
|
|
765
|
+
shapes: r.check?.shapes ?? [],
|
|
766
|
+
questions: {
|
|
767
|
+
top: r.check?.questions?.top ?? 5,
|
|
768
|
+
severity: r.check?.questions?.severity ?? "warning",
|
|
769
|
+
foundThreshold: r.check?.questions?.foundThreshold ?? null
|
|
770
|
+
}
|
|
771
|
+
},
|
|
772
|
+
provenance: {
|
|
773
|
+
qualified: r.provenance?.qualified ?? true
|
|
774
|
+
},
|
|
775
|
+
stats: {
|
|
776
|
+
coverageThreshold: resolveCoverageThreshold(r.stats?.coverageThreshold)
|
|
777
|
+
},
|
|
778
|
+
fill: {
|
|
779
|
+
temperature: r.fill?.temperature ?? 0,
|
|
780
|
+
maxTurns: r.fill?.maxTurns ?? null,
|
|
781
|
+
cacheDir: r.fill?.cacheDir ?? ".manni/graph/cache",
|
|
782
|
+
fields: r.fill?.fields ?? [...ALL_FILL_FIELDS],
|
|
783
|
+
confidenceThreshold: r.fill?.confidenceThreshold ?? 0.7,
|
|
784
|
+
writeProvenance: r.fill?.writeProvenance ?? true,
|
|
785
|
+
validateGraph: r.fill?.validateGraph ?? true,
|
|
786
|
+
sections: r.fill?.sections ?? false,
|
|
787
|
+
chunkChars: r.fill?.chunkChars ?? DEFAULT_CHUNK_CHARS,
|
|
788
|
+
offline: r.fill?.offline ?? false,
|
|
789
|
+
questions: { perPage: r.fill?.questions?.perPage ?? 3 }
|
|
790
|
+
},
|
|
791
|
+
embed: {
|
|
792
|
+
model: r.embed?.model ?? DEFAULT_MODEL,
|
|
793
|
+
dtype: r.embed?.dtype ?? "q8",
|
|
794
|
+
out: r.embed?.out,
|
|
795
|
+
cacheDir: r.embed?.cacheDir ?? ".manni/graph/embed-cache",
|
|
796
|
+
byLanguage: r.embed?.byLanguage ?? {}
|
|
797
|
+
},
|
|
798
|
+
export: {
|
|
799
|
+
iirds: {
|
|
800
|
+
title: r.export?.iirds?.title,
|
|
801
|
+
creator: r.export?.iirds?.creator,
|
|
802
|
+
version: r.export?.iirds?.version ?? "1.3"
|
|
803
|
+
}
|
|
804
|
+
},
|
|
805
|
+
configPath: abs,
|
|
806
|
+
configDir: dir
|
|
807
|
+
};
|
|
808
|
+
}
|
|
809
|
+
var CONFIG_FILE = {
|
|
810
|
+
section: CONFIG_SECTION,
|
|
811
|
+
// The tool was `dockg` before it joined the family (proposal 0051 §7), but
|
|
812
|
+
// it published no config file under that old name, so — like cite, a11y and
|
|
813
|
+
// docevals — there is no pre-family filename to read (proposal 0051 §2).
|
|
814
|
+
legacyNames: [],
|
|
815
|
+
toError: (message) => new GraphError(message)
|
|
816
|
+
};
|
|
817
|
+
function loadConfig(path, cwd = process.cwd()) {
|
|
818
|
+
const file = path ? readConfigFileSync(path, cwd, CONFIG_FILE) : findConfigFileSync(cwd, CONFIG_FILE);
|
|
819
|
+
if (file === null) return defaultConfig(cwd);
|
|
820
|
+
return parseConfigSection(file.value, file.path, {
|
|
821
|
+
source: file.source,
|
|
822
|
+
collections: file.collections,
|
|
823
|
+
...file.providers === void 0 ? {} : { providers: file.providers }
|
|
824
|
+
});
|
|
825
|
+
}
|
|
826
|
+
function defaultConfig(cwd = process.cwd()) {
|
|
827
|
+
return {
|
|
828
|
+
...parseConfigSection(null, resolve(cwd, DEFAULT_CONFIG_FILENAME)),
|
|
829
|
+
configSource: null
|
|
830
|
+
};
|
|
831
|
+
}
|
|
832
|
+
function loadRunConfig(opts, cwd = process.cwd()) {
|
|
833
|
+
assertCollectionWithoutPaths(opts.collection, opts.paths);
|
|
834
|
+
return opts.noConfig ? defaultConfig(cwd) : loadConfig(opts.configPath, cwd);
|
|
835
|
+
}
|
|
836
|
+
function assertCollectionWithoutPaths(collection, paths) {
|
|
837
|
+
if ((collection ?? []).length > 0 && (paths ?? []).length > 0) {
|
|
838
|
+
throw new GraphError(
|
|
839
|
+
"--collection selects a configured collection; it cannot be combined with paths."
|
|
840
|
+
);
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
// src/graph/core/analyze.ts
|
|
845
|
+
import { createHash } from "node:crypto";
|
|
846
|
+
import { extname } from "node:path";
|
|
847
|
+
import { unified } from "unified";
|
|
848
|
+
import remarkParse from "remark-parse";
|
|
849
|
+
import remarkGfm from "remark-gfm";
|
|
850
|
+
import remarkFrontmatter from "remark-frontmatter";
|
|
851
|
+
import remarkMdx from "remark-mdx";
|
|
852
|
+
import { toString as mdastToString } from "mdast-util-to-string";
|
|
853
|
+
import GithubSlugger from "github-slugger";
|
|
854
|
+
var DOC_FORMATS = [
|
|
855
|
+
"asciidoc",
|
|
856
|
+
"html",
|
|
857
|
+
"markdown",
|
|
858
|
+
"mdx",
|
|
859
|
+
"rst",
|
|
860
|
+
"xml"
|
|
861
|
+
];
|
|
862
|
+
function isTreeFormat(format) {
|
|
863
|
+
return format !== "markdown" && format !== "mdx";
|
|
864
|
+
}
|
|
865
|
+
function isDocFormat(name) {
|
|
866
|
+
return DOC_FORMATS.includes(name);
|
|
867
|
+
}
|
|
868
|
+
function formatOf(path, format) {
|
|
869
|
+
if (format !== void 0) return format;
|
|
870
|
+
const name = parserForExtension(extname(path))?.name;
|
|
871
|
+
return name !== void 0 && isDocFormat(name) ? name : "markdown";
|
|
872
|
+
}
|
|
873
|
+
var processor = unified().use(remarkParse).use(remarkGfm).use(remarkFrontmatter, ["yaml", "toml"]);
|
|
874
|
+
var mdxProcessor = unified().use(remarkParse).use(remarkGfm).use(remarkFrontmatter, ["yaml", "toml"]).use(remarkMdx);
|
|
875
|
+
var IMAGE_ELEMENTS = /* @__PURE__ */ new Set(["img", "image"]);
|
|
876
|
+
function jsxAttributeValue(node, attributeName) {
|
|
877
|
+
const attributes = node.attributes;
|
|
878
|
+
if (!Array.isArray(attributes)) return void 0;
|
|
879
|
+
for (const attribute of attributes) {
|
|
880
|
+
if (attribute.type !== "mdxJsxAttribute") continue;
|
|
881
|
+
if (attribute.name !== attributeName) continue;
|
|
882
|
+
return typeof attribute.value === "string" ? attribute.value : void 0;
|
|
883
|
+
}
|
|
884
|
+
return void 0;
|
|
885
|
+
}
|
|
886
|
+
function hasScheme(target) {
|
|
887
|
+
return /^[a-z][a-z0-9+.-]*:/i.test(target);
|
|
888
|
+
}
|
|
889
|
+
function resolveRelative(docPath, target) {
|
|
890
|
+
const baseSegments = normalizeDocPath(docPath).split("/").slice(0, -1);
|
|
891
|
+
const segments = [...baseSegments];
|
|
892
|
+
for (const part of target.split("/")) {
|
|
893
|
+
if (part === "" || part === ".") continue;
|
|
894
|
+
if (part === "..") {
|
|
895
|
+
if (segments.length === 0) return null;
|
|
896
|
+
if (segments[segments.length - 1] === "..") segments.push("..");
|
|
897
|
+
else segments.pop();
|
|
898
|
+
} else {
|
|
899
|
+
segments.push(part);
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
return segments.join("/");
|
|
903
|
+
}
|
|
904
|
+
var HAS_EXTENSION = /\.[a-z0-9]+$/i;
|
|
905
|
+
function addressesDocument(target, extensions) {
|
|
906
|
+
if (target === "" || !HAS_EXTENSION.test(target)) return true;
|
|
907
|
+
if (extensions.length === 0) return true;
|
|
908
|
+
const ext = target.slice(target.lastIndexOf(".")).toLowerCase();
|
|
909
|
+
return extensions.some((e) => e.toLowerCase() === ext);
|
|
910
|
+
}
|
|
911
|
+
function slugNorm(path) {
|
|
912
|
+
return path.toLowerCase().replace(/[-_]/g, "");
|
|
913
|
+
}
|
|
914
|
+
var PathIndex = class {
|
|
915
|
+
constructor(exact) {
|
|
916
|
+
this.exact = exact;
|
|
917
|
+
for (const path of exact) {
|
|
918
|
+
const lower = path.toLowerCase();
|
|
919
|
+
this.lower.set(lower, this.lower.has(lower) ? null : path);
|
|
920
|
+
const slug = slugNorm(path);
|
|
921
|
+
this.slugged.set(slug, this.slugged.has(slug) ? null : path);
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
exact;
|
|
925
|
+
lower = /* @__PURE__ */ new Map();
|
|
926
|
+
slugged = /* @__PURE__ */ new Map();
|
|
927
|
+
resolve(candidate) {
|
|
928
|
+
if (this.exact.has(candidate)) return candidate;
|
|
929
|
+
return this.lower.get(candidate.toLowerCase()) ?? this.slugged.get(slugNorm(candidate)) ?? void 0;
|
|
930
|
+
}
|
|
931
|
+
};
|
|
932
|
+
function safeDecode(value) {
|
|
933
|
+
try {
|
|
934
|
+
return decodeURIComponent(value);
|
|
935
|
+
} catch {
|
|
936
|
+
return value;
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
function targetCandidates(target, isDirectory, extensions, indexFiles) {
|
|
940
|
+
if (target !== "" && HAS_EXTENSION.test(target)) return [target];
|
|
941
|
+
const extensionCandidates = target === "" ? [] : extensions.map((ext) => `${target}${ext}`);
|
|
942
|
+
const dir = target === "" ? "" : `${target}/`;
|
|
943
|
+
const indexCandidates = [];
|
|
944
|
+
for (const indexFile of indexFiles) {
|
|
945
|
+
for (const ext of extensions)
|
|
946
|
+
indexCandidates.push(`${dir}${indexFile}${ext}`);
|
|
947
|
+
}
|
|
948
|
+
return isDirectory ? [...indexCandidates, ...extensionCandidates] : [...extensionCandidates, ...indexCandidates];
|
|
949
|
+
}
|
|
950
|
+
function routeLanguageFor(path, routes) {
|
|
951
|
+
let best;
|
|
952
|
+
for (const mapping of routes) {
|
|
953
|
+
if (mapping.language === void 0) continue;
|
|
954
|
+
const root = mapping.root;
|
|
955
|
+
const covers = root === "" || path === root || path.startsWith(`${root}/`);
|
|
956
|
+
if (!covers) continue;
|
|
957
|
+
if (best === void 0 || root.length > best.root.length) {
|
|
958
|
+
best = { root, language: mapping.language };
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
return best?.language;
|
|
962
|
+
}
|
|
963
|
+
function resolveRoute(pathPart, routes, index) {
|
|
964
|
+
const isDirectory = /\/+$/.test(pathPart);
|
|
965
|
+
const clean = safeDecode(pathPart).replace(/\/+$/, "");
|
|
966
|
+
let anyMatched = false;
|
|
967
|
+
for (const mapping of routes) {
|
|
968
|
+
if (clean !== mapping.basePath && !clean.startsWith(`${mapping.basePath}/`)) {
|
|
969
|
+
continue;
|
|
970
|
+
}
|
|
971
|
+
const rest = clean.slice(mapping.basePath.length).replace(/^\/+/, "");
|
|
972
|
+
if (!addressesDocument(rest, mapping.extensions)) continue;
|
|
973
|
+
anyMatched = true;
|
|
974
|
+
const prefix = mapping.root ? `${mapping.root}/` : "";
|
|
975
|
+
const stem = rest === "" ? mapping.root : `${prefix}${rest}`;
|
|
976
|
+
const candidates = targetCandidates(
|
|
977
|
+
stem,
|
|
978
|
+
isDirectory || rest === "",
|
|
979
|
+
mapping.extensions,
|
|
980
|
+
mapping.indexFiles
|
|
981
|
+
);
|
|
982
|
+
for (const candidate of candidates) {
|
|
983
|
+
const resolved = index.resolve(candidate);
|
|
984
|
+
if (resolved) return resolved;
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
return anyMatched ? "broken" : null;
|
|
988
|
+
}
|
|
989
|
+
var indexCache = /* @__PURE__ */ new WeakMap();
|
|
990
|
+
function pathIndexFor(allPaths) {
|
|
991
|
+
let index = indexCache.get(allPaths);
|
|
992
|
+
if (!index) {
|
|
993
|
+
index = new PathIndex(allPaths);
|
|
994
|
+
indexCache.set(allPaths, index);
|
|
995
|
+
}
|
|
996
|
+
return index;
|
|
997
|
+
}
|
|
998
|
+
function classifyLink(docPath, rawTarget, allPaths, routes) {
|
|
999
|
+
const raw = rawTarget;
|
|
1000
|
+
if (hasScheme(raw)) {
|
|
1001
|
+
try {
|
|
1002
|
+
return { raw, kind: "external", url: new URL(raw).href };
|
|
1003
|
+
} catch {
|
|
1004
|
+
return null;
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
const hashAt = raw.indexOf("#");
|
|
1008
|
+
const pathPart = hashAt === -1 ? raw : raw.slice(0, hashAt);
|
|
1009
|
+
const anchor = hashAt === -1 ? void 0 : raw.slice(hashAt + 1);
|
|
1010
|
+
if (pathPart === "") return null;
|
|
1011
|
+
if (pathPart.startsWith("/")) {
|
|
1012
|
+
const resolved2 = resolveRoute(pathPart, routes, pathIndexFor(allPaths));
|
|
1013
|
+
if (resolved2 === null) return null;
|
|
1014
|
+
if (resolved2 === "broken") return { raw, kind: "broken" };
|
|
1015
|
+
const link = { raw, kind: "internal", resolvedPath: resolved2 };
|
|
1016
|
+
if (anchor) link.anchor = anchor;
|
|
1017
|
+
return link;
|
|
1018
|
+
}
|
|
1019
|
+
const resolved = resolveRelative(docPath, safeDecode(pathPart));
|
|
1020
|
+
if (resolved !== null) {
|
|
1021
|
+
const index = pathIndexFor(allPaths);
|
|
1022
|
+
let candidates;
|
|
1023
|
+
if (allPaths.has(resolved)) {
|
|
1024
|
+
candidates = [resolved];
|
|
1025
|
+
} else if (HAS_EXTENSION.test(resolved)) {
|
|
1026
|
+
if (!addressesDocument(resolved, DEFAULT_LINK_EXTENSIONS)) return null;
|
|
1027
|
+
candidates = [];
|
|
1028
|
+
} else {
|
|
1029
|
+
candidates = targetCandidates(
|
|
1030
|
+
resolved,
|
|
1031
|
+
pathPart.endsWith("/"),
|
|
1032
|
+
DEFAULT_LINK_EXTENSIONS,
|
|
1033
|
+
DEFAULT_INDEX_FILES
|
|
1034
|
+
);
|
|
1035
|
+
}
|
|
1036
|
+
for (const candidate of candidates) {
|
|
1037
|
+
const hit = index.resolve(candidate);
|
|
1038
|
+
if (hit) {
|
|
1039
|
+
const link = { raw, kind: "internal", resolvedPath: hit };
|
|
1040
|
+
if (anchor) link.anchor = anchor;
|
|
1041
|
+
return link;
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
return { raw, kind: "broken" };
|
|
1046
|
+
}
|
|
1047
|
+
function classifyImage(docPath, rawTarget) {
|
|
1048
|
+
if (hasScheme(rawTarget)) {
|
|
1049
|
+
return { raw: rawTarget, target: rawTarget, external: true };
|
|
1050
|
+
}
|
|
1051
|
+
const resolved = resolveRelative(docPath, rawTarget);
|
|
1052
|
+
return { raw: rawTarget, target: resolved ?? rawTarget, external: false };
|
|
1053
|
+
}
|
|
1054
|
+
function extractorFor(format) {
|
|
1055
|
+
return extractorForExtension(parserByName(format)?.extensions[0] ?? "");
|
|
1056
|
+
}
|
|
1057
|
+
function metadataOf(content, path, format) {
|
|
1058
|
+
try {
|
|
1059
|
+
const meta = format === "markdown" || format === "mdx" ? extractFrontmatter(content, "markdown") : extractorFor(format)?.extract(content, path);
|
|
1060
|
+
return meta === void 0 ? { data: {}, present: false } : { data: meta.data, present: meta.present };
|
|
1061
|
+
} catch (error) {
|
|
1062
|
+
throw new GraphError(`${path}: ${errorMessage(error)}`);
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
function analyzeDoc(content, relPath, allPaths, options = {}) {
|
|
1066
|
+
const routes = options.routes ?? [];
|
|
1067
|
+
const path = normalizeDocPath(relPath);
|
|
1068
|
+
const format = formatOf(path, options.format);
|
|
1069
|
+
const parse = options.parse ?? parseBody;
|
|
1070
|
+
let body = isTreeFormat(format) ? parse(content, path, format) : void 0;
|
|
1071
|
+
const meta = metadataOf(content, path, format);
|
|
1072
|
+
body ??= parse(content, path, format);
|
|
1073
|
+
const links = [];
|
|
1074
|
+
for (const target of body.linkTargets) {
|
|
1075
|
+
const link = classifyLink(path, target, allPaths, routes);
|
|
1076
|
+
if (link) links.push(link);
|
|
1077
|
+
}
|
|
1078
|
+
const routeLanguage = routeLanguageFor(path, routes);
|
|
1079
|
+
return {
|
|
1080
|
+
path,
|
|
1081
|
+
frontmatter: meta.data,
|
|
1082
|
+
frontmatterPresent: meta.present,
|
|
1083
|
+
format,
|
|
1084
|
+
firstH1: body.firstH1,
|
|
1085
|
+
sections: body.sections,
|
|
1086
|
+
links,
|
|
1087
|
+
images: body.imageTargets.map((target) => classifyImage(path, target)),
|
|
1088
|
+
codeLanguages: body.codeLanguages,
|
|
1089
|
+
// Omitted rather than set to undefined, so a doc under no localized route
|
|
1090
|
+
// carries no key at all — `routeLanguage` in JSON output means something.
|
|
1091
|
+
...routeLanguage === void 0 ? {} : { routeLanguage },
|
|
1092
|
+
// Over the content as read — line endings included, so the digest is
|
|
1093
|
+
// byte-faithful and equals `sha256sum <file>` for any valid-UTF-8 file
|
|
1094
|
+
// (ADR 01036). The CRLF corpus fixture depends on this not normalizing.
|
|
1095
|
+
contentHash: createHash("sha256").update(content, "utf8").digest("hex")
|
|
1096
|
+
};
|
|
1097
|
+
}
|
|
1098
|
+
function parseBody(content, path, format) {
|
|
1099
|
+
if (isTreeFormat(format)) return parseTreeBody(content, path, format);
|
|
1100
|
+
const isMdx = format === "mdx";
|
|
1101
|
+
let tree;
|
|
1102
|
+
try {
|
|
1103
|
+
tree = (isMdx ? mdxProcessor : processor).parse(content);
|
|
1104
|
+
} catch (error) {
|
|
1105
|
+
if (!isMdx) throw error;
|
|
1106
|
+
const reason = errorMessage(error);
|
|
1107
|
+
throw new GraphError(`Could not parse MDX in ${path}: ${reason}`);
|
|
1108
|
+
}
|
|
1109
|
+
const sections = [];
|
|
1110
|
+
const linkTargets = [];
|
|
1111
|
+
const imageTargets = [];
|
|
1112
|
+
const codeLanguages = /* @__PURE__ */ new Set();
|
|
1113
|
+
const definitions = /* @__PURE__ */ new Map();
|
|
1114
|
+
let firstH1;
|
|
1115
|
+
visit(tree, (node) => {
|
|
1116
|
+
if (node.type === "definition") {
|
|
1117
|
+
const def = node;
|
|
1118
|
+
definitions.set(def.identifier, def);
|
|
1119
|
+
}
|
|
1120
|
+
});
|
|
1121
|
+
const slugger = new GithubSlugger();
|
|
1122
|
+
const stack = [];
|
|
1123
|
+
const childCount = /* @__PURE__ */ new Map();
|
|
1124
|
+
visit(tree, (node) => {
|
|
1125
|
+
switch (node.type) {
|
|
1126
|
+
case "heading": {
|
|
1127
|
+
const level = node.depth;
|
|
1128
|
+
const title = mdastToString(node);
|
|
1129
|
+
const slug = slugger.slug(title);
|
|
1130
|
+
if (level === 1 && firstH1 === void 0) firstH1 = title;
|
|
1131
|
+
for (let top = stack.at(-1); top !== void 0 && top.level >= level; top = stack.at(-1)) {
|
|
1132
|
+
stack.pop();
|
|
1133
|
+
}
|
|
1134
|
+
const parentSlug = stack.at(-1)?.slug ?? null;
|
|
1135
|
+
const parentKey = parentSlug ?? "";
|
|
1136
|
+
const order = (childCount.get(parentKey) ?? 0) + 1;
|
|
1137
|
+
childCount.set(parentKey, order);
|
|
1138
|
+
sections.push({ slug, title, level, order, parentSlug });
|
|
1139
|
+
stack.push({ level, slug });
|
|
1140
|
+
break;
|
|
1141
|
+
}
|
|
1142
|
+
case "link": {
|
|
1143
|
+
linkTargets.push(node.url);
|
|
1144
|
+
break;
|
|
1145
|
+
}
|
|
1146
|
+
case "linkReference": {
|
|
1147
|
+
const def = definitions.get(
|
|
1148
|
+
node.identifier
|
|
1149
|
+
);
|
|
1150
|
+
if (def) linkTargets.push(def.url);
|
|
1151
|
+
break;
|
|
1152
|
+
}
|
|
1153
|
+
case "image": {
|
|
1154
|
+
imageTargets.push(node.url);
|
|
1155
|
+
break;
|
|
1156
|
+
}
|
|
1157
|
+
case "imageReference": {
|
|
1158
|
+
const def = definitions.get(
|
|
1159
|
+
node.identifier
|
|
1160
|
+
);
|
|
1161
|
+
if (def) imageTargets.push(def.url);
|
|
1162
|
+
break;
|
|
1163
|
+
}
|
|
1164
|
+
case "code": {
|
|
1165
|
+
const lang = node.lang;
|
|
1166
|
+
if (lang) codeLanguages.add(lang);
|
|
1167
|
+
break;
|
|
1168
|
+
}
|
|
1169
|
+
// A JSX element's `href` is a link and its `src` is an image, on any
|
|
1170
|
+
// element (ADR 01022). Those are HTML's own names for the relationships,
|
|
1171
|
+
// so this stays structural — dockg never learns what `<LinkCard>` means.
|
|
1172
|
+
case "mdxJsxFlowElement":
|
|
1173
|
+
case "mdxJsxTextElement": {
|
|
1174
|
+
const href = jsxAttributeValue(node, "href");
|
|
1175
|
+
if (href !== void 0) linkTargets.push(href);
|
|
1176
|
+
const name = node.name ?? "";
|
|
1177
|
+
if (IMAGE_ELEMENTS.has(name.toLowerCase())) {
|
|
1178
|
+
const src = jsxAttributeValue(node, "src");
|
|
1179
|
+
if (src !== void 0) imageTargets.push(src);
|
|
1180
|
+
}
|
|
1181
|
+
break;
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
});
|
|
1185
|
+
return {
|
|
1186
|
+
firstH1,
|
|
1187
|
+
sections,
|
|
1188
|
+
linkTargets,
|
|
1189
|
+
imageTargets,
|
|
1190
|
+
codeLanguages: [...codeLanguages].sort()
|
|
1191
|
+
};
|
|
1192
|
+
}
|
|
1193
|
+
function parseTree(content, path, format) {
|
|
1194
|
+
const parser = parserByName(format);
|
|
1195
|
+
if (parser === void 0) {
|
|
1196
|
+
throw new GraphError(`No parser reads ${format}.`);
|
|
1197
|
+
}
|
|
1198
|
+
try {
|
|
1199
|
+
return parser.parse(content, path);
|
|
1200
|
+
} catch (error) {
|
|
1201
|
+
throw new GraphError(
|
|
1202
|
+
`Could not parse ${format} in ${path}: ${errorMessage(error)}`
|
|
1203
|
+
);
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
var IRI_SAFE_ID = /^[A-Za-z_][A-Za-z0-9_.:-]*$/;
|
|
1207
|
+
function mintTreeSections(roots) {
|
|
1208
|
+
const out = {
|
|
1209
|
+
sections: [],
|
|
1210
|
+
owned: [],
|
|
1211
|
+
nodes: [],
|
|
1212
|
+
unowned: [],
|
|
1213
|
+
firstH1: void 0
|
|
1214
|
+
};
|
|
1215
|
+
const slugger = new GithubSlugger();
|
|
1216
|
+
const taken = /* @__PURE__ */ new Set();
|
|
1217
|
+
const childCount = /* @__PURE__ */ new Map();
|
|
1218
|
+
const anchorFor = (node) => {
|
|
1219
|
+
const id = node.id;
|
|
1220
|
+
if (id !== void 0 && IRI_SAFE_ID.test(id) && !id.startsWith("prov.")) {
|
|
1221
|
+
let anchor2 = id;
|
|
1222
|
+
for (let n = 1; taken.has(anchor2); n++) anchor2 = `${id}-${String(n)}`;
|
|
1223
|
+
taken.add(anchor2);
|
|
1224
|
+
return anchor2;
|
|
1225
|
+
}
|
|
1226
|
+
let anchor = slugger.slug(node.title);
|
|
1227
|
+
while (taken.has(anchor)) anchor = slugger.slug(node.title);
|
|
1228
|
+
taken.add(anchor);
|
|
1229
|
+
return anchor;
|
|
1230
|
+
};
|
|
1231
|
+
const walk = (nodes, parentSlug) => {
|
|
1232
|
+
for (const node of nodes) {
|
|
1233
|
+
if (node.level === 0 || node.synthetic || node.title.trim() === "") {
|
|
1234
|
+
out.unowned.push(...node.children);
|
|
1235
|
+
walk(node.sections, parentSlug);
|
|
1236
|
+
continue;
|
|
1237
|
+
}
|
|
1238
|
+
const slug = anchorFor(node);
|
|
1239
|
+
if (node.level === 1 && out.firstH1 === void 0) {
|
|
1240
|
+
out.firstH1 = node.title;
|
|
1241
|
+
}
|
|
1242
|
+
const parentKey = parentSlug ?? "";
|
|
1243
|
+
const order = (childCount.get(parentKey) ?? 0) + 1;
|
|
1244
|
+
childCount.set(parentKey, order);
|
|
1245
|
+
out.sections.push({
|
|
1246
|
+
slug,
|
|
1247
|
+
title: node.title,
|
|
1248
|
+
level: node.level,
|
|
1249
|
+
order,
|
|
1250
|
+
parentSlug
|
|
1251
|
+
});
|
|
1252
|
+
out.owned.push(node.children);
|
|
1253
|
+
out.nodes.push(node);
|
|
1254
|
+
walk(node.sections, slug);
|
|
1255
|
+
}
|
|
1256
|
+
};
|
|
1257
|
+
walk(roots, null);
|
|
1258
|
+
return out;
|
|
1259
|
+
}
|
|
1260
|
+
function eachContent(nodes, fn) {
|
|
1261
|
+
for (const node of nodes) {
|
|
1262
|
+
fn(node);
|
|
1263
|
+
switch (node.kind) {
|
|
1264
|
+
case "list":
|
|
1265
|
+
for (const item of node.items) eachContent(item.children, fn);
|
|
1266
|
+
break;
|
|
1267
|
+
case "table":
|
|
1268
|
+
for (const row of node.children) {
|
|
1269
|
+
for (const cell of row.children) eachContent(cell.children, fn);
|
|
1270
|
+
}
|
|
1271
|
+
break;
|
|
1272
|
+
case "definitionList":
|
|
1273
|
+
for (const item of node.children) eachContent(item.definition, fn);
|
|
1274
|
+
break;
|
|
1275
|
+
case "admonition":
|
|
1276
|
+
case "blockquote":
|
|
1277
|
+
case "element":
|
|
1278
|
+
eachContent(node.children, fn);
|
|
1279
|
+
break;
|
|
1280
|
+
default:
|
|
1281
|
+
break;
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
function treeContent(sections) {
|
|
1286
|
+
return sections.flatMap((s) => [...s.children, ...treeContent(s.sections)]);
|
|
1287
|
+
}
|
|
1288
|
+
function parseTreeBody(content, path, format) {
|
|
1289
|
+
const tree = parseTree(content, path, format);
|
|
1290
|
+
const minted = mintTreeSections(tree.sections);
|
|
1291
|
+
const imageTargets = [];
|
|
1292
|
+
const codeLanguages = /* @__PURE__ */ new Set();
|
|
1293
|
+
eachContent(treeContent(tree.sections), (node) => {
|
|
1294
|
+
if (node.kind === "image") imageTargets.push(node.url);
|
|
1295
|
+
else if (node.kind === "codeBlock" && node.language) {
|
|
1296
|
+
codeLanguages.add(node.language);
|
|
1297
|
+
}
|
|
1298
|
+
});
|
|
1299
|
+
return {
|
|
1300
|
+
...minted.firstH1 === void 0 ? {} : { firstH1: minted.firstH1 },
|
|
1301
|
+
sections: minted.sections,
|
|
1302
|
+
linkTargets: tree.links.map((l) => l.target),
|
|
1303
|
+
imageTargets,
|
|
1304
|
+
codeLanguages: [...codeLanguages].sort()
|
|
1305
|
+
};
|
|
1306
|
+
}
|
|
1307
|
+
function visit(node, fn) {
|
|
1308
|
+
const children = node.children;
|
|
1309
|
+
if (!children) return;
|
|
1310
|
+
for (const child of children) {
|
|
1311
|
+
fn(child);
|
|
1312
|
+
visit(child, fn);
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1316
|
+
// src/graph/core/discover.ts
|
|
1317
|
+
import { statSync } from "node:fs";
|
|
1318
|
+
import { extname as extname2, relative, resolve as resolve2 } from "node:path";
|
|
1319
|
+
import fg from "fast-glob";
|
|
1320
|
+
|
|
1321
|
+
// src/graph/core/sort.ts
|
|
1322
|
+
function byCodeUnit(a, b) {
|
|
1323
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
// src/graph/core/discover.ts
|
|
1327
|
+
function discoverFiles(inputs, exclude, cwd) {
|
|
1328
|
+
const matches = fg.sync(inputs, {
|
|
1329
|
+
cwd,
|
|
1330
|
+
ignore: exclude,
|
|
1331
|
+
onlyFiles: true,
|
|
1332
|
+
dot: false,
|
|
1333
|
+
unique: true
|
|
1334
|
+
});
|
|
1335
|
+
return [...new Set(matches.map((m) => m.replace(/\\/g, "/")))].sort(
|
|
1336
|
+
byCodeUnit
|
|
1337
|
+
);
|
|
1338
|
+
}
|
|
1339
|
+
var FAMILY_EXCLUDE = ["**/node_modules/**", "**/.git/**"];
|
|
1340
|
+
var DEFAULT_EXTENSIONS = supportedExtensions();
|
|
1341
|
+
var STDIN = "-";
|
|
1342
|
+
function assertInputFormat(paths, as) {
|
|
1343
|
+
if (as === void 0) {
|
|
1344
|
+
if (paths.includes(STDIN)) throw new GraphError(STDIN_REQUIRES_AS);
|
|
1345
|
+
return void 0;
|
|
1346
|
+
}
|
|
1347
|
+
if (!isDocFormat(as)) {
|
|
1348
|
+
throw new GraphError(
|
|
1349
|
+
`Unknown format "${as}". Known formats: ${DOC_FORMATS.join(", ")}.`
|
|
1350
|
+
);
|
|
1351
|
+
}
|
|
1352
|
+
return as;
|
|
1353
|
+
}
|
|
1354
|
+
function expandInputs(inputs, base, ignore) {
|
|
1355
|
+
const named = [];
|
|
1356
|
+
const patterns = [];
|
|
1357
|
+
for (const input of inputs) {
|
|
1358
|
+
if (fg.isDynamicPattern(input)) {
|
|
1359
|
+
patterns.push(input.replace(/\\/g, "/"));
|
|
1360
|
+
continue;
|
|
1361
|
+
}
|
|
1362
|
+
let isDirectory;
|
|
1363
|
+
try {
|
|
1364
|
+
isDirectory = statSync(resolve2(base, input)).isDirectory();
|
|
1365
|
+
} catch {
|
|
1366
|
+
patterns.push(input.replace(/\\/g, "/"));
|
|
1367
|
+
continue;
|
|
1368
|
+
}
|
|
1369
|
+
const literal = fg.convertPathToPattern(input);
|
|
1370
|
+
if (isDirectory) patterns.push(`${literal.replace(/\/$/, "")}/**/*`);
|
|
1371
|
+
else named.push(...glob([literal], base, ignore));
|
|
1372
|
+
}
|
|
1373
|
+
return { named, walked: glob(patterns, base, ignore) };
|
|
1374
|
+
}
|
|
1375
|
+
function glob(patterns, base, ignore) {
|
|
1376
|
+
if (patterns.length === 0) return [];
|
|
1377
|
+
return fg.sync(patterns, {
|
|
1378
|
+
cwd: base,
|
|
1379
|
+
ignore,
|
|
1380
|
+
absolute: true,
|
|
1381
|
+
dot: false,
|
|
1382
|
+
onlyFiles: true
|
|
1383
|
+
});
|
|
1384
|
+
}
|
|
1385
|
+
function normalizeExtensions(exts) {
|
|
1386
|
+
return new Set(
|
|
1387
|
+
exts.map((e) => {
|
|
1388
|
+
const lower = e.toLowerCase();
|
|
1389
|
+
return lower.startsWith(".") ? lower : `.${lower}`;
|
|
1390
|
+
})
|
|
1391
|
+
);
|
|
1392
|
+
}
|
|
1393
|
+
function resolveDocumentSet(config, options = {}, verb = "build", cwd = process.cwd(), base = documentBase(config, options, cwd)) {
|
|
1394
|
+
const paths = options.paths ?? [];
|
|
1395
|
+
const wanted = options.collection ?? [];
|
|
1396
|
+
assertCollectionWithoutPaths(wanted, paths);
|
|
1397
|
+
const format = assertInputFormat(paths, options.as);
|
|
1398
|
+
if (wanted.length > 0 && config.configSource === null) {
|
|
1399
|
+
throw new GraphError("--collection needs a config file to select from.");
|
|
1400
|
+
}
|
|
1401
|
+
const collections = selectCollections(
|
|
1402
|
+
config.collections,
|
|
1403
|
+
wanted,
|
|
1404
|
+
config.configSource ?? DEFAULT_CONFIG_FILENAME,
|
|
1405
|
+
(message) => new GraphError(message)
|
|
1406
|
+
);
|
|
1407
|
+
const exclude = [...FAMILY_EXCLUDE, ...options.exclude ?? []];
|
|
1408
|
+
let named = [];
|
|
1409
|
+
let walked;
|
|
1410
|
+
if (paths.length > 0) {
|
|
1411
|
+
({ named, walked } = expandInputs(
|
|
1412
|
+
paths.filter((p) => p !== STDIN),
|
|
1413
|
+
cwd,
|
|
1414
|
+
exclude
|
|
1415
|
+
));
|
|
1416
|
+
} else {
|
|
1417
|
+
const patterns = collections.flatMap((c) => c.paths);
|
|
1418
|
+
if (patterns.length === 0) {
|
|
1419
|
+
throw new GraphError(
|
|
1420
|
+
`No files to ${verb}. Pass paths/globs, or declare a collection under \`collections:\` in manni.config.yaml.`
|
|
1421
|
+
);
|
|
1422
|
+
}
|
|
1423
|
+
walked = collections.flatMap((c) => {
|
|
1424
|
+
const found = expandInputs(c.paths, config.configDir, [
|
|
1425
|
+
...exclude,
|
|
1426
|
+
...c.exclude
|
|
1427
|
+
]);
|
|
1428
|
+
return [...found.named, ...found.walked];
|
|
1429
|
+
});
|
|
1430
|
+
}
|
|
1431
|
+
const exts = normalizeExtensions(options.ext ?? DEFAULT_EXTENSIONS);
|
|
1432
|
+
const keepNamed = (p) => {
|
|
1433
|
+
const ext = extname2(p);
|
|
1434
|
+
if (format !== void 0 || parserForExtension(ext) !== void 0) {
|
|
1435
|
+
return true;
|
|
1436
|
+
}
|
|
1437
|
+
const label = relative(base, p).replace(/\\/g, "/");
|
|
1438
|
+
warn(`skipped ${label}: ${unsupportedFormatMessage(ext || label)}`);
|
|
1439
|
+
return false;
|
|
1440
|
+
};
|
|
1441
|
+
const keepWalked = (p) => exts.has(extname2(p).toLowerCase());
|
|
1442
|
+
return [
|
|
1443
|
+
...new Set(
|
|
1444
|
+
[...named.filter(keepNamed), ...walked.filter(keepWalked)].map(
|
|
1445
|
+
(p) => relative(base, p).replace(/\\/g, "/")
|
|
1446
|
+
)
|
|
1447
|
+
)
|
|
1448
|
+
].sort(byCodeUnit);
|
|
1449
|
+
}
|
|
1450
|
+
function documentBase(config, options = {}, cwd = process.cwd()) {
|
|
1451
|
+
const typed = (options.paths ?? []).length > 0;
|
|
1452
|
+
return typed || config.collections.length === 0 ? cwd : config.configDir;
|
|
1453
|
+
}
|
|
1454
|
+
function routesFrom(config, base) {
|
|
1455
|
+
return config.routes.map((m) => ({
|
|
1456
|
+
...m,
|
|
1457
|
+
root: relative(base, resolve2(config.configDir, m.root)).replace(/\\/g, "/")
|
|
1458
|
+
}));
|
|
1459
|
+
}
|
|
1460
|
+
function documentSetPatterns(config, options = {}) {
|
|
1461
|
+
const paths = options.paths ?? [];
|
|
1462
|
+
if (paths.length > 0) return paths;
|
|
1463
|
+
return selectCollections(
|
|
1464
|
+
config.collections,
|
|
1465
|
+
options.collection ?? [],
|
|
1466
|
+
config.configSource ?? DEFAULT_CONFIG_FILENAME,
|
|
1467
|
+
(message) => new GraphError(message)
|
|
1468
|
+
).flatMap((c) => c.paths);
|
|
1469
|
+
}
|
|
1470
|
+
|
|
1471
|
+
// src/graph/core/external.ts
|
|
1472
|
+
import { resolve as resolve3 } from "node:path";
|
|
1473
|
+
async function openMetaView(source, cwd, paths, base = cwd) {
|
|
1474
|
+
try {
|
|
1475
|
+
return await metaPageView({
|
|
1476
|
+
cwd: base,
|
|
1477
|
+
...source.configPath === void 0 ? {} : { configPath: resolve3(cwd, source.configPath) },
|
|
1478
|
+
...source.noConfig === void 0 ? {} : { noConfig: source.noConfig },
|
|
1479
|
+
pages: paths.filter((p) => p !== STDIN_PATH).map((p) => resolve3(base, p))
|
|
1480
|
+
});
|
|
1481
|
+
} catch (e) {
|
|
1482
|
+
throw new GraphError(errorMessage(e));
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
function pointerOf(key) {
|
|
1486
|
+
return `/${key.replace(/~/g, "~0").replace(/\//g, "~1")}`;
|
|
1487
|
+
}
|
|
1488
|
+
async function mergePage(view, path, frontmatter, present, format) {
|
|
1489
|
+
let merged;
|
|
1490
|
+
try {
|
|
1491
|
+
merged = await view.merge(path, {
|
|
1492
|
+
data: frontmatter,
|
|
1493
|
+
present,
|
|
1494
|
+
format,
|
|
1495
|
+
lineFor: () => void 0
|
|
1496
|
+
});
|
|
1497
|
+
} catch (e) {
|
|
1498
|
+
throw new GraphError(errorMessage(e));
|
|
1499
|
+
}
|
|
1500
|
+
const data = merged.extracted.data;
|
|
1501
|
+
const supplied = {};
|
|
1502
|
+
for (const key of Object.keys(data)) {
|
|
1503
|
+
if (merged.locate(pointerOf(key)) !== void 0) supplied[key] = data[key];
|
|
1504
|
+
}
|
|
1505
|
+
return { data, supplied };
|
|
1506
|
+
}
|
|
1507
|
+
async function withExternalMetadata(docs, view) {
|
|
1508
|
+
const out = [];
|
|
1509
|
+
for (const doc of docs) {
|
|
1510
|
+
const { data } = await mergePage(
|
|
1511
|
+
view,
|
|
1512
|
+
doc.path,
|
|
1513
|
+
doc.frontmatter,
|
|
1514
|
+
doc.frontmatterPresent,
|
|
1515
|
+
doc.format
|
|
1516
|
+
);
|
|
1517
|
+
out.push(data === doc.frontmatter ? doc : { ...doc, frontmatter: data });
|
|
1518
|
+
}
|
|
1519
|
+
return out;
|
|
1520
|
+
}
|
|
1521
|
+
|
|
1522
|
+
// src/graph/core/localizations.ts
|
|
1523
|
+
var LOCALIZATIONS_FILENAME = "localizations.json";
|
|
1524
|
+
var UNDETERMINED = "und";
|
|
1525
|
+
var LANGUAGE_TAG = /^[A-Za-z]{2,3}(-[A-Za-z]{4})?(-([A-Za-z]{2}|[0-9]{3}))?(-([A-Za-z0-9]{5,8}|[0-9][A-Za-z0-9]{3}))*$/;
|
|
1526
|
+
function isLanguageTag(value) {
|
|
1527
|
+
return LANGUAGE_TAG.test(value);
|
|
1528
|
+
}
|
|
1529
|
+
function canonicalLanguageTag(tag) {
|
|
1530
|
+
try {
|
|
1531
|
+
return Intl.getCanonicalLocales(tag)[0] ?? tag;
|
|
1532
|
+
} catch {
|
|
1533
|
+
return tag;
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
function searchIndexFilename(language) {
|
|
1537
|
+
return `search.${language}.json`;
|
|
1538
|
+
}
|
|
1539
|
+
function vectorIndexFilename(language) {
|
|
1540
|
+
return `vectors.${language}.bin`;
|
|
1541
|
+
}
|
|
1542
|
+
function emitLocalizations(doc) {
|
|
1543
|
+
const languages = [...doc.languages].sort(
|
|
1544
|
+
(a, b) => byCodeUnit(a.language, b.language)
|
|
1545
|
+
);
|
|
1546
|
+
return `${JSON.stringify({ version: doc.version, languages }, null, 2)}
|
|
1547
|
+
`;
|
|
1548
|
+
}
|
|
1549
|
+
function isRecord(v) {
|
|
1550
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
1551
|
+
}
|
|
1552
|
+
function parseLocalizations(text) {
|
|
1553
|
+
let parsed;
|
|
1554
|
+
try {
|
|
1555
|
+
parsed = JSON.parse(text);
|
|
1556
|
+
} catch {
|
|
1557
|
+
return void 0;
|
|
1558
|
+
}
|
|
1559
|
+
if (!isRecord(parsed)) return void 0;
|
|
1560
|
+
if (parsed["version"] !== 1 || !Array.isArray(parsed["languages"])) {
|
|
1561
|
+
return void 0;
|
|
1562
|
+
}
|
|
1563
|
+
for (const entry of parsed["languages"]) {
|
|
1564
|
+
if (!isRecord(entry)) return void 0;
|
|
1565
|
+
const language = entry["language"];
|
|
1566
|
+
const search = entry["search"];
|
|
1567
|
+
if (typeof language !== "string" || !isLanguageTag(language) || typeof entry["documents"] !== "number" || !isRecord(search) || typeof search["path"] !== "string" || typeof search["entries"] !== "number" || typeof search["digest"] !== "string" || !ownsFilename(search["path"], searchIndexFilename(language))) {
|
|
1568
|
+
return void 0;
|
|
1569
|
+
}
|
|
1570
|
+
const v = entry["vectors"];
|
|
1571
|
+
if (v !== void 0) {
|
|
1572
|
+
if (!isRecord(v) || typeof v["path"] !== "string" || typeof v["model"] !== "string" || typeof v["dtype"] !== "string" || typeof v["dims"] !== "number" || typeof v["count"] !== "number" || // Same constraint `search.path` gets: the last segment must be the
|
|
1573
|
+
// filename this language's sidecar would be given. Without it,
|
|
1574
|
+
// `isSafeRelativePath` alone leaves `vectors.path` far more reachable
|
|
1575
|
+
// than `search.path` — and `search --mode vector` opens it.
|
|
1576
|
+
!ownsFilename(v["path"], vectorIndexFilename(language))) {
|
|
1577
|
+
return void 0;
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
}
|
|
1581
|
+
return parsed;
|
|
1582
|
+
}
|
|
1583
|
+
function isSafeRelativePath(path) {
|
|
1584
|
+
if (path === "" || path.startsWith("/") || /^[A-Za-z]:/.test(path)) {
|
|
1585
|
+
return false;
|
|
1586
|
+
}
|
|
1587
|
+
if (path.includes("\\")) return false;
|
|
1588
|
+
const segments = path.split("/");
|
|
1589
|
+
let leading = true;
|
|
1590
|
+
for (const segment of segments) {
|
|
1591
|
+
if (segment === "" || segment === ".") return false;
|
|
1592
|
+
if (segment === "..") {
|
|
1593
|
+
if (!leading) return false;
|
|
1594
|
+
continue;
|
|
1595
|
+
}
|
|
1596
|
+
leading = false;
|
|
1597
|
+
}
|
|
1598
|
+
return true;
|
|
1599
|
+
}
|
|
1600
|
+
function ownsFilename(path, expected) {
|
|
1601
|
+
if (!isSafeRelativePath(path)) return false;
|
|
1602
|
+
return path.slice(path.lastIndexOf("/") + 1) === expected;
|
|
1603
|
+
}
|
|
1604
|
+
|
|
1605
|
+
// src/graph/core/questions.ts
|
|
1606
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
1607
|
+
import { Ajv2020 as Ajv20202 } from "ajv/dist/2020.js";
|
|
1608
|
+
import { isNode, isSeq, LineCounter, parseDocument } from "yaml";
|
|
1609
|
+
|
|
1610
|
+
// src/graph/core/questions-schema.json
|
|
1611
|
+
var questions_schema_default = {
|
|
1612
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
1613
|
+
$id: "manni:graph:questions",
|
|
1614
|
+
title: "manni graph golden-set file",
|
|
1615
|
+
description: "A list of reader questions that span pages or that the docs don't answer (proposal 0087). Each item is a page sample question's object form, plus `answers[].file` and `language`. `graph.questionFiles` names the files, and `manni graph check` asks their questions.",
|
|
1616
|
+
type: "array",
|
|
1617
|
+
items: {
|
|
1618
|
+
type: "object",
|
|
1619
|
+
additionalProperties: false,
|
|
1620
|
+
required: ["question", "answers"],
|
|
1621
|
+
properties: {
|
|
1622
|
+
question: {
|
|
1623
|
+
type: "string",
|
|
1624
|
+
minLength: 1,
|
|
1625
|
+
description: "The question, as a reader would ask it."
|
|
1626
|
+
},
|
|
1627
|
+
answers: {
|
|
1628
|
+
type: "array",
|
|
1629
|
+
items: {
|
|
1630
|
+
type: "object",
|
|
1631
|
+
additionalProperties: false,
|
|
1632
|
+
required: ["file", "lines"],
|
|
1633
|
+
properties: {
|
|
1634
|
+
file: {
|
|
1635
|
+
type: "string",
|
|
1636
|
+
minLength: 1,
|
|
1637
|
+
description: "The page that holds this answer, relative to the config file."
|
|
1638
|
+
},
|
|
1639
|
+
lines: {
|
|
1640
|
+
oneOf: [
|
|
1641
|
+
{ type: "integer", minimum: 1 },
|
|
1642
|
+
{ type: "string", pattern: "^[1-9][0-9]*-[1-9][0-9]*$" }
|
|
1643
|
+
],
|
|
1644
|
+
description: "Body lines of that page, counted as for a citation's claim."
|
|
1645
|
+
},
|
|
1646
|
+
integrity: {
|
|
1647
|
+
type: "string",
|
|
1648
|
+
pattern: "^sha256-[0-9a-f]{64}$",
|
|
1649
|
+
description: "The pin over those lines, under cite's hashing rule. Without it, the lines are not checked for change."
|
|
1650
|
+
},
|
|
1651
|
+
reviewed: {
|
|
1652
|
+
type: "boolean",
|
|
1653
|
+
description: "`false` marks a pin nobody has confirmed. Absent means `true`."
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
},
|
|
1657
|
+
description: "The lines that answer the question, on one page or several. An empty list marks a known gap: a question the docs don't answer."
|
|
1658
|
+
},
|
|
1659
|
+
language: {
|
|
1660
|
+
type: "string",
|
|
1661
|
+
pattern: "^[A-Za-z]{2,3}(-[A-Za-z]{4})?(-([A-Za-z]{2}|[0-9]{3}))?(-([A-Za-z0-9]{5,8}|[0-9][A-Za-z0-9]{3}))*$",
|
|
1662
|
+
description: "The question's language, as a BCP-47 tag. Absent, it is the first answer's page language."
|
|
1663
|
+
},
|
|
1664
|
+
"generated-by": {
|
|
1665
|
+
type: "string",
|
|
1666
|
+
minLength: 1,
|
|
1667
|
+
description: "The model that drafted the question or any of its pins, as `provider/model`."
|
|
1668
|
+
},
|
|
1669
|
+
confidence: {
|
|
1670
|
+
type: "number",
|
|
1671
|
+
minimum: 0,
|
|
1672
|
+
maximum: 1,
|
|
1673
|
+
description: "The drafting model's confidence, 0..1."
|
|
1674
|
+
},
|
|
1675
|
+
reviewed: {
|
|
1676
|
+
type: "boolean",
|
|
1677
|
+
description: "`false` marks a drafted question, and its pins are drafts with it. Absent means `true`."
|
|
1678
|
+
},
|
|
1679
|
+
"reviewed-by": {
|
|
1680
|
+
type: "string",
|
|
1681
|
+
minLength: 1,
|
|
1682
|
+
description: "Who confirmed the question. An optional record."
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
};
|
|
1687
|
+
|
|
1688
|
+
// src/graph/core/questions.ts
|
|
1689
|
+
function isRecord2(value) {
|
|
1690
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1691
|
+
}
|
|
1692
|
+
function readPin(value) {
|
|
1693
|
+
if (!isRecord2(value)) return void 0;
|
|
1694
|
+
const spec = value.lines;
|
|
1695
|
+
const lines = typeof spec === "number" || typeof spec === "string" ? parseLines(spec) : void 0;
|
|
1696
|
+
if (lines === void 0) return void 0;
|
|
1697
|
+
const integrity = value.integrity;
|
|
1698
|
+
return {
|
|
1699
|
+
lines,
|
|
1700
|
+
...typeof integrity === "string" ? { integrity } : {},
|
|
1701
|
+
reviewed: value.reviewed !== false
|
|
1702
|
+
};
|
|
1703
|
+
}
|
|
1704
|
+
function readItem(item) {
|
|
1705
|
+
if (typeof item === "string") {
|
|
1706
|
+
return item === "" ? void 0 : { question: item, answers: [], reviewed: true };
|
|
1707
|
+
}
|
|
1708
|
+
if (!isRecord2(item) || typeof item.question !== "string") return void 0;
|
|
1709
|
+
const question = item.question;
|
|
1710
|
+
if (question === "") return void 0;
|
|
1711
|
+
const answers = Array.isArray(item.answers) ? item.answers.flatMap((a) => readPin(a) ?? []) : [];
|
|
1712
|
+
return { question, answers, reviewed: item.reviewed !== false };
|
|
1713
|
+
}
|
|
1714
|
+
function readSampleQuestions(value) {
|
|
1715
|
+
const items = Array.isArray(value) ? value : value === void 0 ? [] : [value];
|
|
1716
|
+
return items.flatMap((item) => readItem(item) ?? []);
|
|
1717
|
+
}
|
|
1718
|
+
var validateFile;
|
|
1719
|
+
function readQuestionFile(abs, label, text) {
|
|
1720
|
+
if (text === void 0 && !existsSync(abs)) {
|
|
1721
|
+
throw new GraphError(`graph.questionFiles names ${label}, which does not exist.`);
|
|
1722
|
+
}
|
|
1723
|
+
const counter = new LineCounter();
|
|
1724
|
+
const doc = parseDocument(text ?? readFileSync(abs, "utf8"), { lineCounter: counter });
|
|
1725
|
+
const [error] = doc.errors;
|
|
1726
|
+
if (error) throw new GraphError(`${label}: ${error.message}`);
|
|
1727
|
+
const value = doc.toJS() ?? [];
|
|
1728
|
+
validateFile ??= new Ajv20202({ allowUnionTypes: true }).compile(questions_schema_default);
|
|
1729
|
+
if (!validateFile(value) || !Array.isArray(value)) {
|
|
1730
|
+
const [first] = validateFile.errors ?? [];
|
|
1731
|
+
const where = [first?.instancePath, first?.message ?? "is invalid"].filter(Boolean).join(" ");
|
|
1732
|
+
throw new GraphError(`${label}: ${where}.`);
|
|
1733
|
+
}
|
|
1734
|
+
const nodes = isSeq(doc.contents) ? doc.contents.items : [];
|
|
1735
|
+
return value.flatMap((item, n) => {
|
|
1736
|
+
if (!isRecord2(item) || typeof item.question !== "string") return [];
|
|
1737
|
+
const node = nodes[n];
|
|
1738
|
+
const offset = isNode(node) ? node.range[0] : void 0;
|
|
1739
|
+
const answers = Array.isArray(item.answers) ? item.answers.flatMap((a) => {
|
|
1740
|
+
const pin = readPin(a);
|
|
1741
|
+
return pin && isRecord2(a) && typeof a.file === "string" ? [{ ...pin, file: a.file }] : [];
|
|
1742
|
+
}) : [];
|
|
1743
|
+
return [
|
|
1744
|
+
{
|
|
1745
|
+
question: item.question,
|
|
1746
|
+
answers,
|
|
1747
|
+
reviewed: item.reviewed !== false,
|
|
1748
|
+
...typeof item.language === "string" ? { language: item.language } : {},
|
|
1749
|
+
line: offset === void 0 ? 1 : counter.linePos(offset).line
|
|
1750
|
+
}
|
|
1751
|
+
];
|
|
1752
|
+
});
|
|
1753
|
+
}
|
|
1754
|
+
function questionKey(question) {
|
|
1755
|
+
return question.toLowerCase().replace(/[^\p{L}\p{N}\s]/gu, "").replace(/\s+/gu, " ").trim();
|
|
1756
|
+
}
|
|
1757
|
+
var COPIED_SHARE = 0.5;
|
|
1758
|
+
function copiedPairs(question, ...answers) {
|
|
1759
|
+
const words = (text) => text.toLowerCase().match(/[\p{L}\p{N}]+/gu) ?? [];
|
|
1760
|
+
const pairs = (list) => list.slice(1).map((w, i) => `${list[i] ?? ""} ${w}`);
|
|
1761
|
+
const asked = pairs(words(question));
|
|
1762
|
+
if (asked.length === 0) return void 0;
|
|
1763
|
+
const said = new Set(answers.flatMap((a) => pairs(words(a))));
|
|
1764
|
+
return { copied: asked.filter((p) => said.has(p)).length, of: asked.length };
|
|
1765
|
+
}
|
|
1766
|
+
|
|
1767
|
+
export {
|
|
1768
|
+
GraphError,
|
|
1769
|
+
resolveBaseIri,
|
|
1770
|
+
normalizeDocPath,
|
|
1771
|
+
encodeSegment,
|
|
1772
|
+
STDIN_PATH,
|
|
1773
|
+
mintDocIri,
|
|
1774
|
+
mintSectionIri,
|
|
1775
|
+
conceptSlug,
|
|
1776
|
+
mintConceptIri,
|
|
1777
|
+
mintTermConceptIri,
|
|
1778
|
+
mintProductIri,
|
|
1779
|
+
mintSchemeIri,
|
|
1780
|
+
mintAgentIri,
|
|
1781
|
+
mintGraphIri,
|
|
1782
|
+
mintBuildActivityIri,
|
|
1783
|
+
NS,
|
|
1784
|
+
PREFIXES,
|
|
1785
|
+
RDF_TYPE,
|
|
1786
|
+
ROLE,
|
|
1787
|
+
IIRDS_HAS_TOPIC_TYPE,
|
|
1788
|
+
IIRDS_RELATES_TO_PRODUCT_VARIANT,
|
|
1789
|
+
IIRDS_RELATES_TO_LIFECYCLE_PHASE,
|
|
1790
|
+
IIRDS_HAS_SUBJECT,
|
|
1791
|
+
IIRDS_PRODUCT_VARIANT,
|
|
1792
|
+
IIRDS_PACKAGE,
|
|
1793
|
+
IIRDS_IIRDS_VERSION,
|
|
1794
|
+
IIRDS_TOPIC,
|
|
1795
|
+
IIRDS_IS_PART_OF_PACKAGE,
|
|
1796
|
+
IIRDS_HAS_RENDITION,
|
|
1797
|
+
IIRDS_RENDITION,
|
|
1798
|
+
IIRDS_SOURCE,
|
|
1799
|
+
IIRDS_FORMAT,
|
|
1800
|
+
IIRDS_TITLE,
|
|
1801
|
+
IIRDS_LANGUAGE,
|
|
1802
|
+
IIRDS_PARTY,
|
|
1803
|
+
IIRDS_HAS_PARTY_ROLE,
|
|
1804
|
+
IIRDS_CREATOR,
|
|
1805
|
+
IIRDS_RELATES_TO_PARTY,
|
|
1806
|
+
IIRDS_RELATES_TO_VCARD,
|
|
1807
|
+
VCARD_NS,
|
|
1808
|
+
VCARD_ORGANIZATION,
|
|
1809
|
+
VCARD_ORGANIZATION_NAME,
|
|
1810
|
+
GRAPH_NOT_APPLICABLE_TO_VARIANT,
|
|
1811
|
+
GRAPH_NOT_SOFTWARE_SUBJECT,
|
|
1812
|
+
PAGE_TYPE_TO_TOPIC_TYPE,
|
|
1813
|
+
TOPIC_TYPE_IRIS,
|
|
1814
|
+
SOFTWARE_LIFECYCLE_IRIS,
|
|
1815
|
+
SOFTWARE_SUBJECT_IRIS,
|
|
1816
|
+
COVERAGE_FIELDS,
|
|
1817
|
+
SECTION_COVERAGE_FIELDS,
|
|
1818
|
+
COVERAGE_FIELD_NAMES,
|
|
1819
|
+
UNIFORM_COVERAGE_FIELD_NAMES,
|
|
1820
|
+
MODEL_PROFILES,
|
|
1821
|
+
DEFAULT_MODEL,
|
|
1822
|
+
profileFor,
|
|
1823
|
+
withPrefix,
|
|
1824
|
+
ALL_FILL_FIELDS,
|
|
1825
|
+
DEFAULT_CONFIG_FILENAME,
|
|
1826
|
+
CONFIG_SECTION,
|
|
1827
|
+
parseConfig,
|
|
1828
|
+
loadConfig,
|
|
1829
|
+
defaultConfig,
|
|
1830
|
+
loadRunConfig,
|
|
1831
|
+
isTreeFormat,
|
|
1832
|
+
formatOf,
|
|
1833
|
+
hasScheme,
|
|
1834
|
+
resolveRelative,
|
|
1835
|
+
extractorFor,
|
|
1836
|
+
metadataOf,
|
|
1837
|
+
analyzeDoc,
|
|
1838
|
+
parseBody,
|
|
1839
|
+
parseTree,
|
|
1840
|
+
mintTreeSections,
|
|
1841
|
+
byCodeUnit,
|
|
1842
|
+
discoverFiles,
|
|
1843
|
+
DEFAULT_EXTENSIONS,
|
|
1844
|
+
STDIN,
|
|
1845
|
+
assertInputFormat,
|
|
1846
|
+
resolveDocumentSet,
|
|
1847
|
+
documentBase,
|
|
1848
|
+
routesFrom,
|
|
1849
|
+
documentSetPatterns,
|
|
1850
|
+
LOCALIZATIONS_FILENAME,
|
|
1851
|
+
UNDETERMINED,
|
|
1852
|
+
isLanguageTag,
|
|
1853
|
+
canonicalLanguageTag,
|
|
1854
|
+
searchIndexFilename,
|
|
1855
|
+
vectorIndexFilename,
|
|
1856
|
+
emitLocalizations,
|
|
1857
|
+
parseLocalizations,
|
|
1858
|
+
isSafeRelativePath,
|
|
1859
|
+
readSampleQuestions,
|
|
1860
|
+
readQuestionFile,
|
|
1861
|
+
questionKey,
|
|
1862
|
+
COPIED_SHARE,
|
|
1863
|
+
copiedPairs,
|
|
1864
|
+
openMetaView,
|
|
1865
|
+
mergePage,
|
|
1866
|
+
withExternalMetadata
|
|
1867
|
+
};
|
|
1868
|
+
//# sourceMappingURL=chunk-2UJZXVHR.js.map
|