@hawkeyexl/manni 4.8.1 → 4.10.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.
Files changed (173) hide show
  1. package/README.md +1 -1
  2. package/dist/{batch-QMHYWGUA.js → batch-6NICDKRE.js} +12 -12
  3. package/dist/{build-ZGA3O3P4.js → build-3KP2K3XN.js} +11 -11
  4. package/dist/{calibrate-KBMFGKP3.js → calibrate-LUA3DWKD.js} +13 -13
  5. package/dist/{capture-C46UXFRK.js → capture-NETOHCB4.js} +12 -12
  6. package/dist/{check-UMI5ACCE.js → check-7B77ZD2N.js} +11 -11
  7. package/dist/{check-OAJWC3WD.js → check-E4QCB7LS.js} +5 -5
  8. package/dist/{check-CORYIW76.js → check-NLL4NRYA.js} +13 -13
  9. package/dist/{check-LLQ6PJV3.js → check-PTECPIIB.js} +10 -10
  10. package/dist/{chunk-N7J5C35C.js → chunk-2BV4FBC7.js} +2 -2
  11. package/dist/chunk-2BV4FBC7.js.map +1 -0
  12. package/dist/{chunk-PO5W6JAP.js → chunk-2JV7C4YV.js} +7 -7
  13. package/dist/{chunk-Z27GYQOY.js → chunk-2UCC26MO.js} +8 -8
  14. package/dist/{chunk-WBETAXO2.js → chunk-2W34HX2U.js} +5 -5
  15. package/dist/{chunk-ZIGIJBXG.js → chunk-2YJ5H5E6.js} +9 -9
  16. package/dist/{chunk-HWNSIEZK.js → chunk-3E2X2RBU.js} +6 -6
  17. package/dist/{chunk-Q3GFZJTY.js → chunk-4DLF5SA4.js} +35 -17
  18. package/dist/chunk-4DLF5SA4.js.map +1 -0
  19. package/dist/{chunk-BYVH727K.js → chunk-55GMOVKW.js} +2 -2
  20. package/dist/{chunk-C2JPBQCJ.js → chunk-5REEVKGH.js} +2 -2
  21. package/dist/{chunk-XXDXIIQ4.js → chunk-6AGESHHM.js} +2 -2
  22. package/dist/{chunk-GQBVZS5G.js → chunk-6LR73NMO.js} +6 -6
  23. package/dist/{chunk-XKBEHKWO.js → chunk-6M5VJOC2.js} +2 -1
  24. package/dist/{chunk-F734HIHT.js → chunk-7Y3N4Y72.js} +3 -3
  25. package/dist/{chunk-WUFP4V7B.js → chunk-ABHG6I3G.js} +1292 -126
  26. package/dist/chunk-ABHG6I3G.js.map +1 -0
  27. package/dist/{chunk-FEALEYSE.js → chunk-AO5TSDKT.js} +4 -4
  28. package/dist/{chunk-LF6FOF6U.js → chunk-BD7IXBWE.js} +15 -26
  29. package/dist/{chunk-LF6FOF6U.js.map → chunk-BD7IXBWE.js.map} +1 -1
  30. package/dist/{chunk-NB4ILZMQ.js → chunk-CCWMACJL.js} +8 -8
  31. package/dist/{chunk-K43X5VDR.js → chunk-D2UW3ZCK.js} +6 -6
  32. package/dist/{chunk-SV6UEQCU.js → chunk-DFCQ6BMI.js} +4 -4
  33. package/dist/{chunk-ECVQNGTH.js → chunk-DNZUBCGZ.js} +3 -3
  34. package/dist/{chunk-POGYWOJ2.js → chunk-EAUIQADY.js} +3 -3
  35. package/dist/{chunk-XDS3KQCK.js → chunk-G6FNWRAI.js} +4 -4
  36. package/dist/{chunk-6HMLYFEU.js → chunk-G7XD4QH5.js} +810 -5
  37. package/dist/chunk-G7XD4QH5.js.map +1 -0
  38. package/dist/{chunk-WUXD6VBD.js → chunk-GB2XPITA.js} +2 -2
  39. package/dist/{chunk-KPXOJMQ6.js → chunk-GCKHSBEN.js} +2 -2
  40. package/dist/{chunk-6QBJHRFC.js → chunk-GDLHTI5R.js} +129 -26
  41. package/dist/chunk-GDLHTI5R.js.map +1 -0
  42. package/dist/{chunk-NNFSIRVE.js → chunk-GXN7RRHR.js} +3 -3
  43. package/dist/{chunk-RCS5YFY2.js → chunk-H26VDFDS.js} +2 -2
  44. package/dist/{chunk-4VQBHTGA.js → chunk-IJ62BB2T.js} +5 -5
  45. package/dist/{chunk-WT6HMEEF.js → chunk-KBG463UK.js} +35 -8
  46. package/dist/{chunk-WT6HMEEF.js.map → chunk-KBG463UK.js.map} +1 -1
  47. package/dist/{chunk-UWY4B2PM.js → chunk-LQZQ5KGG.js} +4 -4
  48. package/dist/{chunk-VSOYZ7QH.js → chunk-PK7EKJ5T.js} +4 -4
  49. package/dist/{chunk-YVVMC4SZ.js → chunk-QBVP3SQP.js} +4 -4
  50. package/dist/{chunk-6MNOMHFI.js → chunk-QJRQ4BRC.js} +11 -11
  51. package/dist/{chunk-7LC4YJJ3.js → chunk-RODZ7MB7.js} +3 -3
  52. package/dist/{chunk-SXODK43S.js → chunk-RZVCWX5R.js} +4 -4
  53. package/dist/{chunk-5LAKRYXU.js → chunk-SUTMSDQ2.js} +3 -3
  54. package/dist/{chunk-6KKZXB2O.js → chunk-VVVKBUBO.js} +2 -2
  55. package/dist/{chunk-6ZR24A4S.js → chunk-VZVEP2OZ.js} +2 -2
  56. package/dist/{chunk-3FG2UU3H.js → chunk-WN47MNSK.js} +4 -4
  57. package/dist/{chunk-LAU6SVTJ.js → chunk-XU73V5XT.js} +7 -7
  58. package/dist/{chunk-77L5GNVO.js → chunk-Z5YHMRLF.js} +2 -2
  59. package/dist/{chunk-AO66Q66S.js → chunk-ZHRPH52H.js} +2 -2
  60. package/dist/chunk-ZMECS2IJ.js +27 -0
  61. package/dist/chunk-ZMECS2IJ.js.map +1 -0
  62. package/dist/{chunk-VD3EQSBI.js → chunk-ZXXFP2LA.js} +2 -2
  63. package/dist/{cli-SBJY2NQH.js → cli-4YYC6LCY.js} +15 -15
  64. package/dist/{cli-4B5RWL7P.js → cli-BIIUKPTE.js} +13 -12
  65. package/dist/{cli-4B5RWL7P.js.map → cli-BIIUKPTE.js.map} +1 -1
  66. package/dist/{cli-XIQKPNA7.js → cli-EH3I4IUX.js} +32 -32
  67. package/dist/cli-EH3I4IUX.js.map +1 -0
  68. package/dist/{cli-MNNOXWYU.js → cli-HO62TOM2.js} +8 -8
  69. package/dist/cli-LWST5FQH.js +839 -0
  70. package/dist/cli-LWST5FQH.js.map +1 -0
  71. package/dist/{cli-UB5W75GJ.js → cli-P2X7PNY6.js} +12 -12
  72. package/dist/{cli-QR3ZQZA4.js → cli-SGVFZOAW.js} +19 -19
  73. package/dist/{cli-5AML7QR2.js → cli-TELPAMJO.js} +14 -14
  74. package/dist/{cli-I4GBPLRM.js → cli-UETKXHJN.js} +3 -3
  75. package/dist/{cli-WWDARAWS.js → cli-V2DI3K2R.js} +14 -14
  76. package/dist/cli.js +18 -11
  77. package/dist/cli.js.map +1 -1
  78. package/dist/{config-YWSNBFEE.js → config-TYXYQK3I.js} +3 -3
  79. package/dist/docmeta.js +7 -7
  80. package/dist/{github-TIZ3ZR3D.js → github-ESK45CEZ.js} +10 -10
  81. package/dist/{github-WKOJRW7P.js → github-WER7JUTN.js} +12 -12
  82. package/dist/index.js +35 -34
  83. package/dist/index.js.map +1 -1
  84. package/dist/{json-4FUOZ3XX.js → json-QR4G35KA.js} +10 -10
  85. package/dist/{lint-7VQFESHK.js → lint-QTI7XK2A.js} +11 -10
  86. package/dist/{list-7U2MBDIM.js → list-JO4G3TS3.js} +10 -10
  87. package/dist/{list-W6EUAOBV.js → list-O2MJUP5V.js} +10 -10
  88. package/dist/{page-WZLBKSCD.js → page-FSXDXCDD.js} +9 -9
  89. package/dist/{prepare-FPEWAHJH.js → prepare-UPIBTFNS.js} +11 -11
  90. package/dist/{pretty-7M4X4TCY.js → pretty-4IONWSEP.js} +10 -10
  91. package/dist/{pretty-CUCMQU5R.js → pretty-R4BQD2VH.js} +11 -11
  92. package/dist/{reporters-DQVSDXV6.js → reporters-DHO2BXAD.js} +5 -5
  93. package/dist/{reporters-KYJE54JS.js → reporters-FPP6JNDP.js} +9 -9
  94. package/dist/{run-ABGXGOGQ.js → run-YH5Z7RJ7.js} +10 -10
  95. package/dist/{term-HTIG3YDC.js → term-ASM4LVYC.js} +279 -150
  96. package/dist/term-ASM4LVYC.js.map +1 -0
  97. package/dist/{validate-HWNU3MDY.js → validate-7JI3H57P.js} +5 -5
  98. package/package.json +1 -1
  99. package/plugin/manni/.claude-plugin/plugin.json +1 -1
  100. package/dist/chunk-6HMLYFEU.js.map +0 -1
  101. package/dist/chunk-6QBJHRFC.js.map +0 -1
  102. package/dist/chunk-N7J5C35C.js.map +0 -1
  103. package/dist/chunk-Q3GFZJTY.js.map +0 -1
  104. package/dist/chunk-WUFP4V7B.js.map +0 -1
  105. package/dist/cli-XIQKPNA7.js.map +0 -1
  106. package/dist/term-HTIG3YDC.js.map +0 -1
  107. /package/dist/{batch-QMHYWGUA.js.map → batch-6NICDKRE.js.map} +0 -0
  108. /package/dist/{build-ZGA3O3P4.js.map → build-3KP2K3XN.js.map} +0 -0
  109. /package/dist/{calibrate-KBMFGKP3.js.map → calibrate-LUA3DWKD.js.map} +0 -0
  110. /package/dist/{capture-C46UXFRK.js.map → capture-NETOHCB4.js.map} +0 -0
  111. /package/dist/{check-LLQ6PJV3.js.map → check-7B77ZD2N.js.map} +0 -0
  112. /package/dist/{check-OAJWC3WD.js.map → check-E4QCB7LS.js.map} +0 -0
  113. /package/dist/{check-CORYIW76.js.map → check-NLL4NRYA.js.map} +0 -0
  114. /package/dist/{check-UMI5ACCE.js.map → check-PTECPIIB.js.map} +0 -0
  115. /package/dist/{chunk-PO5W6JAP.js.map → chunk-2JV7C4YV.js.map} +0 -0
  116. /package/dist/{chunk-Z27GYQOY.js.map → chunk-2UCC26MO.js.map} +0 -0
  117. /package/dist/{chunk-WBETAXO2.js.map → chunk-2W34HX2U.js.map} +0 -0
  118. /package/dist/{chunk-ZIGIJBXG.js.map → chunk-2YJ5H5E6.js.map} +0 -0
  119. /package/dist/{chunk-HWNSIEZK.js.map → chunk-3E2X2RBU.js.map} +0 -0
  120. /package/dist/{chunk-BYVH727K.js.map → chunk-55GMOVKW.js.map} +0 -0
  121. /package/dist/{chunk-C2JPBQCJ.js.map → chunk-5REEVKGH.js.map} +0 -0
  122. /package/dist/{chunk-XXDXIIQ4.js.map → chunk-6AGESHHM.js.map} +0 -0
  123. /package/dist/{chunk-GQBVZS5G.js.map → chunk-6LR73NMO.js.map} +0 -0
  124. /package/dist/{chunk-XKBEHKWO.js.map → chunk-6M5VJOC2.js.map} +0 -0
  125. /package/dist/{chunk-F734HIHT.js.map → chunk-7Y3N4Y72.js.map} +0 -0
  126. /package/dist/{chunk-FEALEYSE.js.map → chunk-AO5TSDKT.js.map} +0 -0
  127. /package/dist/{chunk-NB4ILZMQ.js.map → chunk-CCWMACJL.js.map} +0 -0
  128. /package/dist/{chunk-K43X5VDR.js.map → chunk-D2UW3ZCK.js.map} +0 -0
  129. /package/dist/{chunk-SV6UEQCU.js.map → chunk-DFCQ6BMI.js.map} +0 -0
  130. /package/dist/{chunk-ECVQNGTH.js.map → chunk-DNZUBCGZ.js.map} +0 -0
  131. /package/dist/{chunk-POGYWOJ2.js.map → chunk-EAUIQADY.js.map} +0 -0
  132. /package/dist/{chunk-XDS3KQCK.js.map → chunk-G6FNWRAI.js.map} +0 -0
  133. /package/dist/{chunk-WUXD6VBD.js.map → chunk-GB2XPITA.js.map} +0 -0
  134. /package/dist/{chunk-KPXOJMQ6.js.map → chunk-GCKHSBEN.js.map} +0 -0
  135. /package/dist/{chunk-NNFSIRVE.js.map → chunk-GXN7RRHR.js.map} +0 -0
  136. /package/dist/{chunk-RCS5YFY2.js.map → chunk-H26VDFDS.js.map} +0 -0
  137. /package/dist/{chunk-4VQBHTGA.js.map → chunk-IJ62BB2T.js.map} +0 -0
  138. /package/dist/{chunk-UWY4B2PM.js.map → chunk-LQZQ5KGG.js.map} +0 -0
  139. /package/dist/{chunk-VSOYZ7QH.js.map → chunk-PK7EKJ5T.js.map} +0 -0
  140. /package/dist/{chunk-YVVMC4SZ.js.map → chunk-QBVP3SQP.js.map} +0 -0
  141. /package/dist/{chunk-6MNOMHFI.js.map → chunk-QJRQ4BRC.js.map} +0 -0
  142. /package/dist/{chunk-7LC4YJJ3.js.map → chunk-RODZ7MB7.js.map} +0 -0
  143. /package/dist/{chunk-SXODK43S.js.map → chunk-RZVCWX5R.js.map} +0 -0
  144. /package/dist/{chunk-5LAKRYXU.js.map → chunk-SUTMSDQ2.js.map} +0 -0
  145. /package/dist/{chunk-6KKZXB2O.js.map → chunk-VVVKBUBO.js.map} +0 -0
  146. /package/dist/{chunk-6ZR24A4S.js.map → chunk-VZVEP2OZ.js.map} +0 -0
  147. /package/dist/{chunk-3FG2UU3H.js.map → chunk-WN47MNSK.js.map} +0 -0
  148. /package/dist/{chunk-LAU6SVTJ.js.map → chunk-XU73V5XT.js.map} +0 -0
  149. /package/dist/{chunk-77L5GNVO.js.map → chunk-Z5YHMRLF.js.map} +0 -0
  150. /package/dist/{chunk-AO66Q66S.js.map → chunk-ZHRPH52H.js.map} +0 -0
  151. /package/dist/{chunk-VD3EQSBI.js.map → chunk-ZXXFP2LA.js.map} +0 -0
  152. /package/dist/{cli-SBJY2NQH.js.map → cli-4YYC6LCY.js.map} +0 -0
  153. /package/dist/{cli-MNNOXWYU.js.map → cli-HO62TOM2.js.map} +0 -0
  154. /package/dist/{cli-UB5W75GJ.js.map → cli-P2X7PNY6.js.map} +0 -0
  155. /package/dist/{cli-QR3ZQZA4.js.map → cli-SGVFZOAW.js.map} +0 -0
  156. /package/dist/{cli-5AML7QR2.js.map → cli-TELPAMJO.js.map} +0 -0
  157. /package/dist/{cli-I4GBPLRM.js.map → cli-UETKXHJN.js.map} +0 -0
  158. /package/dist/{cli-WWDARAWS.js.map → cli-V2DI3K2R.js.map} +0 -0
  159. /package/dist/{config-YWSNBFEE.js.map → config-TYXYQK3I.js.map} +0 -0
  160. /package/dist/{github-TIZ3ZR3D.js.map → github-ESK45CEZ.js.map} +0 -0
  161. /package/dist/{github-WKOJRW7P.js.map → github-WER7JUTN.js.map} +0 -0
  162. /package/dist/{json-4FUOZ3XX.js.map → json-QR4G35KA.js.map} +0 -0
  163. /package/dist/{lint-7VQFESHK.js.map → lint-QTI7XK2A.js.map} +0 -0
  164. /package/dist/{list-7U2MBDIM.js.map → list-JO4G3TS3.js.map} +0 -0
  165. /package/dist/{list-W6EUAOBV.js.map → list-O2MJUP5V.js.map} +0 -0
  166. /package/dist/{page-WZLBKSCD.js.map → page-FSXDXCDD.js.map} +0 -0
  167. /package/dist/{prepare-FPEWAHJH.js.map → prepare-UPIBTFNS.js.map} +0 -0
  168. /package/dist/{pretty-7M4X4TCY.js.map → pretty-4IONWSEP.js.map} +0 -0
  169. /package/dist/{pretty-CUCMQU5R.js.map → pretty-R4BQD2VH.js.map} +0 -0
  170. /package/dist/{reporters-DQVSDXV6.js.map → reporters-DHO2BXAD.js.map} +0 -0
  171. /package/dist/{reporters-KYJE54JS.js.map → reporters-FPP6JNDP.js.map} +0 -0
  172. /package/dist/{run-ABGXGOGQ.js.map → run-YH5Z7RJ7.js.map} +0 -0
  173. /package/dist/{validate-HWNU3MDY.js.map → validate-7JI3H57P.js.map} +0 -0
