@hawkeyexl/manni 4.11.0 → 4.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (238) hide show
  1. package/README.md +1 -1
  2. package/dist/{batch-UAULUMGH.js → batch-KMGZMIAQ.js} +20 -19
  3. package/dist/build-NO4AWCYG.js +36 -0
  4. package/dist/calibrate-XQUG5XAK.js +41 -0
  5. package/dist/capture-5XE3ZMXK.js +38 -0
  6. package/dist/{check-YEOYBFST.js → check-HTNPLWOV.js} +19 -18
  7. package/dist/check-RJ45IBA6.js +34 -0
  8. package/dist/{check-VELUQAUW.js → check-W24BQNCT.js} +35 -34
  9. package/dist/{check-VELUQAUW.js.map → check-W24BQNCT.js.map} +1 -1
  10. package/dist/check-WFXSXICD.js +30 -0
  11. package/dist/{chunk-IGSHYP74.js → chunk-23P7KMJM.js} +4 -4
  12. package/dist/{chunk-HA6MQMOY.js → chunk-24J7TYPU.js} +6 -6
  13. package/dist/{chunk-PCS4VJBV.js → chunk-37QJLVS3.js} +9 -9
  14. package/dist/{chunk-4CK6ZSOK.js → chunk-3P6KCU36.js} +3 -3
  15. package/dist/{chunk-54F74XR3.js → chunk-5JBVFWVP.js} +19 -19
  16. package/dist/{chunk-B7XYNRJQ.js → chunk-6KIYVVKL.js} +2 -2
  17. package/dist/{chunk-J6IDQGJL.js → chunk-6TVH4FI7.js} +469 -85
  18. package/dist/chunk-6TVH4FI7.js.map +1 -0
  19. package/dist/{chunk-GDVZ5VII.js → chunk-7A452BPZ.js} +4 -4
  20. package/dist/{chunk-M42DZCOU.js → chunk-7FCLXEAQ.js} +2 -2
  21. package/dist/{chunk-2MJ62AYQ.js → chunk-7MCQHTQ5.js} +4 -3
  22. package/dist/chunk-7MCQHTQ5.js.map +1 -0
  23. package/dist/{chunk-LBSCW232.js → chunk-7NXPQKSB.js} +7 -7
  24. package/dist/{chunk-OPXWPJDA.js → chunk-A3TEDWBZ.js} +14 -14
  25. package/dist/{chunk-BBT6AVUG.js → chunk-BHHXU2D2.js} +2 -2
  26. package/dist/{chunk-D4N2V43Z.js → chunk-CEI2J42X.js} +13 -7
  27. package/dist/chunk-CEI2J42X.js.map +1 -0
  28. package/dist/{chunk-FQXWVS6J.js → chunk-CMMBWHT2.js} +9 -9
  29. package/dist/{chunk-EIFCP6CZ.js → chunk-CO47QJKZ.js} +2 -2
  30. package/dist/{chunk-2DRHT73U.js → chunk-CVZMKWZ5.js} +913 -1398
  31. package/dist/chunk-CVZMKWZ5.js.map +1 -0
  32. package/dist/{chunk-ADMEPUBT.js → chunk-CXWTNT2O.js} +3 -3
  33. package/dist/{chunk-LKP7QDFN.js → chunk-DAQTRAP5.js} +4 -4
  34. package/dist/chunk-DSWKBZWW.js +16 -0
  35. package/dist/chunk-DSWKBZWW.js.map +1 -0
  36. package/dist/{chunk-PWBH7DCQ.js → chunk-EESH6COU.js} +4 -4
  37. package/dist/{chunk-JPQDNYXH.js → chunk-EM67O2ET.js} +8 -2
  38. package/dist/chunk-EM67O2ET.js.map +1 -0
  39. package/dist/{chunk-HQR2ZBHW.js → chunk-I2XQRRP7.js} +36 -7
  40. package/dist/chunk-I2XQRRP7.js.map +1 -0
  41. package/dist/{chunk-NCPWXHDO.js → chunk-JEUFYSFQ.js} +4 -4
  42. package/dist/{chunk-2IR4T5PO.js → chunk-JJ4RSDSY.js} +2 -2
  43. package/dist/chunk-KCB5JCK4.js +2272 -0
  44. package/dist/chunk-KCB5JCK4.js.map +1 -0
  45. package/dist/{chunk-VSEBFHAY.js → chunk-KFKL4VTL.js} +11369 -10218
  46. package/dist/chunk-KFKL4VTL.js.map +1 -0
  47. package/dist/{chunk-PCQ7ELJH.js → chunk-L2TD7DZB.js} +109 -5
  48. package/dist/chunk-L2TD7DZB.js.map +1 -0
  49. package/dist/{chunk-WDWXAYVH.js → chunk-L3RLGGRK.js} +4 -4
  50. package/dist/{chunk-T7JAOYE5.js → chunk-L75CAZG4.js} +6 -6
  51. package/dist/{chunk-U7CTFN2J.js → chunk-MYRPMSOX.js} +7 -7
  52. package/dist/{chunk-Y6DOMTQD.js → chunk-NCF5NQV5.js} +27 -27
  53. package/dist/chunk-NCF5NQV5.js.map +1 -0
  54. package/dist/{chunk-WQWKYAAK.js → chunk-NUQF5F5J.js} +2 -2
  55. package/dist/{chunk-FUCPZVRY.js → chunk-OEN6FBUW.js} +2 -2
  56. package/dist/{chunk-FBMZJEB3.js → chunk-OKMTUAWO.js} +4 -4
  57. package/dist/{chunk-QLWC7MKD.js → chunk-OTJOBZJ5.js} +135 -135
  58. package/dist/chunk-OTJOBZJ5.js.map +1 -0
  59. package/dist/{chunk-R4WXQIOZ.js → chunk-PCEM5FOZ.js} +3 -3
  60. package/dist/{chunk-4D5IZSXM.js → chunk-PXNCRGUL.js} +3 -3
  61. package/dist/chunk-Q2QC5AZB.js +1868 -0
  62. package/dist/chunk-Q2QC5AZB.js.map +1 -0
  63. package/dist/{chunk-ODRPL3WB.js → chunk-Q3ODX5PF.js} +2 -2
  64. package/dist/{chunk-KGEQJ5CC.js → chunk-RRFFUWDL.js} +8 -8
  65. package/dist/{chunk-NSBXVPZL.js → chunk-S3XUYW5K.js} +17 -17
  66. package/dist/{chunk-LPIF5LIE.js → chunk-SAU2WQFC.js} +2 -2
  67. package/dist/{chunk-MSRU4D4P.js → chunk-SFLICIQV.js} +2 -2
  68. package/dist/{chunk-NGTVREIH.js → chunk-U6IHLEWT.js} +2 -2
  69. package/dist/{chunk-QCHVR4ZM.js → chunk-VM7VAFJW.js} +33 -7
  70. package/dist/chunk-VM7VAFJW.js.map +1 -0
  71. package/dist/{chunk-6HWBRZIN.js → chunk-VQYGLU4C.js} +252 -193
  72. package/dist/chunk-VQYGLU4C.js.map +1 -0
  73. package/dist/{chunk-2IAZEB45.js → chunk-WGMFDG6U.js} +229 -821
  74. package/dist/chunk-WGMFDG6U.js.map +1 -0
  75. package/dist/{chunk-GV56WGL2.js → chunk-WO4JYWZK.js} +1036 -883
  76. package/dist/chunk-WO4JYWZK.js.map +1 -0
  77. package/dist/chunk-XYRUDFKS.js +685 -0
  78. package/dist/chunk-XYRUDFKS.js.map +1 -0
  79. package/dist/{chunk-VQK4VHLF.js → chunk-YQV75FIL.js} +2 -2
  80. package/dist/chunk-YUTVAMWW.js +2 -0
  81. package/dist/{chunk-RLT5SEML.js → chunk-Z5MZCCTT.js} +6 -6
  82. package/dist/{chunk-BKVHX6FU.js → chunk-ZIRBFXDW.js} +5 -10
  83. package/dist/chunk-ZIRBFXDW.js.map +1 -0
  84. package/dist/{cli-O4ABTN4Z.js → cli-236TGVJG.js} +31 -30
  85. package/dist/{cli-O4ABTN4Z.js.map → cli-236TGVJG.js.map} +1 -1
  86. package/dist/{cli-3BTCK4AB.js → cli-3FAPJBEY.js} +27 -26
  87. package/dist/{cli-3BTCK4AB.js.map → cli-3FAPJBEY.js.map} +1 -1
  88. package/dist/{cli-JJMOVIKS.js → cli-BS43EVCD.js} +14 -14
  89. package/dist/{cli-RORDPAPE.js → cli-CMR4FYF6.js} +59 -38
  90. package/dist/cli-CMR4FYF6.js.map +1 -0
  91. package/dist/{cli-ONTC5PKT.js → cli-FX53PBQ3.js} +9 -9
  92. package/dist/{cli-6KZTHWGP.js → cli-IQNJLKSN.js} +37 -36
  93. package/dist/{cli-6KZTHWGP.js.map → cli-IQNJLKSN.js.map} +1 -1
  94. package/dist/{cli-4MF37HAQ.js → cli-KOMXVPXX.js} +26 -25
  95. package/dist/{cli-4MF37HAQ.js.map → cli-KOMXVPXX.js.map} +1 -1
  96. package/dist/{cli-I62SRH3R.js → cli-NGL63E53.js} +14 -13
  97. package/dist/{cli-DRMZBZLB.js → cli-QPGS2MR5.js} +43 -42
  98. package/dist/{cli-DRMZBZLB.js.map → cli-QPGS2MR5.js.map} +1 -1
  99. package/dist/{cli-VID7PJS3.js → cli-RKQX4TI3.js} +23 -22
  100. package/dist/{cli-VID7PJS3.js.map → cli-RKQX4TI3.js.map} +1 -1
  101. package/dist/{cli-VUKMWSSF.js → cli-WNEI5L7P.js} +4 -4
  102. package/dist/cli.js +19 -13
  103. package/dist/cli.js.map +1 -1
  104. package/dist/{config-XDA42RJL.js → config-JJW75SBX.js} +5 -5
  105. package/dist/docmeta.js +13 -12
  106. package/dist/docmeta.js.map +1 -1
  107. package/dist/github-4UR67MEN.js +35 -0
  108. package/dist/github-UPGKMVVF.js +30 -0
  109. package/dist/graph/runtime.d.ts +4 -1
  110. package/dist/graph/runtime.js +20 -9
  111. package/dist/graph/runtime.js.map +1 -1
  112. package/dist/{host-6GURH5HE.js → host-YSTYO5DX.js} +3 -3
  113. package/dist/index.d.ts +192 -26
  114. package/dist/index.js +129 -124
  115. package/dist/index.js.map +1 -1
  116. package/dist/{json-BXY44ED7.js → json-DQIELR36.js} +18 -17
  117. package/dist/labels-XSTJJMSG.js +73 -0
  118. package/dist/labels-XSTJJMSG.js.map +1 -0
  119. package/dist/lint-BLBGGOYM.js +34 -0
  120. package/dist/list-B3RRRWFQ.js +32 -0
  121. package/dist/list-ZFRT3JQH.js +35 -0
  122. package/dist/{page-EV7OUBAU.js → page-5ISEVJR5.js} +18 -16
  123. package/dist/{prepare-JHJDJB6I.js → prepare-KFXXG2CJ.js} +22 -21
  124. package/dist/{prepare-JHJDJB6I.js.map → prepare-KFXXG2CJ.js.map} +1 -1
  125. package/dist/{pretty-Q5Y2PA64.js → pretty-Y7CGQLAF.js} +18 -17
  126. package/dist/{pretty-SCRK66M5.js → pretty-ZISH3Q4F.js} +18 -17
  127. package/dist/{provider-527CO4DM.js → provider-LBX4IXGX.js} +3 -3
  128. package/dist/{release-3D5PK6M7.js → release-VV3UTKE5.js} +3 -3
  129. package/dist/{reporters-M6LJ2IYU.js → reporters-26H3N2KW.js} +3 -3
  130. package/dist/{reporters-A5ADKDYR.js → reporters-4STXJJE2.js} +16 -15
  131. package/dist/{reporters-RBYTASMI.js → reporters-74B4U2GZ.js} +7 -7
  132. package/dist/run-DVGTKM52.js +37 -0
  133. package/dist/{term-CQAGNG3Q.js → term-PLJEYJQV.js} +981 -141
  134. package/dist/term-PLJEYJQV.js.map +1 -0
  135. package/dist/validate-CJNFQHMD.js +19 -0
  136. package/package.json +3 -2
  137. package/plugin/manni/.claude-plugin/plugin.json +1 -1
  138. package/shapes/graph/shapes-1.1.0.ttl +785 -0
  139. package/dist/build-QSPNK5AL.js +0 -35
  140. package/dist/calibrate-KXN4URPM.js +0 -40
  141. package/dist/capture-JHTSUPUC.js +0 -37
  142. package/dist/check-MDGXEUWL.js +0 -20
  143. package/dist/check-WOQRKNZK.js +0 -29
  144. package/dist/chunk-2DRHT73U.js.map +0 -1
  145. package/dist/chunk-2IAZEB45.js.map +0 -1
  146. package/dist/chunk-2MJ62AYQ.js.map +0 -1
  147. package/dist/chunk-4VBSTXN6.js +0 -392
  148. package/dist/chunk-4VBSTXN6.js.map +0 -1
  149. package/dist/chunk-6HWBRZIN.js.map +0 -1
  150. package/dist/chunk-BKVHX6FU.js.map +0 -1
  151. package/dist/chunk-D4N2V43Z.js.map +0 -1
  152. package/dist/chunk-EFW7CAG4.js +0 -387
  153. package/dist/chunk-EFW7CAG4.js.map +0 -1
  154. package/dist/chunk-GV56WGL2.js.map +0 -1
  155. package/dist/chunk-HQR2ZBHW.js.map +0 -1
  156. package/dist/chunk-J6IDQGJL.js.map +0 -1
  157. package/dist/chunk-JPQDNYXH.js.map +0 -1
  158. package/dist/chunk-JROBZ7JA.js +0 -818
  159. package/dist/chunk-JROBZ7JA.js.map +0 -1
  160. package/dist/chunk-PCQ7ELJH.js.map +0 -1
  161. package/dist/chunk-QCHVR4ZM.js.map +0 -1
  162. package/dist/chunk-QLWC7MKD.js.map +0 -1
  163. package/dist/chunk-TU2WUBVZ.js +0 -2
  164. package/dist/chunk-VSEBFHAY.js.map +0 -1
  165. package/dist/chunk-Y6DOMTQD.js.map +0 -1
  166. package/dist/cli-RORDPAPE.js.map +0 -1
  167. package/dist/github-RY3FRA6P.js +0 -29
  168. package/dist/github-YKQSH7FS.js +0 -34
  169. package/dist/lint-YJ2L22BW.js +0 -33
  170. package/dist/list-NSG24VVX.js +0 -31
  171. package/dist/list-V6EGCSHX.js +0 -34
  172. package/dist/run-BUE2DDXN.js +0 -36
  173. package/dist/term-CQAGNG3Q.js.map +0 -1
  174. package/dist/validate-ZBW44RHT.js +0 -18
  175. /package/dist/{batch-UAULUMGH.js.map → batch-KMGZMIAQ.js.map} +0 -0
  176. /package/dist/{build-QSPNK5AL.js.map → build-NO4AWCYG.js.map} +0 -0
  177. /package/dist/{calibrate-KXN4URPM.js.map → calibrate-XQUG5XAK.js.map} +0 -0
  178. /package/dist/{capture-JHTSUPUC.js.map → capture-5XE3ZMXK.js.map} +0 -0
  179. /package/dist/{check-MDGXEUWL.js.map → check-HTNPLWOV.js.map} +0 -0
  180. /package/dist/{check-WOQRKNZK.js.map → check-RJ45IBA6.js.map} +0 -0
  181. /package/dist/{check-YEOYBFST.js.map → check-WFXSXICD.js.map} +0 -0
  182. /package/dist/{chunk-IGSHYP74.js.map → chunk-23P7KMJM.js.map} +0 -0
  183. /package/dist/{chunk-HA6MQMOY.js.map → chunk-24J7TYPU.js.map} +0 -0
  184. /package/dist/{chunk-PCS4VJBV.js.map → chunk-37QJLVS3.js.map} +0 -0
  185. /package/dist/{chunk-4CK6ZSOK.js.map → chunk-3P6KCU36.js.map} +0 -0
  186. /package/dist/{chunk-54F74XR3.js.map → chunk-5JBVFWVP.js.map} +0 -0
  187. /package/dist/{chunk-B7XYNRJQ.js.map → chunk-6KIYVVKL.js.map} +0 -0
  188. /package/dist/{chunk-GDVZ5VII.js.map → chunk-7A452BPZ.js.map} +0 -0
  189. /package/dist/{chunk-M42DZCOU.js.map → chunk-7FCLXEAQ.js.map} +0 -0
  190. /package/dist/{chunk-LBSCW232.js.map → chunk-7NXPQKSB.js.map} +0 -0
  191. /package/dist/{chunk-OPXWPJDA.js.map → chunk-A3TEDWBZ.js.map} +0 -0
  192. /package/dist/{chunk-BBT6AVUG.js.map → chunk-BHHXU2D2.js.map} +0 -0
  193. /package/dist/{chunk-FQXWVS6J.js.map → chunk-CMMBWHT2.js.map} +0 -0
  194. /package/dist/{chunk-EIFCP6CZ.js.map → chunk-CO47QJKZ.js.map} +0 -0
  195. /package/dist/{chunk-ADMEPUBT.js.map → chunk-CXWTNT2O.js.map} +0 -0
  196. /package/dist/{chunk-LKP7QDFN.js.map → chunk-DAQTRAP5.js.map} +0 -0
  197. /package/dist/{chunk-PWBH7DCQ.js.map → chunk-EESH6COU.js.map} +0 -0
  198. /package/dist/{chunk-NCPWXHDO.js.map → chunk-JEUFYSFQ.js.map} +0 -0
  199. /package/dist/{chunk-2IR4T5PO.js.map → chunk-JJ4RSDSY.js.map} +0 -0
  200. /package/dist/{chunk-WDWXAYVH.js.map → chunk-L3RLGGRK.js.map} +0 -0
  201. /package/dist/{chunk-T7JAOYE5.js.map → chunk-L75CAZG4.js.map} +0 -0
  202. /package/dist/{chunk-U7CTFN2J.js.map → chunk-MYRPMSOX.js.map} +0 -0
  203. /package/dist/{chunk-WQWKYAAK.js.map → chunk-NUQF5F5J.js.map} +0 -0
  204. /package/dist/{chunk-FUCPZVRY.js.map → chunk-OEN6FBUW.js.map} +0 -0
  205. /package/dist/{chunk-FBMZJEB3.js.map → chunk-OKMTUAWO.js.map} +0 -0
  206. /package/dist/{chunk-R4WXQIOZ.js.map → chunk-PCEM5FOZ.js.map} +0 -0
  207. /package/dist/{chunk-4D5IZSXM.js.map → chunk-PXNCRGUL.js.map} +0 -0
  208. /package/dist/{chunk-ODRPL3WB.js.map → chunk-Q3ODX5PF.js.map} +0 -0
  209. /package/dist/{chunk-KGEQJ5CC.js.map → chunk-RRFFUWDL.js.map} +0 -0
  210. /package/dist/{chunk-NSBXVPZL.js.map → chunk-S3XUYW5K.js.map} +0 -0
  211. /package/dist/{chunk-LPIF5LIE.js.map → chunk-SAU2WQFC.js.map} +0 -0
  212. /package/dist/{chunk-MSRU4D4P.js.map → chunk-SFLICIQV.js.map} +0 -0
  213. /package/dist/{chunk-NGTVREIH.js.map → chunk-U6IHLEWT.js.map} +0 -0
  214. /package/dist/{chunk-VQK4VHLF.js.map → chunk-YQV75FIL.js.map} +0 -0
  215. /package/dist/{chunk-TU2WUBVZ.js.map → chunk-YUTVAMWW.js.map} +0 -0
  216. /package/dist/{chunk-RLT5SEML.js.map → chunk-Z5MZCCTT.js.map} +0 -0
  217. /package/dist/{cli-JJMOVIKS.js.map → cli-BS43EVCD.js.map} +0 -0
  218. /package/dist/{cli-ONTC5PKT.js.map → cli-FX53PBQ3.js.map} +0 -0
  219. /package/dist/{cli-I62SRH3R.js.map → cli-NGL63E53.js.map} +0 -0
  220. /package/dist/{cli-VUKMWSSF.js.map → cli-WNEI5L7P.js.map} +0 -0
  221. /package/dist/{config-XDA42RJL.js.map → config-JJW75SBX.js.map} +0 -0
  222. /package/dist/{github-RY3FRA6P.js.map → github-4UR67MEN.js.map} +0 -0
  223. /package/dist/{github-YKQSH7FS.js.map → github-UPGKMVVF.js.map} +0 -0
  224. /package/dist/{host-6GURH5HE.js.map → host-YSTYO5DX.js.map} +0 -0
  225. /package/dist/{json-BXY44ED7.js.map → json-DQIELR36.js.map} +0 -0
  226. /package/dist/{lint-YJ2L22BW.js.map → lint-BLBGGOYM.js.map} +0 -0
  227. /package/dist/{list-NSG24VVX.js.map → list-B3RRRWFQ.js.map} +0 -0
  228. /package/dist/{list-V6EGCSHX.js.map → list-ZFRT3JQH.js.map} +0 -0
  229. /package/dist/{page-EV7OUBAU.js.map → page-5ISEVJR5.js.map} +0 -0
  230. /package/dist/{pretty-Q5Y2PA64.js.map → pretty-Y7CGQLAF.js.map} +0 -0
  231. /package/dist/{pretty-SCRK66M5.js.map → pretty-ZISH3Q4F.js.map} +0 -0
  232. /package/dist/{provider-527CO4DM.js.map → provider-LBX4IXGX.js.map} +0 -0
  233. /package/dist/{release-3D5PK6M7.js.map → release-VV3UTKE5.js.map} +0 -0
  234. /package/dist/{reporters-A5ADKDYR.js.map → reporters-26H3N2KW.js.map} +0 -0
  235. /package/dist/{reporters-M6LJ2IYU.js.map → reporters-4STXJJE2.js.map} +0 -0
  236. /package/dist/{reporters-RBYTASMI.js.map → reporters-74B4U2GZ.js.map} +0 -0
  237. /package/dist/{run-BUE2DDXN.js.map → run-DVGTKM52.js.map} +0 -0
  238. /package/dist/{validate-ZBW44RHT.js.map → validate-CJNFQHMD.js.map} +0 -0
