@hawkeyexl/manni 4.3.1 → 4.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -1
- package/dist/batch-GFNLTGOH.js +36 -0
- package/dist/build-COYIQ25L.js +31 -0
- package/dist/calibrate-MDBLJKEE.js +31 -0
- package/dist/capture-LRML2PKV.js +32 -0
- package/dist/check-ASPIHA6B.js +40 -0
- package/dist/check-ASPIHA6B.js.map +1 -0
- package/dist/check-EDLBYL5N.js +27 -0
- package/dist/check-EDLBYL5N.js.map +1 -0
- package/dist/check-HYNGXYJV.js +18 -0
- package/dist/check-HYNGXYJV.js.map +1 -0
- package/dist/chunk-2B7ZNTPV.js +230 -0
- package/dist/chunk-2B7ZNTPV.js.map +1 -0
- package/dist/chunk-2H7UOFLK.js +11 -0
- package/dist/chunk-2H7UOFLK.js.map +1 -0
- package/dist/chunk-37LP5HMZ.js +1042 -0
- package/dist/chunk-37LP5HMZ.js.map +1 -0
- package/dist/chunk-3VK37OR2.js +2957 -0
- package/dist/chunk-3VK37OR2.js.map +1 -0
- package/dist/chunk-4IUC2MNL.js +2165 -0
- package/dist/chunk-4IUC2MNL.js.map +1 -0
- package/dist/{chunk-3R23C5DT.js → chunk-4TSWU2SU.js} +2 -14
- package/dist/chunk-4TSWU2SU.js.map +1 -0
- package/dist/chunk-57NEQRVO.js +10921 -0
- package/dist/chunk-57NEQRVO.js.map +1 -0
- package/dist/chunk-6JSSEWBG.js +6737 -0
- package/dist/chunk-6JSSEWBG.js.map +1 -0
- package/dist/chunk-6OYEI2VV.js +88 -0
- package/dist/chunk-6OYEI2VV.js.map +1 -0
- package/dist/chunk-77AINBYM.js +19 -0
- package/dist/chunk-77AINBYM.js.map +1 -0
- package/dist/chunk-7UKO3ASZ.js +54 -0
- package/dist/chunk-7UKO3ASZ.js.map +1 -0
- package/dist/chunk-A5ULMVHQ.js +164 -0
- package/dist/chunk-A5ULMVHQ.js.map +1 -0
- package/dist/chunk-C4SQM22E.js +299 -0
- package/dist/chunk-C4SQM22E.js.map +1 -0
- package/dist/chunk-CK7SKVHR.js +1042 -0
- package/dist/chunk-CK7SKVHR.js.map +1 -0
- package/dist/{chunk-G5CM2VGQ.js → chunk-DXNZS72W.js} +8 -94
- package/dist/chunk-DXNZS72W.js.map +1 -0
- package/dist/chunk-EPH54CAY.js +374 -0
- package/dist/chunk-EPH54CAY.js.map +1 -0
- package/dist/{chunk-KJR7OVDX.js → chunk-FBEQCK47.js} +56 -137
- package/dist/chunk-FBEQCK47.js.map +1 -0
- package/dist/{chunk-IOYXPBCL.js → chunk-G3T47CFV.js} +1 -7
- package/dist/{chunk-IOYXPBCL.js.map → chunk-G3T47CFV.js.map} +1 -1
- package/dist/chunk-GCQRPUSB.js +1287 -0
- package/dist/chunk-GCQRPUSB.js.map +1 -0
- package/dist/chunk-GLP5PSXB.js +72 -0
- package/dist/chunk-GLP5PSXB.js.map +1 -0
- package/dist/chunk-I2AH3CJJ.js +1192 -0
- package/dist/chunk-I2AH3CJJ.js.map +1 -0
- package/dist/chunk-IDV6HJCB.js +388 -0
- package/dist/chunk-IDV6HJCB.js.map +1 -0
- package/dist/chunk-IKEWBMCN.js +98 -0
- package/dist/chunk-IKEWBMCN.js.map +1 -0
- package/dist/chunk-JCDXE76J.js +52 -0
- package/dist/chunk-JCDXE76J.js.map +1 -0
- package/dist/chunk-JXLTXMJ7.js +455 -0
- package/dist/chunk-JXLTXMJ7.js.map +1 -0
- package/dist/chunk-LJ2RDH3F.js +49 -0
- package/dist/chunk-LJ2RDH3F.js.map +1 -0
- package/dist/chunk-M2JCK5F6.js +805 -0
- package/dist/chunk-M2JCK5F6.js.map +1 -0
- package/dist/chunk-M3W7J6MU.js +4398 -0
- package/dist/chunk-M3W7J6MU.js.map +1 -0
- package/dist/chunk-MMTSSTG7.js +23 -0
- package/dist/chunk-MMTSSTG7.js.map +1 -0
- package/dist/chunk-MNH7QO4Z.js +15 -0
- package/dist/chunk-MNH7QO4Z.js.map +1 -0
- package/dist/chunk-MWJLZMBL.js +934 -0
- package/dist/chunk-MWJLZMBL.js.map +1 -0
- package/dist/chunk-MYMBCTDE.js +387 -0
- package/dist/chunk-MYMBCTDE.js.map +1 -0
- package/dist/chunk-NCPWXHDO.js +683 -0
- package/dist/chunk-NCPWXHDO.js.map +1 -0
- package/dist/chunk-NLXTXE5Y.js +1661 -0
- package/dist/chunk-NLXTXE5Y.js.map +1 -0
- package/dist/{chunk-CFDUZRM2.js → chunk-NXV7WE2D.js} +32 -240
- package/dist/chunk-NXV7WE2D.js.map +1 -0
- package/dist/chunk-OWBRDNRZ.js +16 -0
- package/dist/chunk-OWBRDNRZ.js.map +1 -0
- package/dist/{chunk-KTSJ2ZHA.js → chunk-PAU352SV.js} +5 -3
- package/dist/{chunk-KTSJ2ZHA.js.map → chunk-PAU352SV.js.map} +1 -1
- package/dist/chunk-PCE7QHXJ.js +68 -0
- package/dist/chunk-PCE7QHXJ.js.map +1 -0
- package/dist/chunk-PIKOVN6W.js +1651 -0
- package/dist/chunk-PIKOVN6W.js.map +1 -0
- package/dist/chunk-PNPQTHBT.js +17 -0
- package/dist/chunk-PNPQTHBT.js.map +1 -0
- package/dist/chunk-PU6DFJMY.js +1975 -0
- package/dist/chunk-PU6DFJMY.js.map +1 -0
- package/dist/chunk-Q35YIDBV.js +1202 -0
- package/dist/chunk-Q35YIDBV.js.map +1 -0
- package/dist/{chunk-5HNHEUD5.js → chunk-QQUKGCAJ.js} +3 -3
- package/dist/chunk-QRWGPQKO.js +198 -0
- package/dist/chunk-QRWGPQKO.js.map +1 -0
- package/dist/{chunk-UBMMXS2Y.js → chunk-QZ6LRSNV.js} +69 -48
- package/dist/{chunk-UBMMXS2Y.js.map → chunk-QZ6LRSNV.js.map} +1 -1
- package/dist/chunk-RL5XWQOL.js +3872 -0
- package/dist/chunk-RL5XWQOL.js.map +1 -0
- package/dist/chunk-RNVYGWIC.js +30 -0
- package/dist/chunk-RNVYGWIC.js.map +1 -0
- package/dist/chunk-SE4JN5XN.js +19 -0
- package/dist/chunk-SE4JN5XN.js.map +1 -0
- package/dist/chunk-SKSDRUUK.js +622 -0
- package/dist/chunk-SKSDRUUK.js.map +1 -0
- package/dist/chunk-TIUTIOFB.js +25 -0
- package/dist/chunk-TIUTIOFB.js.map +1 -0
- package/dist/chunk-TK3FC4RF.js +3090 -0
- package/dist/chunk-TK3FC4RF.js.map +1 -0
- package/dist/chunk-TU2WUBVZ.js +2 -0
- package/dist/chunk-TU2WUBVZ.js.map +1 -0
- package/dist/chunk-TZOYZK2E.js +98 -0
- package/dist/chunk-TZOYZK2E.js.map +1 -0
- package/dist/chunk-UJCVAWP7.js +178 -0
- package/dist/chunk-UJCVAWP7.js.map +1 -0
- package/dist/chunk-UKZNLVJW.js +17 -0
- package/dist/chunk-UKZNLVJW.js.map +1 -0
- package/dist/{chunk-HAPTXWU2.js → chunk-UQISLDAV.js} +4 -4
- package/dist/chunk-WB3QM6PP.js +5440 -0
- package/dist/chunk-WB3QM6PP.js.map +1 -0
- package/dist/chunk-YB4IBW3M.js +96 -0
- package/dist/chunk-YB4IBW3M.js.map +1 -0
- package/dist/chunk-YEUYKR62.js +72 -0
- package/dist/chunk-YEUYKR62.js.map +1 -0
- package/dist/chunk-YJOGUXGP.js +634 -0
- package/dist/chunk-YJOGUXGP.js.map +1 -0
- package/dist/chunk-YNHZHSSM.js +41 -0
- package/dist/chunk-YNHZHSSM.js.map +1 -0
- package/dist/chunk-YTURO7SI.js +979 -0
- package/dist/chunk-YTURO7SI.js.map +1 -0
- package/dist/chunk-ZXRAE55H.js +31 -0
- package/dist/chunk-ZXRAE55H.js.map +1 -0
- package/dist/cli-3BIBYHFK.js +473 -0
- package/dist/cli-3BIBYHFK.js.map +1 -0
- package/dist/cli-673OTRGE.js +28 -0
- package/dist/cli-673OTRGE.js.map +1 -0
- package/dist/cli-6HIDIFVT.js +1203 -0
- package/dist/cli-6HIDIFVT.js.map +1 -0
- package/dist/cli-6UB5N6CU.js +232 -0
- package/dist/cli-6UB5N6CU.js.map +1 -0
- package/dist/cli-LFP5ZGYS.js +346 -0
- package/dist/cli-LFP5ZGYS.js.map +1 -0
- package/dist/cli-MN7PYMBI.js +552 -0
- package/dist/cli-MN7PYMBI.js.map +1 -0
- package/dist/cli-PYPX6O6E.js +739 -0
- package/dist/cli-PYPX6O6E.js.map +1 -0
- package/dist/cli-RPM5PELX.js +626 -0
- package/dist/cli-RPM5PELX.js.map +1 -0
- package/dist/cli-VI7VHWNZ.js +423 -0
- package/dist/cli-VI7VHWNZ.js.map +1 -0
- package/dist/cli.d.ts +12 -2
- package/dist/cli.js +109 -7661
- package/dist/cli.js.map +1 -1
- package/dist/docmeta.js +15 -3
- package/dist/docmeta.js.map +1 -1
- package/dist/github-6QMYOHC3.js +27 -0
- package/dist/github-6QMYOHC3.js.map +1 -0
- package/dist/github-SXPGP5DB.js +32 -0
- package/dist/github-SXPGP5DB.js.map +1 -0
- package/dist/index.d.ts +65 -3
- package/dist/index.js +407 -337
- package/dist/index.js.map +1 -1
- package/dist/json-7WV7KL6H.js +17 -0
- package/dist/json-7WV7KL6H.js.map +1 -0
- package/dist/json-SY7KLNC7.js +35 -0
- package/dist/json-SY7KLNC7.js.map +1 -0
- package/dist/lint-ASMJLLPA.js +28 -0
- package/dist/lint-ASMJLLPA.js.map +1 -0
- package/dist/list-KZNVTNVC.js +31 -0
- package/dist/list-KZNVTNVC.js.map +1 -0
- package/dist/list-Q57YTFUQ.js +29 -0
- package/dist/list-Q57YTFUQ.js.map +1 -0
- package/dist/page-KSGV5RD4.js +41 -0
- package/dist/page-KSGV5RD4.js.map +1 -0
- package/dist/picker-3XF36MJF.js +14 -0
- package/dist/picker-3XF36MJF.js.map +1 -0
- package/dist/pretty-A5EGTN35.js +37 -0
- package/dist/pretty-A5EGTN35.js.map +1 -0
- package/dist/pretty-CXSDXNAS.js +43 -0
- package/dist/pretty-CXSDXNAS.js.map +1 -0
- package/dist/reporters-HUY7UXFS.js +42 -0
- package/dist/reporters-HUY7UXFS.js.map +1 -0
- package/dist/reporters-K2VUKSAK.js +71 -0
- package/dist/reporters-K2VUKSAK.js.map +1 -0
- package/dist/reporters-M6LJ2IYU.js +21 -0
- package/dist/reporters-M6LJ2IYU.js.map +1 -0
- package/dist/run-3DYJNRIG.js +33 -0
- package/dist/run-3DYJNRIG.js.map +1 -0
- package/dist/term-BIQUPMOR.js +1592 -0
- package/dist/term-BIQUPMOR.js.map +1 -0
- package/dist/types-Y6TXHM7M.js +10 -0
- package/dist/types-Y6TXHM7M.js.map +1 -0
- package/dist/validate-53RKM2XG.js +16 -0
- package/dist/validate-53RKM2XG.js.map +1 -0
- package/package.json +1 -1
- package/plugin/manni/.claude-plugin/plugin.json +9 -0
- package/plugin/manni/hooks/hooks.json +69 -0
- package/plugin/manni/hooks/manni.mjs +157 -0
- package/plugin/manni/skills/check/SKILL.md +20 -0
- package/plugin/manni/skills/evals/SKILL.md +27 -0
- package/plugin/manni/skills/fix/SKILL.md +56 -0
- package/plugin/manni/skills/setup/SKILL.md +41 -0
- package/dist/batch-A5HZKYIW.js +0 -18
- package/dist/calibrate-S5K6QHUY.js +0 -13
- package/dist/capture-OZEZDABQ.js +0 -15
- package/dist/chunk-3R23C5DT.js.map +0 -1
- package/dist/chunk-CFDUZRM2.js.map +0 -1
- package/dist/chunk-G5CM2VGQ.js.map +0 -1
- package/dist/chunk-KJR7OVDX.js.map +0 -1
- package/dist/chunk-V4KUVE47.js +0 -27170
- package/dist/chunk-V4KUVE47.js.map +0 -1
- package/dist/chunk-ZQBTK3DO.js +0 -26518
- package/dist/chunk-ZQBTK3DO.js.map +0 -1
- package/dist/picker-6HRMETE7.js +0 -12
- package/plugin/tracevals/.claude-plugin/plugin.json +0 -9
- package/plugin/tracevals/hooks/hooks.json +0 -17
- /package/dist/{batch-A5HZKYIW.js.map → batch-GFNLTGOH.js.map} +0 -0
- /package/dist/{calibrate-S5K6QHUY.js.map → build-COYIQ25L.js.map} +0 -0
- /package/dist/{capture-OZEZDABQ.js.map → calibrate-MDBLJKEE.js.map} +0 -0
- /package/dist/{picker-6HRMETE7.js.map → capture-LRML2PKV.js.map} +0 -0
- /package/dist/{chunk-5HNHEUD5.js.map → chunk-QQUKGCAJ.js.map} +0 -0
- /package/dist/{chunk-HAPTXWU2.js.map → chunk-UQISLDAV.js.map} +0 -0
|
@@ -0,0 +1,1975 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
SEVERITIES
|
|
4
|
+
} from "./chunk-77AINBYM.js";
|
|
5
|
+
import {
|
|
6
|
+
codeEndAt,
|
|
7
|
+
codeRegions
|
|
8
|
+
} from "./chunk-IKEWBMCN.js";
|
|
9
|
+
import {
|
|
10
|
+
CONCEPT_FIELDS,
|
|
11
|
+
fieldPointer,
|
|
12
|
+
valueAt
|
|
13
|
+
} from "./chunk-6JSSEWBG.js";
|
|
14
|
+
import {
|
|
15
|
+
STDIN_LABEL,
|
|
16
|
+
STDIN_TOKEN,
|
|
17
|
+
assertNonEmpty,
|
|
18
|
+
extractorByName,
|
|
19
|
+
extractorForExtension,
|
|
20
|
+
gitignoreOptions,
|
|
21
|
+
locateFrontmatter,
|
|
22
|
+
resolveTargetSet
|
|
23
|
+
} from "./chunk-57NEQRVO.js";
|
|
24
|
+
import {
|
|
25
|
+
findConfigFile,
|
|
26
|
+
readConfigFile,
|
|
27
|
+
selectCollections,
|
|
28
|
+
valeConfigPath
|
|
29
|
+
} from "./chunk-Q35YIDBV.js";
|
|
30
|
+
import {
|
|
31
|
+
ToolError,
|
|
32
|
+
errorMessage
|
|
33
|
+
} from "./chunk-G3T47CFV.js";
|
|
34
|
+
|
|
35
|
+
// src/term/errors.ts
|
|
36
|
+
var TermError = class extends ToolError {
|
|
37
|
+
constructor(message) {
|
|
38
|
+
super(message);
|
|
39
|
+
this.name = "TermError";
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// src/term/types.ts
|
|
44
|
+
var TERM_FIELDS = [
|
|
45
|
+
"label",
|
|
46
|
+
"definition",
|
|
47
|
+
"abstract",
|
|
48
|
+
"alt-labels",
|
|
49
|
+
"hidden-labels",
|
|
50
|
+
"broader",
|
|
51
|
+
"narrower",
|
|
52
|
+
"related-terms",
|
|
53
|
+
"see",
|
|
54
|
+
"scope-note"
|
|
55
|
+
];
|
|
56
|
+
var TERM_LIST_FIELDS = [
|
|
57
|
+
"alt-labels",
|
|
58
|
+
"hidden-labels",
|
|
59
|
+
"broader",
|
|
60
|
+
"narrower",
|
|
61
|
+
"related-terms"
|
|
62
|
+
];
|
|
63
|
+
var TERM_WRITE_FORMATS = [
|
|
64
|
+
"markdown",
|
|
65
|
+
"mdx",
|
|
66
|
+
"asciidoc",
|
|
67
|
+
"rst",
|
|
68
|
+
"html",
|
|
69
|
+
"dita",
|
|
70
|
+
"docbook",
|
|
71
|
+
"tbx",
|
|
72
|
+
"skos",
|
|
73
|
+
"csv",
|
|
74
|
+
"json",
|
|
75
|
+
"vale"
|
|
76
|
+
];
|
|
77
|
+
var TERM_RULES = [
|
|
78
|
+
"undefined-term",
|
|
79
|
+
"duplicate-id",
|
|
80
|
+
"label-collision",
|
|
81
|
+
"alt-label-collision",
|
|
82
|
+
"dangling-reference",
|
|
83
|
+
"broader-cycle",
|
|
84
|
+
"see-not-empty",
|
|
85
|
+
"asymmetric-hierarchy",
|
|
86
|
+
"abstract-too-long",
|
|
87
|
+
"unused-term"
|
|
88
|
+
];
|
|
89
|
+
|
|
90
|
+
// src/term/core/config.ts
|
|
91
|
+
import { resolve } from "node:path";
|
|
92
|
+
var TERM_SECTION = "term";
|
|
93
|
+
var DEFAULT_TERM_BASELINE_PATH = ".manni-term-baseline.json";
|
|
94
|
+
var DEFAULT_ABSTRACT_MAX_LENGTH = 60;
|
|
95
|
+
var CONFIG_KEYS = [
|
|
96
|
+
"manifests",
|
|
97
|
+
"abstractMaxLength",
|
|
98
|
+
"baseline",
|
|
99
|
+
"severity",
|
|
100
|
+
"allowEmpty",
|
|
101
|
+
"respectGitignore"
|
|
102
|
+
];
|
|
103
|
+
var COLLECTION_KEYS = ["paths", "exclude"];
|
|
104
|
+
var TOOL_KEYS = ["vale"];
|
|
105
|
+
var SEVERITY_LEVELS = [...SEVERITIES, "off"];
|
|
106
|
+
var CONFIG_FILE = {
|
|
107
|
+
section: TERM_SECTION,
|
|
108
|
+
legacyNames: [],
|
|
109
|
+
toError: (message) => new TermError(message)
|
|
110
|
+
};
|
|
111
|
+
function isMapping(value) {
|
|
112
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
113
|
+
}
|
|
114
|
+
function isLevel(value) {
|
|
115
|
+
return typeof value === "string" && SEVERITY_LEVELS.includes(value);
|
|
116
|
+
}
|
|
117
|
+
function isTermRule(value) {
|
|
118
|
+
return TERM_RULES.includes(value);
|
|
119
|
+
}
|
|
120
|
+
function rejectUnknownKeys(obj, allowed, where, source) {
|
|
121
|
+
for (const key of Object.keys(obj)) {
|
|
122
|
+
if (!allowed.includes(key)) {
|
|
123
|
+
throw new TermError(
|
|
124
|
+
`Unknown key "${key}" under ${where}: in ${source}. Supported keys: ${allowed.join(", ")}.`
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function wrongType(key, expected, source) {
|
|
130
|
+
return new TermError(`term.${key} in ${source} must be ${expected}.`);
|
|
131
|
+
}
|
|
132
|
+
function asBoolean(value, key, source) {
|
|
133
|
+
if (typeof value !== "boolean") throw wrongType(key, "a boolean", source);
|
|
134
|
+
return value;
|
|
135
|
+
}
|
|
136
|
+
function asString(value, key, source) {
|
|
137
|
+
if (typeof value !== "string") throw wrongType(key, "a string", source);
|
|
138
|
+
return value;
|
|
139
|
+
}
|
|
140
|
+
function asStringList(value, key, source) {
|
|
141
|
+
if (!Array.isArray(value) || !value.every((item2) => typeof item2 === "string" && item2.trim() !== "")) {
|
|
142
|
+
throw wrongType(key, "a list of non-empty strings", source);
|
|
143
|
+
}
|
|
144
|
+
return value;
|
|
145
|
+
}
|
|
146
|
+
function asNonNegativeInteger(value, key, source) {
|
|
147
|
+
if (typeof value !== "number" || !Number.isInteger(value) || value < 0) {
|
|
148
|
+
throw wrongType(key, "a non-negative integer", source);
|
|
149
|
+
}
|
|
150
|
+
return value;
|
|
151
|
+
}
|
|
152
|
+
function parseSeverity(value, source) {
|
|
153
|
+
if (!isMapping(value)) throw wrongType("severity", "a mapping", source);
|
|
154
|
+
rejectUnknownKeys(value, TERM_RULES, "term.severity", source);
|
|
155
|
+
const severity = {};
|
|
156
|
+
for (const [rule, level] of Object.entries(value)) {
|
|
157
|
+
if (!isTermRule(rule)) continue;
|
|
158
|
+
if (!isLevel(level)) {
|
|
159
|
+
const quoted = typeof level === "string" ? ` "${level}"` : "";
|
|
160
|
+
throw new TermError(
|
|
161
|
+
`${source}: term.severity.${rule}${quoted} is not a level. Expected ${SEVERITY_LEVELS.join(" | ")}.`
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
severity[rule] = level;
|
|
165
|
+
}
|
|
166
|
+
return severity;
|
|
167
|
+
}
|
|
168
|
+
function parseTermConfig(raw, source) {
|
|
169
|
+
if (raw == null) return {};
|
|
170
|
+
if (!isMapping(raw)) {
|
|
171
|
+
throw new TermError(`term: in ${source} must be a mapping.`);
|
|
172
|
+
}
|
|
173
|
+
for (const key of COLLECTION_KEYS) {
|
|
174
|
+
if (Object.hasOwn(raw, key)) {
|
|
175
|
+
throw new TermError(
|
|
176
|
+
`${source}: term does not carry "${key}". Name a collection under collections:.`
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
for (const key of TOOL_KEYS) {
|
|
181
|
+
if (Object.hasOwn(raw, key)) {
|
|
182
|
+
throw new TermError(
|
|
183
|
+
`${source}: term does not carry "${key}". Vale's settings live under tools.${key}.`
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
rejectUnknownKeys(raw, CONFIG_KEYS, "term", source);
|
|
188
|
+
const config = {};
|
|
189
|
+
if (raw.manifests !== void 0) config.manifests = asStringList(raw.manifests, "manifests", source);
|
|
190
|
+
if (raw.abstractMaxLength !== void 0) {
|
|
191
|
+
config.abstractMaxLength = asNonNegativeInteger(raw.abstractMaxLength, "abstractMaxLength", source);
|
|
192
|
+
}
|
|
193
|
+
if (raw.baseline !== void 0) config.baseline = asString(raw.baseline, "baseline", source);
|
|
194
|
+
if (raw.severity !== void 0) config.severity = parseSeverity(raw.severity, source);
|
|
195
|
+
if (raw.allowEmpty !== void 0) config.allowEmpty = asBoolean(raw.allowEmpty, "allowEmpty", source);
|
|
196
|
+
if (raw.respectGitignore !== void 0) {
|
|
197
|
+
config.respectGitignore = asBoolean(raw.respectGitignore, "respectGitignore", source);
|
|
198
|
+
}
|
|
199
|
+
return config;
|
|
200
|
+
}
|
|
201
|
+
function readTermConfigFile(explicitPath, cwd) {
|
|
202
|
+
return explicitPath ? readConfigFile(explicitPath, cwd, CONFIG_FILE) : findConfigFile(cwd, CONFIG_FILE);
|
|
203
|
+
}
|
|
204
|
+
function toLoaded(file) {
|
|
205
|
+
return {
|
|
206
|
+
config: parseTermConfig(file.value, file.source),
|
|
207
|
+
path: file.path,
|
|
208
|
+
dir: file.dir,
|
|
209
|
+
source: file.source,
|
|
210
|
+
collections: file.collections,
|
|
211
|
+
tools: file.tools
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
var STDIN = "-";
|
|
215
|
+
async function resolveTermRun(opts) {
|
|
216
|
+
const cwd = resolve(opts.cwd);
|
|
217
|
+
const wanted = opts.collection ?? [];
|
|
218
|
+
if (wanted.length > 0 && opts.inputs.some((input) => input !== STDIN)) {
|
|
219
|
+
throw new TermError(
|
|
220
|
+
"--collection selects a configured collection; it cannot be combined with paths."
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
const file = opts.noConfig ? null : await readTermConfigFile(opts.configPath, cwd);
|
|
224
|
+
const loaded = file === null ? null : toLoaded(file);
|
|
225
|
+
if (wanted.length > 0 && loaded === null) {
|
|
226
|
+
throw new TermError("--collection needs a config file to select from.");
|
|
227
|
+
}
|
|
228
|
+
if (loaded) opts.onConfigLoaded?.({ path: loaded.path, dir: loaded.dir });
|
|
229
|
+
const collections = loaded ? selectCollections(loaded.collections, wanted, loaded.source, (message) => new TermError(message)) : [];
|
|
230
|
+
const fromCollections = opts.inputs.length === 0;
|
|
231
|
+
const inputs = fromCollections ? collections.flatMap((c) => c.paths) : opts.inputs;
|
|
232
|
+
const base = fromCollections && inputs.length > 0 && loaded ? loaded.dir : cwd;
|
|
233
|
+
const manifests = loaded ? (loaded.config.manifests ?? []).map((written) => ({ path: resolve(loaded.dir, written), written })) : [];
|
|
234
|
+
return {
|
|
235
|
+
config: loaded ? loaded.config : null,
|
|
236
|
+
inputs,
|
|
237
|
+
base,
|
|
238
|
+
collections,
|
|
239
|
+
fromCollections,
|
|
240
|
+
manifests,
|
|
241
|
+
tools: loaded ? loaded.tools : {},
|
|
242
|
+
...loaded ? { configDir: loaded.dir, configPath: loaded.path, configSource: loaded.source } : {},
|
|
243
|
+
...file === null ? {} : { configFile: file }
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// src/term/commands/run.ts
|
|
248
|
+
import { existsSync } from "node:fs";
|
|
249
|
+
import { isAbsolute, relative, resolve as resolve3 } from "node:path";
|
|
250
|
+
|
|
251
|
+
// src/term/core/load-set.ts
|
|
252
|
+
import { readFile } from "node:fs/promises";
|
|
253
|
+
import { extname, resolve as resolve2 } from "node:path";
|
|
254
|
+
|
|
255
|
+
// src/term/core/writers/markup.ts
|
|
256
|
+
function xmlText(value) {
|
|
257
|
+
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
258
|
+
}
|
|
259
|
+
function xmlAttribute(value) {
|
|
260
|
+
return xmlText(value).replaceAll('"', """);
|
|
261
|
+
}
|
|
262
|
+
function paragraphsOf(definition) {
|
|
263
|
+
if (definition === void 0) return [];
|
|
264
|
+
return definition.split(/\r?\n[ \t]*\r?\n/).map(
|
|
265
|
+
(paragraph) => paragraph.split(/\r?\n/).map((line) => line.trim()).filter((line) => line !== "")
|
|
266
|
+
).filter((lines) => lines.length > 0);
|
|
267
|
+
}
|
|
268
|
+
function paragraphText(lines) {
|
|
269
|
+
return lines.join(" ");
|
|
270
|
+
}
|
|
271
|
+
function isAcronym(label) {
|
|
272
|
+
return new RegExp("\\p{L}", "u").test(label) && !new RegExp("\\p{Ll}", "u").test(label);
|
|
273
|
+
}
|
|
274
|
+
function sharedLanguage(terms) {
|
|
275
|
+
const [first] = terms;
|
|
276
|
+
const language = first?.language;
|
|
277
|
+
if (language === void 0) return void 0;
|
|
278
|
+
return terms.every((t) => t.language === language) ? language : void 0;
|
|
279
|
+
}
|
|
280
|
+
function reindent(text, indent, eol) {
|
|
281
|
+
return text.split("\n").map((line, i) => i === 0 || line === "" ? line : `${indent}${line}`).join(eol);
|
|
282
|
+
}
|
|
283
|
+
function fileOf(lines) {
|
|
284
|
+
return lines.map((line) => `${line}
|
|
285
|
+
`).join("");
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// src/term/core/writers/entries.ts
|
|
289
|
+
var LIST_HOLDS = ["label", "definition", "alt-labels"];
|
|
290
|
+
var DITA_HOLDS = ["label", "definition", "alt-labels", "scope-note"];
|
|
291
|
+
var DOCBOOK_HOLDS = ["label", "definition", "alt-labels", "see", "related-terms"];
|
|
292
|
+
function labelsOf(record) {
|
|
293
|
+
return [record.label, ...record["alt-labels"] ?? []];
|
|
294
|
+
}
|
|
295
|
+
function markdownEntry(record) {
|
|
296
|
+
const lines = labelsOf(record);
|
|
297
|
+
const paragraphs = paragraphsOf(record.definition);
|
|
298
|
+
if (paragraphs.length === 0) return [...lines, ":"].join("\n");
|
|
299
|
+
paragraphs.forEach((paragraph, p) => {
|
|
300
|
+
if (p > 0) lines.push("");
|
|
301
|
+
paragraph.forEach((line, i) => {
|
|
302
|
+
lines.push(p === 0 && i === 0 ? `: ${line}` : ` ${line}`);
|
|
303
|
+
});
|
|
304
|
+
});
|
|
305
|
+
return lines.join("\n");
|
|
306
|
+
}
|
|
307
|
+
function asciidocEntry(record) {
|
|
308
|
+
const labels = labelsOf(record);
|
|
309
|
+
const paragraphs = paragraphsOf(record.definition);
|
|
310
|
+
const lines = labels.map((label) => `${label}::`);
|
|
311
|
+
paragraphs.forEach((paragraph, p) => {
|
|
312
|
+
if (p > 0) lines.push("+");
|
|
313
|
+
paragraph.forEach((line, i) => {
|
|
314
|
+
if (p === 0 && i === 0) lines[lines.length - 1] = `${lines[lines.length - 1] ?? ""} ${line}`;
|
|
315
|
+
else lines.push(line);
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
return lines.join("\n");
|
|
319
|
+
}
|
|
320
|
+
function rstEntry(record) {
|
|
321
|
+
const lines = labelsOf(record);
|
|
322
|
+
paragraphsOf(record.definition).forEach((paragraph, p) => {
|
|
323
|
+
if (p > 0) lines.push("");
|
|
324
|
+
for (const line of paragraph) lines.push(` ${line}`);
|
|
325
|
+
});
|
|
326
|
+
return lines.join("\n");
|
|
327
|
+
}
|
|
328
|
+
function blockDefinition(open, close, paragraph, definition) {
|
|
329
|
+
const paragraphs = paragraphsOf(definition);
|
|
330
|
+
const [only] = paragraphs;
|
|
331
|
+
if (only === void 0) return [];
|
|
332
|
+
if (paragraphs.length === 1) return [`${open}${xmlText(paragraphText(only))}${close}`];
|
|
333
|
+
return [
|
|
334
|
+
open,
|
|
335
|
+
...paragraphs.map((lines) => ` <${paragraph}>${xmlText(paragraphText(lines))}</${paragraph}>`),
|
|
336
|
+
close
|
|
337
|
+
];
|
|
338
|
+
}
|
|
339
|
+
function htmlDlEntry(term) {
|
|
340
|
+
const [label, ...alts] = labelsOf(term.record);
|
|
341
|
+
return [
|
|
342
|
+
`<dt id="${xmlAttribute(term.id)}">${xmlText(label ?? "")}</dt>`,
|
|
343
|
+
...alts.map((alt) => `<dt>${xmlText(alt)}</dt>`),
|
|
344
|
+
...blockDefinition("<dd>", "</dd>", "p", term.record.definition)
|
|
345
|
+
].join("\n");
|
|
346
|
+
}
|
|
347
|
+
function ditaEntry(term, language) {
|
|
348
|
+
const { record } = term;
|
|
349
|
+
const alts = record["alt-labels"] ?? [];
|
|
350
|
+
const scopeNote = record["scope-note"];
|
|
351
|
+
const lang = language === void 0 ? "" : ` xml:lang="${xmlAttribute(language)}"`;
|
|
352
|
+
const body = scopeNote === void 0 && alts.length === 0 ? [] : [
|
|
353
|
+
" <glossBody>",
|
|
354
|
+
...scopeNote === void 0 ? [] : [` <glossUsage>${xmlText(scopeNote)}</glossUsage>`],
|
|
355
|
+
...alts.flatMap((alt) => {
|
|
356
|
+
const element = isAcronym(alt) ? "glossAcronym" : "glossSynonym";
|
|
357
|
+
return [" <glossAlt>", ` <${element}>${xmlText(alt)}</${element}>`, " </glossAlt>"];
|
|
358
|
+
}),
|
|
359
|
+
" </glossBody>"
|
|
360
|
+
];
|
|
361
|
+
return [
|
|
362
|
+
`<glossentry id="${xmlAttribute(term.id)}"${lang}>`,
|
|
363
|
+
` <glossterm>${xmlText(record.label)}</glossterm>`,
|
|
364
|
+
...blockDefinition("<glossdef>", "</glossdef>", "p", record.definition).map((line) => ` ${line}`),
|
|
365
|
+
...body,
|
|
366
|
+
"</glossentry>"
|
|
367
|
+
].join("\n");
|
|
368
|
+
}
|
|
369
|
+
function docbookEntry(term) {
|
|
370
|
+
const { record } = term;
|
|
371
|
+
const related = record["related-terms"] ?? [];
|
|
372
|
+
const paragraphs = paragraphsOf(record.definition);
|
|
373
|
+
const glossdef = paragraphs.length === 0 && related.length === 0 ? [] : [
|
|
374
|
+
" <glossdef>",
|
|
375
|
+
...paragraphs.map((lines) => ` <para>${xmlText(paragraphText(lines))}</para>`),
|
|
376
|
+
...related.map((target) => ` <glossseealso>${xmlText(target)}</glossseealso>`),
|
|
377
|
+
" </glossdef>"
|
|
378
|
+
];
|
|
379
|
+
return [
|
|
380
|
+
`<glossentry xml:id="${xmlAttribute(term.id)}">`,
|
|
381
|
+
` <glossterm>${xmlText(record.label)}</glossterm>`,
|
|
382
|
+
...(record["alt-labels"] ?? []).map(
|
|
383
|
+
(alt) => isAcronym(alt) ? ` <acronym>${xmlText(alt)}</acronym>` : ` <glossterm>${xmlText(alt)}</glossterm>`
|
|
384
|
+
),
|
|
385
|
+
...glossdef,
|
|
386
|
+
...record.see === void 0 ? [] : [` <glosssee>${xmlText(record.see)}</glosssee>`],
|
|
387
|
+
"</glossentry>"
|
|
388
|
+
].join("\n");
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// src/term/core/id.ts
|
|
392
|
+
import { slug } from "github-slugger";
|
|
393
|
+
function slugOf(label) {
|
|
394
|
+
return slug(label.trim());
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// src/term/core/readers/normalize.ts
|
|
398
|
+
function nothing() {
|
|
399
|
+
return { terms: [], notices: [] };
|
|
400
|
+
}
|
|
401
|
+
function textOf(value) {
|
|
402
|
+
let text;
|
|
403
|
+
if (typeof value === "string") text = value;
|
|
404
|
+
else if (typeof value === "number" && Number.isFinite(value)) text = String(value);
|
|
405
|
+
else return void 0;
|
|
406
|
+
const trimmed = text.trim();
|
|
407
|
+
return trimmed === "" ? void 0 : trimmed;
|
|
408
|
+
}
|
|
409
|
+
function listOf(value) {
|
|
410
|
+
const items = Array.isArray(value) ? value : [value];
|
|
411
|
+
const list = items.map(textOf).filter((item2) => item2 !== void 0);
|
|
412
|
+
return list.length === 0 ? void 0 : list;
|
|
413
|
+
}
|
|
414
|
+
function collapse(text) {
|
|
415
|
+
return text.replace(/\s+/g, " ").trim();
|
|
416
|
+
}
|
|
417
|
+
function isListField(field) {
|
|
418
|
+
return TERM_LIST_FIELDS.includes(field);
|
|
419
|
+
}
|
|
420
|
+
function recordOf(raw) {
|
|
421
|
+
const label = textOf(raw.label);
|
|
422
|
+
if (label === void 0) return void 0;
|
|
423
|
+
const record = { label };
|
|
424
|
+
for (const field of TERM_FIELDS) {
|
|
425
|
+
if (isListField(field)) {
|
|
426
|
+
const list = listOf(raw[field]);
|
|
427
|
+
if (list !== void 0) record[field] = list;
|
|
428
|
+
} else if (field !== "label") {
|
|
429
|
+
const text = textOf(raw[field]);
|
|
430
|
+
if (text !== void 0) record[field] = text;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
return record;
|
|
434
|
+
}
|
|
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
|
+
function linesFor(record, lines) {
|
|
454
|
+
const kept = {};
|
|
455
|
+
for (const field of TERM_FIELDS) {
|
|
456
|
+
const line = lines[field];
|
|
457
|
+
if (line !== void 0 && record[field] !== void 0) kept[field] = line;
|
|
458
|
+
}
|
|
459
|
+
return kept;
|
|
460
|
+
}
|
|
461
|
+
function idFor(record, recordId, constructId) {
|
|
462
|
+
return textOf(recordId) ?? textOf(constructId) ?? slugOf(record.label);
|
|
463
|
+
}
|
|
464
|
+
function languageOf(input) {
|
|
465
|
+
return textOf(input.metadata["language"]) ?? textOf(input.metadata["xml:lang"]);
|
|
466
|
+
}
|
|
467
|
+
function declares(input, type) {
|
|
468
|
+
const value = input.metadata["type"];
|
|
469
|
+
return typeof value === "string" && value.trim() === type;
|
|
470
|
+
}
|
|
471
|
+
function skipped(input, line, label) {
|
|
472
|
+
return `${input.file}:${line}: skipped a ${label} entry with no term.`;
|
|
473
|
+
}
|
|
474
|
+
function termOf(input, parts) {
|
|
475
|
+
const language = languageOf(input);
|
|
476
|
+
const location = {
|
|
477
|
+
file: input.file,
|
|
478
|
+
...input.path === void 0 ? {} : { path: input.path },
|
|
479
|
+
construct: parts.construct,
|
|
480
|
+
line: parts.line,
|
|
481
|
+
fieldLines: linesFor(parts.record, parts.lines),
|
|
482
|
+
...parts.span === void 0 ? {} : { span: parts.span }
|
|
483
|
+
};
|
|
484
|
+
return {
|
|
485
|
+
id: idFor(parts.record, parts.recordId, parts.constructId),
|
|
486
|
+
record: parts.record,
|
|
487
|
+
...language === void 0 ? {} : { language },
|
|
488
|
+
location
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// src/term/core/readers/splice.ts
|
|
493
|
+
function sameValue(a, b) {
|
|
494
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
495
|
+
}
|
|
496
|
+
function sameFields(a, b, fields) {
|
|
497
|
+
return fields.every((field) => sameValue(a[field], b[field]));
|
|
498
|
+
}
|
|
499
|
+
function lineEnding(content) {
|
|
500
|
+
return content.includes("\r\n") ? "\r\n" : "\n";
|
|
501
|
+
}
|
|
502
|
+
function indentAt(content, offset) {
|
|
503
|
+
const lineStart = content.lastIndexOf("\n", offset - 1) + 1;
|
|
504
|
+
return /^[ \t]*/.exec(content.slice(lineStart, offset))?.[0] ?? "";
|
|
505
|
+
}
|
|
506
|
+
function applyEntries(input, read8, terms, write) {
|
|
507
|
+
const { content } = input;
|
|
508
|
+
const current = read8(input).terms;
|
|
509
|
+
const eol = lineEnding(content);
|
|
510
|
+
const edits = [];
|
|
511
|
+
for (const term of terms) {
|
|
512
|
+
const span = term.location.span;
|
|
513
|
+
if (span === void 0) {
|
|
514
|
+
throw new TermError(
|
|
515
|
+
`${input.file}: term "${term.id}" cannot be written in place, because its entry has no position in the file.`
|
|
516
|
+
);
|
|
517
|
+
}
|
|
518
|
+
const found = current.find((t) => t.location.span?.start === span.start && t.location.span.end === span.end);
|
|
519
|
+
if (found === void 0) {
|
|
520
|
+
throw new TermError(
|
|
521
|
+
`${input.file}: term "${term.id}" does not match an entry in the file. Read the file again before writing it.`
|
|
522
|
+
);
|
|
523
|
+
}
|
|
524
|
+
if (sameFields(found.record, term.record, write.holds) && (!write.id || found.id === term.id)) continue;
|
|
525
|
+
const text = reindent(write.serialize(term, input), indentAt(content, span.start), eol);
|
|
526
|
+
edits.push({ start: span.start, end: span.end, text });
|
|
527
|
+
}
|
|
528
|
+
let next = content;
|
|
529
|
+
for (const edit of [...edits].sort((a, b) => b.start - a.start)) {
|
|
530
|
+
next = next.slice(0, edit.start) + edit.text + next.slice(edit.end);
|
|
531
|
+
}
|
|
532
|
+
return next;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
// src/term/core/readers/xml.ts
|
|
536
|
+
import { DOMParser } from "@xmldom/xmldom";
|
|
537
|
+
var cache = /* @__PURE__ */ new WeakMap();
|
|
538
|
+
var LINE_BREAK = /\r\n|\r|\n|\u0085|\u2028|\u2029/g;
|
|
539
|
+
function lineStarts(source) {
|
|
540
|
+
const starts = [0];
|
|
541
|
+
for (const match of source.matchAll(LINE_BREAK)) starts.push(match.index + match[0].length);
|
|
542
|
+
return starts;
|
|
543
|
+
}
|
|
544
|
+
function parseXml(input) {
|
|
545
|
+
const cached = cache.get(input);
|
|
546
|
+
if (cached !== void 0) return cached;
|
|
547
|
+
const shift = input.content.charCodeAt(0) === 65279 ? 1 : 0;
|
|
548
|
+
const body = input.content.slice(shift);
|
|
549
|
+
const errors = [];
|
|
550
|
+
let parsed = null;
|
|
551
|
+
try {
|
|
552
|
+
const doc = new DOMParser({
|
|
553
|
+
onError: (level, message) => {
|
|
554
|
+
if (level !== "error" && level !== "fatalError") return;
|
|
555
|
+
if (/entity not found/i.test(message)) return;
|
|
556
|
+
errors.push(message);
|
|
557
|
+
}
|
|
558
|
+
}).parseFromString(body, "text/xml");
|
|
559
|
+
const root = doc.documentElement;
|
|
560
|
+
if (errors.length === 0 && root !== null) parsed = { root, body, shift, starts: lineStarts(body) };
|
|
561
|
+
} catch {
|
|
562
|
+
parsed = null;
|
|
563
|
+
}
|
|
564
|
+
cache.set(input, parsed);
|
|
565
|
+
return parsed;
|
|
566
|
+
}
|
|
567
|
+
function nameOf(el) {
|
|
568
|
+
return (el.localName ?? el.nodeName).toLowerCase();
|
|
569
|
+
}
|
|
570
|
+
function childrenOf(el, name) {
|
|
571
|
+
const out = [];
|
|
572
|
+
for (let i = 0; i < el.children.length; i++) {
|
|
573
|
+
const child = el.children.item(i);
|
|
574
|
+
if (child !== null && (name === void 0 || nameOf(child) === name)) out.push(child);
|
|
575
|
+
}
|
|
576
|
+
return out;
|
|
577
|
+
}
|
|
578
|
+
function descendantsOf(el, name) {
|
|
579
|
+
const out = [];
|
|
580
|
+
const walk = (parent) => {
|
|
581
|
+
for (const child of childrenOf(parent)) {
|
|
582
|
+
if (nameOf(child) === name) out.push(child);
|
|
583
|
+
walk(child);
|
|
584
|
+
}
|
|
585
|
+
};
|
|
586
|
+
walk(el);
|
|
587
|
+
return out;
|
|
588
|
+
}
|
|
589
|
+
function textOfElement(el) {
|
|
590
|
+
return collapse(el.textContent ?? "");
|
|
591
|
+
}
|
|
592
|
+
function lineOfElement(el) {
|
|
593
|
+
return el.lineNumber ?? 1;
|
|
594
|
+
}
|
|
595
|
+
function skipOpaque(body, from) {
|
|
596
|
+
const opaque = [
|
|
597
|
+
["<!--", "-->"],
|
|
598
|
+
["<![CDATA[", "]]>"],
|
|
599
|
+
["<?", "?>"],
|
|
600
|
+
["<!", ">"]
|
|
601
|
+
];
|
|
602
|
+
for (const [open, close] of opaque) {
|
|
603
|
+
if (body.startsWith(open, from)) {
|
|
604
|
+
const end = body.indexOf(close, from + open.length);
|
|
605
|
+
return end === -1 ? body.length : end + close.length;
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
return void 0;
|
|
609
|
+
}
|
|
610
|
+
function tagEnd(body, from) {
|
|
611
|
+
let quote;
|
|
612
|
+
for (let i = from + 1; i < body.length; i++) {
|
|
613
|
+
const ch = body[i];
|
|
614
|
+
if (quote !== void 0) {
|
|
615
|
+
if (ch === quote) quote = void 0;
|
|
616
|
+
} else if (ch === '"' || ch === "'") {
|
|
617
|
+
quote = ch;
|
|
618
|
+
} else if (ch === ">") {
|
|
619
|
+
return { end: i + 1, selfClosing: body[i - 1] === "/" };
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
return void 0;
|
|
623
|
+
}
|
|
624
|
+
function namedAt(body, at, name) {
|
|
625
|
+
if (!body.startsWith(name, at)) return false;
|
|
626
|
+
const after = body[at + name.length];
|
|
627
|
+
return after === void 0 || /[\s/>]/.test(after);
|
|
628
|
+
}
|
|
629
|
+
function spanOfElement(xml, el) {
|
|
630
|
+
const lineStart = xml.starts[(el.lineNumber ?? 1) - 1];
|
|
631
|
+
if (lineStart === void 0) return void 0;
|
|
632
|
+
const start = lineStart + (el.columnNumber ?? 1) - 1;
|
|
633
|
+
const { body } = xml;
|
|
634
|
+
if (body[start] !== "<") return void 0;
|
|
635
|
+
const name = el.nodeName;
|
|
636
|
+
const open = tagEnd(body, start);
|
|
637
|
+
if (open === void 0) return void 0;
|
|
638
|
+
if (open.selfClosing) return { start: start + xml.shift, end: open.end + xml.shift };
|
|
639
|
+
let depth = 1;
|
|
640
|
+
let i = open.end;
|
|
641
|
+
while (i < body.length) {
|
|
642
|
+
const lt = body.indexOf("<", i);
|
|
643
|
+
if (lt === -1) return void 0;
|
|
644
|
+
const skipTo = skipOpaque(body, lt);
|
|
645
|
+
if (skipTo !== void 0) {
|
|
646
|
+
i = skipTo;
|
|
647
|
+
continue;
|
|
648
|
+
}
|
|
649
|
+
const tag = tagEnd(body, lt);
|
|
650
|
+
if (tag === void 0) return void 0;
|
|
651
|
+
if (body[lt + 1] === "/" && namedAt(body, lt + 2, name)) {
|
|
652
|
+
depth -= 1;
|
|
653
|
+
if (depth === 0) return { start: start + xml.shift, end: tag.end + xml.shift };
|
|
654
|
+
} else if (namedAt(body, lt + 1, name) && !tag.selfClosing) {
|
|
655
|
+
depth += 1;
|
|
656
|
+
}
|
|
657
|
+
i = tag.end;
|
|
658
|
+
}
|
|
659
|
+
return void 0;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
// src/term/core/readers/dita.ts
|
|
663
|
+
function definitionOf(glossdef) {
|
|
664
|
+
const paragraphs = childrenOf(glossdef, "p");
|
|
665
|
+
if (paragraphs.length === 0) return textOfElement(glossdef);
|
|
666
|
+
return paragraphs.map(textOfElement).filter((text) => text !== "").join("\n\n");
|
|
667
|
+
}
|
|
668
|
+
function readEntry(input, xml, entry, construct, label) {
|
|
669
|
+
const raw = {};
|
|
670
|
+
const lines = {};
|
|
671
|
+
const [glossterm] = childrenOf(entry, "glossterm");
|
|
672
|
+
if (glossterm !== void 0) {
|
|
673
|
+
raw.label = textOfElement(glossterm);
|
|
674
|
+
lines.label = lineOfElement(glossterm);
|
|
675
|
+
}
|
|
676
|
+
const [glossdef] = childrenOf(entry, "glossdef");
|
|
677
|
+
if (glossdef !== void 0) {
|
|
678
|
+
raw.definition = definitionOf(glossdef);
|
|
679
|
+
lines.definition = lineOfElement(glossdef);
|
|
680
|
+
}
|
|
681
|
+
const alts = [];
|
|
682
|
+
for (const body of childrenOf(entry, "glossbody")) {
|
|
683
|
+
const [usage] = childrenOf(body, "glossusage");
|
|
684
|
+
if (usage !== void 0 && raw["scope-note"] === void 0) {
|
|
685
|
+
raw["scope-note"] = textOfElement(usage);
|
|
686
|
+
lines["scope-note"] = lineOfElement(usage);
|
|
687
|
+
}
|
|
688
|
+
for (const alt of childrenOf(body, "glossalt")) {
|
|
689
|
+
for (const form of childrenOf(alt)) {
|
|
690
|
+
const name = nameOf(form);
|
|
691
|
+
if (name !== "glosssynonym" && name !== "glossacronym") continue;
|
|
692
|
+
alts.push(textOfElement(form));
|
|
693
|
+
lines["alt-labels"] ??= lineOfElement(form);
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
raw["alt-labels"] = alts;
|
|
698
|
+
const line = lineOfElement(entry);
|
|
699
|
+
const record = recordOf(raw);
|
|
700
|
+
if (record === void 0) return skipped(input, line, label);
|
|
701
|
+
const span = spanOfElement(xml, entry);
|
|
702
|
+
return termOf(input, {
|
|
703
|
+
record,
|
|
704
|
+
constructId: entry.getAttribute("id"),
|
|
705
|
+
construct,
|
|
706
|
+
line,
|
|
707
|
+
lines,
|
|
708
|
+
...span === void 0 ? {} : { span }
|
|
709
|
+
});
|
|
710
|
+
}
|
|
711
|
+
function collect(input, xml, entries, construct, label) {
|
|
712
|
+
const result = nothing();
|
|
713
|
+
for (const entry of entries) {
|
|
714
|
+
const read8 = readEntry(input, xml, entry, construct, label);
|
|
715
|
+
if (typeof read8 === "string") result.notices.push(read8);
|
|
716
|
+
else result.terms.push(read8);
|
|
717
|
+
}
|
|
718
|
+
return result;
|
|
719
|
+
}
|
|
720
|
+
var GLOSSENTRY_LABEL = "DITA glossentry";
|
|
721
|
+
var GLOSSGROUP_LABEL = "DITA glossgroup";
|
|
722
|
+
function readGlossentry(input) {
|
|
723
|
+
const xml = parseXml(input);
|
|
724
|
+
if (xml === null || nameOf(xml.root) !== "glossentry") return nothing();
|
|
725
|
+
return collect(input, xml, [xml.root], "dita-glossentry", GLOSSENTRY_LABEL);
|
|
726
|
+
}
|
|
727
|
+
function readGlossgroup(input) {
|
|
728
|
+
const xml = parseXml(input);
|
|
729
|
+
if (xml === null || nameOf(xml.root) !== "glossgroup") return nothing();
|
|
730
|
+
return collect(input, xml, descendantsOf(xml.root, "glossentry"), "dita-glossgroup", GLOSSGROUP_LABEL);
|
|
731
|
+
}
|
|
732
|
+
var ditaGlossentryReader = {
|
|
733
|
+
construct: "dita-glossentry",
|
|
734
|
+
label: GLOSSENTRY_LABEL,
|
|
735
|
+
formats: ["xml"],
|
|
736
|
+
read: readGlossentry,
|
|
737
|
+
// The glossentry is the file's root, so the file's `xml:lang` sits on it and
|
|
738
|
+
// is written again when the entry is.
|
|
739
|
+
apply: (input, terms) => applyEntries(input, readGlossentry, terms, {
|
|
740
|
+
holds: DITA_HOLDS,
|
|
741
|
+
id: true,
|
|
742
|
+
serialize: (term, file) => ditaEntry(term, textOf(file.metadata["xml:lang"]) === void 0 ? void 0 : term.language)
|
|
743
|
+
})
|
|
744
|
+
};
|
|
745
|
+
var ditaGlossgroupReader = {
|
|
746
|
+
construct: "dita-glossgroup",
|
|
747
|
+
label: GLOSSGROUP_LABEL,
|
|
748
|
+
formats: ["xml"],
|
|
749
|
+
read: readGlossgroup,
|
|
750
|
+
apply: (input, terms) => applyEntries(input, readGlossgroup, terms, { holds: DITA_HOLDS, id: true, serialize: (term) => ditaEntry(term) })
|
|
751
|
+
};
|
|
752
|
+
|
|
753
|
+
// src/term/core/readers/docbook.ts
|
|
754
|
+
var LABEL = "DocBook glossary";
|
|
755
|
+
function referenceOf(el) {
|
|
756
|
+
return textOf(textOfElement(el)) ?? textOf(el.getAttribute("otherterm"));
|
|
757
|
+
}
|
|
758
|
+
function definitionOf2(glossdef) {
|
|
759
|
+
const children = childrenOf(glossdef);
|
|
760
|
+
const blocks = children.filter((child) => nameOf(child) !== "glossseealso");
|
|
761
|
+
if (blocks.length === 0) return children.length === 0 ? textOfElement(glossdef) : "";
|
|
762
|
+
return blocks.map(textOfElement).filter((text) => text !== "").join("\n\n");
|
|
763
|
+
}
|
|
764
|
+
function read(input) {
|
|
765
|
+
const xml = parseXml(input);
|
|
766
|
+
if (xml === null) return nothing();
|
|
767
|
+
const glossaries = nameOf(xml.root) === "glossary" ? [xml.root] : descendantsOf(xml.root, "glossary");
|
|
768
|
+
if (glossaries.length === 0) return nothing();
|
|
769
|
+
const seen = /* @__PURE__ */ new Set();
|
|
770
|
+
const result = nothing();
|
|
771
|
+
for (const glossary of glossaries) {
|
|
772
|
+
for (const entry of descendantsOf(glossary, "glossentry")) {
|
|
773
|
+
if (seen.has(entry)) continue;
|
|
774
|
+
seen.add(entry);
|
|
775
|
+
const raw = {};
|
|
776
|
+
const lines = {};
|
|
777
|
+
const alts = [];
|
|
778
|
+
const definitions = [];
|
|
779
|
+
const related = [];
|
|
780
|
+
for (const child of childrenOf(entry)) {
|
|
781
|
+
const name = nameOf(child);
|
|
782
|
+
if (name === "glossterm" && raw.label === void 0) {
|
|
783
|
+
raw.label = textOfElement(child);
|
|
784
|
+
lines.label = lineOfElement(child);
|
|
785
|
+
} else if (name === "glossterm" || name === "acronym") {
|
|
786
|
+
alts.push(textOfElement(child));
|
|
787
|
+
lines["alt-labels"] ??= lineOfElement(child);
|
|
788
|
+
} else if (name === "glossdef") {
|
|
789
|
+
definitions.push(definitionOf2(child));
|
|
790
|
+
lines.definition ??= lineOfElement(child);
|
|
791
|
+
for (const seeAlso of childrenOf(child, "glossseealso")) {
|
|
792
|
+
const target = referenceOf(seeAlso);
|
|
793
|
+
if (target !== void 0) related.push(target);
|
|
794
|
+
lines["related-terms"] ??= lineOfElement(seeAlso);
|
|
795
|
+
}
|
|
796
|
+
} else if (name === "glosssee" && raw.see === void 0) {
|
|
797
|
+
raw.see = referenceOf(child);
|
|
798
|
+
lines.see = lineOfElement(child);
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
raw["alt-labels"] = alts;
|
|
802
|
+
raw.definition = definitions.filter((text) => text !== "").join("\n\n");
|
|
803
|
+
raw["related-terms"] = related;
|
|
804
|
+
const line = lineOfElement(entry);
|
|
805
|
+
const record = recordOf(raw);
|
|
806
|
+
if (record === void 0) {
|
|
807
|
+
result.notices.push(skipped(input, line, LABEL));
|
|
808
|
+
continue;
|
|
809
|
+
}
|
|
810
|
+
const span = spanOfElement(xml, entry);
|
|
811
|
+
result.terms.push(
|
|
812
|
+
termOf(input, {
|
|
813
|
+
record,
|
|
814
|
+
constructId: entry.getAttribute("xml:id"),
|
|
815
|
+
construct: "docbook-glossary",
|
|
816
|
+
line,
|
|
817
|
+
lines,
|
|
818
|
+
...span === void 0 ? {} : { span }
|
|
819
|
+
})
|
|
820
|
+
);
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
return result;
|
|
824
|
+
}
|
|
825
|
+
var docbookGlossaryReader = {
|
|
826
|
+
construct: "docbook-glossary",
|
|
827
|
+
label: LABEL,
|
|
828
|
+
formats: ["xml"],
|
|
829
|
+
read,
|
|
830
|
+
apply: (input, terms) => applyEntries(input, read, terms, { holds: DOCBOOK_HOLDS, id: true, serialize: docbookEntry })
|
|
831
|
+
};
|
|
832
|
+
|
|
833
|
+
// src/term/core/readers/html.ts
|
|
834
|
+
import { parse } from "parse5";
|
|
835
|
+
var cache2 = /* @__PURE__ */ new WeakMap();
|
|
836
|
+
function parseHtml(input) {
|
|
837
|
+
const cached = cache2.get(input);
|
|
838
|
+
if (cached !== void 0) return cached;
|
|
839
|
+
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;
|
|
843
|
+
}
|
|
844
|
+
function isElement(node) {
|
|
845
|
+
return "tagName" in node;
|
|
846
|
+
}
|
|
847
|
+
function childElements(node) {
|
|
848
|
+
return node.childNodes.filter(isElement);
|
|
849
|
+
}
|
|
850
|
+
function elementsNamed(node, name) {
|
|
851
|
+
const out = [];
|
|
852
|
+
const walk = (parent) => {
|
|
853
|
+
for (const child of childElements(parent)) {
|
|
854
|
+
if (child.tagName === name) out.push(child);
|
|
855
|
+
walk(child);
|
|
856
|
+
}
|
|
857
|
+
};
|
|
858
|
+
walk(node);
|
|
859
|
+
return out;
|
|
860
|
+
}
|
|
861
|
+
function rawText(node) {
|
|
862
|
+
let text = "";
|
|
863
|
+
for (const child of node.childNodes) {
|
|
864
|
+
if (child.nodeName === "#text" && "value" in child) text += child.value;
|
|
865
|
+
else if (isElement(child)) text += rawText(child);
|
|
866
|
+
}
|
|
867
|
+
return text;
|
|
868
|
+
}
|
|
869
|
+
function textOfNode(node) {
|
|
870
|
+
return collapse(rawText(node));
|
|
871
|
+
}
|
|
872
|
+
function attr(el, name) {
|
|
873
|
+
return el.attrs.find((a) => a.name === name)?.value;
|
|
874
|
+
}
|
|
875
|
+
function lineOf(el) {
|
|
876
|
+
return el.sourceCodeLocation?.startLine ?? 1;
|
|
877
|
+
}
|
|
878
|
+
function spanOf(parsed, first, last) {
|
|
879
|
+
const start = first.sourceCodeLocation?.startOffset;
|
|
880
|
+
const end = last.sourceCodeLocation?.endOffset;
|
|
881
|
+
if (start === void 0 || end === void 0) return void 0;
|
|
882
|
+
return { start: start + parsed.shift, end: end + parsed.shift };
|
|
883
|
+
}
|
|
884
|
+
function definitionOf3(dd) {
|
|
885
|
+
const paragraphs = childElements(dd).filter((child) => child.tagName === "p");
|
|
886
|
+
if (paragraphs.length === 0) return textOfNode(dd);
|
|
887
|
+
return paragraphs.map(textOfNode).filter((text) => text !== "").join("\n\n");
|
|
888
|
+
}
|
|
889
|
+
function listItems(dl) {
|
|
890
|
+
return childElements(dl).flatMap((child) => child.tagName === "div" ? childElements(child) : [child]);
|
|
891
|
+
}
|
|
892
|
+
var DL_LABEL = "dl";
|
|
893
|
+
function readDl(input) {
|
|
894
|
+
if (!declares(input, "term-set")) return nothing();
|
|
895
|
+
const parsed = parseHtml(input);
|
|
896
|
+
const result = nothing();
|
|
897
|
+
for (const dl of elementsNamed(parsed.root, "dl")) {
|
|
898
|
+
const items = listItems(dl).filter((item2) => item2.tagName === "dt" || item2.tagName === "dd");
|
|
899
|
+
let i = 0;
|
|
900
|
+
while (i < items.length) {
|
|
901
|
+
const dts = [];
|
|
902
|
+
const dds = [];
|
|
903
|
+
for (let item2 = items[i]; item2?.tagName === "dt"; item2 = items[++i]) dts.push(item2);
|
|
904
|
+
for (let item2 = items[i]; item2?.tagName === "dd"; item2 = items[++i]) dds.push(item2);
|
|
905
|
+
const first = dts[0] ?? dds[0];
|
|
906
|
+
const last = dds[dds.length - 1] ?? dts[dts.length - 1];
|
|
907
|
+
if (first === void 0 || last === void 0) break;
|
|
908
|
+
const named = dts.filter((dt) => textOfNode(dt) !== "");
|
|
909
|
+
const [labelDt, ...altDts] = named;
|
|
910
|
+
const [dd] = dds;
|
|
911
|
+
const raw = {
|
|
912
|
+
label: labelDt === void 0 ? void 0 : textOfNode(labelDt),
|
|
913
|
+
"alt-labels": altDts.map(textOfNode),
|
|
914
|
+
definition: dd === void 0 ? void 0 : definitionOf3(dd)
|
|
915
|
+
};
|
|
916
|
+
const lines = {
|
|
917
|
+
label: labelDt === void 0 ? void 0 : lineOf(labelDt),
|
|
918
|
+
"alt-labels": altDts[0] === void 0 ? void 0 : lineOf(altDts[0]),
|
|
919
|
+
definition: dd === void 0 ? void 0 : lineOf(dd)
|
|
920
|
+
};
|
|
921
|
+
const line = lineOf(first);
|
|
922
|
+
const record = recordOf(raw);
|
|
923
|
+
if (record === void 0) {
|
|
924
|
+
result.notices.push(skipped(input, line, DL_LABEL));
|
|
925
|
+
continue;
|
|
926
|
+
}
|
|
927
|
+
const span = spanOf(parsed, first, last);
|
|
928
|
+
const constructId = dts.map((dt) => textOf(attr(dt, "id"))).find((id) => id !== void 0);
|
|
929
|
+
result.terms.push(
|
|
930
|
+
termOf(input, {
|
|
931
|
+
record,
|
|
932
|
+
constructId,
|
|
933
|
+
construct: "html-dl",
|
|
934
|
+
line,
|
|
935
|
+
lines,
|
|
936
|
+
...span === void 0 ? {} : { span }
|
|
937
|
+
})
|
|
938
|
+
);
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
return result;
|
|
942
|
+
}
|
|
943
|
+
var DFN_LABEL = "dfn";
|
|
944
|
+
function insideDt(el) {
|
|
945
|
+
let parent = el.parentNode;
|
|
946
|
+
while (parent !== null && "tagName" in parent) {
|
|
947
|
+
if (parent.tagName === "dt") return true;
|
|
948
|
+
parent = parent.parentNode;
|
|
949
|
+
}
|
|
950
|
+
return false;
|
|
951
|
+
}
|
|
952
|
+
function dfnFields(dfn) {
|
|
953
|
+
const title = textOf(attr(dfn, "title"));
|
|
954
|
+
if (title !== void 0) return { label: title };
|
|
955
|
+
const content = dfn.childNodes.filter(
|
|
956
|
+
(child) => child.nodeName === "#text" && "value" in child ? child.value.trim() !== "" : isElement(child)
|
|
957
|
+
);
|
|
958
|
+
const [only] = content;
|
|
959
|
+
if (content.length === 1 && only !== void 0 && isElement(only) && only.tagName === "abbr") {
|
|
960
|
+
const abbrTitle = textOf(attr(only, "title"));
|
|
961
|
+
if (abbrTitle !== void 0) return { label: abbrTitle, alt: textOfNode(only) };
|
|
962
|
+
}
|
|
963
|
+
return { label: textOfNode(dfn) };
|
|
964
|
+
}
|
|
965
|
+
function readDfn(input) {
|
|
966
|
+
if (!declares(input, "term-set")) return nothing();
|
|
967
|
+
const parsed = parseHtml(input);
|
|
968
|
+
const result = nothing();
|
|
969
|
+
for (const dfn of elementsNamed(parsed.root, "dfn")) {
|
|
970
|
+
if (insideDt(dfn)) continue;
|
|
971
|
+
const { label, alt } = dfnFields(dfn);
|
|
972
|
+
const line = lineOf(dfn);
|
|
973
|
+
const record = recordOf({ label, "alt-labels": alt });
|
|
974
|
+
if (record === void 0) {
|
|
975
|
+
result.notices.push(skipped(input, line, DFN_LABEL));
|
|
976
|
+
continue;
|
|
977
|
+
}
|
|
978
|
+
const span = spanOf(parsed, dfn, dfn);
|
|
979
|
+
const term = termOf(input, {
|
|
980
|
+
record,
|
|
981
|
+
constructId: attr(dfn, "id"),
|
|
982
|
+
construct: "html-dfn",
|
|
983
|
+
line,
|
|
984
|
+
lines: { label: line, "alt-labels": line },
|
|
985
|
+
...span === void 0 ? {} : { span }
|
|
986
|
+
});
|
|
987
|
+
result.terms.push(term);
|
|
988
|
+
}
|
|
989
|
+
return result;
|
|
990
|
+
}
|
|
991
|
+
var htmlDlReader = {
|
|
992
|
+
construct: "html-dl",
|
|
993
|
+
label: DL_LABEL,
|
|
994
|
+
formats: ["html"],
|
|
995
|
+
read: readDl,
|
|
996
|
+
apply: (input, terms) => applyEntries(input, readDl, terms, { holds: LIST_HOLDS, id: true, serialize: htmlDlEntry })
|
|
997
|
+
};
|
|
998
|
+
var htmlDfnReader = {
|
|
999
|
+
construct: "html-dfn",
|
|
1000
|
+
label: DFN_LABEL,
|
|
1001
|
+
formats: ["html"],
|
|
1002
|
+
read: readDfn
|
|
1003
|
+
};
|
|
1004
|
+
|
|
1005
|
+
// src/term/core/readers/manifest.ts
|
|
1006
|
+
import { isMap, isNode, isScalar, isSeq, LineCounter, parseDocument, stringify as stringifyYaml } from "yaml";
|
|
1007
|
+
var LABEL2 = "manifest";
|
|
1008
|
+
var FIELDS = new Set(TERM_FIELDS);
|
|
1009
|
+
function isField(key) {
|
|
1010
|
+
return FIELDS.has(key);
|
|
1011
|
+
}
|
|
1012
|
+
function read2(input) {
|
|
1013
|
+
if ((input.path ?? input.file).toLowerCase().endsWith(".json")) {
|
|
1014
|
+
try {
|
|
1015
|
+
JSON.parse(input.content);
|
|
1016
|
+
} catch (error) {
|
|
1017
|
+
throw new TermError(`${input.file}: could not be parsed as JSON: ${errorMessage(error)}`);
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
const lineCounter = new LineCounter();
|
|
1021
|
+
const doc = parseDocument(input.content, { lineCounter, prettyErrors: false });
|
|
1022
|
+
const [firstError] = doc.errors;
|
|
1023
|
+
if (firstError !== void 0) {
|
|
1024
|
+
throw new TermError(`${input.file}: could not be parsed as YAML: ${firstError.message}`);
|
|
1025
|
+
}
|
|
1026
|
+
const lineOf2 = (node) => {
|
|
1027
|
+
const range = node?.range;
|
|
1028
|
+
return range === void 0 || range === null ? void 0 : lineCounter.linePos(range[0]).line;
|
|
1029
|
+
};
|
|
1030
|
+
const root = doc.contents;
|
|
1031
|
+
if (root === null) return { terms: [], notices: [] };
|
|
1032
|
+
if (!isMap(root)) {
|
|
1033
|
+
throw new TermError(`${input.file}: a term manifest is a mapping of id to entry.`);
|
|
1034
|
+
}
|
|
1035
|
+
const terms = [];
|
|
1036
|
+
const notices = [];
|
|
1037
|
+
for (const pair of root.items) {
|
|
1038
|
+
const keyNode = isScalar(pair.key) ? pair.key : void 0;
|
|
1039
|
+
const id = textOf(keyNode?.value);
|
|
1040
|
+
const line = lineOf2(keyNode) ?? 1;
|
|
1041
|
+
if (id === void 0) {
|
|
1042
|
+
throw new TermError(`${input.file}:${line}: an entry's key is its id, and must be a non-empty string.`);
|
|
1043
|
+
}
|
|
1044
|
+
const value = pair.value;
|
|
1045
|
+
if (!isMap(value)) {
|
|
1046
|
+
throw new TermError(`${input.file}:${line}: entry "${id}" is not a mapping of fields.`);
|
|
1047
|
+
}
|
|
1048
|
+
const raw = {};
|
|
1049
|
+
const lines = {};
|
|
1050
|
+
for (const field of value.items) {
|
|
1051
|
+
const fieldKey = isScalar(field.key) ? field.key : void 0;
|
|
1052
|
+
const name = fieldKey?.value;
|
|
1053
|
+
if (typeof name !== "string" || !isField(name)) continue;
|
|
1054
|
+
const fieldValue = field.value;
|
|
1055
|
+
raw[name] = isNode(fieldValue) ? fieldValue.toJSON() : fieldValue;
|
|
1056
|
+
lines[name] = lineOf2(fieldKey);
|
|
1057
|
+
}
|
|
1058
|
+
const record = recordOf(raw);
|
|
1059
|
+
if (record === void 0) {
|
|
1060
|
+
notices.push(skipped(input, line, LABEL2));
|
|
1061
|
+
continue;
|
|
1062
|
+
}
|
|
1063
|
+
for (const ignored of ignoredFields(raw)) {
|
|
1064
|
+
notices.push(ignoredNotice(input, lines[ignored.field] ?? line, record.label, ignored));
|
|
1065
|
+
}
|
|
1066
|
+
terms.push(termOf(input, { record, recordId: id, construct: "manifest", line, lines }));
|
|
1067
|
+
}
|
|
1068
|
+
return { terms, notices };
|
|
1069
|
+
}
|
|
1070
|
+
function entryOf(record) {
|
|
1071
|
+
const entry = {};
|
|
1072
|
+
for (const field of TERM_FIELDS) {
|
|
1073
|
+
const value = record[field];
|
|
1074
|
+
if (value !== void 0) entry[field] = value;
|
|
1075
|
+
}
|
|
1076
|
+
return entry;
|
|
1077
|
+
}
|
|
1078
|
+
function currentRecord(value) {
|
|
1079
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return {};
|
|
1080
|
+
const raw = {};
|
|
1081
|
+
for (const field of TERM_FIELDS) raw[field] = value[field];
|
|
1082
|
+
return recordOf(raw) ?? {};
|
|
1083
|
+
}
|
|
1084
|
+
function changedFields(current, record) {
|
|
1085
|
+
return TERM_FIELDS.filter((field) => JSON.stringify(current[field]) !== JSON.stringify(record[field]));
|
|
1086
|
+
}
|
|
1087
|
+
function applyJson(input, terms) {
|
|
1088
|
+
let data;
|
|
1089
|
+
try {
|
|
1090
|
+
data = JSON.parse(input.content);
|
|
1091
|
+
} catch (error) {
|
|
1092
|
+
throw new TermError(`${input.file}: could not be parsed as JSON: ${errorMessage(error)}`);
|
|
1093
|
+
}
|
|
1094
|
+
if (typeof data !== "object" || data === null || Array.isArray(data)) {
|
|
1095
|
+
throw new TermError(`${input.file}: a term manifest is a mapping of id to entry.`);
|
|
1096
|
+
}
|
|
1097
|
+
const root = data;
|
|
1098
|
+
let changed = false;
|
|
1099
|
+
for (const term of terms) {
|
|
1100
|
+
const existing = root[term.id];
|
|
1101
|
+
if (typeof existing !== "object" || existing === null || Array.isArray(existing)) {
|
|
1102
|
+
if (existing !== void 0) {
|
|
1103
|
+
throw new TermError(`${input.file}: entry "${term.id}" is not a mapping of fields.`);
|
|
1104
|
+
}
|
|
1105
|
+
root[term.id] = entryOf(term.record);
|
|
1106
|
+
changed = true;
|
|
1107
|
+
continue;
|
|
1108
|
+
}
|
|
1109
|
+
const entry = existing;
|
|
1110
|
+
const fields = changedFields(currentRecord(entry), term.record);
|
|
1111
|
+
if (fields.length === 0) continue;
|
|
1112
|
+
const next = {};
|
|
1113
|
+
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];
|
|
1116
|
+
}
|
|
1117
|
+
for (const field of fields) {
|
|
1118
|
+
if (term.record[field] !== void 0 && !(field in next)) next[field] = term.record[field];
|
|
1119
|
+
}
|
|
1120
|
+
root[term.id] = next;
|
|
1121
|
+
changed = true;
|
|
1122
|
+
}
|
|
1123
|
+
if (!changed) return input.content;
|
|
1124
|
+
const text = `${JSON.stringify(root, null, 2)}
|
|
1125
|
+
`;
|
|
1126
|
+
return input.content.includes("\r\n") ? text.replaceAll("\n", "\r\n") : text;
|
|
1127
|
+
}
|
|
1128
|
+
function entryRanges(root) {
|
|
1129
|
+
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];
|
|
1135
|
+
if (id !== void 0 && start !== void 0 && end !== void 0) ranges.set(id, { start, end });
|
|
1136
|
+
}
|
|
1137
|
+
return ranges;
|
|
1138
|
+
}
|
|
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];
|
|
1143
|
+
if (value === void 0) {
|
|
1144
|
+
entry.delete(field);
|
|
1145
|
+
} else if (Array.isArray(value)) {
|
|
1146
|
+
const previous = entry.get(field, true);
|
|
1147
|
+
const node = doc.createNode(value);
|
|
1148
|
+
node.flow = isSeq(previous) && previous.flow === true;
|
|
1149
|
+
entry.set(field, node);
|
|
1150
|
+
} else {
|
|
1151
|
+
entry.set(field, value);
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
return fields.length > 0;
|
|
1155
|
+
}
|
|
1156
|
+
function applyYaml(input, terms) {
|
|
1157
|
+
const { content } = input;
|
|
1158
|
+
const doc = parseDocument(content, { prettyErrors: false });
|
|
1159
|
+
const [firstError] = doc.errors;
|
|
1160
|
+
if (firstError !== void 0) {
|
|
1161
|
+
throw new TermError(`${input.file}: could not be parsed as YAML: ${firstError.message}`);
|
|
1162
|
+
}
|
|
1163
|
+
const eol = content.includes("\r\n") ? "\r\n" : "\n";
|
|
1164
|
+
const root = doc.contents;
|
|
1165
|
+
if (root === null) {
|
|
1166
|
+
if (terms.length === 0) return content;
|
|
1167
|
+
const entries = Object.fromEntries(terms.map((term) => [term.id, entryOf(term.record)]));
|
|
1168
|
+
return stringifyYaml(entries, { lineWidth: 0 }).replaceAll("\n", eol);
|
|
1169
|
+
}
|
|
1170
|
+
if (!isMap(root)) {
|
|
1171
|
+
throw new TermError(`${input.file}: a term manifest is a mapping of id to entry.`);
|
|
1172
|
+
}
|
|
1173
|
+
const wholeFile = root.flow === true;
|
|
1174
|
+
const before = entryRanges(root);
|
|
1175
|
+
const changed = [];
|
|
1176
|
+
const added = [];
|
|
1177
|
+
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)));
|
|
1181
|
+
added.push(term.id);
|
|
1182
|
+
continue;
|
|
1183
|
+
}
|
|
1184
|
+
if (!isMap(pair.value)) {
|
|
1185
|
+
throw new TermError(`${input.file}: entry "${term.id}" is not a mapping of fields.`);
|
|
1186
|
+
}
|
|
1187
|
+
if (editEntry(doc, pair.value, term.record)) changed.push(term.id);
|
|
1188
|
+
}
|
|
1189
|
+
if (changed.length === 0 && added.length === 0) return content;
|
|
1190
|
+
const text = doc.toString({ lineWidth: 0 });
|
|
1191
|
+
if (wholeFile) return text.replaceAll("\n", eol);
|
|
1192
|
+
const written = parseDocument(text).contents;
|
|
1193
|
+
const after = isMap(written) ? entryRanges(written) : /* @__PURE__ */ new Map();
|
|
1194
|
+
const entryText = (id) => {
|
|
1195
|
+
const range = after.get(id);
|
|
1196
|
+
if (range === void 0) throw new TermError(`${input.file}: could not write entry "${id}".`);
|
|
1197
|
+
return text.slice(range.start, range.end).replaceAll("\n", eol);
|
|
1198
|
+
};
|
|
1199
|
+
let next = content;
|
|
1200
|
+
const edits = changed.map((id) => ({ id, range: before.get(id) })).sort((a, b) => (b.range?.start ?? 0) - (a.range?.start ?? 0));
|
|
1201
|
+
for (const { id, range } of edits) {
|
|
1202
|
+
if (range === void 0) throw new TermError(`${input.file}: could not write entry "${id}".`);
|
|
1203
|
+
next = next.slice(0, range.start) + entryText(id) + next.slice(range.end);
|
|
1204
|
+
}
|
|
1205
|
+
if (added.length > 0) {
|
|
1206
|
+
if (next !== "" && !next.endsWith("\n")) next += eol;
|
|
1207
|
+
next += added.map((id) => `${entryText(id)}${eol}`).join("");
|
|
1208
|
+
}
|
|
1209
|
+
return next;
|
|
1210
|
+
}
|
|
1211
|
+
function isJson(input) {
|
|
1212
|
+
return (input.path ?? input.file).toLowerCase().endsWith(".json");
|
|
1213
|
+
}
|
|
1214
|
+
var manifestReader = {
|
|
1215
|
+
construct: "manifest",
|
|
1216
|
+
label: LABEL2,
|
|
1217
|
+
formats: ["manifest"],
|
|
1218
|
+
read: read2,
|
|
1219
|
+
apply: (input, terms) => isJson(input) ? applyJson(input, terms) : applyYaml(input, terms)
|
|
1220
|
+
};
|
|
1221
|
+
|
|
1222
|
+
// src/term/core/readers/page.ts
|
|
1223
|
+
var LABEL3 = "page";
|
|
1224
|
+
function read3(input) {
|
|
1225
|
+
if (!declares(input, "term")) return nothing();
|
|
1226
|
+
const raw = {};
|
|
1227
|
+
const lines = {};
|
|
1228
|
+
for (const field of TERM_FIELDS) {
|
|
1229
|
+
raw[field] = input.metadata[field];
|
|
1230
|
+
lines[field] = input.lineFor(`/${field}`);
|
|
1231
|
+
}
|
|
1232
|
+
const record = recordOf(raw);
|
|
1233
|
+
if (record === void 0) return { terms: [], notices: [skipped(input, 1, LABEL3)] };
|
|
1234
|
+
return {
|
|
1235
|
+
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
|
+
)
|
|
1239
|
+
};
|
|
1240
|
+
}
|
|
1241
|
+
function apply(input, terms) {
|
|
1242
|
+
const [term] = terms;
|
|
1243
|
+
if (term === void 0) return input.content;
|
|
1244
|
+
const [current] = read3(input).terms;
|
|
1245
|
+
if (current === void 0) {
|
|
1246
|
+
throw new TermError(`${input.file}: is not a term page any more. Read the file again before writing it.`);
|
|
1247
|
+
}
|
|
1248
|
+
const patch = {};
|
|
1249
|
+
const deletions = [];
|
|
1250
|
+
for (const field of TERM_FIELDS) {
|
|
1251
|
+
if (sameFields(current.record, term.record, [field])) continue;
|
|
1252
|
+
const value = term.record[field];
|
|
1253
|
+
if (value === void 0) deletions.push(field);
|
|
1254
|
+
else patch[field] = value;
|
|
1255
|
+
}
|
|
1256
|
+
if (Object.keys(patch).length === 0 && deletions.length === 0) return input.content;
|
|
1257
|
+
const extractor = extractorByName(input.format);
|
|
1258
|
+
if (extractor?.apply === void 0) {
|
|
1259
|
+
throw new TermError(`${input.file}: manni cannot write ${input.format} metadata.`);
|
|
1260
|
+
}
|
|
1261
|
+
const filePath = input.path ?? input.file;
|
|
1262
|
+
let next;
|
|
1263
|
+
try {
|
|
1264
|
+
next = extractor.apply(input.content, patch, { deletions, filePath });
|
|
1265
|
+
} catch (error) {
|
|
1266
|
+
throw new TermError(`${input.file}: ${errorMessage(error)}`);
|
|
1267
|
+
}
|
|
1268
|
+
const written = extractor.extract(next, filePath).data;
|
|
1269
|
+
for (const field of deletions) {
|
|
1270
|
+
if (written[field] !== void 0) {
|
|
1271
|
+
throw new TermError(`${input.file}: could not remove ${field} from its ${input.format} metadata. Remove it by hand.`);
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
return next;
|
|
1275
|
+
}
|
|
1276
|
+
var pageReader = {
|
|
1277
|
+
construct: "page",
|
|
1278
|
+
label: LABEL3,
|
|
1279
|
+
formats: ["markdown", "mdx", "asciidoc", "rst", "html", "xml"],
|
|
1280
|
+
read: read3,
|
|
1281
|
+
apply
|
|
1282
|
+
};
|
|
1283
|
+
|
|
1284
|
+
// src/term/core/readers/structured.ts
|
|
1285
|
+
var STRUCTURED_READERS = [
|
|
1286
|
+
pageReader,
|
|
1287
|
+
manifestReader,
|
|
1288
|
+
ditaGlossentryReader,
|
|
1289
|
+
ditaGlossgroupReader,
|
|
1290
|
+
docbookGlossaryReader,
|
|
1291
|
+
htmlDlReader,
|
|
1292
|
+
htmlDfnReader
|
|
1293
|
+
];
|
|
1294
|
+
|
|
1295
|
+
// src/term/core/readers/body.ts
|
|
1296
|
+
function textStart(line) {
|
|
1297
|
+
return line.start + (line.text.length - line.text.trimStart().length);
|
|
1298
|
+
}
|
|
1299
|
+
function isBlank(line) {
|
|
1300
|
+
return line.text.trim() === "";
|
|
1301
|
+
}
|
|
1302
|
+
function nextNonBlank(lines, from) {
|
|
1303
|
+
let k = from;
|
|
1304
|
+
for (let line = lines[k]; line !== void 0 && !line.code && isBlank(line); line = lines[k]) k++;
|
|
1305
|
+
return k;
|
|
1306
|
+
}
|
|
1307
|
+
function bodyLines(input) {
|
|
1308
|
+
const { content } = input;
|
|
1309
|
+
const bodyStart = locateFrontmatter(content)?.closeEnd ?? 0;
|
|
1310
|
+
const body = content.slice(bodyStart);
|
|
1311
|
+
const code = codeRegions(body, input.format, { spans: false });
|
|
1312
|
+
let line = 1;
|
|
1313
|
+
for (let i = 0; i < bodyStart; i++) {
|
|
1314
|
+
if (content.charCodeAt(i) === 10) line++;
|
|
1315
|
+
}
|
|
1316
|
+
const out = [];
|
|
1317
|
+
let pos = bodyStart;
|
|
1318
|
+
while (pos < content.length) {
|
|
1319
|
+
const nl = content.indexOf("\n", pos);
|
|
1320
|
+
const stop = nl === -1 ? content.length : nl;
|
|
1321
|
+
const end = stop > pos && content.charCodeAt(stop - 1) === 13 ? stop - 1 : stop;
|
|
1322
|
+
out.push({
|
|
1323
|
+
text: content.slice(pos, end),
|
|
1324
|
+
start: pos,
|
|
1325
|
+
end,
|
|
1326
|
+
line,
|
|
1327
|
+
code: codeEndAt(code, pos - bodyStart) !== void 0
|
|
1328
|
+
});
|
|
1329
|
+
line++;
|
|
1330
|
+
pos = stop + 1;
|
|
1331
|
+
}
|
|
1332
|
+
return out;
|
|
1333
|
+
}
|
|
1334
|
+
function definitionText(paragraphs) {
|
|
1335
|
+
const text = paragraphs.map(
|
|
1336
|
+
(lines) => lines.map((l) => l.trim()).filter((l) => l !== "").join(" ")
|
|
1337
|
+
).filter((p) => p !== "").join("\n\n");
|
|
1338
|
+
return text === "" ? void 0 : text;
|
|
1339
|
+
}
|
|
1340
|
+
function termOf2(input, construct, entry) {
|
|
1341
|
+
const [first, ...rest] = entry.labels;
|
|
1342
|
+
const label = first?.text.trim() ?? "";
|
|
1343
|
+
const record = { label };
|
|
1344
|
+
const fieldLines = { label: first?.line ?? entry.definitionLine };
|
|
1345
|
+
const alts = rest.map((l) => l.text.trim()).filter((t) => t !== "");
|
|
1346
|
+
const [firstAlt] = rest;
|
|
1347
|
+
if (alts.length > 0 && firstAlt !== void 0) {
|
|
1348
|
+
record["alt-labels"] = alts;
|
|
1349
|
+
fieldLines["alt-labels"] = firstAlt.line;
|
|
1350
|
+
}
|
|
1351
|
+
record.definition = entry.definition;
|
|
1352
|
+
fieldLines.definition = entry.definitionLine;
|
|
1353
|
+
const language = input.metadata["language"];
|
|
1354
|
+
return {
|
|
1355
|
+
id: slugOf(label),
|
|
1356
|
+
record,
|
|
1357
|
+
...typeof language === "string" && language.trim() !== "" ? { language: language.trim() } : {},
|
|
1358
|
+
location: {
|
|
1359
|
+
file: input.file,
|
|
1360
|
+
...input.path === void 0 ? {} : { path: input.path },
|
|
1361
|
+
construct,
|
|
1362
|
+
line: first?.line ?? entry.definitionLine,
|
|
1363
|
+
fieldLines,
|
|
1364
|
+
span: { start: entry.start, end: entry.end }
|
|
1365
|
+
}
|
|
1366
|
+
};
|
|
1367
|
+
}
|
|
1368
|
+
function skippedNotice(input, line, label, missing) {
|
|
1369
|
+
return `${input.file}:${String(line)}: skipped a ${label} entry with no ${missing}.`;
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
// src/term/core/readers/asciidoc-glossary.ts
|
|
1373
|
+
var LABEL4 = "[glossary] list";
|
|
1374
|
+
var ATTRIBUTE = /^\[glossary\][ \t]*$/;
|
|
1375
|
+
var ITEM = /^[ \t]*(.*?[^:\s])::(?:[ \t]+(.*))?$/;
|
|
1376
|
+
var BLOCK_TITLE = /^\.[^.\s]/;
|
|
1377
|
+
var LIST_END = /^(?:=+[ \t]|\[.*\][ \t]*$|(?:-{4,}|={4,}|\*{4,}|\.{4,}|_{4,}|\+{4,}|\|===)[ \t]*$)/;
|
|
1378
|
+
function item(line) {
|
|
1379
|
+
const match = ITEM.exec(line.text);
|
|
1380
|
+
const term = match?.[1];
|
|
1381
|
+
if (match === null || term === void 0) return void 0;
|
|
1382
|
+
const text = match[2]?.trim();
|
|
1383
|
+
return { term, text: text === "" ? void 0 : text };
|
|
1384
|
+
}
|
|
1385
|
+
function read4(input) {
|
|
1386
|
+
const terms = [];
|
|
1387
|
+
const notices = [];
|
|
1388
|
+
const lines = bodyLines(input);
|
|
1389
|
+
let i = 0;
|
|
1390
|
+
while (i < lines.length) {
|
|
1391
|
+
const line = lines[i];
|
|
1392
|
+
i++;
|
|
1393
|
+
if (line === void 0 || line.code || !ATTRIBUTE.test(line.text)) continue;
|
|
1394
|
+
let start = i;
|
|
1395
|
+
for (let l = lines[start]; l !== void 0 && !l.code && (isBlank(l) || BLOCK_TITLE.test(l.text)); l = lines[start]) {
|
|
1396
|
+
start++;
|
|
1397
|
+
}
|
|
1398
|
+
const first = lines[start];
|
|
1399
|
+
if (first === void 0 || first.code || item(first) === void 0) continue;
|
|
1400
|
+
i = readList(input, lines, start, terms, notices);
|
|
1401
|
+
}
|
|
1402
|
+
return { terms, notices };
|
|
1403
|
+
}
|
|
1404
|
+
function readList(input, lines, at, terms, notices) {
|
|
1405
|
+
let pending = [];
|
|
1406
|
+
let open;
|
|
1407
|
+
const close = () => {
|
|
1408
|
+
if (open !== void 0) {
|
|
1409
|
+
const text = definitionText(open.paragraphs);
|
|
1410
|
+
const [firstLabel] = open.labels;
|
|
1411
|
+
if (text !== void 0 && firstLabel !== void 0) {
|
|
1412
|
+
terms.push(
|
|
1413
|
+
termOf2(input, "asciidoc-glossary", {
|
|
1414
|
+
labels: open.labels.map((l) => ({ text: itemTerm(l), line: l.line })),
|
|
1415
|
+
definition: text,
|
|
1416
|
+
definitionLine: open.definitionLine,
|
|
1417
|
+
start: textStart(firstLabel),
|
|
1418
|
+
end: open.last.end
|
|
1419
|
+
})
|
|
1420
|
+
);
|
|
1421
|
+
} else if (firstLabel !== void 0) {
|
|
1422
|
+
notices.push(skippedNotice(input, firstLabel.line, LABEL4, "definition"));
|
|
1423
|
+
}
|
|
1424
|
+
open = void 0;
|
|
1425
|
+
}
|
|
1426
|
+
const [firstPending] = pending;
|
|
1427
|
+
if (firstPending !== void 0) {
|
|
1428
|
+
notices.push(skippedNotice(input, firstPending.line, LABEL4, "definition"));
|
|
1429
|
+
pending = [];
|
|
1430
|
+
}
|
|
1431
|
+
};
|
|
1432
|
+
let i = at;
|
|
1433
|
+
for (; ; ) {
|
|
1434
|
+
const line = lines[i];
|
|
1435
|
+
if (line === void 0 || line.code) break;
|
|
1436
|
+
if (isBlank(line)) {
|
|
1437
|
+
close();
|
|
1438
|
+
const k = nextNonBlank(lines, i);
|
|
1439
|
+
const next = lines[k];
|
|
1440
|
+
if (next === void 0 || next.code || item(next) === void 0) break;
|
|
1441
|
+
i = k;
|
|
1442
|
+
continue;
|
|
1443
|
+
}
|
|
1444
|
+
const entry = item(line);
|
|
1445
|
+
if (entry !== void 0) {
|
|
1446
|
+
if (open !== void 0) close();
|
|
1447
|
+
pending.push(line);
|
|
1448
|
+
if (entry.text !== void 0) {
|
|
1449
|
+
open = { labels: pending, definitionLine: line.line, paragraphs: [[entry.text]], last: line };
|
|
1450
|
+
pending = [];
|
|
1451
|
+
}
|
|
1452
|
+
i++;
|
|
1453
|
+
continue;
|
|
1454
|
+
}
|
|
1455
|
+
if (line.text.trim() === "+" && open !== void 0) {
|
|
1456
|
+
open.paragraphs.push([]);
|
|
1457
|
+
i++;
|
|
1458
|
+
continue;
|
|
1459
|
+
}
|
|
1460
|
+
if (LIST_END.test(line.text) || BLOCK_TITLE.test(line.text)) break;
|
|
1461
|
+
if (open !== void 0) {
|
|
1462
|
+
open.paragraphs.at(-1)?.push(line.text);
|
|
1463
|
+
open.last = line;
|
|
1464
|
+
} else if (pending.length > 0) {
|
|
1465
|
+
open = { labels: pending, definitionLine: line.line, paragraphs: [[line.text]], last: line };
|
|
1466
|
+
pending = [];
|
|
1467
|
+
} else {
|
|
1468
|
+
break;
|
|
1469
|
+
}
|
|
1470
|
+
i++;
|
|
1471
|
+
}
|
|
1472
|
+
close();
|
|
1473
|
+
return i;
|
|
1474
|
+
}
|
|
1475
|
+
function itemTerm(line) {
|
|
1476
|
+
return item(line)?.term ?? line.text;
|
|
1477
|
+
}
|
|
1478
|
+
var asciidocGlossaryReader = {
|
|
1479
|
+
construct: "asciidoc-glossary",
|
|
1480
|
+
label: LABEL4,
|
|
1481
|
+
formats: ["asciidoc"],
|
|
1482
|
+
read: read4,
|
|
1483
|
+
apply: (input, terms) => applyEntries(input, read4, terms, { holds: LIST_HOLDS, id: false, serialize: (term) => asciidocEntry(term.record) })
|
|
1484
|
+
};
|
|
1485
|
+
|
|
1486
|
+
// src/term/core/readers/markdown-deflist.ts
|
|
1487
|
+
var LABEL5 = "definition list";
|
|
1488
|
+
var DEFINITION = /^:(?:[ \t]+(.*))?$/;
|
|
1489
|
+
var INDENTED = /^(?: {4}|\t)/;
|
|
1490
|
+
var HEADING = /^#{1,6}(?:[ \t]|$)/;
|
|
1491
|
+
function definitionStart(line) {
|
|
1492
|
+
if (line === void 0 || line.code) return void 0;
|
|
1493
|
+
const match = DEFINITION.exec(line.text);
|
|
1494
|
+
return match === null ? void 0 : match[1] ?? "";
|
|
1495
|
+
}
|
|
1496
|
+
function read5(input) {
|
|
1497
|
+
const terms = [];
|
|
1498
|
+
const notices = [];
|
|
1499
|
+
if (input.metadata["type"] !== "term-set") return { terms, notices };
|
|
1500
|
+
const lines = bodyLines(input);
|
|
1501
|
+
let i = 0;
|
|
1502
|
+
while (i < lines.length) {
|
|
1503
|
+
const first = lines[i];
|
|
1504
|
+
if (first === void 0) break;
|
|
1505
|
+
if (first.code || isBlank(first)) {
|
|
1506
|
+
i++;
|
|
1507
|
+
continue;
|
|
1508
|
+
}
|
|
1509
|
+
const labels = [];
|
|
1510
|
+
let j = i;
|
|
1511
|
+
for (; ; ) {
|
|
1512
|
+
const line = lines[j];
|
|
1513
|
+
if (line === void 0 || line.code || isBlank(line) || definitionStart(line) !== void 0) break;
|
|
1514
|
+
labels.push(line);
|
|
1515
|
+
j++;
|
|
1516
|
+
}
|
|
1517
|
+
const opener = definitionStart(lines[j]);
|
|
1518
|
+
if (opener === void 0) {
|
|
1519
|
+
i = j === i ? i + 1 : j;
|
|
1520
|
+
continue;
|
|
1521
|
+
}
|
|
1522
|
+
if (labels.length === 0 || labels.some((l) => HEADING.test(l.text))) {
|
|
1523
|
+
const orphan = lines[j];
|
|
1524
|
+
if (orphan !== void 0) notices.push(skippedNotice(input, orphan.line, LABEL5, "term"));
|
|
1525
|
+
i = readDefinitions(lines, j, []);
|
|
1526
|
+
continue;
|
|
1527
|
+
}
|
|
1528
|
+
const definitions = [];
|
|
1529
|
+
i = readDefinitions(lines, j, definitions);
|
|
1530
|
+
const firstLabel = labels[0];
|
|
1531
|
+
const [kept] = definitions;
|
|
1532
|
+
if (firstLabel === void 0 || kept === void 0) continue;
|
|
1533
|
+
const text = definitionText(kept.paragraphs);
|
|
1534
|
+
if (text === void 0) {
|
|
1535
|
+
notices.push(skippedNotice(input, firstLabel.line, LABEL5, "definition"));
|
|
1536
|
+
continue;
|
|
1537
|
+
}
|
|
1538
|
+
for (const extra of definitions.slice(1)) {
|
|
1539
|
+
notices.push(
|
|
1540
|
+
`${input.file}:${String(extra.line)}: kept the first of ${String(definitions.length)} definitions for "${firstLabel.text.trim()}".`
|
|
1541
|
+
);
|
|
1542
|
+
}
|
|
1543
|
+
const last = lastContentLine(lines, i);
|
|
1544
|
+
terms.push(
|
|
1545
|
+
termOf2(input, "markdown-deflist", {
|
|
1546
|
+
labels: labels.map((l) => ({ text: l.text, line: l.line })),
|
|
1547
|
+
definition: text,
|
|
1548
|
+
definitionLine: kept.line,
|
|
1549
|
+
start: textStart(firstLabel),
|
|
1550
|
+
end: last?.end ?? firstLabel.end
|
|
1551
|
+
})
|
|
1552
|
+
);
|
|
1553
|
+
}
|
|
1554
|
+
return { terms, notices };
|
|
1555
|
+
}
|
|
1556
|
+
function lastContentLine(lines, stop) {
|
|
1557
|
+
for (let k = stop - 1; k >= 0; k--) {
|
|
1558
|
+
const line = lines[k];
|
|
1559
|
+
if (line !== void 0 && !isBlank(line)) return line;
|
|
1560
|
+
}
|
|
1561
|
+
return void 0;
|
|
1562
|
+
}
|
|
1563
|
+
function readDefinitions(lines, at, out) {
|
|
1564
|
+
let i = at;
|
|
1565
|
+
for (; ; ) {
|
|
1566
|
+
const opener = lines[i];
|
|
1567
|
+
const text = definitionStart(opener);
|
|
1568
|
+
if (opener === void 0 || text === void 0) return i;
|
|
1569
|
+
const definition = { line: opener.line, paragraphs: [[text]] };
|
|
1570
|
+
out.push(definition);
|
|
1571
|
+
i++;
|
|
1572
|
+
for (; ; ) {
|
|
1573
|
+
const line = lines[i];
|
|
1574
|
+
if (line === void 0 || line.code) return i;
|
|
1575
|
+
if (definitionStart(line) !== void 0) break;
|
|
1576
|
+
if (!isBlank(line)) {
|
|
1577
|
+
definition.paragraphs.at(-1)?.push(line.text.replace(INDENTED, ""));
|
|
1578
|
+
i++;
|
|
1579
|
+
continue;
|
|
1580
|
+
}
|
|
1581
|
+
const k = nextNonBlank(lines, i);
|
|
1582
|
+
const next = lines[k];
|
|
1583
|
+
if (next === void 0 || next.code) return i;
|
|
1584
|
+
if (definitionStart(next) !== void 0) {
|
|
1585
|
+
i = k;
|
|
1586
|
+
break;
|
|
1587
|
+
}
|
|
1588
|
+
if (!INDENTED.test(next.text)) return i;
|
|
1589
|
+
definition.paragraphs.push([]);
|
|
1590
|
+
i = k;
|
|
1591
|
+
}
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1594
|
+
var markdownDeflistReader = {
|
|
1595
|
+
construct: "markdown-deflist",
|
|
1596
|
+
label: LABEL5,
|
|
1597
|
+
formats: ["markdown", "mdx"],
|
|
1598
|
+
read: read5,
|
|
1599
|
+
apply: (input, terms) => applyEntries(input, read5, terms, { holds: LIST_HOLDS, id: false, serialize: (term) => markdownEntry(term.record) })
|
|
1600
|
+
};
|
|
1601
|
+
|
|
1602
|
+
// src/term/core/readers/rst-glossary.ts
|
|
1603
|
+
var LABEL6 = ".. glossary::";
|
|
1604
|
+
var DIRECTIVE = /^[ \t]*\.\.[ \t]+glossary::[ \t]*$/;
|
|
1605
|
+
var CODE_DIRECTIVE = /^[ \t]*\.\.[ \t]+(?:code-block|code|sourcecode)::/;
|
|
1606
|
+
var EXPLICIT_MARKUP = /^[ \t]*\.\.(?:[ \t]|$)/;
|
|
1607
|
+
var OPTION = /^[ \t]*:[^:\s][^:]*:(?:[ \t].*)?$/;
|
|
1608
|
+
var CLASSIFIER = /[ \t]+:[ \t]+/;
|
|
1609
|
+
function indentOf(text) {
|
|
1610
|
+
let width = 0;
|
|
1611
|
+
for (const ch of text) {
|
|
1612
|
+
if (ch === " ") width++;
|
|
1613
|
+
else if (ch === " ") width += 8 - width % 8;
|
|
1614
|
+
else break;
|
|
1615
|
+
}
|
|
1616
|
+
return width;
|
|
1617
|
+
}
|
|
1618
|
+
function opensLiteral(line) {
|
|
1619
|
+
if (CODE_DIRECTIVE.test(line.text)) return true;
|
|
1620
|
+
return !EXPLICIT_MARKUP.test(line.text) && line.text.trimEnd().endsWith("::");
|
|
1621
|
+
}
|
|
1622
|
+
function read6(input) {
|
|
1623
|
+
const terms = [];
|
|
1624
|
+
const notices = [];
|
|
1625
|
+
const lines = bodyLines(input);
|
|
1626
|
+
let i = 0;
|
|
1627
|
+
while (i < lines.length) {
|
|
1628
|
+
const line = lines[i];
|
|
1629
|
+
if (line === void 0) break;
|
|
1630
|
+
if (isBlank(line)) {
|
|
1631
|
+
i++;
|
|
1632
|
+
continue;
|
|
1633
|
+
}
|
|
1634
|
+
if (DIRECTIVE.test(line.text)) {
|
|
1635
|
+
i = readGlossary(input, lines, i, terms, notices);
|
|
1636
|
+
continue;
|
|
1637
|
+
}
|
|
1638
|
+
i = opensLiteral(line) ? blockEnd(lines, i + 1, indentOf(line.text)) : i + 1;
|
|
1639
|
+
}
|
|
1640
|
+
return { terms, notices };
|
|
1641
|
+
}
|
|
1642
|
+
function blockEnd(lines, from, indent) {
|
|
1643
|
+
let k = from;
|
|
1644
|
+
for (let l = lines[k]; l !== void 0 && (isBlank(l) || indentOf(l.text) > indent); l = lines[k]) k++;
|
|
1645
|
+
return k;
|
|
1646
|
+
}
|
|
1647
|
+
function readGlossary(input, lines, at, terms, notices) {
|
|
1648
|
+
const directive = lines[at];
|
|
1649
|
+
if (directive === void 0) return at + 1;
|
|
1650
|
+
const end = blockEnd(lines, at + 1, indentOf(directive.text));
|
|
1651
|
+
let i = at + 1;
|
|
1652
|
+
for (let l = lines[i]; i < end && l !== void 0 && !isBlank(l) && OPTION.test(l.text); l = lines[i]) i++;
|
|
1653
|
+
let base;
|
|
1654
|
+
let labels = [];
|
|
1655
|
+
let definition;
|
|
1656
|
+
let orphan = false;
|
|
1657
|
+
const close = () => {
|
|
1658
|
+
const [first] = labels;
|
|
1659
|
+
if (first !== void 0) {
|
|
1660
|
+
const text = definition === void 0 ? void 0 : definitionText(definition.paragraphs);
|
|
1661
|
+
if (definition !== void 0 && text !== void 0) {
|
|
1662
|
+
terms.push(
|
|
1663
|
+
termOf2(input, "rst-glossary", {
|
|
1664
|
+
labels: labels.map((l) => ({ text: termText(l), line: l.line })),
|
|
1665
|
+
definition: text,
|
|
1666
|
+
definitionLine: definition.line,
|
|
1667
|
+
start: textStart(first),
|
|
1668
|
+
end: definition.last.end
|
|
1669
|
+
})
|
|
1670
|
+
);
|
|
1671
|
+
} else {
|
|
1672
|
+
notices.push(skippedNotice(input, first.line, LABEL6, "definition"));
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1675
|
+
labels = [];
|
|
1676
|
+
definition = void 0;
|
|
1677
|
+
};
|
|
1678
|
+
let blank = false;
|
|
1679
|
+
for (; i < end; i++) {
|
|
1680
|
+
const line = lines[i];
|
|
1681
|
+
if (line === void 0) break;
|
|
1682
|
+
if (isBlank(line)) {
|
|
1683
|
+
if (definition !== void 0) definition.gap = true;
|
|
1684
|
+
blank = true;
|
|
1685
|
+
continue;
|
|
1686
|
+
}
|
|
1687
|
+
const indent = indentOf(line.text);
|
|
1688
|
+
base ??= indent;
|
|
1689
|
+
if (indent <= base) {
|
|
1690
|
+
if (definition !== void 0 || blank) close();
|
|
1691
|
+
orphan = false;
|
|
1692
|
+
blank = false;
|
|
1693
|
+
labels.push(line);
|
|
1694
|
+
continue;
|
|
1695
|
+
}
|
|
1696
|
+
blank = false;
|
|
1697
|
+
if (definition !== void 0) {
|
|
1698
|
+
if (definition.gap) {
|
|
1699
|
+
definition.paragraphs.push([]);
|
|
1700
|
+
definition.gap = false;
|
|
1701
|
+
}
|
|
1702
|
+
definition.paragraphs.at(-1)?.push(line.text);
|
|
1703
|
+
definition.last = line;
|
|
1704
|
+
} else if (labels.length > 0) {
|
|
1705
|
+
definition = { line: line.line, paragraphs: [[line.text]], last: line, gap: false };
|
|
1706
|
+
} else if (!orphan) {
|
|
1707
|
+
notices.push(skippedNotice(input, line.line, LABEL6, "term"));
|
|
1708
|
+
orphan = true;
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
close();
|
|
1712
|
+
return end;
|
|
1713
|
+
}
|
|
1714
|
+
function termText(line) {
|
|
1715
|
+
const text = line.text.trim();
|
|
1716
|
+
const match = CLASSIFIER.exec(text);
|
|
1717
|
+
return match === null ? text : text.slice(0, match.index);
|
|
1718
|
+
}
|
|
1719
|
+
var rstGlossaryReader = {
|
|
1720
|
+
construct: "rst-glossary",
|
|
1721
|
+
label: LABEL6,
|
|
1722
|
+
formats: ["rst"],
|
|
1723
|
+
read: read6,
|
|
1724
|
+
apply: (input, terms) => applyEntries(input, read6, terms, { holds: LIST_HOLDS, id: false, serialize: (term) => rstEntry(term.record) })
|
|
1725
|
+
};
|
|
1726
|
+
|
|
1727
|
+
// src/term/core/readers/text.ts
|
|
1728
|
+
var TEXT_READERS = [
|
|
1729
|
+
markdownDeflistReader,
|
|
1730
|
+
asciidocGlossaryReader,
|
|
1731
|
+
rstGlossaryReader
|
|
1732
|
+
];
|
|
1733
|
+
|
|
1734
|
+
// src/term/core/readers/index.ts
|
|
1735
|
+
var TERM_READERS = [...STRUCTURED_READERS, ...TEXT_READERS];
|
|
1736
|
+
function readersForFormat(format, readers = TERM_READERS) {
|
|
1737
|
+
return readers.filter((reader) => reader.formats.includes(format));
|
|
1738
|
+
}
|
|
1739
|
+
function readerForConstruct(construct, readers = TERM_READERS) {
|
|
1740
|
+
return readers.find((reader) => reader.construct === construct);
|
|
1741
|
+
}
|
|
1742
|
+
|
|
1743
|
+
// src/term/core/load-set.ts
|
|
1744
|
+
var MANIFEST_FORMAT = "manifest";
|
|
1745
|
+
var MANIFEST_EXTENSIONS = /* @__PURE__ */ new Set([".yaml", ".yml", ".json"]);
|
|
1746
|
+
function manifestInput(content, file, path) {
|
|
1747
|
+
return { content, file, path, format: MANIFEST_FORMAT, metadata: {}, lineFor: () => void 0 };
|
|
1748
|
+
}
|
|
1749
|
+
function labelsOf2(value) {
|
|
1750
|
+
if (typeof value === "string") return value.trim() === "" ? [] : [value];
|
|
1751
|
+
if (Array.isArray(value)) {
|
|
1752
|
+
return value.filter((item2) => typeof item2 === "string" && item2.trim() !== "");
|
|
1753
|
+
}
|
|
1754
|
+
return [];
|
|
1755
|
+
}
|
|
1756
|
+
function referencesOf(input) {
|
|
1757
|
+
const references = [];
|
|
1758
|
+
const add = (value, pointer) => {
|
|
1759
|
+
for (const label of labelsOf2(value)) {
|
|
1760
|
+
const line = input.lineFor(pointer);
|
|
1761
|
+
references.push({ file: input.file, label, ...line === void 0 ? {} : { line } });
|
|
1762
|
+
}
|
|
1763
|
+
};
|
|
1764
|
+
for (const path of CONCEPT_FIELDS) add(valueAt(input.metadata, path), fieldPointer(path));
|
|
1765
|
+
return references;
|
|
1766
|
+
}
|
|
1767
|
+
function read7(input, readers, set) {
|
|
1768
|
+
for (const reader of readersForFormat(input.format, readers)) {
|
|
1769
|
+
const result = reader.read(input);
|
|
1770
|
+
set.terms.push(...result.terms);
|
|
1771
|
+
set.notices.push(...result.notices);
|
|
1772
|
+
}
|
|
1773
|
+
}
|
|
1774
|
+
function extractInput(content, file, path, format) {
|
|
1775
|
+
const extractor = extractorByName(format);
|
|
1776
|
+
if (extractor === void 0) {
|
|
1777
|
+
throw new TermError(`${file}: no reader for format "${format}".`);
|
|
1778
|
+
}
|
|
1779
|
+
let extracted;
|
|
1780
|
+
try {
|
|
1781
|
+
extracted = extractor.extract(content, path ?? file);
|
|
1782
|
+
} catch (error) {
|
|
1783
|
+
throw new TermError(`${file}: could not be read as ${format}: ${errorMessage(error)}`);
|
|
1784
|
+
}
|
|
1785
|
+
return {
|
|
1786
|
+
content,
|
|
1787
|
+
file,
|
|
1788
|
+
...path === void 0 ? {} : { path },
|
|
1789
|
+
format: extractor.name,
|
|
1790
|
+
metadata: extracted.data,
|
|
1791
|
+
lineFor: extracted.lineFor
|
|
1792
|
+
};
|
|
1793
|
+
}
|
|
1794
|
+
async function loadTermSet(opts) {
|
|
1795
|
+
const { run } = opts;
|
|
1796
|
+
const readers = opts.readers ?? TERM_READERS;
|
|
1797
|
+
const exclude = opts.exclude ?? [];
|
|
1798
|
+
const allowEmpty = opts.allowEmpty ?? run.config?.allowEmpty === true;
|
|
1799
|
+
const usingStdin = run.inputs.includes(STDIN_TOKEN);
|
|
1800
|
+
const inputs = run.inputs.filter((input) => input !== STDIN_TOKEN);
|
|
1801
|
+
if (usingStdin && (opts.as === void 0 || opts.as === "")) {
|
|
1802
|
+
throw new TermError("reading stdin needs --as <format>.");
|
|
1803
|
+
}
|
|
1804
|
+
if (inputs.length === 0 && !usingStdin && run.manifests.length === 0) {
|
|
1805
|
+
throw new TermError(
|
|
1806
|
+
"No files to read. Pass paths/globs, or declare a collection under `collections:` in manni.config.yaml."
|
|
1807
|
+
);
|
|
1808
|
+
}
|
|
1809
|
+
const set = { terms: [], references: [], notices: [] };
|
|
1810
|
+
if (inputs.length > 0) {
|
|
1811
|
+
const { files, gitignoreSkipped, named } = await resolveTargetSet({
|
|
1812
|
+
inputs,
|
|
1813
|
+
cwd: run.base,
|
|
1814
|
+
exclude,
|
|
1815
|
+
...opts.exts === void 0 ? {} : { exts: opts.exts },
|
|
1816
|
+
allowEmpty,
|
|
1817
|
+
...gitignoreOptions({
|
|
1818
|
+
...opts.noGitignore === true ? { flag: false } : {},
|
|
1819
|
+
...run.config?.respectGitignore === void 0 ? {} : { configured: run.config.respectGitignore },
|
|
1820
|
+
...opts.onNotice ? { onNotice: opts.onNotice } : {}
|
|
1821
|
+
})
|
|
1822
|
+
});
|
|
1823
|
+
assertNonEmpty({
|
|
1824
|
+
files,
|
|
1825
|
+
inputs,
|
|
1826
|
+
usingStdin,
|
|
1827
|
+
allowEmpty,
|
|
1828
|
+
exclude,
|
|
1829
|
+
...opts.exts === void 0 ? {} : { exts: opts.exts },
|
|
1830
|
+
gitignoreSkipped,
|
|
1831
|
+
action: "read"
|
|
1832
|
+
});
|
|
1833
|
+
const namedFiles = new Set(named);
|
|
1834
|
+
for (const file of files) {
|
|
1835
|
+
const path = resolve2(run.base, file);
|
|
1836
|
+
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);
|
|
1844
|
+
continue;
|
|
1845
|
+
}
|
|
1846
|
+
const extractor = extractorForExtension(extname(file));
|
|
1847
|
+
if (extractor === void 0) {
|
|
1848
|
+
throw new TermError(`${file}: no reader for its extension. Pass --as <format> through stdin to read it.`);
|
|
1849
|
+
}
|
|
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);
|
|
1857
|
+
set.references.push(...referencesOf(input));
|
|
1858
|
+
read7(input, readers, set);
|
|
1859
|
+
}
|
|
1860
|
+
}
|
|
1861
|
+
if (usingStdin && opts.as !== void 0) {
|
|
1862
|
+
const input = extractInput(opts.stdin ?? "", STDIN_LABEL, void 0, opts.as);
|
|
1863
|
+
set.references.push(...referencesOf(input));
|
|
1864
|
+
read7(input, readers, set);
|
|
1865
|
+
}
|
|
1866
|
+
for (const { path, written } of run.manifests) {
|
|
1867
|
+
let content;
|
|
1868
|
+
try {
|
|
1869
|
+
content = await readFile(path, "utf8");
|
|
1870
|
+
} catch {
|
|
1871
|
+
const source = run.configSource ?? "manni.config.yaml";
|
|
1872
|
+
throw new TermError(`${source}: term.manifests "${written}" does not exist.`);
|
|
1873
|
+
}
|
|
1874
|
+
read7(manifestInput(content, path, path), readers, set);
|
|
1875
|
+
}
|
|
1876
|
+
if (set.terms.length === 0 && !allowEmpty) {
|
|
1877
|
+
throw new TermError(
|
|
1878
|
+
"no terms found. A term is a page declaring type: term, or an entry in a file declaring type: term-set."
|
|
1879
|
+
);
|
|
1880
|
+
}
|
|
1881
|
+
return set;
|
|
1882
|
+
}
|
|
1883
|
+
|
|
1884
|
+
// src/term/commands/run.ts
|
|
1885
|
+
async function loadTerms(opts) {
|
|
1886
|
+
const cwd = resolve3(opts.cwd ?? process.cwd());
|
|
1887
|
+
const run = await resolveTermRun({
|
|
1888
|
+
cwd,
|
|
1889
|
+
inputs: opts.inputs,
|
|
1890
|
+
...opts.configPath === void 0 ? {} : { configPath: opts.configPath },
|
|
1891
|
+
...opts.collection === void 0 ? {} : { collection: opts.collection }
|
|
1892
|
+
});
|
|
1893
|
+
const set = await loadSet(run, opts);
|
|
1894
|
+
return { cwd, run, set };
|
|
1895
|
+
}
|
|
1896
|
+
async function loadSet(run, opts) {
|
|
1897
|
+
const exclude = [
|
|
1898
|
+
.../* @__PURE__ */ new Set([
|
|
1899
|
+
...opts.exclude ?? [],
|
|
1900
|
+
...run.fromCollections ? run.collections.flatMap((c) => c.exclude) : []
|
|
1901
|
+
])
|
|
1902
|
+
];
|
|
1903
|
+
const set = await loadTermSet({
|
|
1904
|
+
run,
|
|
1905
|
+
exclude,
|
|
1906
|
+
...opts.exts === void 0 ? {} : { exts: opts.exts },
|
|
1907
|
+
...opts.allowEmpty === true ? { allowEmpty: true } : {},
|
|
1908
|
+
...opts.noGitignore === true ? { noGitignore: true } : {},
|
|
1909
|
+
...opts.stdin === void 0 ? {} : { stdin: opts.stdin },
|
|
1910
|
+
...opts.as === void 0 ? {} : { as: opts.as },
|
|
1911
|
+
...opts.onNotice === void 0 ? {} : { onNotice: opts.onNotice },
|
|
1912
|
+
...opts.readers === void 0 ? {} : { readers: opts.readers }
|
|
1913
|
+
});
|
|
1914
|
+
for (const message of set.notices) opts.onNotice?.(message);
|
|
1915
|
+
return set;
|
|
1916
|
+
}
|
|
1917
|
+
function formatChoice(value, allowed) {
|
|
1918
|
+
const found = allowed.find((candidate) => candidate === value);
|
|
1919
|
+
if (found === void 0) {
|
|
1920
|
+
throw new TermError(`unknown format "${value}". Expected ${allowed.join(" | ")}.`);
|
|
1921
|
+
}
|
|
1922
|
+
return found;
|
|
1923
|
+
}
|
|
1924
|
+
function displayPath(path, cwd) {
|
|
1925
|
+
if (!isAbsolute(path)) return path;
|
|
1926
|
+
const rel = relative(cwd, path);
|
|
1927
|
+
return (rel === "" ? "." : rel).replaceAll("\\", "/");
|
|
1928
|
+
}
|
|
1929
|
+
function valeConfigFor(run) {
|
|
1930
|
+
if (run.configDir === void 0) return void 0;
|
|
1931
|
+
const path = valeConfigPath(run.tools, run.configDir);
|
|
1932
|
+
if (path !== void 0 && !existsSync(path)) {
|
|
1933
|
+
const source = run.configSource ?? "manni.config.yaml";
|
|
1934
|
+
throw new TermError(`${source}: tools.vale.config "${run.tools.vale?.config ?? path}" does not exist.`);
|
|
1935
|
+
}
|
|
1936
|
+
return path;
|
|
1937
|
+
}
|
|
1938
|
+
function plural(n, one, many = `${one}s`) {
|
|
1939
|
+
return `${String(n)} ${n === 1 ? one : many}`;
|
|
1940
|
+
}
|
|
1941
|
+
|
|
1942
|
+
export {
|
|
1943
|
+
TermError,
|
|
1944
|
+
TERM_FIELDS,
|
|
1945
|
+
TERM_WRITE_FORMATS,
|
|
1946
|
+
TERM_RULES,
|
|
1947
|
+
DEFAULT_TERM_BASELINE_PATH,
|
|
1948
|
+
DEFAULT_ABSTRACT_MAX_LENGTH,
|
|
1949
|
+
resolveTermRun,
|
|
1950
|
+
xmlText,
|
|
1951
|
+
xmlAttribute,
|
|
1952
|
+
sharedLanguage,
|
|
1953
|
+
reindent,
|
|
1954
|
+
fileOf,
|
|
1955
|
+
LIST_HOLDS,
|
|
1956
|
+
DITA_HOLDS,
|
|
1957
|
+
DOCBOOK_HOLDS,
|
|
1958
|
+
markdownEntry,
|
|
1959
|
+
asciidocEntry,
|
|
1960
|
+
rstEntry,
|
|
1961
|
+
htmlDlEntry,
|
|
1962
|
+
ditaEntry,
|
|
1963
|
+
docbookEntry,
|
|
1964
|
+
TERM_READERS,
|
|
1965
|
+
readerForConstruct,
|
|
1966
|
+
MANIFEST_FORMAT,
|
|
1967
|
+
extractInput,
|
|
1968
|
+
loadTerms,
|
|
1969
|
+
loadSet,
|
|
1970
|
+
formatChoice,
|
|
1971
|
+
displayPath,
|
|
1972
|
+
valeConfigFor,
|
|
1973
|
+
plural
|
|
1974
|
+
};
|
|
1975
|
+
//# sourceMappingURL=chunk-PU6DFJMY.js.map
|