@@ -10,7 +10,7 @@ import {
10
10
  CONCEPT_FIELDS,
11
11
  fieldPointer,
12
12
  valueAt
13
- } from "./chunk-WBETAXO2.js";
13
+ } from "./chunk-2W34HX2U.js";
14
14
  import {
15
15
  STDIN_LABEL,
16
16
  STDIN_TOKEN,
@@ -19,14 +19,15 @@ import {
19
19
  extractorForExtension,
20
20
  gitignoreOptions,
21
21
  locateFrontmatter,
22
- resolveTargetSet
23
- } from "./chunk-6HMLYFEU.js";
22
+ resolveTargetSet,
23
+ supportedExtensions
24
+ } from "./chunk-G7XD4QH5.js";
24
25
  import {
25
26
  findConfigFile,
26
27
  readConfigFile,
27
28
  selectCollections,
28
29
  valeConfigPath
29
- } from "./chunk-XKBEHKWO.js";
30
+ } from "./chunk-6M5VJOC2.js";
30
31
  import {
31
32
  ToolError,
32
33
  errorMessage
@@ -51,7 +52,21 @@ var TERM_FIELDS = [
51
52
  "narrower",
52
53
  "related-terms",
53
54
  "see",
54
- "scope-note"
55
+ "scope-note",
56
+ "subject-field",
57
+ "contexts",
58
+ "notes",
59
+ "sources",
60
+ "customer-subsets",
61
+ "project-subsets",
62
+ "cross-references",
63
+ "external-cross-references",
64
+ "graphics",
65
+ "transactions",
66
+ "tbx-elements",
67
+ "concept-entry",
68
+ "designations",
69
+ "tbx-markup"
55
70
  ];
56
71
  var TERM_LIST_FIELDS = [
57
72
  "alt-labels",
@@ -60,6 +75,32 @@ var TERM_LIST_FIELDS = [
60
75
  "narrower",
61
76
  "related-terms"
62
77
  ];
78
+ var TERM_AUX_FIELDS = [
79
+ "definition",
80
+ "subject-field",
81
+ "contexts",
82
+ "notes",
83
+ "sources",
84
+ "customer-subsets",
85
+ "project-subsets",
86
+ "cross-references",
87
+ "external-cross-references",
88
+ "graphics",
89
+ "transactions",
90
+ "tbx-elements"
91
+ ];
92
+ var TERM_DESIGNATION_FIELDS = [
93
+ "administrative-status",
94
+ "part-of-speech",
95
+ "grammatical-gender",
96
+ "grammatical-number",
97
+ "term-type",
98
+ "term-location",
99
+ "geographical-usage",
100
+ "register",
101
+ "reading",
102
+ "reading-note"
103
+ ];
63
104
  var TERM_WRITE_FORMATS = [
64
105
  "markdown",
65
106
  "mdx",
@@ -69,6 +110,7 @@ var TERM_WRITE_FORMATS = [
69
110
  "dita",
70
111
  "docbook",
71
112
  "tbx",
113
+ "tbx3",
72
114
  "skos",
73
115
  "csv",
74
116
  "json",
@@ -244,6 +286,33 @@ async function resolveTermRun(opts) {
244
286
  };
245
287
  }
246
288
 
289
+ // src/term/core/writers/render-util.ts
290
+ var DEFAULT_LANGUAGE = "en";
291
+ function languageOf(term) {
292
+ return term.language ?? DEFAULT_LANGUAGE;
293
+ }
294
+ function languageKey(term) {
295
+ return languageOf(term).toLowerCase();
296
+ }
297
+ function isMultilingual(terms) {
298
+ return new Set(terms.map(languageKey)).size > 1;
299
+ }
300
+ function droppedFields(terms, held) {
301
+ const dropped = [];
302
+ for (const term of terms) {
303
+ for (const field of TERM_FIELDS) {
304
+ if (term.record[field] !== void 0 && !held.includes(field)) dropped.push({ id: term.id, field });
305
+ }
306
+ }
307
+ return dropped;
308
+ }
309
+ function requireShape(format, target, shape) {
310
+ if (target.shape === shape) return;
311
+ throw new TermError(
312
+ shape === "file" ? `-f ${format} writes one file, not a directory. Pass -o <file>.` : `-f ${format} writes a styles directory, not a file. Pass -o <styles directory>.`
313
+ );
314
+ }
315
+
247
316
  // src/term/commands/run.ts
248
317
  import { existsSync } from "node:fs";
249
318
  import { isAbsolute, relative, resolve as resolve3 } from "node:path";
@@ -417,39 +486,159 @@ function collapse(text) {
417
486
  function isListField(field) {
418
487
  return TERM_LIST_FIELDS.includes(field);
419
488
  }
420
- function recordOf(raw) {
489
+ function isAuxField(field) {
490
+ return TERM_AUX_FIELDS.includes(field);
491
+ }
492
+ function isMapping2(value) {
493
+ return typeof value === "object" && value !== null && !Array.isArray(value) && !(value instanceof Date);
494
+ }
495
+ function itemsOf(value) {
496
+ return Array.isArray(value) ? value : [value];
497
+ }
498
+ function pointerOf(path) {
499
+ return path.map((segment) => `/${String(segment).replaceAll("~", "~0").replaceAll("/", "~1")}`).join("");
500
+ }
501
+ function issueNotice(input, line, label, issue) {
502
+ return `${input.file}:${line}: ignored ${issue.what} on "${label}": ${issue.why}.`;
503
+ }
504
+ function oneValue(value, key, path, where, issues) {
505
+ const text = textOf(value);
506
+ if (text !== void 0 || value === void 0 || value === null || typeof value === "string") return text;
507
+ const article = /^[aeiou]/.test(key) ? "an" : "a";
508
+ const holds = Array.isArray(value) ? "holds one value, not a list" : typeof value === "object" ? "holds text, not a mapping" : "holds text";
509
+ issues?.push({ path, what: `${key}${where}`, why: `${article} ${key} ${holds}` });
510
+ return void 0;
511
+ }
512
+ function dateText(value) {
513
+ if (!(value instanceof Date) || Number.isNaN(value.getTime())) return textOf(value);
514
+ const iso = value.toISOString();
515
+ return iso.endsWith("T00:00:00.000Z") ? iso.slice(0, 10) : iso;
516
+ }
517
+ function mappedItems(value, key, path, where, issues, why, build) {
518
+ if (value === void 0 || value === null) return void 0;
519
+ const list = [];
520
+ itemsOf(value).forEach((item2, i) => {
521
+ const built = build(item2);
522
+ if (built !== void 0) list.push(built);
523
+ else if (item2 !== null && item2 !== void 0 && typeof item2 !== "string") {
524
+ issues?.push({ path: Array.isArray(value) ? [...path, i] : path, what: `${key} item${where}`, why });
525
+ }
526
+ });
527
+ return list.length === 0 ? void 0 : list;
528
+ }
529
+ function linkOf(item2) {
530
+ const bare = textOf(item2);
531
+ if (bare !== void 0) return { target: bare };
532
+ if (!isMapping2(item2)) return void 0;
533
+ const target = textOf(item2["target"]);
534
+ if (target === void 0) return void 0;
535
+ const text = textOf(item2["text"]);
536
+ return text === void 0 ? { target } : { target, text };
537
+ }
538
+ function transactionOf(item2) {
539
+ if (!isMapping2(item2)) return void 0;
540
+ const type = textOf(item2["type"]);
541
+ if (type === void 0) return void 0;
542
+ const transaction = { type };
543
+ const date = dateText(item2["date"]);
544
+ if (date !== void 0) transaction.date = date;
545
+ const responsibility = textOf(item2["responsibility"]);
546
+ if (responsibility !== void 0) transaction.responsibility = responsibility;
547
+ return transaction;
548
+ }
549
+ function setAux(target, field, value, path, where, issues) {
550
+ switch (field) {
551
+ case "definition":
552
+ case "subject-field": {
553
+ const text = oneValue(value, field, path, where, issues);
554
+ if (text !== void 0) target[field] = text;
555
+ return;
556
+ }
557
+ case "cross-references":
558
+ case "external-cross-references":
559
+ case "graphics": {
560
+ const why = `a ${field} item is text or a mapping with a target`;
561
+ const links = mappedItems(value, field, path, where, issues, why, linkOf);
562
+ if (links !== void 0) target[field] = links;
563
+ return;
564
+ }
565
+ case "transactions": {
566
+ const why = "a transactions item is a mapping with a type";
567
+ const transactions = mappedItems(value, field, path, where, issues, why, transactionOf);
568
+ if (transactions !== void 0) target[field] = transactions;
569
+ return;
570
+ }
571
+ default: {
572
+ const list = listOf(value);
573
+ if (list !== void 0) target[field] = list;
574
+ }
575
+ }
576
+ }
577
+ function conceptEntryOf(value, issues) {
578
+ if (value === void 0 || value === null) return void 0;
579
+ if (!isMapping2(value)) {
580
+ issues?.push({ path: ["concept-entry"], what: "concept-entry", why: "a concept-entry holds a mapping of fields" });
581
+ return void 0;
582
+ }
583
+ const entry = {};
584
+ for (const field of TERM_AUX_FIELDS) {
585
+ setAux(entry, field, value[field], ["concept-entry", field], " in concept-entry", issues);
586
+ }
587
+ return Object.keys(entry).length === 0 ? void 0 : entry;
588
+ }
589
+ function designationsOf(value, names, issues) {
590
+ if (value === void 0 || value === null) return void 0;
591
+ const list = [];
592
+ itemsOf(value).forEach((item2, i) => {
593
+ const path = Array.isArray(value) ? ["designations", i] : ["designations"];
594
+ const term = isMapping2(item2) ? textOf(item2["term"]) : void 0;
595
+ if (!isMapping2(item2) || term === void 0) {
596
+ issues?.push({ path, what: "designations item", why: "a designations item is a mapping with a term" });
597
+ return;
598
+ }
599
+ if (!names.includes(term)) {
600
+ issues?.push({ path, what: `designations item "${term}"`, why: "it names no label, alt-label or hidden-label" });
601
+ return;
602
+ }
603
+ const where = ` in designations item "${term}"`;
604
+ const designation = { term };
605
+ for (const key of TERM_DESIGNATION_FIELDS) {
606
+ const text = oneValue(item2[key], key, [...path, key], where, issues);
607
+ if (text !== void 0) designation[key] = text;
608
+ }
609
+ const comments = listOf(item2["transfer-comments"]);
610
+ if (comments !== void 0) designation["transfer-comments"] = comments;
611
+ for (const field of TERM_AUX_FIELDS) setAux(designation, field, item2[field], [...path, field], where, issues);
612
+ list.push(designation);
613
+ });
614
+ return list.length === 0 ? void 0 : list;
615
+ }
616
+ function recordOf(raw, issues) {
421
617
  const label = textOf(raw.label);
422
618
  if (label === void 0) return void 0;
423
619
  const record = { label };
424
620
  for (const field of TERM_FIELDS) {
425
- if (isListField(field)) {
426
- const list = listOf(raw[field]);
621
+ const value = raw[field];
622
+ if (field === "label") continue;
623
+ if (isListField(field) || field === "tbx-markup") {
624
+ const list = listOf(value);
427
625
  if (list !== void 0) record[field] = list;
428
- } else if (field !== "label") {
429
- const text = textOf(raw[field]);
626
+ } else if (isAuxField(field)) {
627
+ setAux(record, field, value, [field], "", issues);
628
+ } else if (field === "concept-entry") {
629
+ const entry = conceptEntryOf(value, issues);
630
+ if (entry !== void 0) record[field] = entry;
631
+ } else if (field === "designations") {
632
+ const names = [label, ...record["alt-labels"] ?? [], ...record["hidden-labels"] ?? []];
633
+ const designations = designationsOf(value, names, issues);
634
+ if (designations !== void 0) record[field] = designations;
635
+ } else {
636
+ const text = oneValue(value, field, [field], "", issues);
430
637
  if (text !== void 0) record[field] = text;
431
638
  }
432
639
  }
433
640
  return record;
434
641
  }
435
- function ignoredFields(raw) {
436
- const ignored = [];
437
- for (const field of TERM_FIELDS) {
438
- if (field === "label" || isListField(field)) continue;
439
- const value = raw[field];
440
- if (value === void 0 || value === null || typeof value === "string") continue;
441
- if (textOf(value) !== void 0) continue;
442
- const given = Array.isArray(value) ? "list" : typeof value === "object" ? "mapping" : "other";
443
- ignored.push({ field, given });
444
- }
445
- return ignored;
446
- }
447
- function ignoredNotice(input, line, label, ignored) {
448
- const { field, given } = ignored;
449
- const article = /^[aeiou]/.test(field) ? "an" : "a";
450
- const holds = given === "list" ? "holds one value, not a list" : given === "mapping" ? "holds text, not a mapping" : "holds text";
451
- return `${input.file}:${line}: ignored ${field} on "${label}": ${article} ${field} ${holds}.`;
452
- }
453
642
  function linesFor(record, lines) {
454
643
  const kept = {};
455
644
  for (const field of TERM_FIELDS) {
@@ -461,7 +650,7 @@ function linesFor(record, lines) {
461
650
  function idFor(record, recordId, constructId) {
462
651
  return textOf(recordId) ?? textOf(constructId) ?? slugOf(record.label);
463
652
  }
464
- function languageOf(input) {
653
+ function languageOf2(input) {
465
654
  return textOf(input.metadata["language"]) ?? textOf(input.metadata["xml:lang"]);
466
655
  }
467
656
  function declares(input, type) {
@@ -472,7 +661,7 @@ function skipped(input, line, label) {
472
661
  return `${input.file}:${line}: skipped a ${label} entry with no term.`;
473
662
  }
474
663
  function termOf(input, parts) {
475
- const language = languageOf(input);
664
+ const language = textOf(parts.language) ?? languageOf2(input);
476
665
  const location = {
477
666
  file: input.file,
478
667
  ...input.path === void 0 ? {} : { path: input.path },
@@ -547,7 +736,7 @@ function parseXml(input) {
547
736
  const shift = input.content.charCodeAt(0) === 65279 ? 1 : 0;
548
737
  const body = input.content.slice(shift);
549
738
  const errors = [];
550
- let parsed = null;
739
+ let parsed2 = null;
551
740
  try {
552
741
  const doc = new DOMParser({
553
742
  onError: (level, message) => {
@@ -557,12 +746,12 @@ function parseXml(input) {
557
746
  }
558
747
  }).parseFromString(body, "text/xml");
559
748
  const root = doc.documentElement;
560
- if (errors.length === 0 && root !== null) parsed = { root, body, shift, starts: lineStarts(body) };
749
+ if (errors.length === 0 && root !== null) parsed2 = { root, body, shift, starts: lineStarts(body) };
561
750
  } catch {
562
- parsed = null;
751
+ parsed2 = null;
563
752
  }
564
- cache.set(input, parsed);
565
- return parsed;
753
+ cache.set(input, parsed2);
754
+ return parsed2;
566
755
  }
567
756
  function nameOf(el) {
568
757
  return (el.localName ?? el.nodeName).toLowerCase();
@@ -837,9 +1026,9 @@ function parseHtml(input) {
837
1026
  const cached = cache2.get(input);
838
1027
  if (cached !== void 0) return cached;
839
1028
  const shift = input.content.charCodeAt(0) === 65279 ? 1 : 0;
840
- const parsed = { root: parse(input.content.slice(shift), { sourceCodeLocationInfo: true }), shift };
841
- cache2.set(input, parsed);
842
- return parsed;
1029
+ const parsed2 = { root: parse(input.content.slice(shift), { sourceCodeLocationInfo: true }), shift };
1030
+ cache2.set(input, parsed2);
1031
+ return parsed2;
843
1032
  }
844
1033
  function isElement(node) {
845
1034
  return "tagName" in node;
@@ -875,11 +1064,11 @@ function attr(el, name) {
875
1064
  function lineOf(el) {
876
1065
  return el.sourceCodeLocation?.startLine ?? 1;
877
1066
  }
878
- function spanOf(parsed, first, last) {
1067
+ function spanOf(parsed2, first, last) {
879
1068
  const start = first.sourceCodeLocation?.startOffset;
880
1069
  const end = last.sourceCodeLocation?.endOffset;
881
1070
  if (start === void 0 || end === void 0) return void 0;
882
- return { start: start + parsed.shift, end: end + parsed.shift };
1071
+ return { start: start + parsed2.shift, end: end + parsed2.shift };
883
1072
  }
884
1073
  function definitionOf3(dd) {
885
1074
  const paragraphs = childElements(dd).filter((child) => child.tagName === "p");
@@ -892,9 +1081,9 @@ function listItems(dl) {
892
1081
  var DL_LABEL = "dl";
893
1082
  function readDl(input) {
894
1083
  if (!declares(input, "term-set")) return nothing();
895
- const parsed = parseHtml(input);
1084
+ const parsed2 = parseHtml(input);
896
1085
  const result = nothing();
897
- for (const dl of elementsNamed(parsed.root, "dl")) {
1086
+ for (const dl of elementsNamed(parsed2.root, "dl")) {
898
1087
  const items = listItems(dl).filter((item2) => item2.tagName === "dt" || item2.tagName === "dd");
899
1088
  let i = 0;
900
1089
  while (i < items.length) {
@@ -924,7 +1113,7 @@ function readDl(input) {
924
1113
  result.notices.push(skipped(input, line, DL_LABEL));
925
1114
  continue;
926
1115
  }
927
- const span = spanOf(parsed, first, last);
1116
+ const span = spanOf(parsed2, first, last);
928
1117
  const constructId = dts.map((dt) => textOf(attr(dt, "id"))).find((id) => id !== void 0);
929
1118
  result.terms.push(
930
1119
  termOf(input, {
@@ -964,9 +1153,9 @@ function dfnFields(dfn) {
964
1153
  }
965
1154
  function readDfn(input) {
966
1155
  if (!declares(input, "term-set")) return nothing();
967
- const parsed = parseHtml(input);
1156
+ const parsed2 = parseHtml(input);
968
1157
  const result = nothing();
969
- for (const dfn of elementsNamed(parsed.root, "dfn")) {
1158
+ for (const dfn of elementsNamed(parsed2.root, "dfn")) {
970
1159
  if (insideDt(dfn)) continue;
971
1160
  const { label, alt } = dfnFields(dfn);
972
1161
  const line = lineOf(dfn);
@@ -975,7 +1164,7 @@ function readDfn(input) {
975
1164
  result.notices.push(skipped(input, line, DFN_LABEL));
976
1165
  continue;
977
1166
  }
978
- const span = spanOf(parsed, dfn, dfn);
1167
+ const span = spanOf(parsed2, dfn, dfn);
979
1168
  const term = termOf(input, {
980
1169
  record,
981
1170
  constructId: attr(dfn, "id"),
@@ -1009,6 +1198,10 @@ var FIELDS = new Set(TERM_FIELDS);
1009
1198
  function isField(key) {
1010
1199
  return FIELDS.has(key);
1011
1200
  }
1201
+ var ENTRY_KEYS = ["language", ...TERM_FIELDS];
1202
+ function isEntryKey(key) {
1203
+ return key === "language" || isField(key);
1204
+ }
1012
1205
  function read2(input) {
1013
1206
  if ((input.path ?? input.file).toLowerCase().endsWith(".json")) {
1014
1207
  try {
@@ -1034,14 +1227,14 @@ function read2(input) {
1034
1227
  }
1035
1228
  const terms = [];
1036
1229
  const notices = [];
1037
- for (const pair of root.items) {
1038
- const keyNode = isScalar(pair.key) ? pair.key : void 0;
1230
+ for (const pair2 of root.items) {
1231
+ const keyNode = isScalar(pair2.key) ? pair2.key : void 0;
1039
1232
  const id = textOf(keyNode?.value);
1040
1233
  const line = lineOf2(keyNode) ?? 1;
1041
1234
  if (id === void 0) {
1042
1235
  throw new TermError(`${input.file}:${line}: an entry's key is its id, and must be a non-empty string.`);
1043
1236
  }
1044
- const value = pair.value;
1237
+ const value = pair2.value;
1045
1238
  if (!isMap(value)) {
1046
1239
  throw new TermError(`${input.file}:${line}: entry "${id}" is not a mapping of fields.`);
1047
1240
  }
@@ -1055,34 +1248,45 @@ function read2(input) {
1055
1248
  raw[name] = isNode(fieldValue) ? fieldValue.toJSON() : fieldValue;
1056
1249
  lines[name] = lineOf2(fieldKey);
1057
1250
  }
1058
- const record = recordOf(raw);
1251
+ const issues = [];
1252
+ const record = recordOf(raw, issues);
1059
1253
  if (record === void 0) {
1060
1254
  notices.push(skipped(input, line, LABEL2));
1061
1255
  continue;
1062
1256
  }
1063
- for (const ignored of ignoredFields(raw)) {
1064
- notices.push(ignoredNotice(input, lines[ignored.field] ?? line, record.label, ignored));
1257
+ for (const issue of issues) {
1258
+ const nested = issue.path.length > 1 ? value.getIn(issue.path, true) : void 0;
1259
+ const [top] = issue.path;
1260
+ const topLine = typeof top === "string" && isField(top) ? lines[top] : void 0;
1261
+ notices.push(issueNotice(input, (isNode(nested) ? lineOf2(nested) : void 0) ?? topLine ?? line, record.label, issue));
1065
1262
  }
1066
- terms.push(termOf(input, { record, recordId: id, construct: "manifest", line, lines }));
1263
+ const language = value.get("language");
1264
+ terms.push(termOf(input, { record, recordId: id, construct: "manifest", line, lines, language }));
1067
1265
  }
1068
1266
  return { terms, notices };
1069
1267
  }
1070
- function entryOf(record) {
1268
+ function entryValues(language, record) {
1269
+ return { ...record, ...language === void 0 ? {} : { language } };
1270
+ }
1271
+ function entryOf(term) {
1272
+ const values = entryValues(term.language, term.record);
1071
1273
  const entry = {};
1072
- for (const field of TERM_FIELDS) {
1073
- const value = record[field];
1074
- if (value !== void 0) entry[field] = value;
1274
+ for (const key of ENTRY_KEYS) {
1275
+ const value = values[key];
1276
+ if (value !== void 0) entry[key] = value;
1075
1277
  }
1076
1278
  return entry;
1077
1279
  }
1078
- function currentRecord(value) {
1280
+ function currentValues(value) {
1079
1281
  if (typeof value !== "object" || value === null || Array.isArray(value)) return {};
1282
+ const entry = value;
1080
1283
  const raw = {};
1081
- for (const field of TERM_FIELDS) raw[field] = value[field];
1082
- return recordOf(raw) ?? {};
1284
+ for (const field of TERM_FIELDS) raw[field] = entry[field];
1285
+ return entryValues(textOf(entry["language"]), recordOf(raw) ?? {});
1083
1286
  }
1084
- function changedFields(current, record) {
1085
- return TERM_FIELDS.filter((field) => JSON.stringify(current[field]) !== JSON.stringify(record[field]));
1287
+ function changedKeys(current, term) {
1288
+ const next = entryValues(term.language, term.record);
1289
+ return ENTRY_KEYS.filter((key) => JSON.stringify(current[key]) !== JSON.stringify(next[key]));
1086
1290
  }
1087
1291
  function applyJson(input, terms) {
1088
1292
  let data;
@@ -1102,20 +1306,21 @@ function applyJson(input, terms) {
1102
1306
  if (existing !== void 0) {
1103
1307
  throw new TermError(`${input.file}: entry "${term.id}" is not a mapping of fields.`);
1104
1308
  }
1105
- root[term.id] = entryOf(term.record);
1309
+ root[term.id] = entryOf(term);
1106
1310
  changed = true;
1107
1311
  continue;
1108
1312
  }
1109
1313
  const entry = existing;
1110
- const fields = changedFields(currentRecord(entry), term.record);
1111
- if (fields.length === 0) continue;
1314
+ const keys = changedKeys(currentValues(entry), term);
1315
+ if (keys.length === 0) continue;
1316
+ const values = entryValues(term.language, term.record);
1112
1317
  const next = {};
1113
1318
  for (const [key, value] of Object.entries(entry)) {
1114
- if (!isField(key) || !fields.includes(key)) next[key] = value;
1115
- else if (term.record[key] !== void 0) next[key] = term.record[key];
1319
+ if (!isEntryKey(key) || !keys.includes(key)) next[key] = value;
1320
+ else if (values[key] !== void 0) next[key] = values[key];
1116
1321
  }
1117
- for (const field of fields) {
1118
- if (term.record[field] !== void 0 && !(field in next)) next[field] = term.record[field];
1322
+ for (const key of keys) {
1323
+ if (values[key] !== void 0 && !(key in next)) next[key] = values[key];
1119
1324
  }
1120
1325
  root[term.id] = next;
1121
1326
  changed = true;
@@ -1127,31 +1332,34 @@ function applyJson(input, terms) {
1127
1332
  }
1128
1333
  function entryRanges(root) {
1129
1334
  const ranges = /* @__PURE__ */ new Map();
1130
- for (const pair of root.items) {
1131
- if (!isScalar(pair.key)) continue;
1132
- const id = textOf(pair.key.value);
1133
- const start = pair.key.range?.[0];
1134
- const end = isNode(pair.value) ? pair.value.range?.[1] : pair.key.range?.[1];
1335
+ for (const pair2 of root.items) {
1336
+ if (!isScalar(pair2.key)) continue;
1337
+ const id = textOf(pair2.key.value);
1338
+ const start = pair2.key.range?.[0];
1339
+ const end = isNode(pair2.value) ? pair2.value.range?.[1] : pair2.key.range?.[1];
1135
1340
  if (id !== void 0 && start !== void 0 && end !== void 0) ranges.set(id, { start, end });
1136
1341
  }
1137
1342
  return ranges;
1138
1343
  }
1139
- function editEntry(doc, entry, record) {
1140
- const fields = changedFields(currentRecord(entry.toJSON()), record);
1141
- for (const field of fields) {
1142
- const value = record[field];
1344
+ function editEntry(doc, entry, term) {
1345
+ const keys = changedKeys(currentValues(entry.toJSON()), term);
1346
+ const values = entryValues(term.language, term.record);
1347
+ for (const key of keys) {
1348
+ const value = values[key];
1143
1349
  if (value === void 0) {
1144
- entry.delete(field);
1350
+ entry.delete(key);
1145
1351
  } else if (Array.isArray(value)) {
1146
- const previous = entry.get(field, true);
1352
+ const previous = entry.get(key, true);
1147
1353
  const node = doc.createNode(value);
1148
1354
  node.flow = isSeq(previous) && previous.flow === true;
1149
- entry.set(field, node);
1355
+ entry.set(key, node);
1356
+ } else if (typeof value === "object" && value !== null) {
1357
+ entry.set(key, doc.createNode(value));
1150
1358
  } else {
1151
- entry.set(field, value);
1359
+ entry.set(key, value);
1152
1360
  }
1153
1361
  }
1154
- return fields.length > 0;
1362
+ return keys.length > 0;
1155
1363
  }
1156
1364
  function applyYaml(input, terms) {
1157
1365
  const { content } = input;
@@ -1164,7 +1372,7 @@ function applyYaml(input, terms) {
1164
1372
  const root = doc.contents;
1165
1373
  if (root === null) {
1166
1374
  if (terms.length === 0) return content;
1167
- const entries = Object.fromEntries(terms.map((term) => [term.id, entryOf(term.record)]));
1375
+ const entries = Object.fromEntries(terms.map((term) => [term.id, entryOf(term)]));
1168
1376
  return stringifyYaml(entries, { lineWidth: 0 }).replaceAll("\n", eol);
1169
1377
  }
1170
1378
  if (!isMap(root)) {
@@ -1175,16 +1383,16 @@ function applyYaml(input, terms) {
1175
1383
  const changed = [];
1176
1384
  const added = [];
1177
1385
  for (const term of terms) {
1178
- const pair = root.items.find((item2) => isScalar(item2.key) && textOf(item2.key.value) === term.id);
1179
- if (pair === void 0) {
1180
- root.add(doc.createPair(term.id, entryOf(term.record)));
1386
+ const pair2 = root.items.find((item2) => isScalar(item2.key) && textOf(item2.key.value) === term.id);
1387
+ if (pair2 === void 0) {
1388
+ root.add(doc.createPair(term.id, entryOf(term)));
1181
1389
  added.push(term.id);
1182
1390
  continue;
1183
1391
  }
1184
- if (!isMap(pair.value)) {
1392
+ if (!isMap(pair2.value)) {
1185
1393
  throw new TermError(`${input.file}: entry "${term.id}" is not a mapping of fields.`);
1186
1394
  }
1187
- if (editEntry(doc, pair.value, term.record)) changed.push(term.id);
1395
+ if (editEntry(doc, pair2.value, term)) changed.push(term.id);
1188
1396
  }
1189
1397
  if (changed.length === 0 && added.length === 0) return content;
1190
1398
  const text = doc.toString({ lineWidth: 0 });
@@ -1229,13 +1437,12 @@ function read3(input) {
1229
1437
  raw[field] = input.metadata[field];
1230
1438
  lines[field] = input.lineFor(`/${field}`);
1231
1439
  }
1232
- const record = recordOf(raw);
1440
+ const issues = [];
1441
+ const record = recordOf(raw, issues);
1233
1442
  if (record === void 0) return { terms: [], notices: [skipped(input, 1, LABEL3)] };
1234
1443
  return {
1235
1444
  terms: [termOf(input, { record, recordId: input.metadata["id"], construct: "page", line: 1, lines })],
1236
- notices: ignoredFields(raw).map(
1237
- (ignored) => ignoredNotice(input, lines[ignored.field] ?? 1, record.label, ignored)
1238
- )
1445
+ notices: issues.map((issue) => issueNotice(input, input.lineFor(pointerOf(issue.path)) ?? 1, record.label, issue))
1239
1446
  };
1240
1447
  }
1241
1448
  function apply(input, terms) {
@@ -1281,6 +1488,940 @@ var pageReader = {
1281
1488
  apply
1282
1489
  };
1283
1490
 
1491
+ // src/term/core/readers/tbx.ts
1492
+ import { isDeepStrictEqual as isDeepStrictEqual2 } from "node:util";
1493
+ import { DOMParser as DOMParser3 } from "@xmldom/xmldom";
1494
+
1495
+ // src/term/core/writers/merge.ts
1496
+ import { isDeepStrictEqual } from "node:util";
1497
+ function conceptGroups(terms) {
1498
+ const groups = /* @__PURE__ */ new Map();
1499
+ for (const term of terms) {
1500
+ const group = groups.get(term.id);
1501
+ if (group === void 0) groups.set(term.id, [term]);
1502
+ else group.push(term);
1503
+ }
1504
+ return [...groups.values()];
1505
+ }
1506
+ function mergeFirst(id, values, prefix = "") {
1507
+ const merged = {};
1508
+ const conflicted = /* @__PURE__ */ new Set();
1509
+ for (const value of values) {
1510
+ if (value === void 0) continue;
1511
+ for (const [key, field] of Object.entries(value)) {
1512
+ if (field === void 0) continue;
1513
+ if (!(key in merged)) merged[key] = field;
1514
+ else if (!isDeepStrictEqual(merged[key], field)) conflicted.add(key);
1515
+ }
1516
+ }
1517
+ return {
1518
+ merged,
1519
+ conflicts: Object.keys(merged).filter((key) => conflicted.has(key)).map((key) => ({ id, field: `${prefix}${key}` }))
1520
+ };
1521
+ }
1522
+
1523
+ // src/term/core/readers/tbx-model.ts
1524
+ import { DOMParser as DOMParser2 } from "@xmldom/xmldom";
1525
+ var TBX_V3_NAMESPACE = "urn:iso:std:iso:30042:ed-2";
1526
+ var TBX_MODULE_NAMESPACES = {
1527
+ min: "http://www.tbxinfo.net/ns/min",
1528
+ basic: "http://www.tbxinfo.net/ns/basic",
1529
+ lng: "http://www.tbxinfo.net/ns/linguist"
1530
+ };
1531
+ var sources = /* @__PURE__ */ new WeakMap();
1532
+ function rememberTbxSource(term, source) {
1533
+ sources.set(term.location, source);
1534
+ }
1535
+ function tbxSourceOf(term) {
1536
+ return sources.get(term.location);
1537
+ }
1538
+ function category(name, element, module) {
1539
+ return { name, element, module };
1540
+ }
1541
+ var TBX_CATEGORIES = {
1542
+ definition: category("definition", "descrip", "basic"),
1543
+ subjectField: category("subjectField", "descrip", "min"),
1544
+ context: category("context", "descrip", "basic"),
1545
+ source: category("source", "admin", "basic"),
1546
+ customerSubset: category("customerSubset", "admin", "min"),
1547
+ projectSubset: category("projectSubset", "admin", "basic"),
1548
+ crossReference: category("crossReference", "ref", "basic"),
1549
+ externalCrossReference: category("externalCrossReference", "xref", "min"),
1550
+ xGraphic: category("xGraphic", "xref", "basic"),
1551
+ transactionType: category("transactionType", "transac", "basic"),
1552
+ responsibility: category("responsibility", "transacNote", "basic"),
1553
+ administrativeStatus: category("administrativeStatus", "termNote", "min"),
1554
+ partOfSpeech: category("partOfSpeech", "termNote", "min"),
1555
+ grammaticalGender: category("grammaticalGender", "termNote", "basic"),
1556
+ grammaticalNumber: category("grammaticalNumber", "termNote", "lng"),
1557
+ termType: category("termType", "termNote", "basic"),
1558
+ termLocation: category("termLocation", "termNote", "basic"),
1559
+ geographicalUsage: category("geographicalUsage", "termNote", "basic"),
1560
+ register: category("register", "termNote", "lng"),
1561
+ transferComment: category("transferComment", "termNote", "lng"),
1562
+ reading: category("reading", "admin", "lng"),
1563
+ readingNote: category("readingNote", "adminNote", "lng")
1564
+ };
1565
+ var TBX_TEXT_FIELDS = [
1566
+ ["subject-field", "subjectField"],
1567
+ ["contexts", "context"],
1568
+ ["sources", "source"],
1569
+ ["customer-subsets", "customerSubset"],
1570
+ ["project-subsets", "projectSubset"]
1571
+ ];
1572
+ var TBX_LINK_FIELDS = [
1573
+ ["cross-references", "crossReference"],
1574
+ ["external-cross-references", "externalCrossReference"],
1575
+ ["graphics", "xGraphic"]
1576
+ ];
1577
+ var TBX_TERM_NOTES = [
1578
+ ["administrative-status", "administrativeStatus"],
1579
+ ["part-of-speech", "partOfSpeech"],
1580
+ ["grammatical-gender", "grammaticalGender"],
1581
+ ["grammatical-number", "grammaticalNumber"],
1582
+ ["term-type", "termType"],
1583
+ ["term-location", "termLocation"],
1584
+ ["geographical-usage", "geographicalUsage"],
1585
+ ["register", "register"]
1586
+ ];
1587
+ var TBX_STATUS_VALUES = {
1588
+ preferred: "preferredTerm-admn-sts",
1589
+ admitted: "admittedTerm-admn-sts",
1590
+ deprecated: "deprecatedTerm-admn-sts",
1591
+ superseded: "supersededTerm-admn-sts"
1592
+ };
1593
+ var TBX_NO_STATUS = "none";
1594
+ function lf(text) {
1595
+ return text.replace(/\r\n?/g, "\n");
1596
+ }
1597
+ var markupTexts = /* @__PURE__ */ new Map();
1598
+ function markupText(markup) {
1599
+ if (markupTexts.has(markup)) return markupTexts.get(markup);
1600
+ let text;
1601
+ try {
1602
+ const errors = [];
1603
+ const doc = new DOMParser2({
1604
+ onError: (level, message) => {
1605
+ if ((level === "error" || level === "fatalError") && !/entity not found/i.test(message)) errors.push(message);
1606
+ }
1607
+ }).parseFromString(`<x>${markup}</x>`, "text/xml");
1608
+ const root = doc.documentElement;
1609
+ text = errors.length > 0 || root === null ? void 0 : lf(root.textContent ?? "").trim();
1610
+ } catch {
1611
+ text = void 0;
1612
+ }
1613
+ markupTexts.set(markup, text);
1614
+ return text;
1615
+ }
1616
+ function valueXml(value, markup) {
1617
+ return markup.find((item2) => markupText(item2) === value) ?? xmlText(value);
1618
+ }
1619
+ function prefixOf(format, module) {
1620
+ return format.prefixes?.[module] ?? module;
1621
+ }
1622
+ function categoryXml(name, value, ctx, target) {
1623
+ const cat = TBX_CATEGORIES[name];
1624
+ const dct = ctx.format.style === "dct";
1625
+ const tag = dct ? `${prefixOf(ctx.format, cat.module)}:${cat.name}` : cat.element;
1626
+ const attributes = `${dct ? "" : ` type="${cat.name}"`}${target === void 0 ? "" : ` target="${xmlAttribute(target)}"`}`;
1627
+ if (value === "") return `<${tag}${attributes}/>`;
1628
+ return `<${tag}${attributes}>${valueXml(value, ctx.markup)}</${tag}>`;
1629
+ }
1630
+ function plainXml(tag, value, ctx, attributes = "") {
1631
+ return `<${tag}${attributes}>${valueXml(value, ctx.markup)}</${tag}>`;
1632
+ }
1633
+ function pair(wanted, pool, same) {
1634
+ const used = /* @__PURE__ */ new Set();
1635
+ const found = wanted.map((w) => {
1636
+ const at = pool.findIndex((s, i) => !used.has(i) && same(w, s));
1637
+ if (at === -1) return void 0;
1638
+ used.add(at);
1639
+ return pool[at];
1640
+ });
1641
+ const left = pool.filter((_, i) => !used.has(i));
1642
+ return found.map((s) => s ?? left.shift());
1643
+ }
1644
+ function linkXml(name, link, ctx) {
1645
+ return categoryXml(name, link.text ?? "", ctx, link.target);
1646
+ }
1647
+ function nest(lines) {
1648
+ return lines.map((line) => ` ${line.replaceAll("\n", "\n ")}`);
1649
+ }
1650
+ var TERM_NOTE_ITEM = new RegExp(
1651
+ `^<(?:termNote(?:Grp)?|[\\w.-]+:(?:${Object.values(TBX_CATEGORIES).filter((cat) => cat.element === "termNote").map((cat) => cat.name).join("|")}))[\\s>/]`
1652
+ );
1653
+ function isTermNoteItem(item2) {
1654
+ return TERM_NOTE_ITEM.test(item2);
1655
+ }
1656
+ function auxLines(aux, ctx, extra = []) {
1657
+ const lines = [];
1658
+ const grouped = aux.definition !== void 0 && (aux.sources !== void 0 || aux.notes !== void 0);
1659
+ if (aux.definition !== void 0) {
1660
+ const definition = categoryXml("definition", aux.definition, ctx);
1661
+ if (grouped) {
1662
+ lines.push(
1663
+ "<descripGrp>",
1664
+ ...nest([
1665
+ definition,
1666
+ ...(aux.sources ?? []).map((s) => categoryXml("source", s, ctx)),
1667
+ ...(aux.notes ?? []).map((n) => plainXml("note", n, ctx))
1668
+ ]),
1669
+ "</descripGrp>"
1670
+ );
1671
+ } else {
1672
+ lines.push(definition);
1673
+ }
1674
+ }
1675
+ for (const [field, name] of TBX_TEXT_FIELDS) {
1676
+ if (field === "sources" && grouped) continue;
1677
+ const value = aux[field];
1678
+ for (const item2 of typeof value === "string" ? [value] : value ?? []) lines.push(categoryXml(name, item2, ctx));
1679
+ }
1680
+ if (!grouped) for (const note of aux.notes ?? []) lines.push(plainXml("note", note, ctx));
1681
+ for (const [field, name] of TBX_LINK_FIELDS) {
1682
+ for (const link of aux[field] ?? []) lines.push(linkXml(name, link, ctx));
1683
+ }
1684
+ for (const transaction of aux.transactions ?? []) {
1685
+ lines.push(
1686
+ "<transacGrp>",
1687
+ ...nest([
1688
+ categoryXml("transactionType", transaction.type, ctx),
1689
+ ...transaction.responsibility === void 0 ? [] : [categoryXml("responsibility", transaction.responsibility, ctx)],
1690
+ ...transaction.date === void 0 ? [] : [plainXml("date", transaction.date, ctx)]
1691
+ ]),
1692
+ "</transacGrp>"
1693
+ );
1694
+ }
1695
+ lines.push(...extra);
1696
+ return lines;
1697
+ }
1698
+ function resolveDesignations(record) {
1699
+ const pool = [
1700
+ { term: record.label, status: "preferred", used: false },
1701
+ ...(record["alt-labels"] ?? []).map((term) => ({ term, status: "admitted", used: false })),
1702
+ ...(record["hidden-labels"] ?? []).map((term) => ({ term, status: "deprecated", used: false }))
1703
+ ];
1704
+ const out = [];
1705
+ for (const designation of record.designations ?? []) {
1706
+ const slot = pool.find((entry) => !entry.used && entry.term === designation.term);
1707
+ if (slot !== void 0) slot.used = true;
1708
+ out.push({ designation, status: designation["administrative-status"] ?? slot?.status ?? "admitted" });
1709
+ }
1710
+ for (const slot of pool) if (!slot.used) out.push({ designation: { term: slot.term }, status: slot.status });
1711
+ return out;
1712
+ }
1713
+ function statusValue(status) {
1714
+ if (status === TBX_NO_STATUS) return void 0;
1715
+ return status in TBX_STATUS_VALUES ? TBX_STATUS_VALUES[status] : status;
1716
+ }
1717
+ function designationLines({ designation, status }, ctx, shape) {
1718
+ const group = shape?.group;
1719
+ const tag = group !== void 0 ? "ntig" : ctx.format.version === 3 ? "termSec" : "tig";
1720
+ const notes = [];
1721
+ for (const [field, name] of TBX_TERM_NOTES) {
1722
+ const value = field === "administrative-status" ? statusValue(status) : designation[field];
1723
+ if (value !== void 0) notes.push(categoryXml(name, value, ctx));
1724
+ }
1725
+ for (const comment of designation["transfer-comments"] ?? []) notes.push(categoryXml("transferComment", comment, ctx));
1726
+ const items = designation["tbx-elements"] ?? [];
1727
+ const reading = [];
1728
+ if (designation.reading !== void 0) {
1729
+ const admin = categoryXml("reading", designation.reading, ctx);
1730
+ if (designation["reading-note"] === void 0) reading.push(admin);
1731
+ else reading.push("<adminGrp>", ...nest([admin, categoryXml("readingNote", designation["reading-note"], ctx)]), "</adminGrp>");
1732
+ }
1733
+ const { "tbx-elements": _items, ...aux } = designation;
1734
+ const head = [plainXml("term", designation.term, ctx, shape?.termAttributes), ...notes, ...items.filter(isTermNoteItem)];
1735
+ const rest = auxLines(aux, ctx, [...reading, ...items.filter((item2) => !isTermNoteItem(item2))]);
1736
+ const body = group === void 0 ? [...head, ...rest] : [`<termGrp${group}>`, ...nest(head), "</termGrp>", ...rest];
1737
+ return [`<${tag}${shape?.attributes ?? ""}>`, ...nest(body), `</${tag}>`];
1738
+ }
1739
+ function languageLines(term, ctx, shape) {
1740
+ const tag = ctx.format.version === 3 ? "langSec" : "langSet";
1741
+ const { record } = term;
1742
+ const aux = {};
1743
+ for (const field of [
1744
+ "definition",
1745
+ "subject-field",
1746
+ "contexts",
1747
+ "notes",
1748
+ "sources",
1749
+ "customer-subsets",
1750
+ "project-subsets",
1751
+ "cross-references",
1752
+ "external-cross-references",
1753
+ "graphics",
1754
+ "transactions"
1755
+ ]) {
1756
+ const value = record[field];
1757
+ if (value !== void 0) Object.assign(aux, { [field]: value });
1758
+ }
1759
+ const designations = resolveDesignations(record);
1760
+ const shapes = pair(designations, shape?.designations ?? [], (d, s) => d.designation.term === s.term);
1761
+ return [
1762
+ `<${tag} xml:lang="${xmlAttribute(term.language ?? DEFAULT_LANGUAGE)}"${shape?.attributes ?? ""}>`,
1763
+ ...nest([
1764
+ ...auxLines(aux, ctx, record["tbx-elements"] ?? []),
1765
+ ...designations.flatMap((d, i) => designationLines(d, ctx, shapes[i]))
1766
+ ]),
1767
+ `</${tag}>`
1768
+ ];
1769
+ }
1770
+ function tbxEntryLines(terms, format, shape) {
1771
+ const [head] = terms;
1772
+ if (head === void 0) return [];
1773
+ const tag = format.version === 3 ? "conceptEntry" : "termEntry";
1774
+ const concept = head.record["concept-entry"] ?? {};
1775
+ const { "tbx-elements": conceptItems, ...conceptAux } = concept;
1776
+ const languages = pair(
1777
+ terms,
1778
+ shape?.languages ?? [],
1779
+ (t, s) => languageKey(t) === (s.language ?? DEFAULT_LANGUAGE).toLowerCase()
1780
+ );
1781
+ return [
1782
+ `<${tag} id="${xmlAttribute(head.id)}"${shape?.attributes ?? ""}>`,
1783
+ ...nest([
1784
+ ...auxLines(conceptAux, { format, markup: head.record["tbx-markup"] ?? [] }, conceptItems ?? []),
1785
+ ...terms.flatMap(
1786
+ (term, i) => languageLines(term, { format, markup: term.record["tbx-markup"] ?? [] }, languages[i])
1787
+ ),
1788
+ ...shape?.unread ?? []
1789
+ ]),
1790
+ `</${tag}>`
1791
+ ];
1792
+ }
1793
+
1794
+ // src/term/core/readers/tbx.ts
1795
+ var LABEL4 = "TBX entry";
1796
+ var parsed = /* @__PURE__ */ new WeakMap();
1797
+ function parseTbx(input) {
1798
+ const cached = parsed.get(input);
1799
+ if (cached !== void 0) return cached;
1800
+ const shift = input.content.charCodeAt(0) === 65279 ? 1 : 0;
1801
+ const body = input.content.slice(shift);
1802
+ const errors = [];
1803
+ let root = null;
1804
+ try {
1805
+ root = new DOMParser3({
1806
+ onError: (level, message) => {
1807
+ if (level !== "error" && level !== "fatalError") return;
1808
+ if (/entity not found/i.test(message)) return;
1809
+ errors.push(message);
1810
+ }
1811
+ }).parseFromString(body, "text/xml").documentElement;
1812
+ } catch (error) {
1813
+ if (errors.length === 0) errors.push(error instanceof Error ? error.message : String(error));
1814
+ }
1815
+ const failure = errors[0] ?? (root === null ? "no root element" : void 0);
1816
+ if (failure !== void 0 || root === null) {
1817
+ throw new TermError(`${input.file}: could not be read as tbx: Invalid XML: ${failure ?? "no root element"}`);
1818
+ }
1819
+ const local = root.localName ?? root.nodeName;
1820
+ if (local !== "martif" && local !== "tbx") {
1821
+ throw new TermError(`${input.file}: is not TBX: its root element is <${root.nodeName}>, not <martif> or <tbx>.`);
1822
+ }
1823
+ const version = local === "martif" ? 2 : 3;
1824
+ const prefixes = { min: "min", basic: "basic", lng: "lng" };
1825
+ for (let i = 0; i < root.attributes.length; i++) {
1826
+ const attribute = root.attributes.item(i);
1827
+ if (attribute === null || !attribute.name.startsWith("xmlns:")) continue;
1828
+ for (const module of Object.keys(TBX_MODULE_NAMESPACES)) {
1829
+ if (TBX_MODULE_NAMESPACES[module] === attribute.value) prefixes[module] = attribute.name.slice("xmlns:".length);
1830
+ }
1831
+ }
1832
+ const xml = { root, body, shift, starts: lineStarts(body) };
1833
+ const doc = {
1834
+ input,
1835
+ xml,
1836
+ ns: root.namespaceURI ?? "",
1837
+ document: {
1838
+ content: input.content,
1839
+ version,
1840
+ style: version === 3 && root.getAttribute("style") === "dct" ? "dct" : "dca",
1841
+ prefixes
1842
+ }
1843
+ };
1844
+ const bodyEl = structuralChildren(doc, root, "text").flatMap((text) => structuralChildren(doc, text, "body"))[0];
1845
+ if (bodyEl !== void 0) {
1846
+ const inner = innerSpan(doc, bodyEl);
1847
+ if (inner !== void 0) doc.document.body = inner;
1848
+ }
1849
+ const headerEl = structuralChildren(doc, root, version === 3 ? "tbxHeader" : "martifHeader")[0];
1850
+ const header = headerEl === void 0 ? void 0 : innerSpan(doc, headerEl);
1851
+ if (header !== void 0) doc.document.header = header;
1852
+ const backEl = structuralChildren(doc, root, "text").flatMap((text) => structuralChildren(doc, text, "back"))[0];
1853
+ const back = backEl === void 0 ? void 0 : innerSpan(doc, backEl);
1854
+ if (back !== void 0) doc.document.back = back;
1855
+ parsed.set(input, doc);
1856
+ return doc;
1857
+ }
1858
+ function isStructural(doc, el, local) {
1859
+ return el.localName === local && (el.namespaceURI ?? "") === doc.ns;
1860
+ }
1861
+ function structuralChildren(doc, el, local) {
1862
+ return childrenOf(el).filter((child) => isStructural(doc, child, local));
1863
+ }
1864
+ function onlyAttributes(el, allowed) {
1865
+ for (let i = 0; i < el.attributes.length; i++) {
1866
+ const name = el.attributes.item(i)?.name;
1867
+ if (name === void 0 || name === "xmlns" || name.startsWith("xmlns:")) continue;
1868
+ if (!allowed.includes(name)) return false;
1869
+ }
1870
+ return true;
1871
+ }
1872
+ function attributesOf(el, own = []) {
1873
+ let out = "";
1874
+ for (let i = 0; i < el.attributes.length; i++) {
1875
+ const attribute = el.attributes.item(i);
1876
+ if (attribute !== null && !own.includes(attribute.name)) out += ` ${attribute.name}="${xmlAttribute(attribute.value)}"`;
1877
+ }
1878
+ return out;
1879
+ }
1880
+ function categoryOf(doc, el) {
1881
+ const dct = doc.document.style === "dct";
1882
+ for (const cat of Object.values(TBX_CATEGORIES)) {
1883
+ if (dct) {
1884
+ if (el.localName === cat.name && el.namespaceURI === TBX_MODULE_NAMESPACES[cat.module]) return cat;
1885
+ } else if (isStructural(doc, el, cat.element) && el.getAttribute("type") === cat.name) {
1886
+ return cat;
1887
+ }
1888
+ }
1889
+ return void 0;
1890
+ }
1891
+ function categoryAttributes(doc, cat) {
1892
+ const linked = cat.element === "ref" || cat.element === "xref";
1893
+ return [...doc.document.style === "dct" ? [] : ["type"], ...linked ? ["target"] : []];
1894
+ }
1895
+ function innerSpan(doc, el) {
1896
+ const span = spanOfElement(doc.xml, el);
1897
+ if (span === void 0) return void 0;
1898
+ const open = tagEnd(doc.xml.body, span.start - doc.xml.shift);
1899
+ if (open === void 0) return void 0;
1900
+ const start = open.end + doc.xml.shift;
1901
+ if (open.selfClosing) return { start, end: start };
1902
+ return { start, end: doc.input.content.lastIndexOf("</", span.end - 1) };
1903
+ }
1904
+ var DTD_ENTITY = /&(?!(?:amp|lt|gt|quot|apos);|#)/;
1905
+ function valueOf(doc, el, allowMarkup = true, entities = false) {
1906
+ const text = lf(el.textContent ?? "").trim();
1907
+ if (text === "") return void 0;
1908
+ const inner = innerSpan(doc, el);
1909
+ const source = inner === void 0 ? void 0 : lf(doc.input.content.slice(inner.start, inner.end)).trim();
1910
+ const entity = source !== void 0 && DTD_ENTITY.test(source);
1911
+ if (entity && !entities) return void 0;
1912
+ let marked = entity;
1913
+ for (let i = 0; i < el.childNodes.length; i++) {
1914
+ const type = el.childNodes.item(i)?.nodeType;
1915
+ if (type === 1 || type === 7 || type === 8) marked = true;
1916
+ }
1917
+ if (!marked) return { text };
1918
+ if (!allowMarkup || source === void 0) return void 0;
1919
+ return markupText(source) === text ? { text, markup: source } : void 0;
1920
+ }
1921
+ function categoryValue(doc, el, name, allowMarkup = true) {
1922
+ const cat = TBX_CATEGORIES[name];
1923
+ if (categoryOf(doc, el) !== cat || !onlyAttributes(el, categoryAttributes(doc, cat))) return void 0;
1924
+ return valueOf(doc, el, allowMarkup);
1925
+ }
1926
+ function plainValue(doc, el, local, allowMarkup = true) {
1927
+ if (!isStructural(doc, el, local) || !onlyAttributes(el, [])) return void 0;
1928
+ return valueOf(doc, el, allowMarkup);
1929
+ }
1930
+ function itemOf(doc, el) {
1931
+ const { content } = doc.input;
1932
+ const span = spanOfElement(doc.xml, el);
1933
+ if (span === void 0) return `<${el.nodeName}/>`;
1934
+ const indent = indentAt(content, span.start);
1935
+ const lines = lf(content.slice(span.start, span.end)).split("\n");
1936
+ const text = lines.map((line, i) => i > 0 && line.startsWith(indent) ? line.slice(indent.length) : line).join("\n");
1937
+ const declarations = namespacesNeeded(doc, el).map(([prefix, uri]) => ` ${prefix === "" ? "xmlns" : `xmlns:${prefix}`}="${uri.replaceAll('"', "&quot;")}"`).join("");
1938
+ const nameEnd = 1 + el.nodeName.length;
1939
+ return `${text.slice(0, nameEnd)}${declarations}${text.slice(nameEnd)}`;
1940
+ }
1941
+ function namespacesNeeded(doc, el) {
1942
+ const used = /* @__PURE__ */ new Set();
1943
+ const declared = /* @__PURE__ */ new Set();
1944
+ const walk = (node) => {
1945
+ if (node.prefix !== null && node.prefix !== "") used.add(node.prefix);
1946
+ for (let i = 0; i < node.attributes.length; i++) {
1947
+ const name = node.attributes.item(i)?.name ?? "";
1948
+ if (name === "xmlns") declared.add("");
1949
+ else if (name.startsWith("xmlns:")) declared.add(name.slice("xmlns:".length));
1950
+ else if (name.includes(":")) used.add(name.slice(0, name.indexOf(":")));
1951
+ }
1952
+ for (const child of childrenOf(node)) walk(child);
1953
+ };
1954
+ walk(el);
1955
+ if ((el.prefix ?? "") === "" && (el.namespaceURI ?? "") !== doc.ns && el.namespaceURI !== TBX_V3_NAMESPACE) {
1956
+ used.add("");
1957
+ }
1958
+ const out = [];
1959
+ for (const prefix of used) {
1960
+ if (prefix === "xml" || declared.has(prefix)) continue;
1961
+ const uri = el.lookupNamespaceURI(prefix === "" ? null : prefix);
1962
+ if (uri !== null && uri !== "" && uri !== TBX_V3_NAMESPACE) out.push([prefix, uri]);
1963
+ }
1964
+ return out;
1965
+ }
1966
+ function push(aux, field, item2) {
1967
+ const list = aux[field] ?? [];
1968
+ list.push(item2);
1969
+ Object.assign(aux, { [field]: list });
1970
+ }
1971
+ function definitionGroup(doc, el) {
1972
+ if (!isStructural(doc, el, "descripGrp") || !onlyAttributes(el, [])) return void 0;
1973
+ const [first, ...rest] = childrenOf(el);
1974
+ if (first === void 0 || rest.length === 0) return void 0;
1975
+ const definition = categoryValue(doc, first, "definition");
1976
+ if (definition === void 0) return void 0;
1977
+ const sources2 = [];
1978
+ const notes = [];
1979
+ for (const child of rest) {
1980
+ const source = notes.length === 0 ? categoryValue(doc, child, "source") : void 0;
1981
+ const note = source === void 0 ? plainValue(doc, child, "note") : void 0;
1982
+ if (source !== void 0) sources2.push(source);
1983
+ else if (note !== void 0) notes.push(note);
1984
+ else return void 0;
1985
+ }
1986
+ return { definition, sources: sources2, notes };
1987
+ }
1988
+ function linkOf2(doc, el, name) {
1989
+ const cat = TBX_CATEGORIES[name];
1990
+ if (categoryOf(doc, el) !== cat || !onlyAttributes(el, categoryAttributes(doc, cat))) return void 0;
1991
+ const target = el.getAttribute("target");
1992
+ if (target === null || target === "" || target !== target.trim()) return void 0;
1993
+ if (lf(el.textContent ?? "").trim() === "") return { link: { target } };
1994
+ const value = valueOf(doc, el);
1995
+ if (value === void 0) return void 0;
1996
+ return { link: { target, text: value.text }, value };
1997
+ }
1998
+ function transactionOf2(doc, el) {
1999
+ if (!isStructural(doc, el, "transacGrp") || !onlyAttributes(el, [])) return void 0;
2000
+ const children = childrenOf(el);
2001
+ const [first] = children;
2002
+ const type = first === void 0 ? void 0 : categoryValue(doc, first, "transactionType", false);
2003
+ if (type === void 0) return void 0;
2004
+ const transaction = { type: type.text };
2005
+ let i = 1;
2006
+ const next = children[i];
2007
+ const responsibility = next === void 0 ? void 0 : categoryValue(doc, next, "responsibility", false);
2008
+ if (responsibility !== void 0) {
2009
+ transaction.responsibility = responsibility.text;
2010
+ i += 1;
2011
+ }
2012
+ const last = children[i];
2013
+ const date = last === void 0 ? void 0 : plainValue(doc, last, "date", false);
2014
+ if (date !== void 0) {
2015
+ transaction.date = date.text;
2016
+ i += 1;
2017
+ }
2018
+ return i === children.length ? transaction : void 0;
2019
+ }
2020
+ function readingGroup(doc, el) {
2021
+ if (!isStructural(doc, el, "adminGrp") || !onlyAttributes(el, [])) return void 0;
2022
+ const children = childrenOf(el);
2023
+ const [first, second] = children;
2024
+ if (children.length !== 2 || first === void 0 || second === void 0) return void 0;
2025
+ const reading = categoryValue(doc, first, "reading", false);
2026
+ const note = categoryValue(doc, second, "readingNote");
2027
+ return reading === void 0 || note === void 0 ? void 0 : { reading, note };
2028
+ }
2029
+ function statusOf(text) {
2030
+ for (const [status, value] of Object.entries(TBX_STATUS_VALUES)) if (value === text) return status;
2031
+ return text in TBX_STATUS_VALUES || text === TBX_NO_STATUS ? void 0 : text;
2032
+ }
2033
+ function readLevel(doc, children, level, read8) {
2034
+ let { aux } = read8;
2035
+ const items = [];
2036
+ const seen = [];
2037
+ const keep = (value) => {
2038
+ seen.push(value);
2039
+ if (value.markup !== void 0) read8.markup.push(value.markup);
2040
+ return value.text;
2041
+ };
2042
+ const definitionEl = children.find(
2043
+ (child) => categoryValue(doc, child, "definition") !== void 0 || definitionGroup(doc, child) !== void 0
2044
+ );
2045
+ const mapped = (child) => {
2046
+ const cat = categoryOf(doc, child);
2047
+ const is = (name) => cat === TBX_CATEGORIES[name];
2048
+ if (child === definitionEl) {
2049
+ const group = definitionGroup(doc, child);
2050
+ const plain = categoryValue(doc, child, "definition");
2051
+ const definition = group?.definition ?? plain;
2052
+ if (definition === void 0) return false;
2053
+ aux.definition = keep(definition);
2054
+ for (const source of group?.sources ?? []) push(aux, "sources", keep(source));
2055
+ for (const note of group?.notes ?? []) push(aux, "notes", keep(note));
2056
+ return true;
2057
+ }
2058
+ if (definitionEl !== void 0 && (is("source") || isStructural(doc, child, "note"))) return false;
2059
+ if (isStructural(doc, child, "note")) {
2060
+ const note = plainValue(doc, child, "note");
2061
+ if (note === void 0) return false;
2062
+ push(aux, "notes", keep(note));
2063
+ return true;
2064
+ }
2065
+ if (isStructural(doc, child, "transacGrp")) {
2066
+ const transaction = transactionOf2(doc, child);
2067
+ if (transaction === void 0) return false;
2068
+ for (const text of [transaction.type, transaction.responsibility, transaction.date]) if (text !== void 0) keep({ text });
2069
+ push(aux, "transactions", transaction);
2070
+ return true;
2071
+ }
2072
+ if (level === "term" && isStructural(doc, child, "adminGrp")) {
2073
+ const group = readingGroup(doc, child);
2074
+ if (group === void 0 || aux.reading !== void 0) return false;
2075
+ aux.reading = keep(group.reading);
2076
+ aux["reading-note"] = keep(group.note);
2077
+ return true;
2078
+ }
2079
+ for (const [field, name] of TBX_TEXT_FIELDS) {
2080
+ if (!is(name)) continue;
2081
+ const value = categoryValue(doc, child, name);
2082
+ if (value === void 0) return false;
2083
+ if (field === "subject-field") {
2084
+ if (aux["subject-field"] !== void 0) return false;
2085
+ aux["subject-field"] = keep(value);
2086
+ } else {
2087
+ push(aux, field, keep(value));
2088
+ }
2089
+ return true;
2090
+ }
2091
+ for (const [field, name] of TBX_LINK_FIELDS) {
2092
+ if (!is(name)) continue;
2093
+ const link = linkOf2(doc, child, name);
2094
+ if (link === void 0) return false;
2095
+ if (link.value !== void 0) keep(link.value);
2096
+ push(aux, field, link.link);
2097
+ return true;
2098
+ }
2099
+ if (level !== "term") return false;
2100
+ if (is("reading")) {
2101
+ const reading = categoryValue(doc, child, "reading", false);
2102
+ if (reading === void 0 || aux.reading !== void 0) return false;
2103
+ aux.reading = keep(reading);
2104
+ return true;
2105
+ }
2106
+ if (is("transferComment")) {
2107
+ const comment = categoryValue(doc, child, "transferComment");
2108
+ if (comment === void 0 || aux["transfer-comments"] !== void 0) return false;
2109
+ aux["transfer-comments"] = [keep(comment)];
2110
+ return true;
2111
+ }
2112
+ for (const [field, name] of TBX_TERM_NOTES) {
2113
+ if (!is(name)) continue;
2114
+ const value = categoryValue(doc, child, name, field !== "administrative-status");
2115
+ if (value === void 0 || aux[field] !== void 0) return false;
2116
+ if (field === "administrative-status") {
2117
+ const status = statusOf(value.text);
2118
+ if (status === void 0) return false;
2119
+ keep(value);
2120
+ aux[field] = status;
2121
+ } else {
2122
+ aux[field] = keep(value);
2123
+ }
2124
+ return true;
2125
+ }
2126
+ return false;
2127
+ };
2128
+ for (const child of children) {
2129
+ const saved = read8.fits === void 0 ? void 0 : { aux: structuredClone(aux), markup: read8.markup.length };
2130
+ seen.length = 0;
2131
+ if (mapped(child) && (read8.fits === void 0 || seen.every(read8.fits))) continue;
2132
+ if (saved !== void 0) {
2133
+ aux = read8.aux = saved.aux;
2134
+ read8.markup.length = saved.markup;
2135
+ }
2136
+ items.push(itemOf(doc, child));
2137
+ }
2138
+ const ordered = level === "term" ? [...items.filter(isTermNoteItem), ...items.filter((i) => !isTermNoteItem(i))] : items;
2139
+ if (ordered.length > 0) aux["tbx-elements"] = ordered;
2140
+ }
2141
+ function readDesignation(doc, el, fits) {
2142
+ let children = childrenOf(el);
2143
+ let group;
2144
+ if (isStructural(doc, el, "ntig")) {
2145
+ [group] = structuralChildren(doc, el, "termGrp");
2146
+ if (group === void 0) return void 0;
2147
+ children = [...childrenOf(group), ...children.filter((child) => child !== group)];
2148
+ }
2149
+ const termEl = children.find((child) => isStructural(doc, child, "term"));
2150
+ const term = termEl === void 0 ? void 0 : valueOf(doc, termEl, true, true);
2151
+ const text = termEl === void 0 ? void 0 : textOf(lf(termEl.textContent ?? ""));
2152
+ if (termEl === void 0 || text === void 0) return void 0;
2153
+ const read8 = { aux: { term: text }, markup: term?.markup === void 0 ? [] : [term.markup], ...fits === void 0 ? {} : { fits } };
2154
+ readLevel(
2155
+ doc,
2156
+ children.filter((child) => child !== termEl),
2157
+ "term",
2158
+ read8
2159
+ );
2160
+ const { "administrative-status": status, ...designation } = read8.aux;
2161
+ const shape = {
2162
+ term: text,
2163
+ attributes: attributesOf(el),
2164
+ termAttributes: attributesOf(termEl),
2165
+ ...group === void 0 ? {} : { group: attributesOf(group) }
2166
+ };
2167
+ return {
2168
+ designation,
2169
+ term: term ?? { text },
2170
+ markup: read8.markup,
2171
+ status: status ?? TBX_NO_STATUS,
2172
+ line: lineOfElement(termEl),
2173
+ shape
2174
+ };
2175
+ }
2176
+ function labelsOf2(read8) {
2177
+ const preferred = read8.findIndex((d) => d.status === "preferred");
2178
+ const labelAt = preferred === -1 ? 0 : preferred;
2179
+ const alts = [];
2180
+ const hiddens = [];
2181
+ const order = [];
2182
+ const altOrder = [];
2183
+ const hiddenOrder = [];
2184
+ const designations = read8.map((d, i) => {
2185
+ const { status } = d;
2186
+ let kind;
2187
+ if (i === labelAt) kind = "label";
2188
+ else if (status === "deprecated" || status === "superseded") kind = "deprecated";
2189
+ else kind = "admitted";
2190
+ if (kind === "admitted") {
2191
+ alts.push(d.designation.term);
2192
+ altOrder.push(i);
2193
+ } else if (kind === "deprecated") {
2194
+ hiddens.push(d.designation.term);
2195
+ hiddenOrder.push(i);
2196
+ }
2197
+ const implied = kind === "label" ? "preferred" : kind;
2198
+ return status === implied ? d.designation : { ...d.designation, "administrative-status": status };
2199
+ });
2200
+ order.push(labelAt, ...altOrder, ...hiddenOrder);
2201
+ const reordered = order.some((at, i) => at !== i);
2202
+ const detailed = designations.some((d) => Object.keys(d).length > 1);
2203
+ return {
2204
+ label: read8[labelAt]?.designation.term ?? "",
2205
+ alts,
2206
+ hiddens,
2207
+ designations: reordered || detailed ? designations : void 0
2208
+ };
2209
+ }
2210
+ function readParts(doc, entry, fits) {
2211
+ const languageTag = doc.document.version === 3 ? "langSec" : "langSet";
2212
+ const designationTags = doc.document.version === 3 ? ["termSec"] : ["tig", "ntig"];
2213
+ const children = childrenOf(entry);
2214
+ const concept = { aux: { term: "" }, markup: [], ...fits === void 0 ? {} : { fits: fits.concept } };
2215
+ readLevel(
2216
+ doc,
2217
+ children.filter((child) => !isStructural(doc, child, languageTag)),
2218
+ "concept",
2219
+ concept
2220
+ );
2221
+ const languages = children.filter((child) => isStructural(doc, child, languageTag)).map((el, i) => {
2222
+ const at = fits?.languages[i];
2223
+ const designations = [];
2224
+ const others = [];
2225
+ for (const child of childrenOf(el)) {
2226
+ const isDesignation = designationTags.some((tag) => isStructural(doc, child, tag));
2227
+ const designation = isDesignation ? readDesignation(doc, child, at) : void 0;
2228
+ if (designation !== void 0) designations.push(designation);
2229
+ else others.push(child);
2230
+ }
2231
+ const language = { aux: { term: "" }, markup: [], ...at === void 0 ? {} : { fits: at } };
2232
+ if (designations.length > 0) readLevel(doc, others, "language", language);
2233
+ return { el, designations, language };
2234
+ });
2235
+ return { concept, languages };
2236
+ }
2237
+ function markupOf(concept, language) {
2238
+ return [.../* @__PURE__ */ new Set([...concept.markup, ...language.language.markup, ...language.designations.flatMap((d) => d.markup)])];
2239
+ }
2240
+ function fitsOf(parts) {
2241
+ const pools = parts.languages.map((language) => markupOf(parts.concept, language));
2242
+ if (pools.every((pool) => pool.length === 0)) return void 0;
2243
+ const fits = (pool, terms) => (value) => pool.find((item2) => markupText(item2) === value.text) === value.markup && terms.every((term) => term.text !== value.text || term.markup === value.markup);
2244
+ return {
2245
+ concept: fits(
2246
+ [...new Set(pools.flat())],
2247
+ parts.languages.flatMap((language) => language.designations.map((d) => d.term))
2248
+ ),
2249
+ languages: parts.languages.map((language, i) => fits(pools[i] ?? [], language.designations.map((d) => d.term)))
2250
+ };
2251
+ }
2252
+ function readEntry2(doc, entry, result) {
2253
+ const { input } = doc;
2254
+ const first = readParts(doc, entry);
2255
+ const fits = fitsOf(first);
2256
+ const parts = fits === void 0 ? first : readParts(doc, entry, fits);
2257
+ const { concept } = parts;
2258
+ const { term: _none, ...conceptAux } = concept.aux;
2259
+ const span = spanOfElement(doc.xml, entry);
2260
+ const rootLanguage = doc.xml.root.getAttribute("xml:lang");
2261
+ const read8 = [];
2262
+ let entryId = textOf(entry.getAttribute("id"));
2263
+ const shape = { attributes: attributesOf(entry, ["id"]), languages: [] };
2264
+ for (const part of parts.languages) {
2265
+ const { el: langEl, designations } = part;
2266
+ if (designations.length === 0) {
2267
+ result.notices.push(skipped(input, lineOfElement(langEl), "TBX"));
2268
+ (shape.unread ??= []).push(itemOf(doc, langEl));
2269
+ continue;
2270
+ }
2271
+ const { term: _term, ...languageAux } = part.language.aux;
2272
+ const labels = labelsOf2(designations);
2273
+ const markup = markupOf(concept, part);
2274
+ const raw = {
2275
+ ...languageAux,
2276
+ label: labels.label,
2277
+ "alt-labels": labels.alts,
2278
+ "hidden-labels": labels.hiddens,
2279
+ ...Object.keys(conceptAux).length === 0 ? {} : { "concept-entry": structuredClone(conceptAux) },
2280
+ ...labels.designations === void 0 ? {} : { designations: labels.designations },
2281
+ ...markup.length === 0 ? {} : { "tbx-markup": markup }
2282
+ };
2283
+ const record = recordOf(raw);
2284
+ if (record === void 0) continue;
2285
+ entryId ??= slugOf(record.label);
2286
+ const term = termOf(input, {
2287
+ record,
2288
+ language: langEl.getAttribute("xml:lang") ?? rootLanguage,
2289
+ constructId: entryId,
2290
+ construct: "tbx-entry",
2291
+ line: lineOfElement(langEl),
2292
+ lines: { label: designations[0]?.line },
2293
+ ...span === void 0 ? {} : { span }
2294
+ });
2295
+ if (span !== void 0) rememberTbxSource(term, { document: doc.document, span, shape });
2296
+ shape.languages.push({
2297
+ language: term.language,
2298
+ attributes: attributesOf(langEl, ["xml:lang"]),
2299
+ designations: designations.map((d) => d.shape)
2300
+ });
2301
+ read8.push(term);
2302
+ }
2303
+ result.terms.push(...read8);
2304
+ }
2305
+ function readTbx(input) {
2306
+ const doc = parseTbx(input);
2307
+ const result = nothing();
2308
+ const body = doc.document.body;
2309
+ if (body === void 0) return result;
2310
+ const entryTag = doc.document.version === 3 ? "conceptEntry" : "termEntry";
2311
+ for (const text of structuralChildren(doc, doc.xml.root, "text")) {
2312
+ for (const bodyEl of structuralChildren(doc, text, "body")) {
2313
+ for (const entry of structuralChildren(doc, bodyEl, entryTag)) readEntry2(doc, entry, result);
2314
+ }
2315
+ }
2316
+ return result;
2317
+ }
2318
+ function sameTerm(a, b) {
2319
+ return a.id === b.id && a.language === b.language && sameFields(a.record, b.record, TERM_FIELDS);
2320
+ }
2321
+ function applyTbx(input, terms, conflicts) {
2322
+ const spliced = spliceEntries(input, terms, false);
2323
+ conflicts?.push(...spliced.conflicts);
2324
+ return spliced.content;
2325
+ }
2326
+ function exportTbxSource(document, file, terms) {
2327
+ const input = { content: document.content, file, format: "tbx", metadata: {}, lineFor: () => void 0 };
2328
+ return spliceEntries(input, terms, true);
2329
+ }
2330
+ function removeSpan(content, start, end) {
2331
+ const lineStart = content.lastIndexOf("\n", start - 1) + 1;
2332
+ const after = /^[ \t]*(\r?\n|$)/.exec(content.slice(end))?.[0];
2333
+ if (!/^[ \t]*$/.test(content.slice(lineStart, start)) || after === void 0) {
2334
+ return content.slice(0, start) + content.slice(end);
2335
+ }
2336
+ return content.slice(0, lineStart) + content.slice(end + after.length);
2337
+ }
2338
+ function spliceEntries(input, terms, exporting) {
2339
+ const doc = parseTbx(input);
2340
+ const { content } = input;
2341
+ const groups = /* @__PURE__ */ new Map();
2342
+ for (const term of readTbx(input).terms) {
2343
+ const span = term.location.span;
2344
+ if (span === void 0) continue;
2345
+ const group = groups.get(span.start) ?? { end: span.end, current: [], next: [] };
2346
+ group.current.push(term);
2347
+ groups.set(span.start, group);
2348
+ }
2349
+ for (const term of terms) {
2350
+ const span = term.location.span;
2351
+ if (span === void 0) {
2352
+ throw new TermError(
2353
+ `${input.file}: term "${term.id}" cannot be written in place, because its entry has no position in the file.`
2354
+ );
2355
+ }
2356
+ const group = groups.get(span.start);
2357
+ if (group?.end !== span.end) {
2358
+ throw new TermError(
2359
+ `${input.file}: term "${term.id}" does not match an entry in the file. Read the file again before writing it.`
2360
+ );
2361
+ }
2362
+ group.next.push(term);
2363
+ }
2364
+ const eol = lineEnding(content);
2365
+ let next = content;
2366
+ const conflicts = [];
2367
+ for (const [start, group] of [...groups.entries()].sort((a, b) => b[0] - a[0])) {
2368
+ if (group.next.length === 0) {
2369
+ if (exporting) next = removeSpan(next, start, group.end);
2370
+ continue;
2371
+ }
2372
+ const written = exporting || group.next.length >= group.current.length ? group.next : merge(group.current, group.next);
2373
+ const unchanged = written.length === group.current.length && written.every((t, i) => {
2374
+ const was = group.current[i];
2375
+ return was !== void 0 && sameTerm(was, t);
2376
+ });
2377
+ if (unchanged) continue;
2378
+ const shape = group.current[0] === void 0 ? void 0 : tbxSourceOf(group.current[0])?.shape;
2379
+ const edited = withEditedConcept(written, group.current);
2380
+ conflicts.push(...edited.conflicts);
2381
+ const lines = tbxEntryLines(edited.terms, doc.document, shape);
2382
+ const text = reindent(lines.join("\n"), indentAt(content, start), eol);
2383
+ next = next.slice(0, start) + text + next.slice(group.end);
2384
+ }
2385
+ return { content: next, conflicts };
2386
+ }
2387
+ function withEditedConcept(written, current) {
2388
+ const [head, ...rest] = written;
2389
+ if (head === void 0) return { terms: written, conflicts: [] };
2390
+ const read8 = current[0]?.record["concept-entry"] ?? {};
2391
+ const concepts = written.map((t) => t.record["concept-entry"] ?? {});
2392
+ const edits = (concept2) => TERM_AUX_FIELDS.filter((field) => !isDeepStrictEqual2(concept2[field], read8[field]));
2393
+ const { conflicts } = mergeFirst(
2394
+ head.id,
2395
+ concepts.map((c) => Object.fromEntries(edits(c).map((field) => [field, { value: c[field] }]))),
2396
+ "concept-entry."
2397
+ );
2398
+ const concept = {};
2399
+ for (const field of TERM_AUX_FIELDS) {
2400
+ copyField(concept, concepts.find((c) => edits(c).includes(field)) ?? read8, field);
2401
+ }
2402
+ const { "concept-entry": _old, ...record } = head.record;
2403
+ const joined = Object.keys(concept).length === 0 ? record : { ...record, "concept-entry": concept };
2404
+ return { terms: [{ ...head, record: joined }, ...rest], conflicts };
2405
+ }
2406
+ function copyField(to, from, field) {
2407
+ const value = from[field];
2408
+ if (value !== void 0) to[field] = value;
2409
+ }
2410
+ function merge(current, given) {
2411
+ const left = [...given];
2412
+ return current.map((term) => {
2413
+ const at = left.findIndex((t) => languageKey(t) === languageKey(term));
2414
+ return at === -1 ? term : left.splice(at, 1)[0] ?? term;
2415
+ });
2416
+ }
2417
+ var tbxEntryReader = {
2418
+ construct: "tbx-entry",
2419
+ label: LABEL4,
2420
+ formats: ["tbx"],
2421
+ read: readTbx,
2422
+ apply: applyTbx
2423
+ };
2424
+
1284
2425
  // src/term/core/readers/structured.ts
1285
2426
  var STRUCTURED_READERS = [
1286
2427
  pageReader,
@@ -1289,7 +2430,8 @@ var STRUCTURED_READERS = [
1289
2430
  ditaGlossgroupReader,
1290
2431
  docbookGlossaryReader,
1291
2432
  htmlDlReader,
1292
- htmlDfnReader
2433
+ htmlDfnReader,
2434
+ tbxEntryReader
1293
2435
  ];
1294
2436
 
1295
2437
  // src/term/core/readers/body.ts
@@ -1370,7 +2512,7 @@ function skippedNotice(input, line, label, missing) {
1370
2512
  }
1371
2513
 
1372
2514
  // src/term/core/readers/asciidoc-glossary.ts
1373
- var LABEL4 = "[glossary] list";
2515
+ var LABEL5 = "[glossary] list";
1374
2516
  var ATTRIBUTE = /^\[glossary\][ \t]*$/;
1375
2517
  var ITEM = /^[ \t]*(.*?[^:\s])::(?:[ \t]+(.*))?$/;
1376
2518
  var BLOCK_TITLE = /^\.[^.\s]/;
@@ -1419,13 +2561,13 @@ function readList(input, lines, at, terms, notices) {
1419
2561
  })
1420
2562
  );
1421
2563
  } else if (firstLabel !== void 0) {
1422
- notices.push(skippedNotice(input, firstLabel.line, LABEL4, "definition"));
2564
+ notices.push(skippedNotice(input, firstLabel.line, LABEL5, "definition"));
1423
2565
  }
1424
2566
  open = void 0;
1425
2567
  }
1426
2568
  const [firstPending] = pending;
1427
2569
  if (firstPending !== void 0) {
1428
- notices.push(skippedNotice(input, firstPending.line, LABEL4, "definition"));
2570
+ notices.push(skippedNotice(input, firstPending.line, LABEL5, "definition"));
1429
2571
  pending = [];
1430
2572
  }
1431
2573
  };
@@ -1477,14 +2619,14 @@ function itemTerm(line) {
1477
2619
  }
1478
2620
  var asciidocGlossaryReader = {
1479
2621
  construct: "asciidoc-glossary",
1480
- label: LABEL4,
2622
+ label: LABEL5,
1481
2623
  formats: ["asciidoc"],
1482
2624
  read: read4,
1483
2625
  apply: (input, terms) => applyEntries(input, read4, terms, { holds: LIST_HOLDS, id: false, serialize: (term) => asciidocEntry(term.record) })
1484
2626
  };
1485
2627
 
1486
2628
  // src/term/core/readers/markdown-deflist.ts
1487
- var LABEL5 = "definition list";
2629
+ var LABEL6 = "definition list";
1488
2630
  var DEFINITION = /^:(?:[ \t]+(.*))?$/;
1489
2631
  var INDENTED = /^(?: {4}|\t)/;
1490
2632
  var HEADING = /^#{1,6}(?:[ \t]|$)/;
@@ -1521,7 +2663,7 @@ function read5(input) {
1521
2663
  }
1522
2664
  if (labels.length === 0 || labels.some((l) => HEADING.test(l.text))) {
1523
2665
  const orphan = lines[j];
1524
- if (orphan !== void 0) notices.push(skippedNotice(input, orphan.line, LABEL5, "term"));
2666
+ if (orphan !== void 0) notices.push(skippedNotice(input, orphan.line, LABEL6, "term"));
1525
2667
  i = readDefinitions(lines, j, []);
1526
2668
  continue;
1527
2669
  }
@@ -1532,7 +2674,7 @@ function read5(input) {
1532
2674
  if (firstLabel === void 0 || kept === void 0) continue;
1533
2675
  const text = definitionText(kept.paragraphs);
1534
2676
  if (text === void 0) {
1535
- notices.push(skippedNotice(input, firstLabel.line, LABEL5, "definition"));
2677
+ notices.push(skippedNotice(input, firstLabel.line, LABEL6, "definition"));
1536
2678
  continue;
1537
2679
  }
1538
2680
  for (const extra of definitions.slice(1)) {
@@ -1593,14 +2735,14 @@ function readDefinitions(lines, at, out) {
1593
2735
  }
1594
2736
  var markdownDeflistReader = {
1595
2737
  construct: "markdown-deflist",
1596
- label: LABEL5,
2738
+ label: LABEL6,
1597
2739
  formats: ["markdown", "mdx"],
1598
2740
  read: read5,
1599
2741
  apply: (input, terms) => applyEntries(input, read5, terms, { holds: LIST_HOLDS, id: false, serialize: (term) => markdownEntry(term.record) })
1600
2742
  };
1601
2743
 
1602
2744
  // src/term/core/readers/rst-glossary.ts
1603
- var LABEL6 = ".. glossary::";
2745
+ var LABEL7 = ".. glossary::";
1604
2746
  var DIRECTIVE = /^[ \t]*\.\.[ \t]+glossary::[ \t]*$/;
1605
2747
  var CODE_DIRECTIVE = /^[ \t]*\.\.[ \t]+(?:code-block|code|sourcecode)::/;
1606
2748
  var EXPLICIT_MARKUP = /^[ \t]*\.\.(?:[ \t]|$)/;
@@ -1669,7 +2811,7 @@ function readGlossary(input, lines, at, terms, notices) {
1669
2811
  })
1670
2812
  );
1671
2813
  } else {
1672
- notices.push(skippedNotice(input, first.line, LABEL6, "definition"));
2814
+ notices.push(skippedNotice(input, first.line, LABEL7, "definition"));
1673
2815
  }
1674
2816
  }
1675
2817
  labels = [];
@@ -1704,7 +2846,7 @@ function readGlossary(input, lines, at, terms, notices) {
1704
2846
  } else if (labels.length > 0) {
1705
2847
  definition = { line: line.line, paragraphs: [[line.text]], last: line, gap: false };
1706
2848
  } else if (!orphan) {
1707
- notices.push(skippedNotice(input, line.line, LABEL6, "term"));
2849
+ notices.push(skippedNotice(input, line.line, LABEL7, "term"));
1708
2850
  orphan = true;
1709
2851
  }
1710
2852
  }
@@ -1718,7 +2860,7 @@ function termText(line) {
1718
2860
  }
1719
2861
  var rstGlossaryReader = {
1720
2862
  construct: "rst-glossary",
1721
- label: LABEL6,
2863
+ label: LABEL7,
1722
2864
  formats: ["rst"],
1723
2865
  read: read6,
1724
2866
  apply: (input, terms) => applyEntries(input, read6, terms, { holds: LIST_HOLDS, id: false, serialize: (term) => rstEntry(term.record) })
@@ -1743,10 +2885,18 @@ function readerForConstruct(construct, readers = TERM_READERS) {
1743
2885
  // src/term/core/load-set.ts
1744
2886
  var MANIFEST_FORMAT = "manifest";
1745
2887
  var MANIFEST_EXTENSIONS = /* @__PURE__ */ new Set([".yaml", ".yml", ".json"]);
2888
+ var TBX_FORMAT = "tbx";
2889
+ var TBX_EXTENSION = ".tbx";
2890
+ function tbxInput(content, file, path) {
2891
+ return { content, file, ...path === void 0 ? {} : { path }, format: TBX_FORMAT, metadata: {}, lineFor: () => void 0 };
2892
+ }
2893
+ function defaultExtensions() {
2894
+ return [...supportedExtensions(), TBX_EXTENSION];
2895
+ }
1746
2896
  function manifestInput(content, file, path) {
1747
2897
  return { content, file, path, format: MANIFEST_FORMAT, metadata: {}, lineFor: () => void 0 };
1748
2898
  }
1749
- function labelsOf2(value) {
2899
+ function labelsOf3(value) {
1750
2900
  if (typeof value === "string") return value.trim() === "" ? [] : [value];
1751
2901
  if (Array.isArray(value)) {
1752
2902
  return value.filter((item2) => typeof item2 === "string" && item2.trim() !== "");
@@ -1756,7 +2906,7 @@ function labelsOf2(value) {
1756
2906
  function referencesOf(input) {
1757
2907
  const references = [];
1758
2908
  const add = (value, pointer) => {
1759
- for (const label of labelsOf2(value)) {
2909
+ for (const label of labelsOf3(value)) {
1760
2910
  const line = input.lineFor(pointer);
1761
2911
  references.push({ file: input.file, label, ...line === void 0 ? {} : { line } });
1762
2912
  }
@@ -1791,6 +2941,13 @@ function extractInput(content, file, path, format) {
1791
2941
  lineFor: extracted.lineFor
1792
2942
  };
1793
2943
  }
2944
+ async function readInput(path, file) {
2945
+ try {
2946
+ return await readFile(path, "utf8");
2947
+ } catch (error) {
2948
+ throw new TermError(`${file}: could not be read: ${errorMessage(error)}`);
2949
+ }
2950
+ }
1794
2951
  async function loadTermSet(opts) {
1795
2952
  const { run } = opts;
1796
2953
  const readers = opts.readers ?? TERM_READERS;
@@ -1812,7 +2969,7 @@ async function loadTermSet(opts) {
1812
2969
  inputs,
1813
2970
  cwd: run.base,
1814
2971
  exclude,
1815
- ...opts.exts === void 0 ? {} : { exts: opts.exts },
2972
+ exts: opts.exts ?? defaultExtensions(),
1816
2973
  allowEmpty,
1817
2974
  ...gitignoreOptions({
1818
2975
  ...opts.noGitignore === true ? { flag: false } : {},
@@ -1834,32 +2991,24 @@ async function loadTermSet(opts) {
1834
2991
  for (const file of files) {
1835
2992
  const path = resolve2(run.base, file);
1836
2993
  if (namedFiles.has(file) && MANIFEST_EXTENSIONS.has(extname(file).toLowerCase())) {
1837
- let content2;
1838
- try {
1839
- content2 = await readFile(path, "utf8");
1840
- } catch (error) {
1841
- throw new TermError(`${file}: could not be read: ${errorMessage(error)}`);
1842
- }
1843
- read7(manifestInput(content2, file, path), readers, set);
2994
+ read7(manifestInput(await readInput(path, file), file, path), readers, set);
2995
+ continue;
2996
+ }
2997
+ if (extname(file).toLowerCase() === TBX_EXTENSION) {
2998
+ read7(tbxInput(await readInput(path, file), file, path), readers, set);
1844
2999
  continue;
1845
3000
  }
1846
3001
  const extractor = extractorForExtension(extname(file));
1847
3002
  if (extractor === void 0) {
1848
3003
  throw new TermError(`${file}: no reader for its extension. Pass --as <format> through stdin to read it.`);
1849
3004
  }
1850
- let content;
1851
- try {
1852
- content = await readFile(path, "utf8");
1853
- } catch (error) {
1854
- throw new TermError(`${file}: could not be read: ${errorMessage(error)}`);
1855
- }
1856
- const input = extractInput(content, file, path, extractor.name);
3005
+ const input = extractInput(await readInput(path, file), file, path, extractor.name);
1857
3006
  set.references.push(...referencesOf(input));
1858
3007
  read7(input, readers, set);
1859
3008
  }
1860
3009
  }
1861
3010
  if (usingStdin && opts.as !== void 0) {
1862
- const input = extractInput(opts.stdin ?? "", STDIN_LABEL, void 0, opts.as);
3011
+ const input = opts.as.toLowerCase() === TBX_FORMAT ? tbxInput(opts.stdin ?? "", STDIN_LABEL) : extractInput(opts.stdin ?? "", STDIN_LABEL, void 0, opts.as);
1863
3012
  set.references.push(...referencesOf(input));
1864
3013
  read7(input, readers, set);
1865
3014
  }
@@ -1871,7 +3020,8 @@ async function loadTermSet(opts) {
1871
3020
  const source = run.configSource ?? "manni.config.yaml";
1872
3021
  throw new TermError(`${source}: term.manifests "${written}" does not exist.`);
1873
3022
  }
1874
- read7(manifestInput(content, path, path), readers, set);
3023
+ const isTbx = extname(path).toLowerCase() === TBX_EXTENSION;
3024
+ read7(isTbx ? tbxInput(content, path, path) : manifestInput(content, path, path), readers, set);
1875
3025
  }
1876
3026
  if (set.terms.length === 0 && !allowEmpty) {
1877
3027
  throw new TermError(
@@ -1942,11 +3092,19 @@ function plural(n, one, many = `${one}s`) {
1942
3092
  export {
1943
3093
  TermError,
1944
3094
  TERM_FIELDS,
3095
+ TERM_AUX_FIELDS,
3096
+ TERM_DESIGNATION_FIELDS,
1945
3097
  TERM_WRITE_FORMATS,
1946
3098
  TERM_RULES,
1947
3099
  DEFAULT_TERM_BASELINE_PATH,
1948
3100
  DEFAULT_ABSTRACT_MAX_LENGTH,
1949
3101
  resolveTermRun,
3102
+ DEFAULT_LANGUAGE,
3103
+ languageOf,
3104
+ languageKey,
3105
+ isMultilingual,
3106
+ droppedFields,
3107
+ requireShape,
1950
3108
  xmlText,
1951
3109
  xmlAttribute,
1952
3110
  sharedLanguage,
@@ -1961,9 +3119,17 @@ export {
1961
3119
  htmlDlEntry,
1962
3120
  ditaEntry,
1963
3121
  docbookEntry,
3122
+ conceptGroups,
3123
+ mergeFirst,
3124
+ TBX_V3_NAMESPACE,
3125
+ tbxSourceOf,
3126
+ lf,
3127
+ tbxEntryLines,
3128
+ exportTbxSource,
1964
3129
  TERM_READERS,
1965
3130
  readerForConstruct,
1966
3131
  MANIFEST_FORMAT,
3132
+ tbxInput,
1967
3133
  extractInput,
1968
3134
  loadTerms,
1969
3135
  loadSet,
@@ -1972,4 +3138,4 @@ export {
1972
3138
  valeConfigFor,
1973
3139
  plural
1974
3140
  };
1975
- //# sourceMappingURL=chunk-WUFP4V7B.js.map
3141
+ //# sourceMappingURL=chunk-ABHG6I3G.js.map