@@ -1,8 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- DEFAULT_CONFIG_FILENAME,
4
- DEFAULT_INDEX_FILES,
5
- DEFAULT_LINK_EXTENSIONS,
6
3
  GRAPH_NOT_APPLICABLE_TO_VARIANT,
7
4
  GRAPH_NOT_SOFTWARE_SUBJECT,
8
5
  GraphError,
@@ -18,12 +15,18 @@ import {
18
15
  ROLE,
19
16
  SOFTWARE_LIFECYCLE_IRIS,
20
17
  SOFTWARE_SUBJECT_IRIS,
18
+ STDIN,
21
19
  STDIN_PATH,
22
20
  TOPIC_TYPE_IRIS,
23
- assertCollectionWithoutPaths,
21
+ analyzeDoc,
22
+ assertInputFormat,
24
23
  byCodeUnit,
24
+ canonicalLanguageTag,
25
25
  conceptSlug,
26
+ documentBase,
27
+ documentSetPatterns,
26
28
  encodeSegment,
29
+ hasScheme,
27
30
  loadRunConfig,
28
31
  mintAgentIri,
29
32
  mintBuildActivityIri,
@@ -33,521 +36,42 @@ import {
33
36
  mintProductIri,
34
37
  mintSchemeIri,
35
38
  mintSectionIri,
36
- normalizeDocPath
37
- } from "./chunk-JROBZ7JA.js";
38
- import {
39
- parserByName,
40
- parserForExtension,
41
- supportedExtensions,
42
- unsupportedFormatMessage
43
- } from "./chunk-2IR4T5PO.js";
44
- import {
45
- metaPageView
46
- } from "./chunk-LKP7QDFN.js";
39
+ mintTermConceptIri,
40
+ normalizeDocPath,
41
+ openMetaView,
42
+ parseBody,
43
+ readSampleQuestions,
44
+ resolveDocumentSet,
45
+ resolveRelative,
46
+ routesFrom,
47
+ withExternalMetadata
48
+ } from "./chunk-Q2QC5AZB.js";
47
49
  import {
48
- STDIN_REQUIRES_AS,
49
50
  writeTextAtomic
50
- } from "./chunk-GV56WGL2.js";
51
- import {
52
- extractFrontmatter,
53
- extractorForExtension
54
- } from "./chunk-VSEBFHAY.js";
55
- import {
56
- selectCollections
57
- } from "./chunk-QLWC7MKD.js";
51
+ } from "./chunk-WO4JYWZK.js";
58
52
  import {
59
- warn
60
- } from "./chunk-HX44GB4Z.js";
53
+ termLabelSource
54
+ } from "./chunk-DSWKBZWW.js";
61
55
  import {
62
56
  package_default
63
- } from "./chunk-2MJ62AYQ.js";
57
+ } from "./chunk-7MCQHTQ5.js";
64
58
  import {
65
59
  errorMessage
66
60
  } from "./chunk-G3T47CFV.js";
67
61
 
68
62
  // src/graph/commands/build.ts
69
63
  import { mkdirSync, readFileSync as readFileSync2, writeFileSync } from "node:fs";
70
- import { dirname, resolve as resolve3 } from "node:path";
71
-
72
- // src/graph/core/analyze.ts
73
- import { createHash } from "node:crypto";
74
- import { extname } from "node:path";
75
- import { unified } from "unified";
76
- import remarkParse from "remark-parse";
77
- import remarkGfm from "remark-gfm";
78
- import remarkFrontmatter from "remark-frontmatter";
79
- import remarkMdx from "remark-mdx";
80
- import { toString as mdastToString } from "mdast-util-to-string";
81
- import GithubSlugger from "github-slugger";
82
- var DOC_FORMATS = [
83
- "asciidoc",
84
- "html",
85
- "markdown",
86
- "mdx",
87
- "rst",
88
- "xml"
89
- ];
90
- function isTreeFormat(format) {
91
- return format !== "markdown" && format !== "mdx";
92
- }
93
- function isDocFormat(name) {
94
- return DOC_FORMATS.includes(name);
95
- }
96
- function formatOf(path, format) {
97
- if (format !== void 0) return format;
98
- const name = parserForExtension(extname(path))?.name;
99
- return name !== void 0 && isDocFormat(name) ? name : "markdown";
100
- }
101
- var processor = unified().use(remarkParse).use(remarkGfm).use(remarkFrontmatter, ["yaml", "toml"]);
102
- var mdxProcessor = unified().use(remarkParse).use(remarkGfm).use(remarkFrontmatter, ["yaml", "toml"]).use(remarkMdx);
103
- var IMAGE_ELEMENTS = /* @__PURE__ */ new Set(["img", "image"]);
104
- function jsxAttributeValue(node, attributeName) {
105
- const attributes = node.attributes;
106
- if (!Array.isArray(attributes)) return void 0;
107
- for (const attribute of attributes) {
108
- if (attribute.type !== "mdxJsxAttribute") continue;
109
- if (attribute.name !== attributeName) continue;
110
- return typeof attribute.value === "string" ? attribute.value : void 0;
111
- }
112
- return void 0;
113
- }
114
- function hasScheme(target) {
115
- return /^[a-z][a-z0-9+.-]*:/i.test(target);
116
- }
117
- function resolveRelative(docPath, target) {
118
- const baseSegments = normalizeDocPath(docPath).split("/").slice(0, -1);
119
- const segments = [...baseSegments];
120
- for (const part of target.split("/")) {
121
- if (part === "" || part === ".") continue;
122
- if (part === "..") {
123
- if (segments.length === 0) return null;
124
- if (segments[segments.length - 1] === "..") segments.push("..");
125
- else segments.pop();
126
- } else {
127
- segments.push(part);
128
- }
129
- }
130
- return segments.join("/");
131
- }
132
- var HAS_EXTENSION = /\.[a-z0-9]+$/i;
133
- function addressesDocument(target, extensions) {
134
- if (target === "" || !HAS_EXTENSION.test(target)) return true;
135
- if (extensions.length === 0) return true;
136
- const ext = target.slice(target.lastIndexOf(".")).toLowerCase();
137
- return extensions.some((e) => e.toLowerCase() === ext);
138
- }
139
- function slugNorm(path) {
140
- return path.toLowerCase().replace(/[-_]/g, "");
141
- }
142
- var PathIndex = class {
143
- constructor(exact) {
144
- this.exact = exact;
145
- for (const path of exact) {
146
- const lower = path.toLowerCase();
147
- this.lower.set(lower, this.lower.has(lower) ? null : path);
148
- const slug = slugNorm(path);
149
- this.slugged.set(slug, this.slugged.has(slug) ? null : path);
150
- }
151
- }
152
- exact;
153
- lower = /* @__PURE__ */ new Map();
154
- slugged = /* @__PURE__ */ new Map();
155
- resolve(candidate) {
156
- if (this.exact.has(candidate)) return candidate;
157
- return this.lower.get(candidate.toLowerCase()) ?? this.slugged.get(slugNorm(candidate)) ?? void 0;
158
- }
159
- };
160
- function safeDecode(value) {
161
- try {
162
- return decodeURIComponent(value);
163
- } catch {
164
- return value;
165
- }
166
- }
167
- function targetCandidates(target, isDirectory, extensions, indexFiles) {
168
- if (target !== "" && HAS_EXTENSION.test(target)) return [target];
169
- const extensionCandidates = target === "" ? [] : extensions.map((ext) => `${target}${ext}`);
170
- const dir = target === "" ? "" : `${target}/`;
171
- const indexCandidates = [];
172
- for (const indexFile of indexFiles) {
173
- for (const ext of extensions)
174
- indexCandidates.push(`${dir}${indexFile}${ext}`);
175
- }
176
- return isDirectory ? [...indexCandidates, ...extensionCandidates] : [...extensionCandidates, ...indexCandidates];
177
- }
178
- function routeLanguageFor(path, routes) {
179
- let best;
180
- for (const mapping of routes) {
181
- if (mapping.language === void 0) continue;
182
- const root = mapping.root;
183
- const covers = root === "" || path === root || path.startsWith(`${root}/`);
184
- if (!covers) continue;
185
- if (best === void 0 || root.length > best.root.length) {
186
- best = { root, language: mapping.language };
187
- }
188
- }
189
- return best?.language;
190
- }
191
- function resolveRoute(pathPart, routes, index) {
192
- const isDirectory = /\/+$/.test(pathPart);
193
- const clean = safeDecode(pathPart).replace(/\/+$/, "");
194
- let anyMatched = false;
195
- for (const mapping of routes) {
196
- if (clean !== mapping.basePath && !clean.startsWith(`${mapping.basePath}/`)) {
197
- continue;
198
- }
199
- const rest = clean.slice(mapping.basePath.length).replace(/^\/+/, "");
200
- if (!addressesDocument(rest, mapping.extensions)) continue;
201
- anyMatched = true;
202
- const prefix = mapping.root ? `${mapping.root}/` : "";
203
- const stem = rest === "" ? mapping.root : `${prefix}${rest}`;
204
- const candidates = targetCandidates(
205
- stem,
206
- isDirectory || rest === "",
207
- mapping.extensions,
208
- mapping.indexFiles
209
- );
210
- for (const candidate of candidates) {
211
- const resolved = index.resolve(candidate);
212
- if (resolved) return resolved;
213
- }
214
- }
215
- return anyMatched ? "broken" : null;
216
- }
217
- var indexCache = /* @__PURE__ */ new WeakMap();
218
- function pathIndexFor(allPaths) {
219
- let index = indexCache.get(allPaths);
220
- if (!index) {
221
- index = new PathIndex(allPaths);
222
- indexCache.set(allPaths, index);
223
- }
224
- return index;
225
- }
226
- function classifyLink(docPath, rawTarget, allPaths, routes) {
227
- const raw = rawTarget;
228
- if (hasScheme(raw)) {
229
- try {
230
- return { raw, kind: "external", url: new URL(raw).href };
231
- } catch {
232
- return null;
233
- }
234
- }
235
- const hashAt = raw.indexOf("#");
236
- const pathPart = hashAt === -1 ? raw : raw.slice(0, hashAt);
237
- const anchor = hashAt === -1 ? void 0 : raw.slice(hashAt + 1);
238
- if (pathPart === "") return null;
239
- if (pathPart.startsWith("/")) {
240
- const resolved2 = resolveRoute(pathPart, routes, pathIndexFor(allPaths));
241
- if (resolved2 === null) return null;
242
- if (resolved2 === "broken") return { raw, kind: "broken" };
243
- const link = { raw, kind: "internal", resolvedPath: resolved2 };
244
- if (anchor) link.anchor = anchor;
245
- return link;
246
- }
247
- const resolved = resolveRelative(docPath, safeDecode(pathPart));
248
- if (resolved !== null) {
249
- const index = pathIndexFor(allPaths);
250
- let candidates;
251
- if (allPaths.has(resolved)) {
252
- candidates = [resolved];
253
- } else if (HAS_EXTENSION.test(resolved)) {
254
- if (!addressesDocument(resolved, DEFAULT_LINK_EXTENSIONS)) return null;
255
- candidates = [];
256
- } else {
257
- candidates = targetCandidates(
258
- resolved,
259
- pathPart.endsWith("/"),
260
- DEFAULT_LINK_EXTENSIONS,
261
- DEFAULT_INDEX_FILES
262
- );
263
- }
264
- for (const candidate of candidates) {
265
- const hit = index.resolve(candidate);
266
- if (hit) {
267
- const link = { raw, kind: "internal", resolvedPath: hit };
268
- if (anchor) link.anchor = anchor;
269
- return link;
270
- }
271
- }
272
- }
273
- return { raw, kind: "broken" };
274
- }
275
- function classifyImage(docPath, rawTarget) {
276
- if (hasScheme(rawTarget)) {
277
- return { raw: rawTarget, target: rawTarget, external: true };
278
- }
279
- const resolved = resolveRelative(docPath, rawTarget);
280
- return { raw: rawTarget, target: resolved ?? rawTarget, external: false };
281
- }
282
- function extractorFor(format) {
283
- return extractorForExtension(parserByName(format)?.extensions[0] ?? "");
284
- }
285
- function metadataOf(content, path, format) {
286
- try {
287
- const meta = format === "markdown" || format === "mdx" ? extractFrontmatter(content, "markdown") : extractorFor(format)?.extract(content, path);
288
- return meta === void 0 ? { data: {}, present: false } : { data: meta.data, present: meta.present };
289
- } catch (error) {
290
- throw new GraphError(`${path}: ${errorMessage(error)}`);
291
- }
292
- }
293
- function analyzeDoc(content, relPath, allPaths, options = {}) {
294
- const routes = options.routes ?? [];
295
- const path = normalizeDocPath(relPath);
296
- const format = formatOf(path, options.format);
297
- const parse = options.parse ?? parseBody;
298
- let body = isTreeFormat(format) ? parse(content, path, format) : void 0;
299
- const meta = metadataOf(content, path, format);
300
- body ??= parse(content, path, format);
301
- const links = [];
302
- for (const target of body.linkTargets) {
303
- const link = classifyLink(path, target, allPaths, routes);
304
- if (link) links.push(link);
305
- }
306
- const routeLanguage = routeLanguageFor(path, routes);
307
- return {
308
- path,
309
- frontmatter: meta.data,
310
- frontmatterPresent: meta.present,
311
- format,
312
- firstH1: body.firstH1,
313
- sections: body.sections,
314
- links,
315
- images: body.imageTargets.map((target) => classifyImage(path, target)),
316
- codeLanguages: body.codeLanguages,
317
- // Omitted rather than set to undefined, so a doc under no localized route
318
- // carries no key at all — `routeLanguage` in JSON output means something.
319
- ...routeLanguage === void 0 ? {} : { routeLanguage },
320
- // Over the content as read — line endings included, so the digest is
321
- // byte-faithful and equals `sha256sum <file>` for any valid-UTF-8 file
322
- // (ADR 01036). The CRLF corpus fixture depends on this not normalizing.
323
- contentHash: createHash("sha256").update(content, "utf8").digest("hex")
324
- };
325
- }
326
- function parseBody(content, path, format) {
327
- if (isTreeFormat(format)) return parseTreeBody(content, path, format);
328
- const isMdx = format === "mdx";
329
- let tree;
330
- try {
331
- tree = (isMdx ? mdxProcessor : processor).parse(content);
332
- } catch (error) {
333
- if (!isMdx) throw error;
334
- const reason = errorMessage(error);
335
- throw new GraphError(`Could not parse MDX in ${path}: ${reason}`);
336
- }
337
- const sections = [];
338
- const linkTargets = [];
339
- const imageTargets = [];
340
- const codeLanguages = /* @__PURE__ */ new Set();
341
- const definitions = /* @__PURE__ */ new Map();
342
- let firstH1;
343
- visit(tree, (node) => {
344
- if (node.type === "definition") {
345
- const def = node;
346
- definitions.set(def.identifier, def);
347
- }
348
- });
349
- const slugger = new GithubSlugger();
350
- const stack = [];
351
- const childCount = /* @__PURE__ */ new Map();
352
- visit(tree, (node) => {
353
- switch (node.type) {
354
- case "heading": {
355
- const level = node.depth;
356
- const title = mdastToString(node);
357
- const slug = slugger.slug(title);
358
- if (level === 1 && firstH1 === void 0) firstH1 = title;
359
- for (let top = stack.at(-1); top !== void 0 && top.level >= level; top = stack.at(-1)) {
360
- stack.pop();
361
- }
362
- const parentSlug = stack.at(-1)?.slug ?? null;
363
- const parentKey = parentSlug ?? "";
364
- const order = (childCount.get(parentKey) ?? 0) + 1;
365
- childCount.set(parentKey, order);
366
- sections.push({ slug, title, level, order, parentSlug });
367
- stack.push({ level, slug });
368
- break;
369
- }
370
- case "link": {
371
- linkTargets.push(node.url);
372
- break;
373
- }
374
- case "linkReference": {
375
- const def = definitions.get(
376
- node.identifier
377
- );
378
- if (def) linkTargets.push(def.url);
379
- break;
380
- }
381
- case "image": {
382
- imageTargets.push(node.url);
383
- break;
384
- }
385
- case "imageReference": {
386
- const def = definitions.get(
387
- node.identifier
388
- );
389
- if (def) imageTargets.push(def.url);
390
- break;
391
- }
392
- case "code": {
393
- const lang = node.lang;
394
- if (lang) codeLanguages.add(lang);
395
- break;
396
- }
397
- // A JSX element's `href` is a link and its `src` is an image, on any
398
- // element (ADR 01022). Those are HTML's own names for the relationships,
399
- // so this stays structural — dockg never learns what `<LinkCard>` means.
400
- case "mdxJsxFlowElement":
401
- case "mdxJsxTextElement": {
402
- const href = jsxAttributeValue(node, "href");
403
- if (href !== void 0) linkTargets.push(href);
404
- const name = node.name ?? "";
405
- if (IMAGE_ELEMENTS.has(name.toLowerCase())) {
406
- const src = jsxAttributeValue(node, "src");
407
- if (src !== void 0) imageTargets.push(src);
408
- }
409
- break;
410
- }
411
- }
412
- });
413
- return {
414
- firstH1,
415
- sections,
416
- linkTargets,
417
- imageTargets,
418
- codeLanguages: [...codeLanguages].sort()
419
- };
420
- }
421
- function parseTree(content, path, format) {
422
- const parser = parserByName(format);
423
- if (parser === void 0) {
424
- throw new GraphError(`No parser reads ${format}.`);
425
- }
426
- try {
427
- return parser.parse(content, path);
428
- } catch (error) {
429
- throw new GraphError(
430
- `Could not parse ${format} in ${path}: ${errorMessage(error)}`
431
- );
432
- }
433
- }
434
- var IRI_SAFE_ID = /^[A-Za-z_][A-Za-z0-9_.:-]*$/;
435
- function mintTreeSections(roots) {
436
- const out = {
437
- sections: [],
438
- owned: [],
439
- unowned: [],
440
- firstH1: void 0
441
- };
442
- const slugger = new GithubSlugger();
443
- const taken = /* @__PURE__ */ new Set();
444
- const childCount = /* @__PURE__ */ new Map();
445
- const anchorFor = (node) => {
446
- const id = node.id;
447
- if (id !== void 0 && IRI_SAFE_ID.test(id) && !id.startsWith("prov.")) {
448
- let anchor2 = id;
449
- for (let n = 1; taken.has(anchor2); n++) anchor2 = `${id}-${String(n)}`;
450
- taken.add(anchor2);
451
- return anchor2;
452
- }
453
- let anchor = slugger.slug(node.title);
454
- while (taken.has(anchor)) anchor = slugger.slug(node.title);
455
- taken.add(anchor);
456
- return anchor;
457
- };
458
- const walk = (nodes, parentSlug) => {
459
- for (const node of nodes) {
460
- if (node.level === 0 || node.synthetic || node.title.trim() === "") {
461
- out.unowned.push(...node.children);
462
- walk(node.sections, parentSlug);
463
- continue;
464
- }
465
- const slug = anchorFor(node);
466
- if (node.level === 1 && out.firstH1 === void 0) {
467
- out.firstH1 = node.title;
468
- }
469
- const parentKey = parentSlug ?? "";
470
- const order = (childCount.get(parentKey) ?? 0) + 1;
471
- childCount.set(parentKey, order);
472
- out.sections.push({
473
- slug,
474
- title: node.title,
475
- level: node.level,
476
- order,
477
- parentSlug
478
- });
479
- out.owned.push(node.children);
480
- walk(node.sections, slug);
481
- }
482
- };
483
- walk(roots, null);
484
- return out;
485
- }
486
- function eachContent(nodes, fn) {
487
- for (const node of nodes) {
488
- fn(node);
489
- switch (node.kind) {
490
- case "list":
491
- for (const item of node.items) eachContent(item.children, fn);
492
- break;
493
- case "table":
494
- for (const row of node.children) {
495
- for (const cell of row.children) eachContent(cell.children, fn);
496
- }
497
- break;
498
- case "definitionList":
499
- for (const item of node.children) eachContent(item.definition, fn);
500
- break;
501
- case "admonition":
502
- case "blockquote":
503
- case "element":
504
- eachContent(node.children, fn);
505
- break;
506
- default:
507
- break;
508
- }
509
- }
510
- }
511
- function treeContent(sections) {
512
- return sections.flatMap((s) => [...s.children, ...treeContent(s.sections)]);
513
- }
514
- function parseTreeBody(content, path, format) {
515
- const tree = parseTree(content, path, format);
516
- const minted = mintTreeSections(tree.sections);
517
- const imageTargets = [];
518
- const codeLanguages = /* @__PURE__ */ new Set();
519
- eachContent(treeContent(tree.sections), (node) => {
520
- if (node.kind === "image") imageTargets.push(node.url);
521
- else if (node.kind === "codeBlock" && node.language) {
522
- codeLanguages.add(node.language);
523
- }
524
- });
525
- return {
526
- ...minted.firstH1 === void 0 ? {} : { firstH1: minted.firstH1 },
527
- sections: minted.sections,
528
- linkTargets: tree.links.map((l) => l.target),
529
- imageTargets,
530
- codeLanguages: [...codeLanguages].sort()
531
- };
532
- }
533
- function visit(node, fn) {
534
- const children = node.children;
535
- if (!children) return;
536
- for (const child of children) {
537
- fn(child);
538
- visit(child, fn);
539
- }
540
- }
64
+ import { dirname, resolve } from "node:path";
541
65
 
542
66
  // src/graph/core/analyze-cache.ts
543
- import { createHash as createHash2 } from "node:crypto";
67
+ import { createHash } from "node:crypto";
544
68
  import { mkdir } from "node:fs/promises";
545
69
  import { readFileSync } from "node:fs";
546
70
  import { join } from "node:path";
547
71
  var ANALYZE_CACHE_DIR = ".manni/graph/analyze-cache";
548
72
  var ENTRY_VERSION = 1;
549
73
  function sha256(text) {
550
- return createHash2("sha256").update(text, "utf8").digest("hex");
74
+ return createHash("sha256").update(text, "utf8").digest("hex");
551
75
  }
552
76
  var isStrings = (value) => Array.isArray(value) && value.every((v) => typeof v === "string");
553
77
  function isSection(value) {
@@ -609,87 +133,73 @@ function readEntry(file, key) {
609
133
  }
610
134
  }
611
135
 
612
- // src/graph/core/localizations.ts
613
- var LOCALIZATIONS_FILENAME = "localizations.json";
614
- var UNDETERMINED = "und";
615
- 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}))*$/;
616
- function isLanguageTag(value) {
617
- return LANGUAGE_TAG.test(value);
618
- }
619
- function canonicalLanguageTag(tag) {
620
- try {
621
- return Intl.getCanonicalLocales(tag)[0] ?? tag;
622
- } catch {
623
- return tag;
624
- }
625
- }
626
- function searchIndexFilename(language) {
627
- return `search.${language}.json`;
628
- }
629
- function vectorIndexFilename(language) {
630
- return `vectors.${language}.bin`;
136
+ // src/graph/core/concepts.ts
137
+ function canonicalLanguage(tag) {
138
+ return tag === void 0 || tag === "" ? void 0 : canonicalLanguageTag(tag);
139
+ }
140
+ var primary = (tag) => (tag.split("-")[0] ?? "").toLowerCase();
141
+ var MAX_REDIRECTS = 8;
142
+ var built = /* @__PURE__ */ new WeakMap();
143
+ function termIndex(terms) {
144
+ const cached = built.get(terms);
145
+ if (cached !== void 0) return cached;
146
+ const index = buildTermIndex(terms);
147
+ built.set(terms, index);
148
+ return index;
631
149
  }
632
- function emitLocalizations(doc) {
633
- const languages = [...doc.languages].sort(
634
- (a, b) => byCodeUnit(a.language, b.language)
150
+ function buildTermIndex(terms) {
151
+ const sorted = [...terms].map((t) => ({ term: t, language: canonicalLanguage(t.language) })).sort(
152
+ (a, b) => byCodeUnit(a.term.id, b.term.id) || byCodeUnit(a.language ?? "", b.language ?? "") || byCodeUnit(a.term.label, b.term.label)
635
153
  );
636
- return `${JSON.stringify({ version: doc.version, languages }, null, 2)}
637
- `;
638
- }
639
- function isRecord(v) {
640
- return typeof v === "object" && v !== null && !Array.isArray(v);
641
- }
642
- function parseLocalizations(text) {
643
- let parsed;
644
- try {
645
- parsed = JSON.parse(text);
646
- } catch {
647
- return void 0;
648
- }
649
- if (!isRecord(parsed)) return void 0;
650
- if (parsed["version"] !== 1 || !Array.isArray(parsed["languages"])) {
651
- return void 0;
652
- }
653
- for (const entry of parsed["languages"]) {
654
- if (!isRecord(entry)) return void 0;
655
- const language = entry["language"];
656
- const search = entry["search"];
657
- 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))) {
658
- return void 0;
154
+ const groups = /* @__PURE__ */ new Map();
155
+ const redirects = [];
156
+ const byLabel = /* @__PURE__ */ new Map();
157
+ const byId = /* @__PURE__ */ new Map();
158
+ const byAlt = /* @__PURE__ */ new Map();
159
+ const put = (map, value, key) => {
160
+ const k = value.toLowerCase();
161
+ const list = map.get(k);
162
+ if (list) list.push(key);
163
+ else map.set(k, [key]);
164
+ };
165
+ for (const { term, language } of sorted) {
166
+ const target = term.see === void 0 ? { id: term.id } : { see: term.see, language };
167
+ if (term.see === void 0) {
168
+ const group = groups.get(term.id);
169
+ if (group) group.push(term);
170
+ else groups.set(term.id, [term]);
171
+ } else {
172
+ redirects.push(term);
659
173
  }
660
- const v = entry["vectors"];
661
- if (v !== void 0) {
662
- 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
663
- // filename this language's sidecar would be given. Without it,
664
- // `isSafeRelativePath` alone leaves `vectors.path` far more reachable
665
- // than `search.path` — and `search --mode vector` opens it.
666
- !ownsFilename(v["path"], vectorIndexFilename(language))) {
667
- return void 0;
174
+ put(byLabel, term.label, { language, target });
175
+ put(byId, term.id, { language, target });
176
+ for (const alt of term.altLabels ?? []) put(byAlt, alt, { language, target });
177
+ }
178
+ const tiers = [byLabel, byId, byAlt];
179
+ const resolve2 = (label, language, depth) => {
180
+ const wanted = canonicalLanguage(language);
181
+ const passes = wanted === void 0 ? [() => true] : [
182
+ (k) => k.language === wanted,
183
+ (k) => k.language !== void 0 && primary(k.language) === primary(wanted),
184
+ () => true
185
+ ];
186
+ const needle = label.toLowerCase();
187
+ for (const pass of passes) {
188
+ for (const tier of tiers) {
189
+ const hit = tier.get(needle)?.find(pass);
190
+ if (hit === void 0) continue;
191
+ if ("id" in hit.target) return hit.target.id;
192
+ if (depth >= MAX_REDIRECTS) return void 0;
193
+ return resolve2(hit.target.see, hit.target.language ?? wanted, depth + 1);
668
194
  }
669
195
  }
670
- }
671
- return parsed;
672
- }
673
- function isSafeRelativePath(path) {
674
- if (path === "" || path.startsWith("/") || /^[A-Za-z]:/.test(path)) {
675
- return false;
676
- }
677
- if (path.includes("\\")) return false;
678
- const segments = path.split("/");
679
- let leading = true;
680
- for (const segment of segments) {
681
- if (segment === "" || segment === ".") return false;
682
- if (segment === "..") {
683
- if (!leading) return false;
684
- continue;
685
- }
686
- leading = false;
687
- }
688
- return true;
689
- }
690
- function ownsFilename(path, expected) {
691
- if (!isSafeRelativePath(path)) return false;
692
- return path.slice(path.lastIndexOf("/") + 1) === expected;
196
+ return void 0;
197
+ };
198
+ return {
199
+ groups,
200
+ redirects,
201
+ resolve: (label, language) => groups.size === 0 ? void 0 : resolve2(label, language, 0)
202
+ };
693
203
  }
694
204
 
695
205
  // src/graph/core/derive.ts
@@ -699,6 +209,15 @@ function resolveProvDocPath(docPath, raw, docByPath) {
699
209
  const repoRelative = normalizeDocPath(raw);
700
210
  return docByPath.has(repoRelative) ? repoRelative : null;
701
211
  }
212
+ function termConceptCount(termbase) {
213
+ return termIndex(termbase).groups.size;
214
+ }
215
+ var INVERSE = {
216
+ broader: "narrower",
217
+ narrower: "broader",
218
+ related: "related"
219
+ };
220
+ var CONCEPT_SCHEME_TITLE = "manni graph concepts";
702
221
  var iri = (value) => ({ kind: "iri", value });
703
222
  var lit = (value) => ({ kind: "literal", value });
704
223
  var typedLit = (value, datatype) => ({
@@ -789,7 +308,10 @@ function deriveGraph(docs, options) {
789
308
  const quads = [];
790
309
  const add = (s, p, o) => quads.push({ s, p, o });
791
310
  const mintedConcepts = /* @__PURE__ */ new Set();
792
- const concept = (label) => {
311
+ const terms = termIndex(sources.has("terms") ? options.termbase ?? [] : []);
312
+ const concept = (label, language) => {
313
+ const id = terms.resolve(label, language);
314
+ if (id !== void 0) return mintTermConceptIri(baseIri, id);
793
315
  const c = mintConceptIri(baseIri, label);
794
316
  add(c, RDF_TYPE, iri(`${NS.skos}Concept`));
795
317
  add(c, `${NS.skos}prefLabel`, lit(label));
@@ -797,6 +319,10 @@ function deriveGraph(docs, options) {
797
319
  mintedConcepts.add(c);
798
320
  return c;
799
321
  };
322
+ const hierarchy = (s, relation, o) => {
323
+ add(s, `${NS.skos}${relation}`, iri(o));
324
+ add(o, `${NS.skos}${INVERSE[relation]}`, iri(s));
325
+ };
800
326
  const variantNode = (label) => {
801
327
  const variant = mintProductIri(baseIri, label);
802
328
  add(variant, RDF_TYPE, iri(IIRDS_PRODUCT_VARIANT));
@@ -885,6 +411,9 @@ function deriveGraph(docs, options) {
885
411
  const fm = doc.frontmatter;
886
412
  const block = graphBlock(fm);
887
413
  const harvested = resolveGraph(block, fm);
414
+ const pageLanguage = canonicalLanguage(
415
+ asString(fmValue(fm, ["lang", "language"])) ?? doc.routeLanguage
416
+ );
888
417
  let createdEmitted = false;
889
418
  let modifiedEmitted = false;
890
419
  add(docIri, RDF_TYPE, iri(`${NS.graph}Document`));
@@ -917,9 +446,13 @@ function deriveGraph(docs, options) {
917
446
  add(docIri, `${NS.dcterms}modified`, dateTerm(modified));
918
447
  modifiedEmitted = true;
919
448
  }
920
- const language = asString(fmValue(fm, ["lang", "language"])) ?? doc.routeLanguage;
921
- if (language) {
922
- add(docIri, `${NS.dcterms}language`, lit(canonicalLanguageTag(language)));
449
+ if (pageLanguage) add(docIri, `${NS.dcterms}language`, lit(pageLanguage));
450
+ for (const { question } of readSampleQuestions(fmValue(fm, ["sample-questions"]))) {
451
+ add(
452
+ docIri,
453
+ `${NS.graph}sampleQuestion`,
454
+ pageLanguage ? { kind: "literal", value: question, language: pageLanguage } : lit(question)
455
+ );
923
456
  }
924
457
  for (const raw of asStringArray(fmValue(fm, ["translation-of"]))) {
925
458
  provTargetEdge(
@@ -930,10 +463,10 @@ function deriveGraph(docs, options) {
930
463
  `${NS.schema}workTranslation`
931
464
  );
932
465
  }
466
+ const blockLabel = block ? asString(block["label"]) : void 0;
933
467
  if (block) {
934
- const label = asString(block["label"]);
935
- if (label) {
936
- const topic = concept(label);
468
+ if (blockLabel) {
469
+ const topic = concept(blockLabel, pageLanguage);
937
470
  add(docIri, `${NS.foaf}primaryTopic`, iri(topic));
938
471
  for (const alt of asStringArray(block["alt-labels"])) {
939
472
  add(topic, `${NS.skos}altLabel`, lit(alt));
@@ -944,11 +477,19 @@ function deriveGraph(docs, options) {
944
477
  ["related-concepts", "related"]
945
478
  ]) {
946
479
  for (const value of asStringArray(block[key])) {
947
- add(topic, `${NS.skos}${predicate}`, iri(concept(value)));
480
+ hierarchy(topic, predicate, concept(value, pageLanguage));
948
481
  }
949
482
  }
950
483
  }
951
484
  }
485
+ if (!blockLabel && asString(fm["type"]) === "term") {
486
+ const id = asString(fm["id"]);
487
+ const label = asString(fm["label"]);
488
+ const termId = (id !== void 0 && terms.groups.has(id) ? id : void 0) ?? (label === void 0 ? void 0 : terms.resolve(label, pageLanguage));
489
+ if (termId !== void 0) {
490
+ add(docIri, `${NS.foaf}primaryTopic`, iri(mintTermConceptIri(baseIri, termId)));
491
+ }
492
+ }
952
493
  emitIirdsTyping(docIri, harvested);
953
494
  }
954
495
  if (sources.has("tags")) {
@@ -957,7 +498,7 @@ function deriveGraph(docs, options) {
957
498
  ...asStringArray(harvested["concepts"])
958
499
  ];
959
500
  for (const label of labels) {
960
- add(docIri, `${NS.dcterms}subject`, iri(concept(label)));
501
+ add(docIri, `${NS.dcterms}subject`, iri(concept(label, pageLanguage)));
961
502
  }
962
503
  }
963
504
  if (sources.has("sections")) {
@@ -982,7 +523,7 @@ function deriveGraph(docs, options) {
982
523
  const meta = asRecord(sectionMeta[section.slug]);
983
524
  emitIirdsTyping(secIri, meta);
984
525
  for (const label of asStringArray(meta["concepts"])) {
985
- add(secIri, `${NS.dcterms}subject`, iri(concept(label)));
526
+ add(secIri, `${NS.dcterms}subject`, iri(concept(label, pageLanguage)));
986
527
  }
987
528
  }
988
529
  for (const slug of Object.keys(sectionMeta)) {
@@ -1099,10 +640,13 @@ function deriveGraph(docs, options) {
1099
640
  }
1100
641
  const label = block ? asString(block["label"]) : void 0;
1101
642
  if (label && filled.has("label")) {
643
+ const id = terms.resolve(label, pageLanguage);
1102
644
  add(
1103
645
  activity,
1104
646
  `${NS.prov}generated`,
1105
- iri(mintConceptIri(baseIri, label))
647
+ iri(
648
+ id === void 0 ? mintConceptIri(baseIri, label) : mintTermConceptIri(baseIri, id)
649
+ )
1106
650
  );
1107
651
  }
1108
652
  }
@@ -1132,15 +676,70 @@ function deriveGraph(docs, options) {
1132
676
  );
1133
677
  }
1134
678
  }
679
+ const tagged = (value, language) => language === void 0 ? lit(value) : { kind: "literal", value, language };
680
+ for (const [id, entries] of terms.groups) {
681
+ const c = mintTermConceptIri(baseIri, id);
682
+ add(c, RDF_TYPE, iri(`${NS.skos}Concept`));
683
+ add(c, `${NS.skos}inScheme`, iri(mintSchemeIri(baseIri)));
684
+ mintedConcepts.add(c);
685
+ for (const entry of entries) {
686
+ const language = canonicalLanguage(entry.language);
687
+ add(c, `${NS.skos}prefLabel`, tagged(entry.label, language));
688
+ for (const [values, predicate] of [
689
+ [entry.altLabels, "altLabel"],
690
+ [entry.hiddenLabels, "hiddenLabel"],
691
+ [entry.definition, "definition"],
692
+ [entry.scopeNote, "scopeNote"]
693
+ ]) {
694
+ for (const value of asStringArray(values)) {
695
+ add(c, `${NS.skos}${predicate}`, tagged(value, language));
696
+ }
697
+ }
698
+ for (const relation of ["broader", "narrower", "related"]) {
699
+ for (const value of entry[relation] ?? []) {
700
+ hierarchy(c, relation, concept(value, language));
701
+ }
702
+ }
703
+ if (entry.notation !== void 0) add(c, `${NS.skos}notation`, lit(entry.notation));
704
+ for (const [values, predicate] of [
705
+ [entry.exactMatches, "exactMatch"],
706
+ [entry.closeMatches, "closeMatch"],
707
+ [entry.broadMatches, "broadMatch"],
708
+ [entry.narrowMatches, "narrowMatch"],
709
+ [entry.relatedMatches, "relatedMatch"]
710
+ ]) {
711
+ for (const value of values ?? []) add(c, `${NS.skos}${predicate}`, iri(value));
712
+ }
713
+ }
714
+ }
715
+ for (const entry of terms.redirects) {
716
+ const language = canonicalLanguage(entry.language);
717
+ const target = entry.see === void 0 ? void 0 : terms.resolve(entry.see, language);
718
+ if (target === void 0) continue;
719
+ add(
720
+ mintTermConceptIri(baseIri, target),
721
+ `${NS.skos}altLabel`,
722
+ tagged(entry.label, language)
723
+ );
724
+ }
1135
725
  if (mintedConcepts.size > 0) {
1136
726
  const scheme = mintSchemeIri(baseIri);
1137
727
  add(scheme, RDF_TYPE, iri(`${NS.skos}ConceptScheme`));
1138
- add(scheme, `${NS.dcterms}title`, lit("manni graph concepts"));
728
+ add(scheme, `${NS.dcterms}title`, lit(CONCEPT_SCHEME_TITLE));
729
+ const broader = `${NS.skos}broader`;
730
+ const hasBroader = new Set(
731
+ quads.filter((q) => q.p === broader).map((q) => q.s)
732
+ );
733
+ for (const c of mintedConcepts) {
734
+ if (hasBroader.has(c)) continue;
735
+ add(c, `${NS.skos}topConceptOf`, iri(scheme));
736
+ add(scheme, `${NS.skos}hasTopConcept`, iri(c));
737
+ }
1139
738
  }
1140
739
  return dedupe(quads);
1141
740
  }
1142
741
  function quadKey(q) {
1143
- const o = q.o.kind === "iri" ? `i:${q.o.value}` : `l:${q.o.value}|${q.o.datatype ?? ""}`;
742
+ const o = q.o.kind === "iri" ? `i:${q.o.value}` : `l:${q.o.value}|${q.o.datatype ?? ""}|${q.o.language ?? ""}`;
1144
743
  return `${q.s}|${q.p}|${o}`;
1145
744
  }
1146
745
  function dedupe(quads) {
@@ -1155,154 +754,6 @@ function dedupe(quads) {
1155
754
  return out;
1156
755
  }
1157
756
 
1158
- // src/graph/core/discover.ts
1159
- import { statSync } from "node:fs";
1160
- import { extname as extname2, relative, resolve } from "node:path";
1161
- import fg from "fast-glob";
1162
- function discoverFiles(inputs, exclude, cwd) {
1163
- const matches = fg.sync(inputs, {
1164
- cwd,
1165
- ignore: exclude,
1166
- onlyFiles: true,
1167
- dot: false,
1168
- unique: true
1169
- });
1170
- return [...new Set(matches.map((m) => m.replace(/\\/g, "/")))].sort(
1171
- byCodeUnit
1172
- );
1173
- }
1174
- var FAMILY_EXCLUDE = ["**/node_modules/**", "**/.git/**"];
1175
- var DEFAULT_EXTENSIONS = supportedExtensions();
1176
- var STDIN = "-";
1177
- function assertInputFormat(paths, as) {
1178
- if (as === void 0) {
1179
- if (paths.includes(STDIN)) throw new GraphError(STDIN_REQUIRES_AS);
1180
- return void 0;
1181
- }
1182
- if (!isDocFormat(as)) {
1183
- throw new GraphError(
1184
- `Unknown format "${as}". Known formats: ${DOC_FORMATS.join(", ")}.`
1185
- );
1186
- }
1187
- return as;
1188
- }
1189
- function expandInputs(inputs, base, ignore) {
1190
- const named = [];
1191
- const patterns = [];
1192
- for (const input of inputs) {
1193
- if (fg.isDynamicPattern(input)) {
1194
- patterns.push(input.replace(/\\/g, "/"));
1195
- continue;
1196
- }
1197
- let isDirectory;
1198
- try {
1199
- isDirectory = statSync(resolve(base, input)).isDirectory();
1200
- } catch {
1201
- patterns.push(input.replace(/\\/g, "/"));
1202
- continue;
1203
- }
1204
- const literal = fg.convertPathToPattern(input);
1205
- if (isDirectory) patterns.push(`${literal.replace(/\/$/, "")}/**/*`);
1206
- else named.push(...glob([literal], base, ignore));
1207
- }
1208
- return { named, walked: glob(patterns, base, ignore) };
1209
- }
1210
- function glob(patterns, base, ignore) {
1211
- if (patterns.length === 0) return [];
1212
- return fg.sync(patterns, {
1213
- cwd: base,
1214
- ignore,
1215
- absolute: true,
1216
- dot: false,
1217
- onlyFiles: true
1218
- });
1219
- }
1220
- function normalizeExtensions(exts) {
1221
- return new Set(
1222
- exts.map((e) => {
1223
- const lower = e.toLowerCase();
1224
- return lower.startsWith(".") ? lower : `.${lower}`;
1225
- })
1226
- );
1227
- }
1228
- function resolveDocumentSet(config, options = {}, verb = "build", cwd = process.cwd(), base = documentBase(config, options, cwd)) {
1229
- const paths = options.paths ?? [];
1230
- const wanted = options.collection ?? [];
1231
- assertCollectionWithoutPaths(wanted, paths);
1232
- const format = assertInputFormat(paths, options.as);
1233
- if (wanted.length > 0 && config.configSource === null) {
1234
- throw new GraphError("--collection needs a config file to select from.");
1235
- }
1236
- const collections = selectCollections(
1237
- config.collections,
1238
- wanted,
1239
- config.configSource ?? DEFAULT_CONFIG_FILENAME,
1240
- (message) => new GraphError(message)
1241
- );
1242
- const exclude = [...FAMILY_EXCLUDE, ...options.exclude ?? []];
1243
- let named = [];
1244
- let walked;
1245
- if (paths.length > 0) {
1246
- ({ named, walked } = expandInputs(
1247
- paths.filter((p) => p !== STDIN),
1248
- cwd,
1249
- exclude
1250
- ));
1251
- } else {
1252
- const patterns = collections.flatMap((c) => c.paths);
1253
- if (patterns.length === 0) {
1254
- throw new GraphError(
1255
- `No files to ${verb}. Pass paths/globs, or declare a collection under \`collections:\` in manni.config.yaml.`
1256
- );
1257
- }
1258
- walked = collections.flatMap((c) => {
1259
- const found = expandInputs(c.paths, config.configDir, [
1260
- ...exclude,
1261
- ...c.exclude
1262
- ]);
1263
- return [...found.named, ...found.walked];
1264
- });
1265
- }
1266
- const exts = normalizeExtensions(options.ext ?? DEFAULT_EXTENSIONS);
1267
- const keepNamed = (p) => {
1268
- const ext = extname2(p);
1269
- if (format !== void 0 || parserForExtension(ext) !== void 0) {
1270
- return true;
1271
- }
1272
- const label = relative(base, p).replace(/\\/g, "/");
1273
- warn(`skipped ${label}: ${unsupportedFormatMessage(ext || label)}`);
1274
- return false;
1275
- };
1276
- const keepWalked = (p) => exts.has(extname2(p).toLowerCase());
1277
- return [
1278
- ...new Set(
1279
- [...named.filter(keepNamed), ...walked.filter(keepWalked)].map(
1280
- (p) => relative(base, p).replace(/\\/g, "/")
1281
- )
1282
- )
1283
- ].sort(byCodeUnit);
1284
- }
1285
- function documentBase(config, options = {}, cwd = process.cwd()) {
1286
- const typed = (options.paths ?? []).length > 0;
1287
- return typed || config.collections.length === 0 ? cwd : config.configDir;
1288
- }
1289
- function routesFrom(config, base) {
1290
- return config.routes.map((m) => ({
1291
- ...m,
1292
- root: relative(base, resolve(config.configDir, m.root)).replace(/\\/g, "/")
1293
- }));
1294
- }
1295
- function documentSetPatterns(config, options = {}) {
1296
- const paths = options.paths ?? [];
1297
- if (paths.length > 0) return paths;
1298
- return selectCollections(
1299
- config.collections,
1300
- options.collection ?? [],
1301
- config.configSource ?? DEFAULT_CONFIG_FILENAME,
1302
- (message) => new GraphError(message)
1303
- ).flatMap((c) => c.paths);
1304
- }
1305
-
1306
757
  // src/graph/core/emit.ts
1307
758
  var SAFE_LOCAL = /^[A-Za-z_][A-Za-z0-9_-]*$/;
1308
759
  var ILLEGAL_IRI_CHARS = '<>"{}|^`\\';
@@ -1343,6 +794,7 @@ function renderTerm(term) {
1343
794
  if (term.datatype === INTEGER && INTEGER_RE.test(term.value))
1344
795
  return term.value;
1345
796
  const quoted = `"${escapeLiteral(term.value)}"`;
797
+ if (term.language) return `${quoted}@${term.language}`;
1346
798
  return term.datatype ? `${quoted}^^${shorten(term.datatype)}` : quoted;
1347
799
  }
1348
800
  function compareTerms(a, b) {
@@ -1351,7 +803,9 @@ function compareTerms(a, b) {
1351
803
  if (byValue !== 0) return byValue;
1352
804
  const da = a.kind === "literal" ? a.datatype ?? "" : "";
1353
805
  const db = b.kind === "literal" ? b.datatype ?? "" : "";
1354
- return byCodeUnit(da, db);
806
+ const la = a.kind === "literal" ? a.language ?? "" : "";
807
+ const lb = b.kind === "literal" ? b.language ?? "" : "";
808
+ return byCodeUnit(da, db) || byCodeUnit(la, lb);
1355
809
  }
1356
810
  function emitTurtle(quads) {
1357
811
  shortenMemo.clear();
@@ -1640,57 +1094,6 @@ async function suppressGraphOutput(docs, sets) {
1640
1094
  return out;
1641
1095
  }
1642
1096
 
1643
- // src/graph/core/external.ts
1644
- import { resolve as resolve2 } from "node:path";
1645
- async function openMetaView(source, cwd, paths, base = cwd) {
1646
- try {
1647
- return await metaPageView({
1648
- cwd: base,
1649
- ...source.configPath === void 0 ? {} : { configPath: resolve2(cwd, source.configPath) },
1650
- ...source.noConfig === void 0 ? {} : { noConfig: source.noConfig },
1651
- pages: paths.filter((p) => p !== STDIN_PATH).map((p) => resolve2(base, p))
1652
- });
1653
- } catch (e) {
1654
- throw new GraphError(errorMessage(e));
1655
- }
1656
- }
1657
- function pointerOf(key) {
1658
- return `/${key.replace(/~/g, "~0").replace(/\//g, "~1")}`;
1659
- }
1660
- async function mergePage(view, path, frontmatter, present, format) {
1661
- let merged;
1662
- try {
1663
- merged = await view.merge(path, {
1664
- data: frontmatter,
1665
- present,
1666
- format,
1667
- lineFor: () => void 0
1668
- });
1669
- } catch (e) {
1670
- throw new GraphError(errorMessage(e));
1671
- }
1672
- const data = merged.extracted.data;
1673
- const supplied = {};
1674
- for (const key of Object.keys(data)) {
1675
- if (merged.locate(pointerOf(key)) !== void 0) supplied[key] = data[key];
1676
- }
1677
- return { data, supplied };
1678
- }
1679
- async function withExternalMetadata(docs, view) {
1680
- const out = [];
1681
- for (const doc of docs) {
1682
- const { data } = await mergePage(
1683
- view,
1684
- doc.path,
1685
- doc.frontmatter,
1686
- doc.frontmatterPresent,
1687
- doc.format
1688
- );
1689
- out.push(data === doc.frontmatter ? doc : { ...doc, frontmatter: data });
1690
- }
1691
- return out;
1692
- }
1693
-
1694
1097
  // src/graph/commands/build.ts
1695
1098
  var GIT_ABSENT_WARNING = "the graph has no revision history or commit agents";
1696
1099
  function gitAbsentWarning(reason) {
@@ -1717,10 +1120,17 @@ async function buildGraph(opts = {}) {
1717
1120
  const base = documentBase(config, opts, cwd);
1718
1121
  const files = resolveDocumentSet(config, opts, "build", cwd, base);
1719
1122
  const usingStdin = (opts.paths ?? []).includes(STDIN);
1720
- const outPath = resolve3(cwd, opts.out ?? config.out);
1123
+ const outPath = resolve(cwd, opts.out ?? config.out);
1721
1124
  if (files.length === 0 && !usingStdin) {
1722
1125
  if (opts.allowEmpty) {
1723
- return { outPath, docs: 0, quads: 0, warnings: [], turtle: emitTurtle([]) };
1126
+ return {
1127
+ outPath,
1128
+ docs: 0,
1129
+ quads: 0,
1130
+ concepts: { total: 0, fromTermbase: 0 },
1131
+ warnings: [],
1132
+ turtle: emitTurtle([])
1133
+ };
1724
1134
  }
1725
1135
  throw new GraphError(
1726
1136
  `No input files matched: ${documentSetPatterns(config, opts).join(", ")} (cwd: ${cwd})`
@@ -1730,14 +1140,14 @@ async function buildGraph(opts = {}) {
1730
1140
  throw new GraphError("graph build was given `-` but no stdin content.");
1731
1141
  }
1732
1142
  const allPaths = new Set(usingStdin ? [...files, STDIN_PATH] : files);
1733
- const cache = new AnalyzeCache(resolve3(cwd, ANALYZE_CACHE_DIR));
1143
+ const cache = new AnalyzeCache(resolve(cwd, ANALYZE_CACHE_DIR));
1734
1144
  const analyzeOptions = {
1735
1145
  routes: routesFrom(config, base),
1736
1146
  ...format === void 0 ? {} : { format },
1737
1147
  parse: cache.parse
1738
1148
  };
1739
1149
  const read = files.map(
1740
- (path) => analyzeDoc(readFileSync2(resolve3(base, path), "utf8"), path, allPaths, analyzeOptions)
1150
+ (path) => analyzeDoc(readFileSync2(resolve(base, path), "utf8"), path, allPaths, analyzeOptions)
1741
1151
  );
1742
1152
  if (usingStdin && opts.stdinContent !== void 0) {
1743
1153
  read.push(analyzeDoc(opts.stdinContent, STDIN_PATH, allPaths, analyzeOptions));
@@ -1762,6 +1172,21 @@ async function buildGraph(opts = {}) {
1762
1172
  warnings.push(gitAbsentWarning(errorMessage(e)));
1763
1173
  }
1764
1174
  }
1175
+ const source = termLabelSource();
1176
+ let termbase = [];
1177
+ if (config.build.derive.includes("terms") && source !== void 0) {
1178
+ try {
1179
+ termbase = await source({
1180
+ cwd,
1181
+ ...opts.config === void 0 ? {} : { configPath: opts.config },
1182
+ ...opts.noConfig === true ? { noConfig: true } : {}
1183
+ });
1184
+ } catch (e) {
1185
+ warnings.push(
1186
+ `the graph holds no termbase concepts: the termbase could not be read \u2014 ${errorMessage(e)}`
1187
+ );
1188
+ }
1189
+ }
1765
1190
  const quads = deriveGraph(docs, {
1766
1191
  baseIri: config.baseIri,
1767
1192
  derive: config.build.derive,
@@ -1769,45 +1194,28 @@ async function buildGraph(opts = {}) {
1769
1194
  // package, one version: the tool no longer has one of its own.
1770
1195
  toolVersion: package_default.version,
1771
1196
  gitHistory,
1772
- qualified: config.provenance.qualified
1197
+ qualified: config.provenance.qualified,
1198
+ termbase
1773
1199
  });
1200
+ const concept = `${NS.skos}Concept`;
1201
+ const concepts = {
1202
+ total: quads.filter((q) => q.p === RDF_TYPE && q.o.value === concept).length,
1203
+ fromTermbase: termConceptCount(termbase)
1204
+ };
1774
1205
  const turtle = emitTurtle(quads);
1775
1206
  await cache.flush();
1776
- return { outPath, docs: docs.length, quads: quads.length, warnings, turtle };
1207
+ return { outPath, docs: docs.length, quads: quads.length, concepts, warnings, turtle };
1777
1208
  }
1778
1209
 
1779
1210
  export {
1780
- formatOf,
1781
- extractorFor,
1782
- metadataOf,
1783
- analyzeDoc,
1784
- parseTree,
1785
- mintTreeSections,
1786
- discoverFiles,
1787
- DEFAULT_EXTENSIONS,
1788
- STDIN,
1789
- assertInputFormat,
1790
- resolveDocumentSet,
1791
- documentBase,
1792
- routesFrom,
1793
- documentSetPatterns,
1794
- LOCALIZATIONS_FILENAME,
1795
- UNDETERMINED,
1796
- isLanguageTag,
1797
- canonicalLanguageTag,
1798
- searchIndexFilename,
1799
- vectorIndexFilename,
1800
- emitLocalizations,
1801
- parseLocalizations,
1802
- isSafeRelativePath,
1211
+ canonicalLanguage,
1212
+ termIndex,
1803
1213
  deriveGraph,
1804
1214
  emitTurtle,
1805
1215
  collectGitHistory,
1806
- openMetaView,
1807
- mergePage,
1808
1216
  GIT_ABSENT_WARNING,
1809
1217
  gitAbsentWarning,
1810
1218
  runBuild,
1811
1219
  buildGraph
1812
1220
  };
1813
- //# sourceMappingURL=chunk-2IAZEB45.js.map
1221
+ //# sourceMappingURL=chunk-WGMFDG6U.js.map