@rqml/cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/README.md +41 -0
- package/dist/chunk-5WRI5ZAA.js +29 -0
- package/dist/chunk-5WRI5ZAA.js.map +1 -0
- package/dist/index.js +3625 -0
- package/dist/index.js.map +1 -0
- package/dist/validate-O3LLP44J.js +3433 -0
- package/dist/validate-O3LLP44J.js.map +1 -0
- package/package.json +40 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,3625 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { __commonJS, __toESM } from './chunk-5WRI5ZAA.js';
|
|
3
|
+
import { existsSync, writeFileSync, readFileSync, readdirSync } from 'fs';
|
|
4
|
+
import { resolve, isAbsolute } from 'path';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
|
|
7
|
+
// ../../node_modules/.pnpm/fast-xml-parser@4.5.6/node_modules/fast-xml-parser/src/util.js
|
|
8
|
+
var require_util = __commonJS({
|
|
9
|
+
"../../node_modules/.pnpm/fast-xml-parser@4.5.6/node_modules/fast-xml-parser/src/util.js"(exports) {
|
|
10
|
+
var nameStartChar = ":A-Za-z_\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD";
|
|
11
|
+
var nameChar = nameStartChar + "\\-.\\d\\u00B7\\u0300-\\u036F\\u203F-\\u2040";
|
|
12
|
+
var nameRegexp = "[" + nameStartChar + "][" + nameChar + "]*";
|
|
13
|
+
var regexName = new RegExp("^" + nameRegexp + "$");
|
|
14
|
+
var getAllMatches = function(string, regex) {
|
|
15
|
+
const matches = [];
|
|
16
|
+
let match = regex.exec(string);
|
|
17
|
+
while (match) {
|
|
18
|
+
const allmatches = [];
|
|
19
|
+
allmatches.startIndex = regex.lastIndex - match[0].length;
|
|
20
|
+
const len = match.length;
|
|
21
|
+
for (let index = 0; index < len; index++) {
|
|
22
|
+
allmatches.push(match[index]);
|
|
23
|
+
}
|
|
24
|
+
matches.push(allmatches);
|
|
25
|
+
match = regex.exec(string);
|
|
26
|
+
}
|
|
27
|
+
return matches;
|
|
28
|
+
};
|
|
29
|
+
var isName = function(string) {
|
|
30
|
+
const match = regexName.exec(string);
|
|
31
|
+
return !(match === null || typeof match === "undefined");
|
|
32
|
+
};
|
|
33
|
+
exports.isExist = function(v) {
|
|
34
|
+
return typeof v !== "undefined";
|
|
35
|
+
};
|
|
36
|
+
exports.isEmptyObject = function(obj) {
|
|
37
|
+
return Object.keys(obj).length === 0;
|
|
38
|
+
};
|
|
39
|
+
exports.merge = function(target, a, arrayMode) {
|
|
40
|
+
if (a) {
|
|
41
|
+
const keys = Object.keys(a);
|
|
42
|
+
const len = keys.length;
|
|
43
|
+
for (let i = 0; i < len; i++) {
|
|
44
|
+
if (arrayMode === "strict") {
|
|
45
|
+
target[keys[i]] = [a[keys[i]]];
|
|
46
|
+
} else {
|
|
47
|
+
target[keys[i]] = a[keys[i]];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
exports.getValue = function(v) {
|
|
53
|
+
if (exports.isExist(v)) {
|
|
54
|
+
return v;
|
|
55
|
+
} else {
|
|
56
|
+
return "";
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
var DANGEROUS_PROPERTY_NAMES = [
|
|
60
|
+
// '__proto__',
|
|
61
|
+
// 'constructor',
|
|
62
|
+
// 'prototype',
|
|
63
|
+
"hasOwnProperty",
|
|
64
|
+
"toString",
|
|
65
|
+
"valueOf",
|
|
66
|
+
"__defineGetter__",
|
|
67
|
+
"__defineSetter__",
|
|
68
|
+
"__lookupGetter__",
|
|
69
|
+
"__lookupSetter__"
|
|
70
|
+
];
|
|
71
|
+
var criticalProperties = ["__proto__", "constructor", "prototype"];
|
|
72
|
+
exports.isName = isName;
|
|
73
|
+
exports.getAllMatches = getAllMatches;
|
|
74
|
+
exports.nameRegexp = nameRegexp;
|
|
75
|
+
exports.DANGEROUS_PROPERTY_NAMES = DANGEROUS_PROPERTY_NAMES;
|
|
76
|
+
exports.criticalProperties = criticalProperties;
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// ../../node_modules/.pnpm/fast-xml-parser@4.5.6/node_modules/fast-xml-parser/src/validator.js
|
|
81
|
+
var require_validator = __commonJS({
|
|
82
|
+
"../../node_modules/.pnpm/fast-xml-parser@4.5.6/node_modules/fast-xml-parser/src/validator.js"(exports) {
|
|
83
|
+
var util = require_util();
|
|
84
|
+
var defaultOptions = {
|
|
85
|
+
allowBooleanAttributes: false,
|
|
86
|
+
//A tag can have attributes without any value
|
|
87
|
+
unpairedTags: []
|
|
88
|
+
};
|
|
89
|
+
exports.validate = function(xmlData, options) {
|
|
90
|
+
options = Object.assign({}, defaultOptions, options);
|
|
91
|
+
const tags = [];
|
|
92
|
+
let tagFound = false;
|
|
93
|
+
let reachedRoot = false;
|
|
94
|
+
if (xmlData[0] === "\uFEFF") {
|
|
95
|
+
xmlData = xmlData.substr(1);
|
|
96
|
+
}
|
|
97
|
+
for (let i = 0; i < xmlData.length; i++) {
|
|
98
|
+
if (xmlData[i] === "<" && xmlData[i + 1] === "?") {
|
|
99
|
+
i += 2;
|
|
100
|
+
i = readPI(xmlData, i);
|
|
101
|
+
if (i.err) return i;
|
|
102
|
+
} else if (xmlData[i] === "<") {
|
|
103
|
+
let tagStartPos = i;
|
|
104
|
+
i++;
|
|
105
|
+
if (xmlData[i] === "!") {
|
|
106
|
+
i = readCommentAndCDATA(xmlData, i);
|
|
107
|
+
continue;
|
|
108
|
+
} else {
|
|
109
|
+
let closingTag = false;
|
|
110
|
+
if (xmlData[i] === "/") {
|
|
111
|
+
closingTag = true;
|
|
112
|
+
i++;
|
|
113
|
+
}
|
|
114
|
+
let tagName = "";
|
|
115
|
+
for (; i < xmlData.length && xmlData[i] !== ">" && xmlData[i] !== " " && xmlData[i] !== " " && xmlData[i] !== "\n" && xmlData[i] !== "\r"; i++) {
|
|
116
|
+
tagName += xmlData[i];
|
|
117
|
+
}
|
|
118
|
+
tagName = tagName.trim();
|
|
119
|
+
if (tagName[tagName.length - 1] === "/") {
|
|
120
|
+
tagName = tagName.substring(0, tagName.length - 1);
|
|
121
|
+
i--;
|
|
122
|
+
}
|
|
123
|
+
if (!validateTagName(tagName)) {
|
|
124
|
+
let msg;
|
|
125
|
+
if (tagName.trim().length === 0) {
|
|
126
|
+
msg = "Invalid space after '<'.";
|
|
127
|
+
} else {
|
|
128
|
+
msg = "Tag '" + tagName + "' is an invalid name.";
|
|
129
|
+
}
|
|
130
|
+
return getErrorObject("InvalidTag", msg, getLineNumberForPosition(xmlData, i));
|
|
131
|
+
}
|
|
132
|
+
const result = readAttributeStr(xmlData, i);
|
|
133
|
+
if (result === false) {
|
|
134
|
+
return getErrorObject("InvalidAttr", "Attributes for '" + tagName + "' have open quote.", getLineNumberForPosition(xmlData, i));
|
|
135
|
+
}
|
|
136
|
+
let attrStr = result.value;
|
|
137
|
+
i = result.index;
|
|
138
|
+
if (attrStr[attrStr.length - 1] === "/") {
|
|
139
|
+
const attrStrStart = i - attrStr.length;
|
|
140
|
+
attrStr = attrStr.substring(0, attrStr.length - 1);
|
|
141
|
+
const isValid = validateAttributeString(attrStr, options);
|
|
142
|
+
if (isValid === true) {
|
|
143
|
+
tagFound = true;
|
|
144
|
+
} else {
|
|
145
|
+
return getErrorObject(isValid.err.code, isValid.err.msg, getLineNumberForPosition(xmlData, attrStrStart + isValid.err.line));
|
|
146
|
+
}
|
|
147
|
+
} else if (closingTag) {
|
|
148
|
+
if (!result.tagClosed) {
|
|
149
|
+
return getErrorObject("InvalidTag", "Closing tag '" + tagName + "' doesn't have proper closing.", getLineNumberForPosition(xmlData, i));
|
|
150
|
+
} else if (attrStr.trim().length > 0) {
|
|
151
|
+
return getErrorObject("InvalidTag", "Closing tag '" + tagName + "' can't have attributes or invalid starting.", getLineNumberForPosition(xmlData, tagStartPos));
|
|
152
|
+
} else if (tags.length === 0) {
|
|
153
|
+
return getErrorObject("InvalidTag", "Closing tag '" + tagName + "' has not been opened.", getLineNumberForPosition(xmlData, tagStartPos));
|
|
154
|
+
} else {
|
|
155
|
+
const otg = tags.pop();
|
|
156
|
+
if (tagName !== otg.tagName) {
|
|
157
|
+
let openPos = getLineNumberForPosition(xmlData, otg.tagStartPos);
|
|
158
|
+
return getErrorObject(
|
|
159
|
+
"InvalidTag",
|
|
160
|
+
"Expected closing tag '" + otg.tagName + "' (opened in line " + openPos.line + ", col " + openPos.col + ") instead of closing tag '" + tagName + "'.",
|
|
161
|
+
getLineNumberForPosition(xmlData, tagStartPos)
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
if (tags.length == 0) {
|
|
165
|
+
reachedRoot = true;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
} else {
|
|
169
|
+
const isValid = validateAttributeString(attrStr, options);
|
|
170
|
+
if (isValid !== true) {
|
|
171
|
+
return getErrorObject(isValid.err.code, isValid.err.msg, getLineNumberForPosition(xmlData, i - attrStr.length + isValid.err.line));
|
|
172
|
+
}
|
|
173
|
+
if (reachedRoot === true) {
|
|
174
|
+
return getErrorObject("InvalidXml", "Multiple possible root nodes found.", getLineNumberForPosition(xmlData, i));
|
|
175
|
+
} else if (options.unpairedTags.indexOf(tagName) !== -1) ; else {
|
|
176
|
+
tags.push({ tagName, tagStartPos });
|
|
177
|
+
}
|
|
178
|
+
tagFound = true;
|
|
179
|
+
}
|
|
180
|
+
for (i++; i < xmlData.length; i++) {
|
|
181
|
+
if (xmlData[i] === "<") {
|
|
182
|
+
if (xmlData[i + 1] === "!") {
|
|
183
|
+
i++;
|
|
184
|
+
i = readCommentAndCDATA(xmlData, i);
|
|
185
|
+
continue;
|
|
186
|
+
} else if (xmlData[i + 1] === "?") {
|
|
187
|
+
i = readPI(xmlData, ++i);
|
|
188
|
+
if (i.err) return i;
|
|
189
|
+
} else {
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
} else if (xmlData[i] === "&") {
|
|
193
|
+
const afterAmp = validateAmpersand(xmlData, i);
|
|
194
|
+
if (afterAmp == -1)
|
|
195
|
+
return getErrorObject("InvalidChar", "char '&' is not expected.", getLineNumberForPosition(xmlData, i));
|
|
196
|
+
i = afterAmp;
|
|
197
|
+
} else {
|
|
198
|
+
if (reachedRoot === true && !isWhiteSpace(xmlData[i])) {
|
|
199
|
+
return getErrorObject("InvalidXml", "Extra text at the end", getLineNumberForPosition(xmlData, i));
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
if (xmlData[i] === "<") {
|
|
204
|
+
i--;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
} else {
|
|
208
|
+
if (isWhiteSpace(xmlData[i])) {
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
return getErrorObject("InvalidChar", "char '" + xmlData[i] + "' is not expected.", getLineNumberForPosition(xmlData, i));
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
if (!tagFound) {
|
|
215
|
+
return getErrorObject("InvalidXml", "Start tag expected.", 1);
|
|
216
|
+
} else if (tags.length == 1) {
|
|
217
|
+
return getErrorObject("InvalidTag", "Unclosed tag '" + tags[0].tagName + "'.", getLineNumberForPosition(xmlData, tags[0].tagStartPos));
|
|
218
|
+
} else if (tags.length > 0) {
|
|
219
|
+
return getErrorObject("InvalidXml", "Invalid '" + JSON.stringify(tags.map((t) => t.tagName), null, 4).replace(/\r?\n/g, "") + "' found.", { line: 1, col: 1 });
|
|
220
|
+
}
|
|
221
|
+
return true;
|
|
222
|
+
};
|
|
223
|
+
function isWhiteSpace(char) {
|
|
224
|
+
return char === " " || char === " " || char === "\n" || char === "\r";
|
|
225
|
+
}
|
|
226
|
+
function readPI(xmlData, i) {
|
|
227
|
+
const start = i;
|
|
228
|
+
for (; i < xmlData.length; i++) {
|
|
229
|
+
if (xmlData[i] == "?" || xmlData[i] == " ") {
|
|
230
|
+
const tagname = xmlData.substr(start, i - start);
|
|
231
|
+
if (i > 5 && tagname === "xml") {
|
|
232
|
+
return getErrorObject("InvalidXml", "XML declaration allowed only at the start of the document.", getLineNumberForPosition(xmlData, i));
|
|
233
|
+
} else if (xmlData[i] == "?" && xmlData[i + 1] == ">") {
|
|
234
|
+
i++;
|
|
235
|
+
break;
|
|
236
|
+
} else {
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return i;
|
|
242
|
+
}
|
|
243
|
+
function readCommentAndCDATA(xmlData, i) {
|
|
244
|
+
if (xmlData.length > i + 5 && xmlData[i + 1] === "-" && xmlData[i + 2] === "-") {
|
|
245
|
+
for (i += 3; i < xmlData.length; i++) {
|
|
246
|
+
if (xmlData[i] === "-" && xmlData[i + 1] === "-" && xmlData[i + 2] === ">") {
|
|
247
|
+
i += 2;
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
} else if (xmlData.length > i + 8 && xmlData[i + 1] === "D" && xmlData[i + 2] === "O" && xmlData[i + 3] === "C" && xmlData[i + 4] === "T" && xmlData[i + 5] === "Y" && xmlData[i + 6] === "P" && xmlData[i + 7] === "E") {
|
|
252
|
+
let angleBracketsCount = 1;
|
|
253
|
+
for (i += 8; i < xmlData.length; i++) {
|
|
254
|
+
if (xmlData[i] === "<") {
|
|
255
|
+
angleBracketsCount++;
|
|
256
|
+
} else if (xmlData[i] === ">") {
|
|
257
|
+
angleBracketsCount--;
|
|
258
|
+
if (angleBracketsCount === 0) {
|
|
259
|
+
break;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
} else if (xmlData.length > i + 9 && xmlData[i + 1] === "[" && xmlData[i + 2] === "C" && xmlData[i + 3] === "D" && xmlData[i + 4] === "A" && xmlData[i + 5] === "T" && xmlData[i + 6] === "A" && xmlData[i + 7] === "[") {
|
|
264
|
+
for (i += 8; i < xmlData.length; i++) {
|
|
265
|
+
if (xmlData[i] === "]" && xmlData[i + 1] === "]" && xmlData[i + 2] === ">") {
|
|
266
|
+
i += 2;
|
|
267
|
+
break;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return i;
|
|
272
|
+
}
|
|
273
|
+
var doubleQuote = '"';
|
|
274
|
+
var singleQuote = "'";
|
|
275
|
+
function readAttributeStr(xmlData, i) {
|
|
276
|
+
let attrStr = "";
|
|
277
|
+
let startChar = "";
|
|
278
|
+
let tagClosed = false;
|
|
279
|
+
for (; i < xmlData.length; i++) {
|
|
280
|
+
if (xmlData[i] === doubleQuote || xmlData[i] === singleQuote) {
|
|
281
|
+
if (startChar === "") {
|
|
282
|
+
startChar = xmlData[i];
|
|
283
|
+
} else if (startChar !== xmlData[i]) ; else {
|
|
284
|
+
startChar = "";
|
|
285
|
+
}
|
|
286
|
+
} else if (xmlData[i] === ">") {
|
|
287
|
+
if (startChar === "") {
|
|
288
|
+
tagClosed = true;
|
|
289
|
+
break;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
attrStr += xmlData[i];
|
|
293
|
+
}
|
|
294
|
+
if (startChar !== "") {
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
297
|
+
return {
|
|
298
|
+
value: attrStr,
|
|
299
|
+
index: i,
|
|
300
|
+
tagClosed
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
var validAttrStrRegxp = new RegExp(`(\\s*)([^\\s=]+)(\\s*=)?(\\s*(['"])(([\\s\\S])*?)\\5)?`, "g");
|
|
304
|
+
function validateAttributeString(attrStr, options) {
|
|
305
|
+
const matches = util.getAllMatches(attrStr, validAttrStrRegxp);
|
|
306
|
+
const attrNames = {};
|
|
307
|
+
for (let i = 0; i < matches.length; i++) {
|
|
308
|
+
if (matches[i][1].length === 0) {
|
|
309
|
+
return getErrorObject("InvalidAttr", "Attribute '" + matches[i][2] + "' has no space in starting.", getPositionFromMatch(matches[i]));
|
|
310
|
+
} else if (matches[i][3] !== void 0 && matches[i][4] === void 0) {
|
|
311
|
+
return getErrorObject("InvalidAttr", "Attribute '" + matches[i][2] + "' is without value.", getPositionFromMatch(matches[i]));
|
|
312
|
+
} else if (matches[i][3] === void 0 && !options.allowBooleanAttributes) {
|
|
313
|
+
return getErrorObject("InvalidAttr", "boolean attribute '" + matches[i][2] + "' is not allowed.", getPositionFromMatch(matches[i]));
|
|
314
|
+
}
|
|
315
|
+
const attrName = matches[i][2];
|
|
316
|
+
if (!validateAttrName(attrName)) {
|
|
317
|
+
return getErrorObject("InvalidAttr", "Attribute '" + attrName + "' is an invalid name.", getPositionFromMatch(matches[i]));
|
|
318
|
+
}
|
|
319
|
+
if (!attrNames.hasOwnProperty(attrName)) {
|
|
320
|
+
attrNames[attrName] = 1;
|
|
321
|
+
} else {
|
|
322
|
+
return getErrorObject("InvalidAttr", "Attribute '" + attrName + "' is repeated.", getPositionFromMatch(matches[i]));
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
return true;
|
|
326
|
+
}
|
|
327
|
+
function validateNumberAmpersand(xmlData, i) {
|
|
328
|
+
let re = /\d/;
|
|
329
|
+
if (xmlData[i] === "x") {
|
|
330
|
+
i++;
|
|
331
|
+
re = /[\da-fA-F]/;
|
|
332
|
+
}
|
|
333
|
+
for (; i < xmlData.length; i++) {
|
|
334
|
+
if (xmlData[i] === ";")
|
|
335
|
+
return i;
|
|
336
|
+
if (!xmlData[i].match(re))
|
|
337
|
+
break;
|
|
338
|
+
}
|
|
339
|
+
return -1;
|
|
340
|
+
}
|
|
341
|
+
function validateAmpersand(xmlData, i) {
|
|
342
|
+
i++;
|
|
343
|
+
if (xmlData[i] === ";")
|
|
344
|
+
return -1;
|
|
345
|
+
if (xmlData[i] === "#") {
|
|
346
|
+
i++;
|
|
347
|
+
return validateNumberAmpersand(xmlData, i);
|
|
348
|
+
}
|
|
349
|
+
let count = 0;
|
|
350
|
+
for (; i < xmlData.length; i++, count++) {
|
|
351
|
+
if (xmlData[i].match(/\w/) && count < 20)
|
|
352
|
+
continue;
|
|
353
|
+
if (xmlData[i] === ";")
|
|
354
|
+
break;
|
|
355
|
+
return -1;
|
|
356
|
+
}
|
|
357
|
+
return i;
|
|
358
|
+
}
|
|
359
|
+
function getErrorObject(code, message, lineNumber) {
|
|
360
|
+
return {
|
|
361
|
+
err: {
|
|
362
|
+
code,
|
|
363
|
+
msg: message,
|
|
364
|
+
line: lineNumber.line || lineNumber,
|
|
365
|
+
col: lineNumber.col
|
|
366
|
+
}
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
function validateAttrName(attrName) {
|
|
370
|
+
return util.isName(attrName);
|
|
371
|
+
}
|
|
372
|
+
function validateTagName(tagname) {
|
|
373
|
+
return util.isName(tagname);
|
|
374
|
+
}
|
|
375
|
+
function getLineNumberForPosition(xmlData, index) {
|
|
376
|
+
const lines = xmlData.substring(0, index).split(/\r?\n/);
|
|
377
|
+
return {
|
|
378
|
+
line: lines.length,
|
|
379
|
+
// column number is last line's length + 1, because column numbering starts at 1:
|
|
380
|
+
col: lines[lines.length - 1].length + 1
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
function getPositionFromMatch(match) {
|
|
384
|
+
return match.startIndex + match[1].length;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
// ../../node_modules/.pnpm/fast-xml-parser@4.5.6/node_modules/fast-xml-parser/src/xmlparser/OptionsBuilder.js
|
|
390
|
+
var require_OptionsBuilder = __commonJS({
|
|
391
|
+
"../../node_modules/.pnpm/fast-xml-parser@4.5.6/node_modules/fast-xml-parser/src/xmlparser/OptionsBuilder.js"(exports) {
|
|
392
|
+
var { DANGEROUS_PROPERTY_NAMES, criticalProperties } = require_util();
|
|
393
|
+
var defaultOnDangerousProperty = (name) => {
|
|
394
|
+
if (DANGEROUS_PROPERTY_NAMES.includes(name)) {
|
|
395
|
+
return "__" + name;
|
|
396
|
+
}
|
|
397
|
+
return name;
|
|
398
|
+
};
|
|
399
|
+
var defaultOptions = {
|
|
400
|
+
preserveOrder: false,
|
|
401
|
+
attributeNamePrefix: "@_",
|
|
402
|
+
attributesGroupName: false,
|
|
403
|
+
textNodeName: "#text",
|
|
404
|
+
ignoreAttributes: true,
|
|
405
|
+
removeNSPrefix: false,
|
|
406
|
+
// remove NS from tag name or attribute name if true
|
|
407
|
+
allowBooleanAttributes: false,
|
|
408
|
+
//a tag can have attributes without any value
|
|
409
|
+
//ignoreRootElement : false,
|
|
410
|
+
parseTagValue: true,
|
|
411
|
+
parseAttributeValue: false,
|
|
412
|
+
trimValues: true,
|
|
413
|
+
//Trim string values of tag and attributes
|
|
414
|
+
cdataPropName: false,
|
|
415
|
+
numberParseOptions: {
|
|
416
|
+
hex: true,
|
|
417
|
+
leadingZeros: true,
|
|
418
|
+
eNotation: true
|
|
419
|
+
},
|
|
420
|
+
tagValueProcessor: function(tagName, val) {
|
|
421
|
+
return val;
|
|
422
|
+
},
|
|
423
|
+
attributeValueProcessor: function(attrName, val) {
|
|
424
|
+
return val;
|
|
425
|
+
},
|
|
426
|
+
stopNodes: [],
|
|
427
|
+
//nested tags will not be parsed even for errors
|
|
428
|
+
alwaysCreateTextNode: false,
|
|
429
|
+
isArray: () => false,
|
|
430
|
+
commentPropName: false,
|
|
431
|
+
unpairedTags: [],
|
|
432
|
+
processEntities: true,
|
|
433
|
+
htmlEntities: false,
|
|
434
|
+
ignoreDeclaration: false,
|
|
435
|
+
ignorePiTags: false,
|
|
436
|
+
transformTagName: false,
|
|
437
|
+
transformAttributeName: false,
|
|
438
|
+
updateTag: function(tagName, jPath, attrs) {
|
|
439
|
+
return tagName;
|
|
440
|
+
},
|
|
441
|
+
// skipEmptyListItem: false
|
|
442
|
+
captureMetaData: false,
|
|
443
|
+
maxNestedTags: 100,
|
|
444
|
+
strictReservedNames: true,
|
|
445
|
+
onDangerousProperty: defaultOnDangerousProperty
|
|
446
|
+
};
|
|
447
|
+
function validatePropertyName(propertyName, optionName) {
|
|
448
|
+
if (typeof propertyName !== "string") {
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
const normalized = propertyName.toLowerCase();
|
|
452
|
+
if (DANGEROUS_PROPERTY_NAMES.some((dangerous) => normalized === dangerous.toLowerCase())) {
|
|
453
|
+
throw new Error(
|
|
454
|
+
`[SECURITY] Invalid ${optionName}: "${propertyName}" is a reserved JavaScript keyword that could cause prototype pollution`
|
|
455
|
+
);
|
|
456
|
+
}
|
|
457
|
+
if (criticalProperties.some((dangerous) => normalized === dangerous.toLowerCase())) {
|
|
458
|
+
throw new Error(
|
|
459
|
+
`[SECURITY] Invalid ${optionName}: "${propertyName}" is a reserved JavaScript keyword that could cause prototype pollution`
|
|
460
|
+
);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
function normalizeProcessEntities(value) {
|
|
464
|
+
if (typeof value === "boolean") {
|
|
465
|
+
return {
|
|
466
|
+
enabled: value,
|
|
467
|
+
// true or false
|
|
468
|
+
maxEntitySize: 1e4,
|
|
469
|
+
maxExpansionDepth: 10,
|
|
470
|
+
maxTotalExpansions: 1e3,
|
|
471
|
+
maxExpandedLength: 1e5,
|
|
472
|
+
allowedTags: null,
|
|
473
|
+
tagFilter: null
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
if (typeof value === "object" && value !== null) {
|
|
477
|
+
return {
|
|
478
|
+
enabled: value.enabled !== false,
|
|
479
|
+
maxEntitySize: Math.max(1, value.maxEntitySize ?? 1e4),
|
|
480
|
+
maxExpansionDepth: Math.max(1, value.maxExpansionDepth ?? 1e4),
|
|
481
|
+
maxTotalExpansions: Math.max(1, value.maxTotalExpansions ?? Infinity),
|
|
482
|
+
maxExpandedLength: Math.max(1, value.maxExpandedLength ?? 1e5),
|
|
483
|
+
maxEntityCount: Math.max(1, value.maxEntityCount ?? 1e3),
|
|
484
|
+
allowedTags: value.allowedTags ?? null,
|
|
485
|
+
tagFilter: value.tagFilter ?? null
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
return normalizeProcessEntities(true);
|
|
489
|
+
}
|
|
490
|
+
var buildOptions = function(options) {
|
|
491
|
+
const built = Object.assign({}, defaultOptions, options);
|
|
492
|
+
const propertyNameOptions = [
|
|
493
|
+
{ value: built.attributeNamePrefix, name: "attributeNamePrefix" },
|
|
494
|
+
{ value: built.attributesGroupName, name: "attributesGroupName" },
|
|
495
|
+
{ value: built.textNodeName, name: "textNodeName" },
|
|
496
|
+
{ value: built.cdataPropName, name: "cdataPropName" },
|
|
497
|
+
{ value: built.commentPropName, name: "commentPropName" }
|
|
498
|
+
];
|
|
499
|
+
for (const { value, name } of propertyNameOptions) {
|
|
500
|
+
if (value) {
|
|
501
|
+
validatePropertyName(value, name);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
if (built.onDangerousProperty === null) {
|
|
505
|
+
built.onDangerousProperty = defaultOnDangerousProperty;
|
|
506
|
+
}
|
|
507
|
+
built.processEntities = normalizeProcessEntities(built.processEntities);
|
|
508
|
+
return built;
|
|
509
|
+
};
|
|
510
|
+
exports.buildOptions = buildOptions;
|
|
511
|
+
exports.defaultOptions = defaultOptions;
|
|
512
|
+
}
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
// ../../node_modules/.pnpm/fast-xml-parser@4.5.6/node_modules/fast-xml-parser/src/xmlparser/xmlNode.js
|
|
516
|
+
var require_xmlNode = __commonJS({
|
|
517
|
+
"../../node_modules/.pnpm/fast-xml-parser@4.5.6/node_modules/fast-xml-parser/src/xmlparser/xmlNode.js"(exports, module) {
|
|
518
|
+
var XmlNode = class {
|
|
519
|
+
constructor(tagname) {
|
|
520
|
+
this.tagname = tagname;
|
|
521
|
+
this.child = [];
|
|
522
|
+
this[":@"] = {};
|
|
523
|
+
}
|
|
524
|
+
add(key, val) {
|
|
525
|
+
if (key === "__proto__") key = "#__proto__";
|
|
526
|
+
this.child.push({ [key]: val });
|
|
527
|
+
}
|
|
528
|
+
addChild(node) {
|
|
529
|
+
if (node.tagname === "__proto__") node.tagname = "#__proto__";
|
|
530
|
+
if (node[":@"] && Object.keys(node[":@"]).length > 0) {
|
|
531
|
+
this.child.push({ [node.tagname]: node.child, [":@"]: node[":@"] });
|
|
532
|
+
} else {
|
|
533
|
+
this.child.push({ [node.tagname]: node.child });
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
};
|
|
537
|
+
module.exports = XmlNode;
|
|
538
|
+
}
|
|
539
|
+
});
|
|
540
|
+
|
|
541
|
+
// ../../node_modules/.pnpm/fast-xml-parser@4.5.6/node_modules/fast-xml-parser/src/xmlparser/DocTypeReader.js
|
|
542
|
+
var require_DocTypeReader = __commonJS({
|
|
543
|
+
"../../node_modules/.pnpm/fast-xml-parser@4.5.6/node_modules/fast-xml-parser/src/xmlparser/DocTypeReader.js"(exports, module) {
|
|
544
|
+
var util = require_util();
|
|
545
|
+
var DocTypeReader = class {
|
|
546
|
+
constructor(options) {
|
|
547
|
+
this.suppressValidationErr = !options;
|
|
548
|
+
this.options = options || {};
|
|
549
|
+
}
|
|
550
|
+
readDocType(xmlData, i) {
|
|
551
|
+
const entities = /* @__PURE__ */ Object.create(null);
|
|
552
|
+
let entityCount = 0;
|
|
553
|
+
if (xmlData[i + 3] === "O" && xmlData[i + 4] === "C" && xmlData[i + 5] === "T" && xmlData[i + 6] === "Y" && xmlData[i + 7] === "P" && xmlData[i + 8] === "E") {
|
|
554
|
+
i = i + 9;
|
|
555
|
+
let angleBracketsCount = 1;
|
|
556
|
+
let hasBody = false, comment = false;
|
|
557
|
+
let exp = "";
|
|
558
|
+
for (; i < xmlData.length; i++) {
|
|
559
|
+
if (xmlData[i] === "<" && !comment) {
|
|
560
|
+
if (hasBody && hasSeq(xmlData, "!ENTITY", i)) {
|
|
561
|
+
i += 7;
|
|
562
|
+
let entityName, val;
|
|
563
|
+
[entityName, val, i] = this.readEntityExp(xmlData, i + 1, this.suppressValidationErr);
|
|
564
|
+
if (val.indexOf("&") === -1) {
|
|
565
|
+
if (this.options.enabled !== false && this.options.maxEntityCount != null && entityCount >= this.options.maxEntityCount) {
|
|
566
|
+
throw new Error(
|
|
567
|
+
`Entity count (${entityCount + 1}) exceeds maximum allowed (${this.options.maxEntityCount})`
|
|
568
|
+
);
|
|
569
|
+
}
|
|
570
|
+
const escaped = entityName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
571
|
+
entities[entityName] = {
|
|
572
|
+
regx: RegExp(`&${escaped};`, "g"),
|
|
573
|
+
val
|
|
574
|
+
};
|
|
575
|
+
entityCount++;
|
|
576
|
+
}
|
|
577
|
+
} else if (hasBody && hasSeq(xmlData, "!ELEMENT", i)) {
|
|
578
|
+
i += 8;
|
|
579
|
+
const { index } = this.readElementExp(xmlData, i + 1);
|
|
580
|
+
i = index;
|
|
581
|
+
} else if (hasBody && hasSeq(xmlData, "!ATTLIST", i)) {
|
|
582
|
+
i += 8;
|
|
583
|
+
} else if (hasBody && hasSeq(xmlData, "!NOTATION", i)) {
|
|
584
|
+
i += 9;
|
|
585
|
+
const { index } = this.readNotationExp(xmlData, i + 1, this.suppressValidationErr);
|
|
586
|
+
i = index;
|
|
587
|
+
} else if (hasSeq(xmlData, "!--", i)) {
|
|
588
|
+
comment = true;
|
|
589
|
+
} else {
|
|
590
|
+
throw new Error(`Invalid DOCTYPE`);
|
|
591
|
+
}
|
|
592
|
+
angleBracketsCount++;
|
|
593
|
+
exp = "";
|
|
594
|
+
} else if (xmlData[i] === ">") {
|
|
595
|
+
if (comment) {
|
|
596
|
+
if (xmlData[i - 1] === "-" && xmlData[i - 2] === "-") {
|
|
597
|
+
comment = false;
|
|
598
|
+
angleBracketsCount--;
|
|
599
|
+
}
|
|
600
|
+
} else {
|
|
601
|
+
angleBracketsCount--;
|
|
602
|
+
}
|
|
603
|
+
if (angleBracketsCount === 0) {
|
|
604
|
+
break;
|
|
605
|
+
}
|
|
606
|
+
} else if (xmlData[i] === "[") {
|
|
607
|
+
hasBody = true;
|
|
608
|
+
} else {
|
|
609
|
+
exp += xmlData[i];
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
if (angleBracketsCount !== 0) {
|
|
613
|
+
throw new Error(`Unclosed DOCTYPE`);
|
|
614
|
+
}
|
|
615
|
+
} else {
|
|
616
|
+
throw new Error(`Invalid Tag instead of DOCTYPE`);
|
|
617
|
+
}
|
|
618
|
+
return { entities, i };
|
|
619
|
+
}
|
|
620
|
+
readEntityExp(xmlData, i) {
|
|
621
|
+
i = skipWhitespace(xmlData, i);
|
|
622
|
+
let entityName = "";
|
|
623
|
+
while (i < xmlData.length && !/\s/.test(xmlData[i]) && xmlData[i] !== '"' && xmlData[i] !== "'") {
|
|
624
|
+
entityName += xmlData[i];
|
|
625
|
+
i++;
|
|
626
|
+
}
|
|
627
|
+
validateEntityName(entityName);
|
|
628
|
+
i = skipWhitespace(xmlData, i);
|
|
629
|
+
if (!this.suppressValidationErr) {
|
|
630
|
+
if (xmlData.substring(i, i + 6).toUpperCase() === "SYSTEM") {
|
|
631
|
+
throw new Error("External entities are not supported");
|
|
632
|
+
} else if (xmlData[i] === "%") {
|
|
633
|
+
throw new Error("Parameter entities are not supported");
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
let entityValue = "";
|
|
637
|
+
[i, entityValue] = this.readIdentifierVal(xmlData, i, "entity");
|
|
638
|
+
if (this.options.enabled !== false && this.options.maxEntitySize != null && entityValue.length > this.options.maxEntitySize) {
|
|
639
|
+
throw new Error(
|
|
640
|
+
`Entity "${entityName}" size (${entityValue.length}) exceeds maximum allowed size (${this.options.maxEntitySize})`
|
|
641
|
+
);
|
|
642
|
+
}
|
|
643
|
+
i--;
|
|
644
|
+
return [entityName, entityValue, i];
|
|
645
|
+
}
|
|
646
|
+
readNotationExp(xmlData, i) {
|
|
647
|
+
i = skipWhitespace(xmlData, i);
|
|
648
|
+
let notationName = "";
|
|
649
|
+
while (i < xmlData.length && !/\s/.test(xmlData[i])) {
|
|
650
|
+
notationName += xmlData[i];
|
|
651
|
+
i++;
|
|
652
|
+
}
|
|
653
|
+
!this.suppressValidationErr && validateEntityName(notationName);
|
|
654
|
+
i = skipWhitespace(xmlData, i);
|
|
655
|
+
const identifierType = xmlData.substring(i, i + 6).toUpperCase();
|
|
656
|
+
if (!this.suppressValidationErr && identifierType !== "SYSTEM" && identifierType !== "PUBLIC") {
|
|
657
|
+
throw new Error(`Expected SYSTEM or PUBLIC, found "${identifierType}"`);
|
|
658
|
+
}
|
|
659
|
+
i += identifierType.length;
|
|
660
|
+
i = skipWhitespace(xmlData, i);
|
|
661
|
+
let publicIdentifier = null;
|
|
662
|
+
let systemIdentifier = null;
|
|
663
|
+
if (identifierType === "PUBLIC") {
|
|
664
|
+
[i, publicIdentifier] = this.readIdentifierVal(xmlData, i, "publicIdentifier");
|
|
665
|
+
i = skipWhitespace(xmlData, i);
|
|
666
|
+
if (xmlData[i] === '"' || xmlData[i] === "'") {
|
|
667
|
+
[i, systemIdentifier] = this.readIdentifierVal(xmlData, i, "systemIdentifier");
|
|
668
|
+
}
|
|
669
|
+
} else if (identifierType === "SYSTEM") {
|
|
670
|
+
[i, systemIdentifier] = this.readIdentifierVal(xmlData, i, "systemIdentifier");
|
|
671
|
+
if (!this.suppressValidationErr && !systemIdentifier) {
|
|
672
|
+
throw new Error("Missing mandatory system identifier for SYSTEM notation");
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
return { notationName, publicIdentifier, systemIdentifier, index: --i };
|
|
676
|
+
}
|
|
677
|
+
readIdentifierVal(xmlData, i, type) {
|
|
678
|
+
let identifierVal = "";
|
|
679
|
+
const startChar = xmlData[i];
|
|
680
|
+
if (startChar !== '"' && startChar !== "'") {
|
|
681
|
+
throw new Error(`Expected quoted string, found "${startChar}"`);
|
|
682
|
+
}
|
|
683
|
+
i++;
|
|
684
|
+
while (i < xmlData.length && xmlData[i] !== startChar) {
|
|
685
|
+
identifierVal += xmlData[i];
|
|
686
|
+
i++;
|
|
687
|
+
}
|
|
688
|
+
if (xmlData[i] !== startChar) {
|
|
689
|
+
throw new Error(`Unterminated ${type} value`);
|
|
690
|
+
}
|
|
691
|
+
i++;
|
|
692
|
+
return [i, identifierVal];
|
|
693
|
+
}
|
|
694
|
+
readElementExp(xmlData, i) {
|
|
695
|
+
i = skipWhitespace(xmlData, i);
|
|
696
|
+
let elementName = "";
|
|
697
|
+
while (i < xmlData.length && !/\s/.test(xmlData[i])) {
|
|
698
|
+
elementName += xmlData[i];
|
|
699
|
+
i++;
|
|
700
|
+
}
|
|
701
|
+
if (!this.suppressValidationErr && !util.isName(elementName)) {
|
|
702
|
+
throw new Error(`Invalid element name: "${elementName}"`);
|
|
703
|
+
}
|
|
704
|
+
i = skipWhitespace(xmlData, i);
|
|
705
|
+
let contentModel = "";
|
|
706
|
+
if (xmlData[i] === "E" && hasSeq(xmlData, "MPTY", i)) {
|
|
707
|
+
i += 4;
|
|
708
|
+
} else if (xmlData[i] === "A" && hasSeq(xmlData, "NY", i)) {
|
|
709
|
+
i += 2;
|
|
710
|
+
} else if (xmlData[i] === "(") {
|
|
711
|
+
i++;
|
|
712
|
+
while (i < xmlData.length && xmlData[i] !== ")") {
|
|
713
|
+
contentModel += xmlData[i];
|
|
714
|
+
i++;
|
|
715
|
+
}
|
|
716
|
+
if (xmlData[i] !== ")") {
|
|
717
|
+
throw new Error("Unterminated content model");
|
|
718
|
+
}
|
|
719
|
+
} else if (!this.suppressValidationErr) {
|
|
720
|
+
throw new Error(`Invalid Element Expression, found "${xmlData[i]}"`);
|
|
721
|
+
}
|
|
722
|
+
return {
|
|
723
|
+
elementName,
|
|
724
|
+
contentModel: contentModel.trim(),
|
|
725
|
+
index: i
|
|
726
|
+
};
|
|
727
|
+
}
|
|
728
|
+
readAttlistExp(xmlData, i) {
|
|
729
|
+
i = skipWhitespace(xmlData, i);
|
|
730
|
+
let elementName = "";
|
|
731
|
+
while (i < xmlData.length && !/\s/.test(xmlData[i])) {
|
|
732
|
+
elementName += xmlData[i];
|
|
733
|
+
i++;
|
|
734
|
+
}
|
|
735
|
+
validateEntityName(elementName);
|
|
736
|
+
i = skipWhitespace(xmlData, i);
|
|
737
|
+
let attributeName = "";
|
|
738
|
+
while (i < xmlData.length && !/\s/.test(xmlData[i])) {
|
|
739
|
+
attributeName += xmlData[i];
|
|
740
|
+
i++;
|
|
741
|
+
}
|
|
742
|
+
if (!validateEntityName(attributeName)) {
|
|
743
|
+
throw new Error(`Invalid attribute name: "${attributeName}"`);
|
|
744
|
+
}
|
|
745
|
+
i = skipWhitespace(xmlData, i);
|
|
746
|
+
let attributeType = "";
|
|
747
|
+
if (xmlData.substring(i, i + 8).toUpperCase() === "NOTATION") {
|
|
748
|
+
attributeType = "NOTATION";
|
|
749
|
+
i += 8;
|
|
750
|
+
i = skipWhitespace(xmlData, i);
|
|
751
|
+
if (xmlData[i] !== "(") {
|
|
752
|
+
throw new Error(`Expected '(', found "${xmlData[i]}"`);
|
|
753
|
+
}
|
|
754
|
+
i++;
|
|
755
|
+
let allowedNotations = [];
|
|
756
|
+
while (i < xmlData.length && xmlData[i] !== ")") {
|
|
757
|
+
let notation = "";
|
|
758
|
+
while (i < xmlData.length && xmlData[i] !== "|" && xmlData[i] !== ")") {
|
|
759
|
+
notation += xmlData[i];
|
|
760
|
+
i++;
|
|
761
|
+
}
|
|
762
|
+
notation = notation.trim();
|
|
763
|
+
if (!validateEntityName(notation)) {
|
|
764
|
+
throw new Error(`Invalid notation name: "${notation}"`);
|
|
765
|
+
}
|
|
766
|
+
allowedNotations.push(notation);
|
|
767
|
+
if (xmlData[i] === "|") {
|
|
768
|
+
i++;
|
|
769
|
+
i = skipWhitespace(xmlData, i);
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
if (xmlData[i] !== ")") {
|
|
773
|
+
throw new Error("Unterminated list of notations");
|
|
774
|
+
}
|
|
775
|
+
i++;
|
|
776
|
+
attributeType += " (" + allowedNotations.join("|") + ")";
|
|
777
|
+
} else {
|
|
778
|
+
while (i < xmlData.length && !/\s/.test(xmlData[i])) {
|
|
779
|
+
attributeType += xmlData[i];
|
|
780
|
+
i++;
|
|
781
|
+
}
|
|
782
|
+
const validTypes = ["CDATA", "ID", "IDREF", "IDREFS", "ENTITY", "ENTITIES", "NMTOKEN", "NMTOKENS"];
|
|
783
|
+
if (!this.suppressValidationErr && !validTypes.includes(attributeType.toUpperCase())) {
|
|
784
|
+
throw new Error(`Invalid attribute type: "${attributeType}"`);
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
i = skipWhitespace(xmlData, i);
|
|
788
|
+
let defaultValue = "";
|
|
789
|
+
if (xmlData.substring(i, i + 8).toUpperCase() === "#REQUIRED") {
|
|
790
|
+
defaultValue = "#REQUIRED";
|
|
791
|
+
i += 8;
|
|
792
|
+
} else if (xmlData.substring(i, i + 7).toUpperCase() === "#IMPLIED") {
|
|
793
|
+
defaultValue = "#IMPLIED";
|
|
794
|
+
i += 7;
|
|
795
|
+
} else {
|
|
796
|
+
[i, defaultValue] = this.readIdentifierVal(xmlData, i, "ATTLIST");
|
|
797
|
+
}
|
|
798
|
+
return {
|
|
799
|
+
elementName,
|
|
800
|
+
attributeName,
|
|
801
|
+
attributeType,
|
|
802
|
+
defaultValue,
|
|
803
|
+
index: i
|
|
804
|
+
};
|
|
805
|
+
}
|
|
806
|
+
};
|
|
807
|
+
var skipWhitespace = (data, index) => {
|
|
808
|
+
while (index < data.length && /\s/.test(data[index])) {
|
|
809
|
+
index++;
|
|
810
|
+
}
|
|
811
|
+
return index;
|
|
812
|
+
};
|
|
813
|
+
function hasSeq(data, seq, i) {
|
|
814
|
+
for (let j = 0; j < seq.length; j++) {
|
|
815
|
+
if (seq[j] !== data[i + j + 1]) return false;
|
|
816
|
+
}
|
|
817
|
+
return true;
|
|
818
|
+
}
|
|
819
|
+
function validateEntityName(name) {
|
|
820
|
+
if (util.isName(name))
|
|
821
|
+
return name;
|
|
822
|
+
else
|
|
823
|
+
throw new Error(`Invalid entity name ${name}`);
|
|
824
|
+
}
|
|
825
|
+
module.exports = DocTypeReader;
|
|
826
|
+
}
|
|
827
|
+
});
|
|
828
|
+
|
|
829
|
+
// ../../node_modules/.pnpm/strnum@1.1.2/node_modules/strnum/strnum.js
|
|
830
|
+
var require_strnum = __commonJS({
|
|
831
|
+
"../../node_modules/.pnpm/strnum@1.1.2/node_modules/strnum/strnum.js"(exports, module) {
|
|
832
|
+
var hexRegex = /^[-+]?0x[a-fA-F0-9]+$/;
|
|
833
|
+
var numRegex = /^([\-\+])?(0*)([0-9]*(\.[0-9]*)?)$/;
|
|
834
|
+
var consider = {
|
|
835
|
+
hex: true,
|
|
836
|
+
// oct: false,
|
|
837
|
+
leadingZeros: true,
|
|
838
|
+
decimalPoint: ".",
|
|
839
|
+
eNotation: true
|
|
840
|
+
//skipLike: /regex/
|
|
841
|
+
};
|
|
842
|
+
function toNumber(str2, options = {}) {
|
|
843
|
+
options = Object.assign({}, consider, options);
|
|
844
|
+
if (!str2 || typeof str2 !== "string") return str2;
|
|
845
|
+
let trimmedStr = str2.trim();
|
|
846
|
+
if (options.skipLike !== void 0 && options.skipLike.test(trimmedStr)) return str2;
|
|
847
|
+
else if (str2 === "0") return 0;
|
|
848
|
+
else if (options.hex && hexRegex.test(trimmedStr)) {
|
|
849
|
+
return parse_int(trimmedStr, 16);
|
|
850
|
+
} else if (trimmedStr.search(/[eE]/) !== -1) {
|
|
851
|
+
const notation = trimmedStr.match(/^([-\+])?(0*)([0-9]*(\.[0-9]*)?[eE][-\+]?[0-9]+)$/);
|
|
852
|
+
if (notation) {
|
|
853
|
+
if (options.leadingZeros) {
|
|
854
|
+
trimmedStr = (notation[1] || "") + notation[3];
|
|
855
|
+
} else {
|
|
856
|
+
if (notation[2] === "0" && notation[3][0] === ".") ; else {
|
|
857
|
+
return str2;
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
return options.eNotation ? Number(trimmedStr) : str2;
|
|
861
|
+
} else {
|
|
862
|
+
return str2;
|
|
863
|
+
}
|
|
864
|
+
} else {
|
|
865
|
+
const match = numRegex.exec(trimmedStr);
|
|
866
|
+
if (match) {
|
|
867
|
+
const sign = match[1];
|
|
868
|
+
const leadingZeros = match[2];
|
|
869
|
+
let numTrimmedByZeros = trimZeros(match[3]);
|
|
870
|
+
if (!options.leadingZeros && leadingZeros.length > 0 && sign && trimmedStr[2] !== ".") return str2;
|
|
871
|
+
else if (!options.leadingZeros && leadingZeros.length > 0 && !sign && trimmedStr[1] !== ".") return str2;
|
|
872
|
+
else if (options.leadingZeros && leadingZeros === str2) return 0;
|
|
873
|
+
else {
|
|
874
|
+
const num = Number(trimmedStr);
|
|
875
|
+
const numStr = "" + num;
|
|
876
|
+
if (numStr.search(/[eE]/) !== -1) {
|
|
877
|
+
if (options.eNotation) return num;
|
|
878
|
+
else return str2;
|
|
879
|
+
} else if (trimmedStr.indexOf(".") !== -1) {
|
|
880
|
+
if (numStr === "0" && numTrimmedByZeros === "") return num;
|
|
881
|
+
else if (numStr === numTrimmedByZeros) return num;
|
|
882
|
+
else if (sign && numStr === "-" + numTrimmedByZeros) return num;
|
|
883
|
+
else return str2;
|
|
884
|
+
}
|
|
885
|
+
if (leadingZeros) {
|
|
886
|
+
return numTrimmedByZeros === numStr || sign + numTrimmedByZeros === numStr ? num : str2;
|
|
887
|
+
} else {
|
|
888
|
+
return trimmedStr === numStr || trimmedStr === sign + numStr ? num : str2;
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
} else {
|
|
892
|
+
return str2;
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
function trimZeros(numStr) {
|
|
897
|
+
if (numStr && numStr.indexOf(".") !== -1) {
|
|
898
|
+
numStr = numStr.replace(/0+$/, "");
|
|
899
|
+
if (numStr === ".") numStr = "0";
|
|
900
|
+
else if (numStr[0] === ".") numStr = "0" + numStr;
|
|
901
|
+
else if (numStr[numStr.length - 1] === ".") numStr = numStr.substr(0, numStr.length - 1);
|
|
902
|
+
return numStr;
|
|
903
|
+
}
|
|
904
|
+
return numStr;
|
|
905
|
+
}
|
|
906
|
+
function parse_int(numStr, base) {
|
|
907
|
+
if (parseInt) return parseInt(numStr, base);
|
|
908
|
+
else if (Number.parseInt) return Number.parseInt(numStr, base);
|
|
909
|
+
else if (window && window.parseInt) return window.parseInt(numStr, base);
|
|
910
|
+
else throw new Error("parseInt, Number.parseInt, window.parseInt are not supported");
|
|
911
|
+
}
|
|
912
|
+
module.exports = toNumber;
|
|
913
|
+
}
|
|
914
|
+
});
|
|
915
|
+
|
|
916
|
+
// ../../node_modules/.pnpm/fast-xml-parser@4.5.6/node_modules/fast-xml-parser/src/ignoreAttributes.js
|
|
917
|
+
var require_ignoreAttributes = __commonJS({
|
|
918
|
+
"../../node_modules/.pnpm/fast-xml-parser@4.5.6/node_modules/fast-xml-parser/src/ignoreAttributes.js"(exports, module) {
|
|
919
|
+
function getIgnoreAttributesFn(ignoreAttributes) {
|
|
920
|
+
if (typeof ignoreAttributes === "function") {
|
|
921
|
+
return ignoreAttributes;
|
|
922
|
+
}
|
|
923
|
+
if (Array.isArray(ignoreAttributes)) {
|
|
924
|
+
return (attrName) => {
|
|
925
|
+
for (const pattern of ignoreAttributes) {
|
|
926
|
+
if (typeof pattern === "string" && attrName === pattern) {
|
|
927
|
+
return true;
|
|
928
|
+
}
|
|
929
|
+
if (pattern instanceof RegExp && pattern.test(attrName)) {
|
|
930
|
+
return true;
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
};
|
|
934
|
+
}
|
|
935
|
+
return () => false;
|
|
936
|
+
}
|
|
937
|
+
module.exports = getIgnoreAttributesFn;
|
|
938
|
+
}
|
|
939
|
+
});
|
|
940
|
+
|
|
941
|
+
// ../../node_modules/.pnpm/fast-xml-parser@4.5.6/node_modules/fast-xml-parser/src/xmlparser/OrderedObjParser.js
|
|
942
|
+
var require_OrderedObjParser = __commonJS({
|
|
943
|
+
"../../node_modules/.pnpm/fast-xml-parser@4.5.6/node_modules/fast-xml-parser/src/xmlparser/OrderedObjParser.js"(exports, module) {
|
|
944
|
+
var util = require_util();
|
|
945
|
+
var xmlNode = require_xmlNode();
|
|
946
|
+
var DocTypeReader = require_DocTypeReader();
|
|
947
|
+
var toNumber = require_strnum();
|
|
948
|
+
var getIgnoreAttributesFn = require_ignoreAttributes();
|
|
949
|
+
var OrderedObjParser = class {
|
|
950
|
+
constructor(options) {
|
|
951
|
+
this.options = options;
|
|
952
|
+
this.currentNode = null;
|
|
953
|
+
this.tagsNodeStack = [];
|
|
954
|
+
this.docTypeEntities = {};
|
|
955
|
+
this.lastEntities = {
|
|
956
|
+
"apos": { regex: /&(apos|#39|#x27);/g, val: "'" },
|
|
957
|
+
"gt": { regex: /&(gt|#62|#x3E);/g, val: ">" },
|
|
958
|
+
"lt": { regex: /&(lt|#60|#x3C);/g, val: "<" },
|
|
959
|
+
"quot": { regex: /&(quot|#34|#x22);/g, val: '"' }
|
|
960
|
+
};
|
|
961
|
+
this.ampEntity = { regex: /&(amp|#38|#x26);/g, val: "&" };
|
|
962
|
+
this.htmlEntities = {
|
|
963
|
+
"space": { regex: /&(nbsp|#160);/g, val: " " },
|
|
964
|
+
// "lt" : { regex: /&(lt|#60);/g, val: "<" },
|
|
965
|
+
// "gt" : { regex: /&(gt|#62);/g, val: ">" },
|
|
966
|
+
// "amp" : { regex: /&(amp|#38);/g, val: "&" },
|
|
967
|
+
// "quot" : { regex: /&(quot|#34);/g, val: "\"" },
|
|
968
|
+
// "apos" : { regex: /&(apos|#39);/g, val: "'" },
|
|
969
|
+
"cent": { regex: /&(cent|#162);/g, val: "\xA2" },
|
|
970
|
+
"pound": { regex: /&(pound|#163);/g, val: "\xA3" },
|
|
971
|
+
"yen": { regex: /&(yen|#165);/g, val: "\xA5" },
|
|
972
|
+
"euro": { regex: /&(euro|#8364);/g, val: "\u20AC" },
|
|
973
|
+
"copyright": { regex: /&(copy|#169);/g, val: "\xA9" },
|
|
974
|
+
"reg": { regex: /&(reg|#174);/g, val: "\xAE" },
|
|
975
|
+
"inr": { regex: /&(inr|#8377);/g, val: "\u20B9" },
|
|
976
|
+
"num_dec": { regex: /&#([0-9]{1,7});/g, val: (_, str2) => fromCodePoint(str2, 10, "&#") },
|
|
977
|
+
"num_hex": { regex: /&#x([0-9a-fA-F]{1,6});/g, val: (_, str2) => fromCodePoint(str2, 16, "&#x") }
|
|
978
|
+
};
|
|
979
|
+
this.addExternalEntities = addExternalEntities;
|
|
980
|
+
this.parseXml = parseXml;
|
|
981
|
+
this.parseTextData = parseTextData;
|
|
982
|
+
this.resolveNameSpace = resolveNameSpace;
|
|
983
|
+
this.buildAttributesMap = buildAttributesMap;
|
|
984
|
+
this.isItStopNode = isItStopNode;
|
|
985
|
+
this.replaceEntitiesValue = replaceEntitiesValue;
|
|
986
|
+
this.readStopNodeData = readStopNodeData;
|
|
987
|
+
this.saveTextToParentTag = saveTextToParentTag;
|
|
988
|
+
this.addChild = addChild;
|
|
989
|
+
this.ignoreAttributesFn = getIgnoreAttributesFn(this.options.ignoreAttributes);
|
|
990
|
+
this.entityExpansionCount = 0;
|
|
991
|
+
this.currentExpandedLength = 0;
|
|
992
|
+
if (this.options.stopNodes && this.options.stopNodes.length > 0) {
|
|
993
|
+
this.stopNodesExact = /* @__PURE__ */ new Set();
|
|
994
|
+
this.stopNodesWildcard = /* @__PURE__ */ new Set();
|
|
995
|
+
for (let i = 0; i < this.options.stopNodes.length; i++) {
|
|
996
|
+
const stopNodeExp = this.options.stopNodes[i];
|
|
997
|
+
if (typeof stopNodeExp !== "string") continue;
|
|
998
|
+
if (stopNodeExp.startsWith("*.")) {
|
|
999
|
+
this.stopNodesWildcard.add(stopNodeExp.substring(2));
|
|
1000
|
+
} else {
|
|
1001
|
+
this.stopNodesExact.add(stopNodeExp);
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
};
|
|
1007
|
+
function addExternalEntities(externalEntities) {
|
|
1008
|
+
const entKeys = Object.keys(externalEntities);
|
|
1009
|
+
for (let i = 0; i < entKeys.length; i++) {
|
|
1010
|
+
const ent = entKeys[i];
|
|
1011
|
+
const escaped = ent.replace(/[.\-+*:]/g, "\\.");
|
|
1012
|
+
this.lastEntities[ent] = {
|
|
1013
|
+
regex: new RegExp("&" + escaped + ";", "g"),
|
|
1014
|
+
val: externalEntities[ent]
|
|
1015
|
+
};
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
function parseTextData(val, tagName, jPath, dontTrim, hasAttributes, isLeafNode, escapeEntities) {
|
|
1019
|
+
if (val !== void 0) {
|
|
1020
|
+
if (this.options.trimValues && !dontTrim) {
|
|
1021
|
+
val = val.trim();
|
|
1022
|
+
}
|
|
1023
|
+
if (val.length > 0) {
|
|
1024
|
+
if (!escapeEntities) val = this.replaceEntitiesValue(val, tagName, jPath);
|
|
1025
|
+
const newval = this.options.tagValueProcessor(tagName, val, jPath, hasAttributes, isLeafNode);
|
|
1026
|
+
if (newval === null || newval === void 0) {
|
|
1027
|
+
return val;
|
|
1028
|
+
} else if (typeof newval !== typeof val || newval !== val) {
|
|
1029
|
+
return newval;
|
|
1030
|
+
} else if (this.options.trimValues) {
|
|
1031
|
+
return parseValue(val, this.options.parseTagValue, this.options.numberParseOptions);
|
|
1032
|
+
} else {
|
|
1033
|
+
const trimmedVal = val.trim();
|
|
1034
|
+
if (trimmedVal === val) {
|
|
1035
|
+
return parseValue(val, this.options.parseTagValue, this.options.numberParseOptions);
|
|
1036
|
+
} else {
|
|
1037
|
+
return val;
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
function resolveNameSpace(tagname) {
|
|
1044
|
+
if (this.options.removeNSPrefix) {
|
|
1045
|
+
const tags = tagname.split(":");
|
|
1046
|
+
const prefix = tagname.charAt(0) === "/" ? "/" : "";
|
|
1047
|
+
if (tags[0] === "xmlns") {
|
|
1048
|
+
return "";
|
|
1049
|
+
}
|
|
1050
|
+
if (tags.length === 2) {
|
|
1051
|
+
tagname = prefix + tags[1];
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
return tagname;
|
|
1055
|
+
}
|
|
1056
|
+
var attrsRegx = new RegExp(`([^\\s=]+)\\s*(=\\s*(['"])([\\s\\S]*?)\\3)?`, "gm");
|
|
1057
|
+
function buildAttributesMap(attrStr, jPath, tagName) {
|
|
1058
|
+
if (this.options.ignoreAttributes !== true && typeof attrStr === "string") {
|
|
1059
|
+
const matches = util.getAllMatches(attrStr, attrsRegx);
|
|
1060
|
+
const len = matches.length;
|
|
1061
|
+
const attrs = {};
|
|
1062
|
+
for (let i = 0; i < len; i++) {
|
|
1063
|
+
const attrName = this.resolveNameSpace(matches[i][1]);
|
|
1064
|
+
if (this.ignoreAttributesFn(attrName, jPath)) {
|
|
1065
|
+
continue;
|
|
1066
|
+
}
|
|
1067
|
+
let oldVal = matches[i][4];
|
|
1068
|
+
let aName = this.options.attributeNamePrefix + attrName;
|
|
1069
|
+
if (attrName.length) {
|
|
1070
|
+
if (this.options.transformAttributeName) {
|
|
1071
|
+
aName = this.options.transformAttributeName(aName);
|
|
1072
|
+
}
|
|
1073
|
+
aName = sanitizeName(aName, this.options);
|
|
1074
|
+
if (oldVal !== void 0) {
|
|
1075
|
+
if (this.options.trimValues) {
|
|
1076
|
+
oldVal = oldVal.trim();
|
|
1077
|
+
}
|
|
1078
|
+
oldVal = this.replaceEntitiesValue(oldVal, tagName, jPath);
|
|
1079
|
+
const newVal = this.options.attributeValueProcessor(attrName, oldVal, jPath);
|
|
1080
|
+
if (newVal === null || newVal === void 0) {
|
|
1081
|
+
attrs[aName] = oldVal;
|
|
1082
|
+
} else if (typeof newVal !== typeof oldVal || newVal !== oldVal) {
|
|
1083
|
+
attrs[aName] = newVal;
|
|
1084
|
+
} else {
|
|
1085
|
+
attrs[aName] = parseValue(
|
|
1086
|
+
oldVal,
|
|
1087
|
+
this.options.parseAttributeValue,
|
|
1088
|
+
this.options.numberParseOptions
|
|
1089
|
+
);
|
|
1090
|
+
}
|
|
1091
|
+
} else if (this.options.allowBooleanAttributes) {
|
|
1092
|
+
attrs[aName] = true;
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
if (!Object.keys(attrs).length) {
|
|
1097
|
+
return;
|
|
1098
|
+
}
|
|
1099
|
+
if (this.options.attributesGroupName) {
|
|
1100
|
+
const attrCollection = {};
|
|
1101
|
+
attrCollection[this.options.attributesGroupName] = attrs;
|
|
1102
|
+
return attrCollection;
|
|
1103
|
+
}
|
|
1104
|
+
return attrs;
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
var parseXml = function(xmlData) {
|
|
1108
|
+
xmlData = xmlData.replace(/\r\n?/g, "\n");
|
|
1109
|
+
const xmlObj = new xmlNode("!xml");
|
|
1110
|
+
let currentNode = xmlObj;
|
|
1111
|
+
let textData = "";
|
|
1112
|
+
let jPath = "";
|
|
1113
|
+
this.entityExpansionCount = 0;
|
|
1114
|
+
this.currentExpandedLength = 0;
|
|
1115
|
+
const docTypeReader = new DocTypeReader(this.options.processEntities);
|
|
1116
|
+
for (let i = 0; i < xmlData.length; i++) {
|
|
1117
|
+
const ch = xmlData[i];
|
|
1118
|
+
if (ch === "<") {
|
|
1119
|
+
if (xmlData[i + 1] === "/") {
|
|
1120
|
+
const closeIndex = findClosingIndex(xmlData, ">", i, "Closing Tag is not closed.");
|
|
1121
|
+
let tagName = xmlData.substring(i + 2, closeIndex).trim();
|
|
1122
|
+
if (this.options.removeNSPrefix) {
|
|
1123
|
+
const colonIndex = tagName.indexOf(":");
|
|
1124
|
+
if (colonIndex !== -1) {
|
|
1125
|
+
tagName = tagName.substr(colonIndex + 1);
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
if (this.options.transformTagName) {
|
|
1129
|
+
tagName = this.options.transformTagName(tagName);
|
|
1130
|
+
}
|
|
1131
|
+
if (currentNode) {
|
|
1132
|
+
textData = this.saveTextToParentTag(textData, currentNode, jPath);
|
|
1133
|
+
}
|
|
1134
|
+
const lastTagName = jPath.substring(jPath.lastIndexOf(".") + 1);
|
|
1135
|
+
if (tagName && this.options.unpairedTags.indexOf(tagName) !== -1) {
|
|
1136
|
+
throw new Error(`Unpaired tag can not be used as closing tag: </${tagName}>`);
|
|
1137
|
+
}
|
|
1138
|
+
let propIndex = 0;
|
|
1139
|
+
if (lastTagName && this.options.unpairedTags.indexOf(lastTagName) !== -1) {
|
|
1140
|
+
propIndex = jPath.lastIndexOf(".", jPath.lastIndexOf(".") - 1);
|
|
1141
|
+
this.tagsNodeStack.pop();
|
|
1142
|
+
} else {
|
|
1143
|
+
propIndex = jPath.lastIndexOf(".");
|
|
1144
|
+
}
|
|
1145
|
+
jPath = jPath.substring(0, propIndex);
|
|
1146
|
+
currentNode = this.tagsNodeStack.pop();
|
|
1147
|
+
textData = "";
|
|
1148
|
+
i = closeIndex;
|
|
1149
|
+
} else if (xmlData[i + 1] === "?") {
|
|
1150
|
+
let tagData = readTagExp(xmlData, i, false, "?>");
|
|
1151
|
+
if (!tagData) throw new Error("Pi Tag is not closed.");
|
|
1152
|
+
textData = this.saveTextToParentTag(textData, currentNode, jPath);
|
|
1153
|
+
if (this.options.ignoreDeclaration && tagData.tagName === "?xml" || this.options.ignorePiTags) ; else {
|
|
1154
|
+
const childNode = new xmlNode(tagData.tagName);
|
|
1155
|
+
childNode.add(this.options.textNodeName, "");
|
|
1156
|
+
if (tagData.tagName !== tagData.tagExp && tagData.attrExpPresent) {
|
|
1157
|
+
childNode[":@"] = this.buildAttributesMap(tagData.tagExp, jPath, tagData.tagName);
|
|
1158
|
+
}
|
|
1159
|
+
this.addChild(currentNode, childNode, jPath, i);
|
|
1160
|
+
}
|
|
1161
|
+
i = tagData.closeIndex + 1;
|
|
1162
|
+
} else if (xmlData.substr(i + 1, 3) === "!--") {
|
|
1163
|
+
const endIndex = findClosingIndex(xmlData, "-->", i + 4, "Comment is not closed.");
|
|
1164
|
+
if (this.options.commentPropName) {
|
|
1165
|
+
const comment = xmlData.substring(i + 4, endIndex - 2);
|
|
1166
|
+
textData = this.saveTextToParentTag(textData, currentNode, jPath);
|
|
1167
|
+
currentNode.add(this.options.commentPropName, [{ [this.options.textNodeName]: comment }]);
|
|
1168
|
+
}
|
|
1169
|
+
i = endIndex;
|
|
1170
|
+
} else if (xmlData.substr(i + 1, 2) === "!D") {
|
|
1171
|
+
const result = docTypeReader.readDocType(xmlData, i);
|
|
1172
|
+
this.docTypeEntities = result.entities;
|
|
1173
|
+
i = result.i;
|
|
1174
|
+
} else if (xmlData.substr(i + 1, 2) === "![") {
|
|
1175
|
+
const closeIndex = findClosingIndex(xmlData, "]]>", i, "CDATA is not closed.") - 2;
|
|
1176
|
+
const tagExp = xmlData.substring(i + 9, closeIndex);
|
|
1177
|
+
textData = this.saveTextToParentTag(textData, currentNode, jPath);
|
|
1178
|
+
let val = this.parseTextData(tagExp, currentNode.tagname, jPath, true, false, true, true);
|
|
1179
|
+
if (val == void 0) val = "";
|
|
1180
|
+
if (this.options.cdataPropName) {
|
|
1181
|
+
currentNode.add(this.options.cdataPropName, [{ [this.options.textNodeName]: tagExp }]);
|
|
1182
|
+
} else {
|
|
1183
|
+
currentNode.add(this.options.textNodeName, val);
|
|
1184
|
+
}
|
|
1185
|
+
i = closeIndex + 2;
|
|
1186
|
+
} else {
|
|
1187
|
+
let result = readTagExp(xmlData, i, this.options.removeNSPrefix);
|
|
1188
|
+
let tagName = result.tagName;
|
|
1189
|
+
const rawTagName = result.rawTagName;
|
|
1190
|
+
let tagExp = result.tagExp;
|
|
1191
|
+
let attrExpPresent = result.attrExpPresent;
|
|
1192
|
+
let closeIndex = result.closeIndex;
|
|
1193
|
+
if (this.options.transformTagName) {
|
|
1194
|
+
const newTagName = this.options.transformTagName(tagName);
|
|
1195
|
+
if (tagExp === tagName) {
|
|
1196
|
+
tagExp = newTagName;
|
|
1197
|
+
}
|
|
1198
|
+
tagName = newTagName;
|
|
1199
|
+
}
|
|
1200
|
+
if (this.options.strictReservedNames && (tagName === this.options.commentPropName || tagName === this.options.cdataPropName || tagName === this.options.textNodeName || tagName === this.options.attributesGroupName)) {
|
|
1201
|
+
throw new Error(`Invalid tag name: ${tagName}`);
|
|
1202
|
+
}
|
|
1203
|
+
if (currentNode && textData) {
|
|
1204
|
+
if (currentNode.tagname !== "!xml") {
|
|
1205
|
+
textData = this.saveTextToParentTag(textData, currentNode, jPath, false);
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
const lastTag = currentNode;
|
|
1209
|
+
if (lastTag && this.options.unpairedTags.indexOf(lastTag.tagname) !== -1) {
|
|
1210
|
+
currentNode = this.tagsNodeStack.pop();
|
|
1211
|
+
jPath = jPath.substring(0, jPath.lastIndexOf("."));
|
|
1212
|
+
}
|
|
1213
|
+
if (tagName !== xmlObj.tagname) {
|
|
1214
|
+
jPath += jPath ? "." + tagName : tagName;
|
|
1215
|
+
}
|
|
1216
|
+
const startIndex = i;
|
|
1217
|
+
if (this.isItStopNode(this.stopNodesExact, this.stopNodesWildcard, jPath, tagName)) {
|
|
1218
|
+
let tagContent = "";
|
|
1219
|
+
if (tagExp.length > 0 && tagExp.lastIndexOf("/") === tagExp.length - 1) {
|
|
1220
|
+
if (tagName[tagName.length - 1] === "/") {
|
|
1221
|
+
tagName = tagName.substr(0, tagName.length - 1);
|
|
1222
|
+
jPath = jPath.substr(0, jPath.length - 1);
|
|
1223
|
+
tagExp = tagName;
|
|
1224
|
+
} else {
|
|
1225
|
+
tagExp = tagExp.substr(0, tagExp.length - 1);
|
|
1226
|
+
}
|
|
1227
|
+
i = result.closeIndex;
|
|
1228
|
+
} else if (this.options.unpairedTags.indexOf(tagName) !== -1) {
|
|
1229
|
+
i = result.closeIndex;
|
|
1230
|
+
} else {
|
|
1231
|
+
const result2 = this.readStopNodeData(xmlData, rawTagName, closeIndex + 1);
|
|
1232
|
+
if (!result2) throw new Error(`Unexpected end of ${rawTagName}`);
|
|
1233
|
+
i = result2.i;
|
|
1234
|
+
tagContent = result2.tagContent;
|
|
1235
|
+
}
|
|
1236
|
+
const childNode = new xmlNode(tagName);
|
|
1237
|
+
if (tagName !== tagExp && attrExpPresent) {
|
|
1238
|
+
childNode[":@"] = this.buildAttributesMap(tagExp, jPath, tagName);
|
|
1239
|
+
}
|
|
1240
|
+
if (tagContent) {
|
|
1241
|
+
tagContent = this.parseTextData(tagContent, tagName, jPath, true, attrExpPresent, true, true);
|
|
1242
|
+
}
|
|
1243
|
+
jPath = jPath.substr(0, jPath.lastIndexOf("."));
|
|
1244
|
+
childNode.add(this.options.textNodeName, tagContent);
|
|
1245
|
+
this.addChild(currentNode, childNode, jPath, startIndex);
|
|
1246
|
+
} else {
|
|
1247
|
+
if (tagExp.length > 0 && tagExp.lastIndexOf("/") === tagExp.length - 1) {
|
|
1248
|
+
if (tagName[tagName.length - 1] === "/") {
|
|
1249
|
+
tagName = tagName.substr(0, tagName.length - 1);
|
|
1250
|
+
jPath = jPath.substr(0, jPath.length - 1);
|
|
1251
|
+
tagExp = tagName;
|
|
1252
|
+
} else {
|
|
1253
|
+
tagExp = tagExp.substr(0, tagExp.length - 1);
|
|
1254
|
+
}
|
|
1255
|
+
if (this.options.transformTagName) {
|
|
1256
|
+
const newTagName = this.options.transformTagName(tagName);
|
|
1257
|
+
if (tagExp === tagName) {
|
|
1258
|
+
tagExp = newTagName;
|
|
1259
|
+
}
|
|
1260
|
+
tagName = newTagName;
|
|
1261
|
+
}
|
|
1262
|
+
const childNode = new xmlNode(tagName);
|
|
1263
|
+
if (tagName !== tagExp && attrExpPresent) {
|
|
1264
|
+
childNode[":@"] = this.buildAttributesMap(tagExp, jPath, tagName);
|
|
1265
|
+
}
|
|
1266
|
+
this.addChild(currentNode, childNode, jPath, startIndex);
|
|
1267
|
+
jPath = jPath.substr(0, jPath.lastIndexOf("."));
|
|
1268
|
+
} else if (this.options.unpairedTags.indexOf(tagName) !== -1) {
|
|
1269
|
+
const childNode = new xmlNode(tagName);
|
|
1270
|
+
if (tagName !== tagExp && attrExpPresent) {
|
|
1271
|
+
childNode[":@"] = this.buildAttributesMap(tagExp, jPath);
|
|
1272
|
+
}
|
|
1273
|
+
this.addChild(currentNode, childNode, jPath, startIndex);
|
|
1274
|
+
jPath = jPath.substr(0, jPath.lastIndexOf("."));
|
|
1275
|
+
i = result.closeIndex;
|
|
1276
|
+
continue;
|
|
1277
|
+
} else {
|
|
1278
|
+
const childNode = new xmlNode(tagName);
|
|
1279
|
+
if (this.tagsNodeStack.length > this.options.maxNestedTags) {
|
|
1280
|
+
throw new Error("Maximum nested tags exceeded");
|
|
1281
|
+
}
|
|
1282
|
+
this.tagsNodeStack.push(currentNode);
|
|
1283
|
+
if (tagName !== tagExp && attrExpPresent) {
|
|
1284
|
+
childNode[":@"] = this.buildAttributesMap(tagExp, jPath, tagName);
|
|
1285
|
+
}
|
|
1286
|
+
this.addChild(currentNode, childNode, jPath);
|
|
1287
|
+
currentNode = childNode;
|
|
1288
|
+
}
|
|
1289
|
+
textData = "";
|
|
1290
|
+
i = closeIndex;
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
} else {
|
|
1294
|
+
textData += xmlData[i];
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
return xmlObj.child;
|
|
1298
|
+
};
|
|
1299
|
+
function addChild(currentNode, childNode, jPath, startIndex) {
|
|
1300
|
+
if (!this.options.captureMetaData) startIndex = void 0;
|
|
1301
|
+
const result = this.options.updateTag(childNode.tagname, jPath, childNode[":@"]);
|
|
1302
|
+
if (result === false) ; else if (typeof result === "string") {
|
|
1303
|
+
childNode.tagname = result;
|
|
1304
|
+
currentNode.addChild(childNode, startIndex);
|
|
1305
|
+
} else {
|
|
1306
|
+
currentNode.addChild(childNode, startIndex);
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
var replaceEntitiesValue = function(val, tagName, jPath) {
|
|
1310
|
+
if (val.indexOf("&") === -1) {
|
|
1311
|
+
return val;
|
|
1312
|
+
}
|
|
1313
|
+
const entityConfig = this.options.processEntities;
|
|
1314
|
+
if (!entityConfig.enabled) {
|
|
1315
|
+
return val;
|
|
1316
|
+
}
|
|
1317
|
+
if (entityConfig.allowedTags) {
|
|
1318
|
+
if (!entityConfig.allowedTags.includes(tagName)) {
|
|
1319
|
+
return val;
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
if (entityConfig.tagFilter) {
|
|
1323
|
+
if (!entityConfig.tagFilter(tagName, jPath)) {
|
|
1324
|
+
return val;
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
for (let entityName in this.docTypeEntities) {
|
|
1328
|
+
const entity = this.docTypeEntities[entityName];
|
|
1329
|
+
const matches = val.match(entity.regx);
|
|
1330
|
+
if (matches) {
|
|
1331
|
+
this.entityExpansionCount += matches.length;
|
|
1332
|
+
if (entityConfig.maxTotalExpansions && this.entityExpansionCount > entityConfig.maxTotalExpansions) {
|
|
1333
|
+
throw new Error(
|
|
1334
|
+
`Entity expansion limit exceeded: ${this.entityExpansionCount} > ${entityConfig.maxTotalExpansions}`
|
|
1335
|
+
);
|
|
1336
|
+
}
|
|
1337
|
+
const lengthBefore = val.length;
|
|
1338
|
+
val = val.replace(entity.regx, entity.val);
|
|
1339
|
+
if (entityConfig.maxExpandedLength) {
|
|
1340
|
+
this.currentExpandedLength += val.length - lengthBefore;
|
|
1341
|
+
if (this.currentExpandedLength > entityConfig.maxExpandedLength) {
|
|
1342
|
+
throw new Error(
|
|
1343
|
+
`Total expanded content size exceeded: ${this.currentExpandedLength} > ${entityConfig.maxExpandedLength}`
|
|
1344
|
+
);
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
if (val.indexOf("&") === -1) return val;
|
|
1350
|
+
for (const entityName of Object.keys(this.lastEntities)) {
|
|
1351
|
+
const entity = this.lastEntities[entityName];
|
|
1352
|
+
const matches = val.match(entity.regex);
|
|
1353
|
+
if (matches) {
|
|
1354
|
+
this.entityExpansionCount += matches.length;
|
|
1355
|
+
if (entityConfig.maxTotalExpansions && this.entityExpansionCount > entityConfig.maxTotalExpansions) {
|
|
1356
|
+
throw new Error(
|
|
1357
|
+
`Entity expansion limit exceeded: ${this.entityExpansionCount} > ${entityConfig.maxTotalExpansions}`
|
|
1358
|
+
);
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
val = val.replace(entity.regex, entity.val);
|
|
1362
|
+
}
|
|
1363
|
+
if (val.indexOf("&") === -1) return val;
|
|
1364
|
+
if (this.options.htmlEntities) {
|
|
1365
|
+
for (const entityName of Object.keys(this.htmlEntities)) {
|
|
1366
|
+
const entity = this.htmlEntities[entityName];
|
|
1367
|
+
const matches = val.match(entity.regex);
|
|
1368
|
+
if (matches) {
|
|
1369
|
+
this.entityExpansionCount += matches.length;
|
|
1370
|
+
if (entityConfig.maxTotalExpansions && this.entityExpansionCount > entityConfig.maxTotalExpansions) {
|
|
1371
|
+
throw new Error(
|
|
1372
|
+
`Entity expansion limit exceeded: ${this.entityExpansionCount} > ${entityConfig.maxTotalExpansions}`
|
|
1373
|
+
);
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
val = val.replace(entity.regex, entity.val);
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
val = val.replace(this.ampEntity.regex, this.ampEntity.val);
|
|
1380
|
+
return val;
|
|
1381
|
+
};
|
|
1382
|
+
function saveTextToParentTag(textData, parentNode, jPath, isLeafNode) {
|
|
1383
|
+
if (textData) {
|
|
1384
|
+
if (isLeafNode === void 0) isLeafNode = parentNode.child.length === 0;
|
|
1385
|
+
textData = this.parseTextData(
|
|
1386
|
+
textData,
|
|
1387
|
+
parentNode.tagname,
|
|
1388
|
+
jPath,
|
|
1389
|
+
false,
|
|
1390
|
+
parentNode[":@"] ? Object.keys(parentNode[":@"]).length !== 0 : false,
|
|
1391
|
+
isLeafNode
|
|
1392
|
+
);
|
|
1393
|
+
if (textData !== void 0 && textData !== "")
|
|
1394
|
+
parentNode.add(this.options.textNodeName, textData);
|
|
1395
|
+
textData = "";
|
|
1396
|
+
}
|
|
1397
|
+
return textData;
|
|
1398
|
+
}
|
|
1399
|
+
function isItStopNode(stopNodesExact, stopNodesWildcard, jPath, currentTagName) {
|
|
1400
|
+
if (stopNodesWildcard && stopNodesWildcard.has(currentTagName)) return true;
|
|
1401
|
+
if (stopNodesExact && stopNodesExact.has(jPath)) return true;
|
|
1402
|
+
return false;
|
|
1403
|
+
}
|
|
1404
|
+
function tagExpWithClosingIndex(xmlData, i, closingChar = ">") {
|
|
1405
|
+
let attrBoundary;
|
|
1406
|
+
let tagExp = "";
|
|
1407
|
+
for (let index = i; index < xmlData.length; index++) {
|
|
1408
|
+
let ch = xmlData[index];
|
|
1409
|
+
if (attrBoundary) {
|
|
1410
|
+
if (ch === attrBoundary) attrBoundary = "";
|
|
1411
|
+
} else if (ch === '"' || ch === "'") {
|
|
1412
|
+
attrBoundary = ch;
|
|
1413
|
+
} else if (ch === closingChar[0]) {
|
|
1414
|
+
if (closingChar[1]) {
|
|
1415
|
+
if (xmlData[index + 1] === closingChar[1]) {
|
|
1416
|
+
return {
|
|
1417
|
+
data: tagExp,
|
|
1418
|
+
index
|
|
1419
|
+
};
|
|
1420
|
+
}
|
|
1421
|
+
} else {
|
|
1422
|
+
return {
|
|
1423
|
+
data: tagExp,
|
|
1424
|
+
index
|
|
1425
|
+
};
|
|
1426
|
+
}
|
|
1427
|
+
} else if (ch === " ") {
|
|
1428
|
+
ch = " ";
|
|
1429
|
+
}
|
|
1430
|
+
tagExp += ch;
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
function findClosingIndex(xmlData, str2, i, errMsg) {
|
|
1434
|
+
const closingIndex = xmlData.indexOf(str2, i);
|
|
1435
|
+
if (closingIndex === -1) {
|
|
1436
|
+
throw new Error(errMsg);
|
|
1437
|
+
} else {
|
|
1438
|
+
return closingIndex + str2.length - 1;
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
function readTagExp(xmlData, i, removeNSPrefix, closingChar = ">") {
|
|
1442
|
+
const result = tagExpWithClosingIndex(xmlData, i + 1, closingChar);
|
|
1443
|
+
if (!result) return;
|
|
1444
|
+
let tagExp = result.data;
|
|
1445
|
+
const closeIndex = result.index;
|
|
1446
|
+
const separatorIndex = tagExp.search(/\s/);
|
|
1447
|
+
let tagName = tagExp;
|
|
1448
|
+
let attrExpPresent = true;
|
|
1449
|
+
if (separatorIndex !== -1) {
|
|
1450
|
+
tagName = tagExp.substring(0, separatorIndex);
|
|
1451
|
+
tagExp = tagExp.substring(separatorIndex + 1).trimStart();
|
|
1452
|
+
}
|
|
1453
|
+
const rawTagName = tagName;
|
|
1454
|
+
if (removeNSPrefix) {
|
|
1455
|
+
const colonIndex = tagName.indexOf(":");
|
|
1456
|
+
if (colonIndex !== -1) {
|
|
1457
|
+
tagName = tagName.substr(colonIndex + 1);
|
|
1458
|
+
attrExpPresent = tagName !== result.data.substr(colonIndex + 1);
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
return {
|
|
1462
|
+
tagName,
|
|
1463
|
+
tagExp,
|
|
1464
|
+
closeIndex,
|
|
1465
|
+
attrExpPresent,
|
|
1466
|
+
rawTagName
|
|
1467
|
+
};
|
|
1468
|
+
}
|
|
1469
|
+
function readStopNodeData(xmlData, tagName, i) {
|
|
1470
|
+
const startIndex = i;
|
|
1471
|
+
let openTagCount = 1;
|
|
1472
|
+
for (; i < xmlData.length; i++) {
|
|
1473
|
+
if (xmlData[i] === "<") {
|
|
1474
|
+
if (xmlData[i + 1] === "/") {
|
|
1475
|
+
const closeIndex = findClosingIndex(xmlData, ">", i, `${tagName} is not closed`);
|
|
1476
|
+
let closeTagName = xmlData.substring(i + 2, closeIndex).trim();
|
|
1477
|
+
if (closeTagName === tagName) {
|
|
1478
|
+
openTagCount--;
|
|
1479
|
+
if (openTagCount === 0) {
|
|
1480
|
+
return {
|
|
1481
|
+
tagContent: xmlData.substring(startIndex, i),
|
|
1482
|
+
i: closeIndex
|
|
1483
|
+
};
|
|
1484
|
+
}
|
|
1485
|
+
}
|
|
1486
|
+
i = closeIndex;
|
|
1487
|
+
} else if (xmlData[i + 1] === "?") {
|
|
1488
|
+
const closeIndex = findClosingIndex(xmlData, "?>", i + 1, "StopNode is not closed.");
|
|
1489
|
+
i = closeIndex;
|
|
1490
|
+
} else if (xmlData.substr(i + 1, 3) === "!--") {
|
|
1491
|
+
const closeIndex = findClosingIndex(xmlData, "-->", i + 3, "StopNode is not closed.");
|
|
1492
|
+
i = closeIndex;
|
|
1493
|
+
} else if (xmlData.substr(i + 1, 2) === "![") {
|
|
1494
|
+
const closeIndex = findClosingIndex(xmlData, "]]>", i, "StopNode is not closed.") - 2;
|
|
1495
|
+
i = closeIndex;
|
|
1496
|
+
} else {
|
|
1497
|
+
const tagData = readTagExp(xmlData, i, ">");
|
|
1498
|
+
if (tagData) {
|
|
1499
|
+
const openTagName = tagData && tagData.tagName;
|
|
1500
|
+
if (openTagName === tagName && tagData.tagExp[tagData.tagExp.length - 1] !== "/") {
|
|
1501
|
+
openTagCount++;
|
|
1502
|
+
}
|
|
1503
|
+
i = tagData.closeIndex;
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
function parseValue(val, shouldParse, options) {
|
|
1510
|
+
if (shouldParse && typeof val === "string") {
|
|
1511
|
+
const newval = val.trim();
|
|
1512
|
+
if (newval === "true") return true;
|
|
1513
|
+
else if (newval === "false") return false;
|
|
1514
|
+
else return toNumber(val, options);
|
|
1515
|
+
} else {
|
|
1516
|
+
if (util.isExist(val)) {
|
|
1517
|
+
return val;
|
|
1518
|
+
} else {
|
|
1519
|
+
return "";
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
function fromCodePoint(str2, base, prefix) {
|
|
1524
|
+
const codePoint = Number.parseInt(str2, base);
|
|
1525
|
+
if (codePoint >= 0 && codePoint <= 1114111) {
|
|
1526
|
+
return String.fromCodePoint(codePoint);
|
|
1527
|
+
} else {
|
|
1528
|
+
return prefix + str2 + ";";
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1531
|
+
function sanitizeName(name, options) {
|
|
1532
|
+
if (util.criticalProperties.includes(name)) {
|
|
1533
|
+
throw new Error(`[SECURITY] Invalid name: "${name}" is a reserved JavaScript keyword that could cause prototype pollution`);
|
|
1534
|
+
} else if (util.DANGEROUS_PROPERTY_NAMES.includes(name)) {
|
|
1535
|
+
return options.onDangerousProperty(name);
|
|
1536
|
+
}
|
|
1537
|
+
return name;
|
|
1538
|
+
}
|
|
1539
|
+
module.exports = OrderedObjParser;
|
|
1540
|
+
}
|
|
1541
|
+
});
|
|
1542
|
+
|
|
1543
|
+
// ../../node_modules/.pnpm/fast-xml-parser@4.5.6/node_modules/fast-xml-parser/src/xmlparser/node2json.js
|
|
1544
|
+
var require_node2json = __commonJS({
|
|
1545
|
+
"../../node_modules/.pnpm/fast-xml-parser@4.5.6/node_modules/fast-xml-parser/src/xmlparser/node2json.js"(exports) {
|
|
1546
|
+
function prettify(node, options) {
|
|
1547
|
+
return compress(node, options);
|
|
1548
|
+
}
|
|
1549
|
+
function compress(arr, options, jPath) {
|
|
1550
|
+
let text2;
|
|
1551
|
+
const compressedObj = {};
|
|
1552
|
+
for (let i = 0; i < arr.length; i++) {
|
|
1553
|
+
const tagObj = arr[i];
|
|
1554
|
+
const property = propName(tagObj);
|
|
1555
|
+
let newJpath = "";
|
|
1556
|
+
if (jPath === void 0) newJpath = property;
|
|
1557
|
+
else newJpath = jPath + "." + property;
|
|
1558
|
+
if (property === options.textNodeName) {
|
|
1559
|
+
if (text2 === void 0) text2 = tagObj[property];
|
|
1560
|
+
else text2 += "" + tagObj[property];
|
|
1561
|
+
} else if (property === void 0) {
|
|
1562
|
+
continue;
|
|
1563
|
+
} else if (tagObj[property]) {
|
|
1564
|
+
let val = compress(tagObj[property], options, newJpath);
|
|
1565
|
+
const isLeaf = isLeafTag(val, options);
|
|
1566
|
+
if (tagObj[":@"]) {
|
|
1567
|
+
assignAttributes(val, tagObj[":@"], newJpath, options);
|
|
1568
|
+
} else if (Object.keys(val).length === 1 && val[options.textNodeName] !== void 0 && !options.alwaysCreateTextNode) {
|
|
1569
|
+
val = val[options.textNodeName];
|
|
1570
|
+
} else if (Object.keys(val).length === 0) {
|
|
1571
|
+
if (options.alwaysCreateTextNode) val[options.textNodeName] = "";
|
|
1572
|
+
else val = "";
|
|
1573
|
+
}
|
|
1574
|
+
if (compressedObj[property] !== void 0 && compressedObj.hasOwnProperty(property)) {
|
|
1575
|
+
if (!Array.isArray(compressedObj[property])) {
|
|
1576
|
+
compressedObj[property] = [compressedObj[property]];
|
|
1577
|
+
}
|
|
1578
|
+
compressedObj[property].push(val);
|
|
1579
|
+
} else {
|
|
1580
|
+
if (options.isArray(property, newJpath, isLeaf)) {
|
|
1581
|
+
compressedObj[property] = [val];
|
|
1582
|
+
} else {
|
|
1583
|
+
compressedObj[property] = val;
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1588
|
+
if (typeof text2 === "string") {
|
|
1589
|
+
if (text2.length > 0) compressedObj[options.textNodeName] = text2;
|
|
1590
|
+
} else if (text2 !== void 0) compressedObj[options.textNodeName] = text2;
|
|
1591
|
+
return compressedObj;
|
|
1592
|
+
}
|
|
1593
|
+
function propName(obj) {
|
|
1594
|
+
const keys = Object.keys(obj);
|
|
1595
|
+
for (let i = 0; i < keys.length; i++) {
|
|
1596
|
+
const key = keys[i];
|
|
1597
|
+
if (key !== ":@") return key;
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
function assignAttributes(obj, attrMap, jpath, options) {
|
|
1601
|
+
if (attrMap) {
|
|
1602
|
+
const keys = Object.keys(attrMap);
|
|
1603
|
+
const len = keys.length;
|
|
1604
|
+
for (let i = 0; i < len; i++) {
|
|
1605
|
+
const atrrName = keys[i];
|
|
1606
|
+
if (options.isArray(atrrName, jpath + "." + atrrName, true, true)) {
|
|
1607
|
+
obj[atrrName] = [attrMap[atrrName]];
|
|
1608
|
+
} else {
|
|
1609
|
+
obj[atrrName] = attrMap[atrrName];
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
function isLeafTag(obj, options) {
|
|
1615
|
+
const { textNodeName } = options;
|
|
1616
|
+
const propCount = Object.keys(obj).length;
|
|
1617
|
+
if (propCount === 0) {
|
|
1618
|
+
return true;
|
|
1619
|
+
}
|
|
1620
|
+
if (propCount === 1 && (obj[textNodeName] || typeof obj[textNodeName] === "boolean" || obj[textNodeName] === 0)) {
|
|
1621
|
+
return true;
|
|
1622
|
+
}
|
|
1623
|
+
return false;
|
|
1624
|
+
}
|
|
1625
|
+
exports.prettify = prettify;
|
|
1626
|
+
}
|
|
1627
|
+
});
|
|
1628
|
+
|
|
1629
|
+
// ../../node_modules/.pnpm/fast-xml-parser@4.5.6/node_modules/fast-xml-parser/src/xmlparser/XMLParser.js
|
|
1630
|
+
var require_XMLParser = __commonJS({
|
|
1631
|
+
"../../node_modules/.pnpm/fast-xml-parser@4.5.6/node_modules/fast-xml-parser/src/xmlparser/XMLParser.js"(exports, module) {
|
|
1632
|
+
var { buildOptions } = require_OptionsBuilder();
|
|
1633
|
+
var OrderedObjParser = require_OrderedObjParser();
|
|
1634
|
+
var { prettify } = require_node2json();
|
|
1635
|
+
var validator = require_validator();
|
|
1636
|
+
var XMLParser2 = class {
|
|
1637
|
+
constructor(options) {
|
|
1638
|
+
this.externalEntities = {};
|
|
1639
|
+
this.options = buildOptions(options);
|
|
1640
|
+
}
|
|
1641
|
+
/**
|
|
1642
|
+
* Parse XML dats to JS object
|
|
1643
|
+
* @param {string|Buffer} xmlData
|
|
1644
|
+
* @param {boolean|Object} validationOption
|
|
1645
|
+
*/
|
|
1646
|
+
parse(xmlData, validationOption) {
|
|
1647
|
+
if (typeof xmlData === "string") ; else if (xmlData.toString) {
|
|
1648
|
+
xmlData = xmlData.toString();
|
|
1649
|
+
} else {
|
|
1650
|
+
throw new Error("XML data is accepted in String or Bytes[] form.");
|
|
1651
|
+
}
|
|
1652
|
+
if (validationOption) {
|
|
1653
|
+
if (validationOption === true) validationOption = {};
|
|
1654
|
+
const result = validator.validate(xmlData, validationOption);
|
|
1655
|
+
if (result !== true) {
|
|
1656
|
+
throw Error(`${result.err.msg}:${result.err.line}:${result.err.col}`);
|
|
1657
|
+
}
|
|
1658
|
+
}
|
|
1659
|
+
const orderedObjParser = new OrderedObjParser(this.options);
|
|
1660
|
+
orderedObjParser.addExternalEntities(this.externalEntities);
|
|
1661
|
+
const orderedResult = orderedObjParser.parseXml(xmlData);
|
|
1662
|
+
if (this.options.preserveOrder || orderedResult === void 0) return orderedResult;
|
|
1663
|
+
else return prettify(orderedResult, this.options);
|
|
1664
|
+
}
|
|
1665
|
+
/**
|
|
1666
|
+
* Add Entity which is not by default supported by this library
|
|
1667
|
+
* @param {string} key
|
|
1668
|
+
* @param {string} value
|
|
1669
|
+
*/
|
|
1670
|
+
addEntity(key, value) {
|
|
1671
|
+
if (value.indexOf("&") !== -1) {
|
|
1672
|
+
throw new Error("Entity value can't have '&'");
|
|
1673
|
+
} else if (key.indexOf("&") !== -1 || key.indexOf(";") !== -1) {
|
|
1674
|
+
throw new Error("An entity must be set without '&' and ';'. Eg. use '#xD' for '
'");
|
|
1675
|
+
} else if (value === "&") {
|
|
1676
|
+
throw new Error("An entity with value '&' is not permitted");
|
|
1677
|
+
} else {
|
|
1678
|
+
this.externalEntities[key] = value;
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
};
|
|
1682
|
+
module.exports = XMLParser2;
|
|
1683
|
+
}
|
|
1684
|
+
});
|
|
1685
|
+
|
|
1686
|
+
// ../../node_modules/.pnpm/fast-xml-parser@4.5.6/node_modules/fast-xml-parser/src/xmlbuilder/orderedJs2Xml.js
|
|
1687
|
+
var require_orderedJs2Xml = __commonJS({
|
|
1688
|
+
"../../node_modules/.pnpm/fast-xml-parser@4.5.6/node_modules/fast-xml-parser/src/xmlbuilder/orderedJs2Xml.js"(exports, module) {
|
|
1689
|
+
var EOL = "\n";
|
|
1690
|
+
function toXml(jArray, options) {
|
|
1691
|
+
let indentation = "";
|
|
1692
|
+
if (options.format && options.indentBy.length > 0) {
|
|
1693
|
+
indentation = EOL;
|
|
1694
|
+
}
|
|
1695
|
+
return arrToStr(jArray, options, "", indentation);
|
|
1696
|
+
}
|
|
1697
|
+
function arrToStr(arr, options, jPath, indentation) {
|
|
1698
|
+
let xmlStr = "";
|
|
1699
|
+
let isPreviousElementTag = false;
|
|
1700
|
+
if (!Array.isArray(arr)) {
|
|
1701
|
+
if (arr !== void 0 && arr !== null) {
|
|
1702
|
+
let text2 = arr.toString();
|
|
1703
|
+
text2 = replaceEntitiesValue(text2, options);
|
|
1704
|
+
return text2;
|
|
1705
|
+
}
|
|
1706
|
+
return "";
|
|
1707
|
+
}
|
|
1708
|
+
for (let i = 0; i < arr.length; i++) {
|
|
1709
|
+
const tagObj = arr[i];
|
|
1710
|
+
const tagName = propName(tagObj);
|
|
1711
|
+
if (tagName === void 0) continue;
|
|
1712
|
+
let newJPath = "";
|
|
1713
|
+
if (jPath.length === 0) newJPath = tagName;
|
|
1714
|
+
else newJPath = `${jPath}.${tagName}`;
|
|
1715
|
+
if (tagName === options.textNodeName) {
|
|
1716
|
+
let tagText = tagObj[tagName];
|
|
1717
|
+
if (!isStopNode(newJPath, options)) {
|
|
1718
|
+
tagText = options.tagValueProcessor(tagName, tagText);
|
|
1719
|
+
tagText = replaceEntitiesValue(tagText, options);
|
|
1720
|
+
}
|
|
1721
|
+
if (isPreviousElementTag) {
|
|
1722
|
+
xmlStr += indentation;
|
|
1723
|
+
}
|
|
1724
|
+
xmlStr += tagText;
|
|
1725
|
+
isPreviousElementTag = false;
|
|
1726
|
+
continue;
|
|
1727
|
+
} else if (tagName === options.cdataPropName) {
|
|
1728
|
+
if (isPreviousElementTag) {
|
|
1729
|
+
xmlStr += indentation;
|
|
1730
|
+
}
|
|
1731
|
+
xmlStr += `<![CDATA[${tagObj[tagName][0][options.textNodeName]}]]>`;
|
|
1732
|
+
isPreviousElementTag = false;
|
|
1733
|
+
continue;
|
|
1734
|
+
} else if (tagName === options.commentPropName) {
|
|
1735
|
+
xmlStr += indentation + `<!--${tagObj[tagName][0][options.textNodeName]}-->`;
|
|
1736
|
+
isPreviousElementTag = true;
|
|
1737
|
+
continue;
|
|
1738
|
+
} else if (tagName[0] === "?") {
|
|
1739
|
+
const attStr2 = attr_to_str(tagObj[":@"], options);
|
|
1740
|
+
const tempInd = tagName === "?xml" ? "" : indentation;
|
|
1741
|
+
let piTextNodeName = tagObj[tagName][0][options.textNodeName];
|
|
1742
|
+
piTextNodeName = piTextNodeName.length !== 0 ? " " + piTextNodeName : "";
|
|
1743
|
+
xmlStr += tempInd + `<${tagName}${piTextNodeName}${attStr2}?>`;
|
|
1744
|
+
isPreviousElementTag = true;
|
|
1745
|
+
continue;
|
|
1746
|
+
}
|
|
1747
|
+
let newIdentation = indentation;
|
|
1748
|
+
if (newIdentation !== "") {
|
|
1749
|
+
newIdentation += options.indentBy;
|
|
1750
|
+
}
|
|
1751
|
+
const attStr = attr_to_str(tagObj[":@"], options);
|
|
1752
|
+
const tagStart = indentation + `<${tagName}${attStr}`;
|
|
1753
|
+
const tagValue = arrToStr(tagObj[tagName], options, newJPath, newIdentation);
|
|
1754
|
+
if (options.unpairedTags.indexOf(tagName) !== -1) {
|
|
1755
|
+
if (options.suppressUnpairedNode) xmlStr += tagStart + ">";
|
|
1756
|
+
else xmlStr += tagStart + "/>";
|
|
1757
|
+
} else if ((!tagValue || tagValue.length === 0) && options.suppressEmptyNode) {
|
|
1758
|
+
xmlStr += tagStart + "/>";
|
|
1759
|
+
} else if (tagValue && tagValue.endsWith(">")) {
|
|
1760
|
+
xmlStr += tagStart + `>${tagValue}${indentation}</${tagName}>`;
|
|
1761
|
+
} else {
|
|
1762
|
+
xmlStr += tagStart + ">";
|
|
1763
|
+
if (tagValue && indentation !== "" && (tagValue.includes("/>") || tagValue.includes("</"))) {
|
|
1764
|
+
xmlStr += indentation + options.indentBy + tagValue + indentation;
|
|
1765
|
+
} else {
|
|
1766
|
+
xmlStr += tagValue;
|
|
1767
|
+
}
|
|
1768
|
+
xmlStr += `</${tagName}>`;
|
|
1769
|
+
}
|
|
1770
|
+
isPreviousElementTag = true;
|
|
1771
|
+
}
|
|
1772
|
+
return xmlStr;
|
|
1773
|
+
}
|
|
1774
|
+
function propName(obj) {
|
|
1775
|
+
const keys = Object.keys(obj);
|
|
1776
|
+
for (let i = 0; i < keys.length; i++) {
|
|
1777
|
+
const key = keys[i];
|
|
1778
|
+
if (!Object.prototype.hasOwnProperty.call(obj, key)) continue;
|
|
1779
|
+
if (key !== ":@") return key;
|
|
1780
|
+
}
|
|
1781
|
+
}
|
|
1782
|
+
function attr_to_str(attrMap, options) {
|
|
1783
|
+
let attrStr = "";
|
|
1784
|
+
if (attrMap && !options.ignoreAttributes) {
|
|
1785
|
+
for (let attr3 in attrMap) {
|
|
1786
|
+
if (!Object.prototype.hasOwnProperty.call(attrMap, attr3)) continue;
|
|
1787
|
+
let attrVal = options.attributeValueProcessor(attr3, attrMap[attr3]);
|
|
1788
|
+
attrVal = replaceEntitiesValue(attrVal, options);
|
|
1789
|
+
if (attrVal === true && options.suppressBooleanAttributes) {
|
|
1790
|
+
attrStr += ` ${attr3.substr(options.attributeNamePrefix.length)}`;
|
|
1791
|
+
} else {
|
|
1792
|
+
attrStr += ` ${attr3.substr(options.attributeNamePrefix.length)}="${attrVal}"`;
|
|
1793
|
+
}
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
return attrStr;
|
|
1797
|
+
}
|
|
1798
|
+
function isStopNode(jPath, options) {
|
|
1799
|
+
jPath = jPath.substr(0, jPath.length - options.textNodeName.length - 1);
|
|
1800
|
+
let tagName = jPath.substr(jPath.lastIndexOf(".") + 1);
|
|
1801
|
+
for (let index in options.stopNodes) {
|
|
1802
|
+
if (options.stopNodes[index] === jPath || options.stopNodes[index] === "*." + tagName) return true;
|
|
1803
|
+
}
|
|
1804
|
+
return false;
|
|
1805
|
+
}
|
|
1806
|
+
function replaceEntitiesValue(textValue, options) {
|
|
1807
|
+
if (textValue && textValue.length > 0 && options.processEntities) {
|
|
1808
|
+
for (let i = 0; i < options.entities.length; i++) {
|
|
1809
|
+
const entity = options.entities[i];
|
|
1810
|
+
textValue = textValue.replace(entity.regex, entity.val);
|
|
1811
|
+
}
|
|
1812
|
+
}
|
|
1813
|
+
return textValue;
|
|
1814
|
+
}
|
|
1815
|
+
module.exports = toXml;
|
|
1816
|
+
}
|
|
1817
|
+
});
|
|
1818
|
+
|
|
1819
|
+
// ../../node_modules/.pnpm/fast-xml-parser@4.5.6/node_modules/fast-xml-parser/src/xmlbuilder/json2xml.js
|
|
1820
|
+
var require_json2xml = __commonJS({
|
|
1821
|
+
"../../node_modules/.pnpm/fast-xml-parser@4.5.6/node_modules/fast-xml-parser/src/xmlbuilder/json2xml.js"(exports, module) {
|
|
1822
|
+
var buildFromOrderedJs = require_orderedJs2Xml();
|
|
1823
|
+
var getIgnoreAttributesFn = require_ignoreAttributes();
|
|
1824
|
+
var defaultOptions = {
|
|
1825
|
+
attributeNamePrefix: "@_",
|
|
1826
|
+
attributesGroupName: false,
|
|
1827
|
+
textNodeName: "#text",
|
|
1828
|
+
ignoreAttributes: true,
|
|
1829
|
+
cdataPropName: false,
|
|
1830
|
+
format: false,
|
|
1831
|
+
indentBy: " ",
|
|
1832
|
+
suppressEmptyNode: false,
|
|
1833
|
+
suppressUnpairedNode: true,
|
|
1834
|
+
suppressBooleanAttributes: true,
|
|
1835
|
+
tagValueProcessor: function(key, a) {
|
|
1836
|
+
return a;
|
|
1837
|
+
},
|
|
1838
|
+
attributeValueProcessor: function(attrName, a) {
|
|
1839
|
+
return a;
|
|
1840
|
+
},
|
|
1841
|
+
preserveOrder: false,
|
|
1842
|
+
commentPropName: false,
|
|
1843
|
+
unpairedTags: [],
|
|
1844
|
+
entities: [
|
|
1845
|
+
{ regex: new RegExp("&", "g"), val: "&" },
|
|
1846
|
+
//it must be on top
|
|
1847
|
+
{ regex: new RegExp(">", "g"), val: ">" },
|
|
1848
|
+
{ regex: new RegExp("<", "g"), val: "<" },
|
|
1849
|
+
{ regex: new RegExp("'", "g"), val: "'" },
|
|
1850
|
+
{ regex: new RegExp('"', "g"), val: """ }
|
|
1851
|
+
],
|
|
1852
|
+
processEntities: true,
|
|
1853
|
+
stopNodes: [],
|
|
1854
|
+
// transformTagName: false,
|
|
1855
|
+
// transformAttributeName: false,
|
|
1856
|
+
oneListGroup: false
|
|
1857
|
+
};
|
|
1858
|
+
function Builder(options) {
|
|
1859
|
+
this.options = Object.assign({}, defaultOptions, options);
|
|
1860
|
+
if (this.options.ignoreAttributes === true || this.options.attributesGroupName) {
|
|
1861
|
+
this.isAttribute = function() {
|
|
1862
|
+
return false;
|
|
1863
|
+
};
|
|
1864
|
+
} else {
|
|
1865
|
+
this.ignoreAttributesFn = getIgnoreAttributesFn(this.options.ignoreAttributes);
|
|
1866
|
+
this.attrPrefixLen = this.options.attributeNamePrefix.length;
|
|
1867
|
+
this.isAttribute = isAttribute;
|
|
1868
|
+
}
|
|
1869
|
+
this.processTextOrObjNode = processTextOrObjNode;
|
|
1870
|
+
if (this.options.format) {
|
|
1871
|
+
this.indentate = indentate;
|
|
1872
|
+
this.tagEndChar = ">\n";
|
|
1873
|
+
this.newLine = "\n";
|
|
1874
|
+
} else {
|
|
1875
|
+
this.indentate = function() {
|
|
1876
|
+
return "";
|
|
1877
|
+
};
|
|
1878
|
+
this.tagEndChar = ">";
|
|
1879
|
+
this.newLine = "";
|
|
1880
|
+
}
|
|
1881
|
+
}
|
|
1882
|
+
Builder.prototype.build = function(jObj) {
|
|
1883
|
+
if (this.options.preserveOrder) {
|
|
1884
|
+
return buildFromOrderedJs(jObj, this.options);
|
|
1885
|
+
} else {
|
|
1886
|
+
if (Array.isArray(jObj) && this.options.arrayNodeName && this.options.arrayNodeName.length > 1) {
|
|
1887
|
+
jObj = {
|
|
1888
|
+
[this.options.arrayNodeName]: jObj
|
|
1889
|
+
};
|
|
1890
|
+
}
|
|
1891
|
+
return this.j2x(jObj, 0, []).val;
|
|
1892
|
+
}
|
|
1893
|
+
};
|
|
1894
|
+
Builder.prototype.j2x = function(jObj, level, ajPath) {
|
|
1895
|
+
let attrStr = "";
|
|
1896
|
+
let val = "";
|
|
1897
|
+
const jPath = ajPath.join(".");
|
|
1898
|
+
for (let key in jObj) {
|
|
1899
|
+
if (!Object.prototype.hasOwnProperty.call(jObj, key)) continue;
|
|
1900
|
+
if (typeof jObj[key] === "undefined") {
|
|
1901
|
+
if (this.isAttribute(key)) {
|
|
1902
|
+
val += "";
|
|
1903
|
+
}
|
|
1904
|
+
} else if (jObj[key] === null) {
|
|
1905
|
+
if (this.isAttribute(key)) {
|
|
1906
|
+
val += "";
|
|
1907
|
+
} else if (key === this.options.cdataPropName) {
|
|
1908
|
+
val += "";
|
|
1909
|
+
} else if (key[0] === "?") {
|
|
1910
|
+
val += this.indentate(level) + "<" + key + "?" + this.tagEndChar;
|
|
1911
|
+
} else {
|
|
1912
|
+
val += this.indentate(level) + "<" + key + "/" + this.tagEndChar;
|
|
1913
|
+
}
|
|
1914
|
+
} else if (jObj[key] instanceof Date) {
|
|
1915
|
+
val += this.buildTextValNode(jObj[key], key, "", level);
|
|
1916
|
+
} else if (typeof jObj[key] !== "object") {
|
|
1917
|
+
const attr3 = this.isAttribute(key);
|
|
1918
|
+
if (attr3 && !this.ignoreAttributesFn(attr3, jPath)) {
|
|
1919
|
+
attrStr += this.buildAttrPairStr(attr3, "" + jObj[key]);
|
|
1920
|
+
} else if (!attr3) {
|
|
1921
|
+
if (key === this.options.textNodeName) {
|
|
1922
|
+
let newval = this.options.tagValueProcessor(key, "" + jObj[key]);
|
|
1923
|
+
val += this.replaceEntitiesValue(newval);
|
|
1924
|
+
} else {
|
|
1925
|
+
val += this.buildTextValNode(jObj[key], key, "", level);
|
|
1926
|
+
}
|
|
1927
|
+
}
|
|
1928
|
+
} else if (Array.isArray(jObj[key])) {
|
|
1929
|
+
const arrLen = jObj[key].length;
|
|
1930
|
+
let listTagVal = "";
|
|
1931
|
+
let listTagAttr = "";
|
|
1932
|
+
for (let j = 0; j < arrLen; j++) {
|
|
1933
|
+
const item = jObj[key][j];
|
|
1934
|
+
if (typeof item === "undefined") ; else if (item === null) {
|
|
1935
|
+
if (key[0] === "?") val += this.indentate(level) + "<" + key + "?" + this.tagEndChar;
|
|
1936
|
+
else val += this.indentate(level) + "<" + key + "/" + this.tagEndChar;
|
|
1937
|
+
} else if (typeof item === "object") {
|
|
1938
|
+
if (this.options.oneListGroup) {
|
|
1939
|
+
const result = this.j2x(item, level + 1, ajPath.concat(key));
|
|
1940
|
+
listTagVal += result.val;
|
|
1941
|
+
if (this.options.attributesGroupName && item.hasOwnProperty(this.options.attributesGroupName)) {
|
|
1942
|
+
listTagAttr += result.attrStr;
|
|
1943
|
+
}
|
|
1944
|
+
} else {
|
|
1945
|
+
listTagVal += this.processTextOrObjNode(item, key, level, ajPath);
|
|
1946
|
+
}
|
|
1947
|
+
} else {
|
|
1948
|
+
if (this.options.oneListGroup) {
|
|
1949
|
+
let textValue = this.options.tagValueProcessor(key, item);
|
|
1950
|
+
textValue = this.replaceEntitiesValue(textValue);
|
|
1951
|
+
listTagVal += textValue;
|
|
1952
|
+
} else {
|
|
1953
|
+
listTagVal += this.buildTextValNode(item, key, "", level);
|
|
1954
|
+
}
|
|
1955
|
+
}
|
|
1956
|
+
}
|
|
1957
|
+
if (this.options.oneListGroup) {
|
|
1958
|
+
listTagVal = this.buildObjectNode(listTagVal, key, listTagAttr, level);
|
|
1959
|
+
}
|
|
1960
|
+
val += listTagVal;
|
|
1961
|
+
} else {
|
|
1962
|
+
if (this.options.attributesGroupName && key === this.options.attributesGroupName) {
|
|
1963
|
+
const Ks = Object.keys(jObj[key]);
|
|
1964
|
+
const L = Ks.length;
|
|
1965
|
+
for (let j = 0; j < L; j++) {
|
|
1966
|
+
attrStr += this.buildAttrPairStr(Ks[j], "" + jObj[key][Ks[j]]);
|
|
1967
|
+
}
|
|
1968
|
+
} else {
|
|
1969
|
+
val += this.processTextOrObjNode(jObj[key], key, level, ajPath);
|
|
1970
|
+
}
|
|
1971
|
+
}
|
|
1972
|
+
}
|
|
1973
|
+
return { attrStr, val };
|
|
1974
|
+
};
|
|
1975
|
+
Builder.prototype.buildAttrPairStr = function(attrName, val) {
|
|
1976
|
+
val = this.options.attributeValueProcessor(attrName, "" + val);
|
|
1977
|
+
val = this.replaceEntitiesValue(val);
|
|
1978
|
+
if (this.options.suppressBooleanAttributes && val === "true") {
|
|
1979
|
+
return " " + attrName;
|
|
1980
|
+
} else return " " + attrName + '="' + val + '"';
|
|
1981
|
+
};
|
|
1982
|
+
function processTextOrObjNode(object, key, level, ajPath) {
|
|
1983
|
+
const result = this.j2x(object, level + 1, ajPath.concat(key));
|
|
1984
|
+
if (object[this.options.textNodeName] !== void 0 && Object.keys(object).length === 1) {
|
|
1985
|
+
return this.buildTextValNode(object[this.options.textNodeName], key, result.attrStr, level);
|
|
1986
|
+
} else {
|
|
1987
|
+
return this.buildObjectNode(result.val, key, result.attrStr, level);
|
|
1988
|
+
}
|
|
1989
|
+
}
|
|
1990
|
+
Builder.prototype.buildObjectNode = function(val, key, attrStr, level) {
|
|
1991
|
+
if (val === "") {
|
|
1992
|
+
if (key[0] === "?") return this.indentate(level) + "<" + key + attrStr + "?" + this.tagEndChar;
|
|
1993
|
+
else {
|
|
1994
|
+
return this.indentate(level) + "<" + key + attrStr + this.closeTag(key) + this.tagEndChar;
|
|
1995
|
+
}
|
|
1996
|
+
} else {
|
|
1997
|
+
let tagEndExp = "</" + key + this.tagEndChar;
|
|
1998
|
+
let piClosingChar = "";
|
|
1999
|
+
if (key[0] === "?") {
|
|
2000
|
+
piClosingChar = "?";
|
|
2001
|
+
tagEndExp = "";
|
|
2002
|
+
}
|
|
2003
|
+
if ((attrStr || attrStr === "") && val.indexOf("<") === -1) {
|
|
2004
|
+
return this.indentate(level) + "<" + key + attrStr + piClosingChar + ">" + val + tagEndExp;
|
|
2005
|
+
} else if (this.options.commentPropName !== false && key === this.options.commentPropName && piClosingChar.length === 0) {
|
|
2006
|
+
return this.indentate(level) + `<!--${val}-->` + this.newLine;
|
|
2007
|
+
} else {
|
|
2008
|
+
return this.indentate(level) + "<" + key + attrStr + piClosingChar + this.tagEndChar + val + this.indentate(level) + tagEndExp;
|
|
2009
|
+
}
|
|
2010
|
+
}
|
|
2011
|
+
};
|
|
2012
|
+
Builder.prototype.closeTag = function(key) {
|
|
2013
|
+
let closeTag = "";
|
|
2014
|
+
if (this.options.unpairedTags.indexOf(key) !== -1) {
|
|
2015
|
+
if (!this.options.suppressUnpairedNode) closeTag = "/";
|
|
2016
|
+
} else if (this.options.suppressEmptyNode) {
|
|
2017
|
+
closeTag = "/";
|
|
2018
|
+
} else {
|
|
2019
|
+
closeTag = `></${key}`;
|
|
2020
|
+
}
|
|
2021
|
+
return closeTag;
|
|
2022
|
+
};
|
|
2023
|
+
Builder.prototype.buildTextValNode = function(val, key, attrStr, level) {
|
|
2024
|
+
if (this.options.cdataPropName !== false && key === this.options.cdataPropName) {
|
|
2025
|
+
return this.indentate(level) + `<![CDATA[${val}]]>` + this.newLine;
|
|
2026
|
+
} else if (this.options.commentPropName !== false && key === this.options.commentPropName) {
|
|
2027
|
+
return this.indentate(level) + `<!--${val}-->` + this.newLine;
|
|
2028
|
+
} else if (key[0] === "?") {
|
|
2029
|
+
return this.indentate(level) + "<" + key + attrStr + "?" + this.tagEndChar;
|
|
2030
|
+
} else {
|
|
2031
|
+
let textValue = this.options.tagValueProcessor(key, val);
|
|
2032
|
+
textValue = this.replaceEntitiesValue(textValue);
|
|
2033
|
+
if (textValue === "") {
|
|
2034
|
+
return this.indentate(level) + "<" + key + attrStr + this.closeTag(key) + this.tagEndChar;
|
|
2035
|
+
} else {
|
|
2036
|
+
return this.indentate(level) + "<" + key + attrStr + ">" + textValue + "</" + key + this.tagEndChar;
|
|
2037
|
+
}
|
|
2038
|
+
}
|
|
2039
|
+
};
|
|
2040
|
+
Builder.prototype.replaceEntitiesValue = function(textValue) {
|
|
2041
|
+
if (textValue && textValue.length > 0 && this.options.processEntities) {
|
|
2042
|
+
for (let i = 0; i < this.options.entities.length; i++) {
|
|
2043
|
+
const entity = this.options.entities[i];
|
|
2044
|
+
textValue = textValue.replace(entity.regex, entity.val);
|
|
2045
|
+
}
|
|
2046
|
+
}
|
|
2047
|
+
return textValue;
|
|
2048
|
+
};
|
|
2049
|
+
function indentate(level) {
|
|
2050
|
+
return this.options.indentBy.repeat(level);
|
|
2051
|
+
}
|
|
2052
|
+
function isAttribute(name) {
|
|
2053
|
+
if (name.startsWith(this.options.attributeNamePrefix) && name !== this.options.textNodeName) {
|
|
2054
|
+
return name.substr(this.attrPrefixLen);
|
|
2055
|
+
} else {
|
|
2056
|
+
return false;
|
|
2057
|
+
}
|
|
2058
|
+
}
|
|
2059
|
+
module.exports = Builder;
|
|
2060
|
+
}
|
|
2061
|
+
});
|
|
2062
|
+
|
|
2063
|
+
// ../../node_modules/.pnpm/fast-xml-parser@4.5.6/node_modules/fast-xml-parser/src/fxp.js
|
|
2064
|
+
var require_fxp = __commonJS({
|
|
2065
|
+
"../../node_modules/.pnpm/fast-xml-parser@4.5.6/node_modules/fast-xml-parser/src/fxp.js"(exports, module) {
|
|
2066
|
+
var validator = require_validator();
|
|
2067
|
+
var XMLParser2 = require_XMLParser();
|
|
2068
|
+
var XMLBuilder2 = require_json2xml();
|
|
2069
|
+
module.exports = {
|
|
2070
|
+
XMLParser: XMLParser2,
|
|
2071
|
+
XMLValidator: validator,
|
|
2072
|
+
XMLBuilder: XMLBuilder2
|
|
2073
|
+
};
|
|
2074
|
+
}
|
|
2075
|
+
});
|
|
2076
|
+
|
|
2077
|
+
// ../core/dist/index.js
|
|
2078
|
+
var import_fast_xml_parser = __toESM(require_fxp(), 1);
|
|
2079
|
+
function allRequirements(doc) {
|
|
2080
|
+
return [...doc.packages.flatMap((p) => p.requirements), ...doc.looseRequirements];
|
|
2081
|
+
}
|
|
2082
|
+
function declaredElements(doc) {
|
|
2083
|
+
const out = [];
|
|
2084
|
+
const push = (id, kind) => {
|
|
2085
|
+
if (id !== void 0) out.push({ id, kind });
|
|
2086
|
+
};
|
|
2087
|
+
for (const p of doc.meta.profiles ?? []) push(p.id, "profile");
|
|
2088
|
+
const c = doc.catalogs;
|
|
2089
|
+
if (c) {
|
|
2090
|
+
for (const t of c.glossary ?? []) push(t.id, "term");
|
|
2091
|
+
for (const a of c.actors ?? []) push(a.id, "actor");
|
|
2092
|
+
for (const s of c.stakeholders ?? []) push(s.id, "stakeholder");
|
|
2093
|
+
for (const x of c.constraints ?? []) push(x.id, "constraint");
|
|
2094
|
+
for (const x of c.policies ?? []) push(x.id, "policy");
|
|
2095
|
+
for (const x of c.decisions ?? []) push(x.id, "decision");
|
|
2096
|
+
for (const x of c.risks ?? []) push(x.id, "risk");
|
|
2097
|
+
}
|
|
2098
|
+
const d = doc.domain;
|
|
2099
|
+
if (d) {
|
|
2100
|
+
for (const e of d.entities ?? []) {
|
|
2101
|
+
push(e.id, "entity");
|
|
2102
|
+
for (const a of e.attrs ?? []) push(a.id, "attr");
|
|
2103
|
+
}
|
|
2104
|
+
for (const r of d.businessRules ?? []) push(r.id, "rule");
|
|
2105
|
+
}
|
|
2106
|
+
const g = doc.goals;
|
|
2107
|
+
if (g) {
|
|
2108
|
+
for (const x of g.goals ?? []) push(x.id, "goal");
|
|
2109
|
+
for (const x of g.qualityGoals ?? []) push(x.id, "qgoal");
|
|
2110
|
+
for (const x of g.obstacles ?? []) push(x.id, "obstacle");
|
|
2111
|
+
for (const x of g.goalLinks ?? []) push(x.id, "goalLink");
|
|
2112
|
+
}
|
|
2113
|
+
const sc = doc.scenarios;
|
|
2114
|
+
if (sc) {
|
|
2115
|
+
for (const x of sc.scenarios ?? []) push(x.id, "scenario");
|
|
2116
|
+
for (const x of sc.misuseCases ?? []) push(x.id, "misuseCase");
|
|
2117
|
+
for (const x of sc.edgeCases ?? []) push(x.id, "edgeCase");
|
|
2118
|
+
}
|
|
2119
|
+
for (const p of doc.packages) {
|
|
2120
|
+
push(p.id, "reqPackage");
|
|
2121
|
+
for (const r of p.requirements) {
|
|
2122
|
+
push(r.id, "req");
|
|
2123
|
+
for (const cr of r.acceptance) push(cr.id, "criterion");
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
2126
|
+
for (const r of doc.looseRequirements) {
|
|
2127
|
+
push(r.id, "req");
|
|
2128
|
+
for (const cr of r.acceptance) push(cr.id, "criterion");
|
|
2129
|
+
}
|
|
2130
|
+
const b = doc.behavior;
|
|
2131
|
+
if (b) {
|
|
2132
|
+
for (const sm of b.stateMachines ?? []) {
|
|
2133
|
+
push(sm.id, "stateMachine");
|
|
2134
|
+
for (const st of sm.states) push(st.id, "state");
|
|
2135
|
+
for (const tr of sm.transitions ?? []) push(tr.id, "transition");
|
|
2136
|
+
}
|
|
2137
|
+
}
|
|
2138
|
+
const it = doc.interfaces;
|
|
2139
|
+
if (it) {
|
|
2140
|
+
for (const api of it.apis ?? []) {
|
|
2141
|
+
push(api.id, "api");
|
|
2142
|
+
for (const ep of api.endpoints ?? []) push(ep.id, "endpoint");
|
|
2143
|
+
}
|
|
2144
|
+
for (const ev of it.events ?? []) push(ev.id, "event");
|
|
2145
|
+
}
|
|
2146
|
+
const v = doc.verification;
|
|
2147
|
+
if (v) {
|
|
2148
|
+
for (const ts of v.testSuites ?? []) push(ts.id, "testSuite");
|
|
2149
|
+
for (const tc of v.testCases ?? []) push(tc.id, "testCase");
|
|
2150
|
+
}
|
|
2151
|
+
for (const e of doc.trace) push(e.id, "edge");
|
|
2152
|
+
const gv = doc.governance;
|
|
2153
|
+
if (gv) {
|
|
2154
|
+
for (const x of gv.issues ?? []) push(x.id, "issue");
|
|
2155
|
+
for (const x of gv.approvals ?? []) push(x.id, "approval");
|
|
2156
|
+
}
|
|
2157
|
+
return out;
|
|
2158
|
+
}
|
|
2159
|
+
var rawSections = /* @__PURE__ */ new WeakMap();
|
|
2160
|
+
function setRawSections(doc, sections) {
|
|
2161
|
+
rawSections.set(doc, sections);
|
|
2162
|
+
}
|
|
2163
|
+
var ATTR_PREFIX = "@_";
|
|
2164
|
+
var ARRAY_TAGS = /* @__PURE__ */ new Set([
|
|
2165
|
+
"author",
|
|
2166
|
+
"profile",
|
|
2167
|
+
"term",
|
|
2168
|
+
"synonym",
|
|
2169
|
+
"actor",
|
|
2170
|
+
"stakeholder",
|
|
2171
|
+
"constraint",
|
|
2172
|
+
"policy",
|
|
2173
|
+
"risk",
|
|
2174
|
+
"ref",
|
|
2175
|
+
"entity",
|
|
2176
|
+
"attr",
|
|
2177
|
+
"rule",
|
|
2178
|
+
"goal",
|
|
2179
|
+
"qgoal",
|
|
2180
|
+
"obstacle",
|
|
2181
|
+
"goalLink",
|
|
2182
|
+
"scenario",
|
|
2183
|
+
"misuseCase",
|
|
2184
|
+
"edgeCase",
|
|
2185
|
+
"stateMachine",
|
|
2186
|
+
"state",
|
|
2187
|
+
"transition",
|
|
2188
|
+
"api",
|
|
2189
|
+
"endpoint",
|
|
2190
|
+
"event",
|
|
2191
|
+
"testSuite",
|
|
2192
|
+
"testCase",
|
|
2193
|
+
"reqPackage",
|
|
2194
|
+
"req",
|
|
2195
|
+
"criterion",
|
|
2196
|
+
"edge",
|
|
2197
|
+
"traceEdge",
|
|
2198
|
+
"issue",
|
|
2199
|
+
"approval"
|
|
2200
|
+
]);
|
|
2201
|
+
var MODELED_SECTIONS = /* @__PURE__ */ new Set([
|
|
2202
|
+
"meta",
|
|
2203
|
+
"catalogs",
|
|
2204
|
+
"domain",
|
|
2205
|
+
"goals",
|
|
2206
|
+
"scenarios",
|
|
2207
|
+
"requirements",
|
|
2208
|
+
"behavior",
|
|
2209
|
+
"interfaces",
|
|
2210
|
+
"verification",
|
|
2211
|
+
"trace",
|
|
2212
|
+
"governance"
|
|
2213
|
+
]);
|
|
2214
|
+
var KNOWN_ROOT_ATTRS = /* @__PURE__ */ new Set([
|
|
2215
|
+
"@_xmlns",
|
|
2216
|
+
"@_xmlns:xsi",
|
|
2217
|
+
"@_xsi:schemaLocation",
|
|
2218
|
+
"@_version",
|
|
2219
|
+
"@_docId",
|
|
2220
|
+
"@_status"
|
|
2221
|
+
]);
|
|
2222
|
+
var parser = new import_fast_xml_parser.XMLParser({
|
|
2223
|
+
ignoreAttributes: false,
|
|
2224
|
+
attributeNamePrefix: ATTR_PREFIX,
|
|
2225
|
+
parseAttributeValue: false,
|
|
2226
|
+
parseTagValue: false,
|
|
2227
|
+
trimValues: true,
|
|
2228
|
+
isArray: (name) => ARRAY_TAGS.has(name)
|
|
2229
|
+
});
|
|
2230
|
+
function isNode(v) {
|
|
2231
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
2232
|
+
}
|
|
2233
|
+
function child(node, name) {
|
|
2234
|
+
return isNode(node) ? node[name] : void 0;
|
|
2235
|
+
}
|
|
2236
|
+
function attr(node, name) {
|
|
2237
|
+
if (!isNode(node)) return void 0;
|
|
2238
|
+
const v = node[ATTR_PREFIX + name];
|
|
2239
|
+
return v == null ? void 0 : String(v);
|
|
2240
|
+
}
|
|
2241
|
+
function numAttr(node, name) {
|
|
2242
|
+
const v = attr(node, name);
|
|
2243
|
+
return v === void 0 ? void 0 : Number(v);
|
|
2244
|
+
}
|
|
2245
|
+
function boolAttr(node, name) {
|
|
2246
|
+
const v = attr(node, name);
|
|
2247
|
+
if (v === void 0) return void 0;
|
|
2248
|
+
if (v === "true" || v === "1") return true;
|
|
2249
|
+
if (v === "false" || v === "0") return false;
|
|
2250
|
+
return void 0;
|
|
2251
|
+
}
|
|
2252
|
+
function text(node) {
|
|
2253
|
+
if (node == null) return void 0;
|
|
2254
|
+
if (typeof node === "string") return node;
|
|
2255
|
+
if (typeof node === "number" || typeof node === "boolean") return String(node);
|
|
2256
|
+
if (isNode(node)) {
|
|
2257
|
+
const t = node["#text"];
|
|
2258
|
+
return t == null ? void 0 : String(t);
|
|
2259
|
+
}
|
|
2260
|
+
return void 0;
|
|
2261
|
+
}
|
|
2262
|
+
function asArray(v) {
|
|
2263
|
+
if (v == null) return [];
|
|
2264
|
+
return Array.isArray(v) ? v : [v];
|
|
2265
|
+
}
|
|
2266
|
+
function collect(container, childName) {
|
|
2267
|
+
return asArray(container).flatMap((c) => asArray(child(c, childName)));
|
|
2268
|
+
}
|
|
2269
|
+
function parseAuthor(node) {
|
|
2270
|
+
const a = { name: text(child(node, "name")) ?? "" };
|
|
2271
|
+
const role = text(child(node, "role"));
|
|
2272
|
+
const org = text(child(node, "org"));
|
|
2273
|
+
const contact = text(child(node, "contact"));
|
|
2274
|
+
if (role !== void 0) a.role = role;
|
|
2275
|
+
if (org !== void 0) a.org = org;
|
|
2276
|
+
if (contact !== void 0) a.contact = contact;
|
|
2277
|
+
return a;
|
|
2278
|
+
}
|
|
2279
|
+
function parseProfile(node) {
|
|
2280
|
+
const p = {
|
|
2281
|
+
id: attr(node, "id") ?? "",
|
|
2282
|
+
type: attr(node, "type") ?? ""
|
|
2283
|
+
};
|
|
2284
|
+
const description = text(child(node, "description"));
|
|
2285
|
+
if (description !== void 0) p.description = description;
|
|
2286
|
+
return p;
|
|
2287
|
+
}
|
|
2288
|
+
function parseMeta(node) {
|
|
2289
|
+
const meta = {
|
|
2290
|
+
title: text(child(node, "title")) ?? "",
|
|
2291
|
+
system: text(child(node, "system")) ?? "",
|
|
2292
|
+
authors: []
|
|
2293
|
+
};
|
|
2294
|
+
const summary = text(child(node, "summary"));
|
|
2295
|
+
if (summary !== void 0) meta.summary = summary;
|
|
2296
|
+
meta.authors = asArray(child(child(node, "authors"), "author")).map(parseAuthor);
|
|
2297
|
+
const datesNode = child(node, "dates");
|
|
2298
|
+
if (isNode(datesNode)) {
|
|
2299
|
+
const dates = {};
|
|
2300
|
+
const created = text(datesNode.created);
|
|
2301
|
+
const updated = text(datesNode.updated);
|
|
2302
|
+
const targetRelease = text(datesNode.targetRelease);
|
|
2303
|
+
if (created !== void 0) dates.created = created;
|
|
2304
|
+
if (updated !== void 0) dates.updated = updated;
|
|
2305
|
+
if (targetRelease !== void 0) dates.targetRelease = targetRelease;
|
|
2306
|
+
if (Object.keys(dates).length > 0) meta.dates = dates;
|
|
2307
|
+
}
|
|
2308
|
+
const convNode = child(node, "conventions");
|
|
2309
|
+
if (isNode(convNode)) {
|
|
2310
|
+
const conv = {};
|
|
2311
|
+
const nk = text(convNode.normativeKeywords);
|
|
2312
|
+
const ic = text(convNode.idConventions);
|
|
2313
|
+
if (nk !== void 0) conv.normativeKeywords = nk;
|
|
2314
|
+
if (ic !== void 0) conv.idConventions = ic;
|
|
2315
|
+
if (Object.keys(conv).length > 0) meta.conventions = conv;
|
|
2316
|
+
}
|
|
2317
|
+
const profiles = asArray(child(child(node, "profiles"), "profile")).map(parseProfile);
|
|
2318
|
+
if (profiles.length > 0) meta.profiles = profiles;
|
|
2319
|
+
return meta;
|
|
2320
|
+
}
|
|
2321
|
+
function parseTerm(node) {
|
|
2322
|
+
const t = {
|
|
2323
|
+
id: attr(node, "id") ?? "",
|
|
2324
|
+
name: text(child(node, "name")) ?? "",
|
|
2325
|
+
definition: text(child(node, "definition")) ?? ""
|
|
2326
|
+
};
|
|
2327
|
+
const synonyms = asArray(child(child(node, "synonyms"), "synonym")).map(
|
|
2328
|
+
(s) => text(s) ?? ""
|
|
2329
|
+
);
|
|
2330
|
+
if (synonyms.length > 0) t.synonyms = synonyms;
|
|
2331
|
+
return t;
|
|
2332
|
+
}
|
|
2333
|
+
function parseActor(node) {
|
|
2334
|
+
const a = { id: attr(node, "id") ?? "", name: attr(node, "name") ?? "" };
|
|
2335
|
+
const type = attr(node, "type");
|
|
2336
|
+
const description = text(child(node, "description"));
|
|
2337
|
+
if (type !== void 0) a.type = type;
|
|
2338
|
+
if (description !== void 0) a.description = description;
|
|
2339
|
+
const refs = asArray(child(child(node, "goals"), "ref")).map(
|
|
2340
|
+
(r) => attr(r, "ref") ?? ""
|
|
2341
|
+
);
|
|
2342
|
+
if (refs.length > 0) a.goalRefs = refs;
|
|
2343
|
+
return a;
|
|
2344
|
+
}
|
|
2345
|
+
function parseStakeholder(node) {
|
|
2346
|
+
const s = {
|
|
2347
|
+
id: attr(node, "id") ?? "",
|
|
2348
|
+
name: attr(node, "name") ?? ""
|
|
2349
|
+
};
|
|
2350
|
+
const org = attr(node, "org");
|
|
2351
|
+
const concerns = text(child(node, "concerns"));
|
|
2352
|
+
if (org !== void 0) s.org = org;
|
|
2353
|
+
if (concerns !== void 0) s.concerns = concerns;
|
|
2354
|
+
return s;
|
|
2355
|
+
}
|
|
2356
|
+
function parseConstraint(node) {
|
|
2357
|
+
const c = {
|
|
2358
|
+
id: attr(node, "id") ?? "",
|
|
2359
|
+
statement: text(child(node, "statement")) ?? ""
|
|
2360
|
+
};
|
|
2361
|
+
const severity = attr(node, "severity");
|
|
2362
|
+
const source = text(child(node, "source"));
|
|
2363
|
+
if (severity !== void 0) c.severity = severity;
|
|
2364
|
+
if (source !== void 0) c.source = source;
|
|
2365
|
+
return c;
|
|
2366
|
+
}
|
|
2367
|
+
function parsePolicy(node) {
|
|
2368
|
+
const p = {
|
|
2369
|
+
id: attr(node, "id") ?? "",
|
|
2370
|
+
obligation: text(child(node, "obligation")) ?? ""
|
|
2371
|
+
};
|
|
2372
|
+
const source = attr(node, "source");
|
|
2373
|
+
const evidence = text(child(node, "evidence"));
|
|
2374
|
+
if (source !== void 0) p.source = source;
|
|
2375
|
+
if (evidence !== void 0) p.evidence = evidence;
|
|
2376
|
+
return p;
|
|
2377
|
+
}
|
|
2378
|
+
function parseDecision(node) {
|
|
2379
|
+
const d = {
|
|
2380
|
+
id: attr(node, "id") ?? "",
|
|
2381
|
+
context: text(child(node, "context")) ?? "",
|
|
2382
|
+
decision: text(child(node, "decision")) ?? ""
|
|
2383
|
+
};
|
|
2384
|
+
const status = attr(node, "status");
|
|
2385
|
+
const alternatives = text(child(node, "alternatives"));
|
|
2386
|
+
const consequences = text(child(node, "consequences"));
|
|
2387
|
+
if (status !== void 0) d.status = status;
|
|
2388
|
+
if (alternatives !== void 0) d.alternatives = alternatives;
|
|
2389
|
+
if (consequences !== void 0) d.consequences = consequences;
|
|
2390
|
+
return d;
|
|
2391
|
+
}
|
|
2392
|
+
function parseRisk(node) {
|
|
2393
|
+
const r = {
|
|
2394
|
+
id: attr(node, "id") ?? "",
|
|
2395
|
+
statement: text(child(node, "statement")) ?? ""
|
|
2396
|
+
};
|
|
2397
|
+
const severity = attr(node, "severity");
|
|
2398
|
+
const mitigation = text(child(node, "mitigation"));
|
|
2399
|
+
if (severity !== void 0) r.severity = severity;
|
|
2400
|
+
if (mitigation !== void 0) r.mitigation = mitigation;
|
|
2401
|
+
return r;
|
|
2402
|
+
}
|
|
2403
|
+
function parseCatalogs(node) {
|
|
2404
|
+
if (!isNode(node)) return void 0;
|
|
2405
|
+
const c = {};
|
|
2406
|
+
const glossary = collect(node.glossary, "term").map(parseTerm);
|
|
2407
|
+
const actors = collect(node.actors, "actor").map(parseActor);
|
|
2408
|
+
const stakeholders = collect(node.stakeholders, "stakeholder").map(parseStakeholder);
|
|
2409
|
+
const constraints = collect(node.constraints, "constraint").map(parseConstraint);
|
|
2410
|
+
const policies = collect(node.policies, "policy").map(parsePolicy);
|
|
2411
|
+
const decisions = collect(node.decisions, "decision").map(parseDecision);
|
|
2412
|
+
const risks = collect(node.risks, "risk").map(parseRisk);
|
|
2413
|
+
if (glossary.length > 0) c.glossary = glossary;
|
|
2414
|
+
if (actors.length > 0) c.actors = actors;
|
|
2415
|
+
if (stakeholders.length > 0) c.stakeholders = stakeholders;
|
|
2416
|
+
if (constraints.length > 0) c.constraints = constraints;
|
|
2417
|
+
if (policies.length > 0) c.policies = policies;
|
|
2418
|
+
if (decisions.length > 0) c.decisions = decisions;
|
|
2419
|
+
if (risks.length > 0) c.risks = risks;
|
|
2420
|
+
return Object.keys(c).length > 0 ? c : void 0;
|
|
2421
|
+
}
|
|
2422
|
+
function parseAttribute(node) {
|
|
2423
|
+
const a = {
|
|
2424
|
+
id: attr(node, "id") ?? "",
|
|
2425
|
+
name: attr(node, "name") ?? "",
|
|
2426
|
+
type: attr(node, "type") ?? ""
|
|
2427
|
+
};
|
|
2428
|
+
const required = boolAttr(node, "required");
|
|
2429
|
+
const description = text(child(node, "description"));
|
|
2430
|
+
const constraints = text(child(node, "constraints"));
|
|
2431
|
+
if (required !== void 0) a.required = required;
|
|
2432
|
+
if (description !== void 0) a.description = description;
|
|
2433
|
+
if (constraints !== void 0) a.constraints = constraints;
|
|
2434
|
+
return a;
|
|
2435
|
+
}
|
|
2436
|
+
function parseEntity(node) {
|
|
2437
|
+
const e = { id: attr(node, "id") ?? "", name: attr(node, "name") ?? "" };
|
|
2438
|
+
const description = text(child(node, "description"));
|
|
2439
|
+
if (description !== void 0) e.description = description;
|
|
2440
|
+
const attrs = asArray(child(node, "attr")).map(parseAttribute);
|
|
2441
|
+
if (attrs.length > 0) e.attrs = attrs;
|
|
2442
|
+
return e;
|
|
2443
|
+
}
|
|
2444
|
+
function parseBusinessRule(node) {
|
|
2445
|
+
const r = {
|
|
2446
|
+
id: attr(node, "id") ?? "",
|
|
2447
|
+
statement: text(child(node, "statement")) ?? ""
|
|
2448
|
+
};
|
|
2449
|
+
const examples = text(child(node, "examples"));
|
|
2450
|
+
if (examples !== void 0) r.examples = examples;
|
|
2451
|
+
return r;
|
|
2452
|
+
}
|
|
2453
|
+
function parseDomain(node) {
|
|
2454
|
+
if (!isNode(node)) return void 0;
|
|
2455
|
+
const d = {};
|
|
2456
|
+
const overview = text(child(node, "overview"));
|
|
2457
|
+
if (overview !== void 0) d.overview = overview;
|
|
2458
|
+
const entities = collect(node.entities, "entity").map(parseEntity);
|
|
2459
|
+
const rules = collect(node.businessRules, "rule").map(parseBusinessRule);
|
|
2460
|
+
if (entities.length > 0) d.entities = entities;
|
|
2461
|
+
if (rules.length > 0) d.businessRules = rules;
|
|
2462
|
+
return Object.keys(d).length > 0 ? d : void 0;
|
|
2463
|
+
}
|
|
2464
|
+
function parseGoal(node) {
|
|
2465
|
+
const g = {
|
|
2466
|
+
id: attr(node, "id") ?? "",
|
|
2467
|
+
title: attr(node, "title") ?? "",
|
|
2468
|
+
statement: text(child(node, "statement")) ?? ""
|
|
2469
|
+
};
|
|
2470
|
+
const priority = attr(node, "priority");
|
|
2471
|
+
const status = attr(node, "status");
|
|
2472
|
+
const ownerRef = attr(node, "ownerRef");
|
|
2473
|
+
const rationale = text(child(node, "rationale"));
|
|
2474
|
+
if (priority !== void 0) g.priority = priority;
|
|
2475
|
+
if (status !== void 0) g.status = status;
|
|
2476
|
+
if (ownerRef !== void 0) g.ownerRef = ownerRef;
|
|
2477
|
+
if (rationale !== void 0) g.rationale = rationale;
|
|
2478
|
+
return g;
|
|
2479
|
+
}
|
|
2480
|
+
function parseQualityGoal(node) {
|
|
2481
|
+
const q = {
|
|
2482
|
+
id: attr(node, "id") ?? "",
|
|
2483
|
+
title: attr(node, "title") ?? "",
|
|
2484
|
+
statement: text(child(node, "statement")) ?? ""
|
|
2485
|
+
};
|
|
2486
|
+
const priority = attr(node, "priority");
|
|
2487
|
+
const status = attr(node, "status");
|
|
2488
|
+
const metric = text(child(node, "metric"));
|
|
2489
|
+
if (priority !== void 0) q.priority = priority;
|
|
2490
|
+
if (status !== void 0) q.status = status;
|
|
2491
|
+
if (metric !== void 0) q.metric = metric;
|
|
2492
|
+
return q;
|
|
2493
|
+
}
|
|
2494
|
+
function parseObstacle(node) {
|
|
2495
|
+
const o = {
|
|
2496
|
+
id: attr(node, "id") ?? "",
|
|
2497
|
+
title: attr(node, "title") ?? "",
|
|
2498
|
+
statement: text(child(node, "statement")) ?? ""
|
|
2499
|
+
};
|
|
2500
|
+
const likelihood = attr(node, "likelihood");
|
|
2501
|
+
const severity = attr(node, "severity");
|
|
2502
|
+
const mitigation = text(child(node, "mitigation"));
|
|
2503
|
+
if (likelihood !== void 0) o.likelihood = likelihood;
|
|
2504
|
+
if (severity !== void 0) o.severity = severity;
|
|
2505
|
+
if (mitigation !== void 0) o.mitigation = mitigation;
|
|
2506
|
+
return o;
|
|
2507
|
+
}
|
|
2508
|
+
function parseGoalLink(node) {
|
|
2509
|
+
const gl = {
|
|
2510
|
+
id: attr(node, "id") ?? "",
|
|
2511
|
+
from: attr(node, "from") ?? "",
|
|
2512
|
+
to: attr(node, "to") ?? "",
|
|
2513
|
+
type: attr(node, "type") ?? "refines"
|
|
2514
|
+
};
|
|
2515
|
+
const confidence = numAttr(node, "confidence");
|
|
2516
|
+
if (confidence !== void 0) gl.confidence = confidence;
|
|
2517
|
+
return gl;
|
|
2518
|
+
}
|
|
2519
|
+
function parseGoals(node) {
|
|
2520
|
+
if (!isNode(node)) return void 0;
|
|
2521
|
+
const g = {};
|
|
2522
|
+
const goals = asArray(node.goal).map(parseGoal);
|
|
2523
|
+
const qgoals = asArray(node.qgoal).map(parseQualityGoal);
|
|
2524
|
+
const obstacles = asArray(node.obstacle).map(parseObstacle);
|
|
2525
|
+
const goalLinks = asArray(node.goalLink).map(parseGoalLink);
|
|
2526
|
+
if (goals.length > 0) g.goals = goals;
|
|
2527
|
+
if (qgoals.length > 0) g.qualityGoals = qgoals;
|
|
2528
|
+
if (obstacles.length > 0) g.obstacles = obstacles;
|
|
2529
|
+
if (goalLinks.length > 0) g.goalLinks = goalLinks;
|
|
2530
|
+
return Object.keys(g).length > 0 ? g : void 0;
|
|
2531
|
+
}
|
|
2532
|
+
function parseScenario(node) {
|
|
2533
|
+
const s = {
|
|
2534
|
+
id: attr(node, "id") ?? "",
|
|
2535
|
+
title: attr(node, "title") ?? "",
|
|
2536
|
+
narrative: text(child(node, "narrative")) ?? ""
|
|
2537
|
+
};
|
|
2538
|
+
const actorRef = attr(node, "actorRef");
|
|
2539
|
+
if (actorRef !== void 0) s.actorRef = actorRef;
|
|
2540
|
+
return s;
|
|
2541
|
+
}
|
|
2542
|
+
function parseScenarios(node) {
|
|
2543
|
+
if (!isNode(node)) return void 0;
|
|
2544
|
+
const s = {};
|
|
2545
|
+
const scenarios = asArray(node.scenario).map(parseScenario);
|
|
2546
|
+
const misuseCases = asArray(node.misuseCase).map(parseScenario);
|
|
2547
|
+
const edgeCases = asArray(node.edgeCase).map(parseScenario);
|
|
2548
|
+
if (scenarios.length > 0) s.scenarios = scenarios;
|
|
2549
|
+
if (misuseCases.length > 0) s.misuseCases = misuseCases;
|
|
2550
|
+
if (edgeCases.length > 0) s.edgeCases = edgeCases;
|
|
2551
|
+
return Object.keys(s).length > 0 ? s : void 0;
|
|
2552
|
+
}
|
|
2553
|
+
function parseCriterion(node) {
|
|
2554
|
+
const crit = { then: text(child(node, "then")) ?? "" };
|
|
2555
|
+
const id = attr(node, "id");
|
|
2556
|
+
const given = text(child(node, "given"));
|
|
2557
|
+
const when = text(child(node, "when"));
|
|
2558
|
+
if (id !== void 0) crit.id = id;
|
|
2559
|
+
if (given !== void 0) crit.given = given;
|
|
2560
|
+
if (when !== void 0) crit.when = when;
|
|
2561
|
+
return crit;
|
|
2562
|
+
}
|
|
2563
|
+
function parseRequirement(node) {
|
|
2564
|
+
const req = {
|
|
2565
|
+
id: attr(node, "id") ?? "",
|
|
2566
|
+
type: attr(node, "type") ?? "FR",
|
|
2567
|
+
title: attr(node, "title") ?? "",
|
|
2568
|
+
statement: text(child(node, "statement")) ?? "",
|
|
2569
|
+
acceptance: []
|
|
2570
|
+
};
|
|
2571
|
+
const status = attr(node, "status");
|
|
2572
|
+
const priority = attr(node, "priority");
|
|
2573
|
+
const ownerRef = attr(node, "ownerRef");
|
|
2574
|
+
const appliesTo = attr(node, "appliesTo");
|
|
2575
|
+
const rationale = text(child(node, "rationale"));
|
|
2576
|
+
const notes = text(child(node, "notes"));
|
|
2577
|
+
if (status !== void 0) req.status = status;
|
|
2578
|
+
if (priority !== void 0) req.priority = priority;
|
|
2579
|
+
if (ownerRef !== void 0) req.ownerRef = ownerRef;
|
|
2580
|
+
if (appliesTo !== void 0) req.appliesTo = appliesTo;
|
|
2581
|
+
if (rationale !== void 0) req.rationale = rationale;
|
|
2582
|
+
if (notes !== void 0) req.notes = notes;
|
|
2583
|
+
req.acceptance = asArray(child(child(node, "acceptance"), "criterion")).map(
|
|
2584
|
+
parseCriterion
|
|
2585
|
+
);
|
|
2586
|
+
return req;
|
|
2587
|
+
}
|
|
2588
|
+
function parsePackage(node) {
|
|
2589
|
+
const pkg = {
|
|
2590
|
+
id: attr(node, "id") ?? "",
|
|
2591
|
+
title: attr(node, "title") ?? "",
|
|
2592
|
+
requirements: asArray(child(node, "req")).map(parseRequirement)
|
|
2593
|
+
};
|
|
2594
|
+
const ownerRef = attr(node, "ownerRef");
|
|
2595
|
+
const description = text(child(node, "description"));
|
|
2596
|
+
if (ownerRef !== void 0) pkg.ownerRef = ownerRef;
|
|
2597
|
+
if (description !== void 0) pkg.description = description;
|
|
2598
|
+
return pkg;
|
|
2599
|
+
}
|
|
2600
|
+
function parseState(node) {
|
|
2601
|
+
const st = { id: attr(node, "id") ?? "", name: attr(node, "name") ?? "" };
|
|
2602
|
+
const type = attr(node, "type");
|
|
2603
|
+
const description = text(child(node, "description"));
|
|
2604
|
+
const onEntry = text(child(node, "onEntry"));
|
|
2605
|
+
const onExit = text(child(node, "onExit"));
|
|
2606
|
+
const invariant = text(child(node, "invariant"));
|
|
2607
|
+
if (type !== void 0) st.type = type;
|
|
2608
|
+
if (description !== void 0) st.description = description;
|
|
2609
|
+
if (onEntry !== void 0) st.onEntry = onEntry;
|
|
2610
|
+
if (onExit !== void 0) st.onExit = onExit;
|
|
2611
|
+
if (invariant !== void 0) st.invariant = invariant;
|
|
2612
|
+
return st;
|
|
2613
|
+
}
|
|
2614
|
+
function parseTransition(node) {
|
|
2615
|
+
const tr = {
|
|
2616
|
+
id: attr(node, "id") ?? "",
|
|
2617
|
+
from: attr(node, "from") ?? "",
|
|
2618
|
+
to: attr(node, "to") ?? ""
|
|
2619
|
+
};
|
|
2620
|
+
const event = attr(node, "event");
|
|
2621
|
+
const description = text(child(node, "description"));
|
|
2622
|
+
const trigger = text(child(node, "trigger"));
|
|
2623
|
+
const guard = text(child(node, "guard"));
|
|
2624
|
+
const action = text(child(node, "action"));
|
|
2625
|
+
if (event !== void 0) tr.event = event;
|
|
2626
|
+
if (description !== void 0) tr.description = description;
|
|
2627
|
+
if (trigger !== void 0) tr.trigger = trigger;
|
|
2628
|
+
if (guard !== void 0) tr.guard = guard;
|
|
2629
|
+
if (action !== void 0) tr.action = action;
|
|
2630
|
+
return tr;
|
|
2631
|
+
}
|
|
2632
|
+
function parseStateMachine(node) {
|
|
2633
|
+
const sm = {
|
|
2634
|
+
id: attr(node, "id") ?? "",
|
|
2635
|
+
name: attr(node, "name") ?? "",
|
|
2636
|
+
initial: attr(node, "initial") ?? "",
|
|
2637
|
+
states: asArray(child(node, "state")).map(parseState)
|
|
2638
|
+
};
|
|
2639
|
+
const entityRef = attr(node, "entityRef");
|
|
2640
|
+
const description = text(child(node, "description"));
|
|
2641
|
+
if (entityRef !== void 0) sm.entityRef = entityRef;
|
|
2642
|
+
if (description !== void 0) sm.description = description;
|
|
2643
|
+
const transitions = asArray(child(node, "transition")).map(parseTransition);
|
|
2644
|
+
if (transitions.length > 0) sm.transitions = transitions;
|
|
2645
|
+
return sm;
|
|
2646
|
+
}
|
|
2647
|
+
function parseBehavior(node) {
|
|
2648
|
+
if (!isNode(node)) return void 0;
|
|
2649
|
+
const stateMachines = asArray(node.stateMachine).map(parseStateMachine);
|
|
2650
|
+
return stateMachines.length > 0 ? { stateMachines } : void 0;
|
|
2651
|
+
}
|
|
2652
|
+
function parseEndpoint(node) {
|
|
2653
|
+
const ep = {
|
|
2654
|
+
id: attr(node, "id") ?? "",
|
|
2655
|
+
method: attr(node, "method") ?? "",
|
|
2656
|
+
path: attr(node, "path") ?? ""
|
|
2657
|
+
};
|
|
2658
|
+
const summary = text(child(node, "summary"));
|
|
2659
|
+
const request = text(child(node, "request"));
|
|
2660
|
+
const response = text(child(node, "response"));
|
|
2661
|
+
const errors = text(child(node, "errors"));
|
|
2662
|
+
if (summary !== void 0) ep.summary = summary;
|
|
2663
|
+
if (request !== void 0) ep.request = request;
|
|
2664
|
+
if (response !== void 0) ep.response = response;
|
|
2665
|
+
if (errors !== void 0) ep.errors = errors;
|
|
2666
|
+
return ep;
|
|
2667
|
+
}
|
|
2668
|
+
function parseApi(node) {
|
|
2669
|
+
const api = { id: attr(node, "id") ?? "", name: attr(node, "name") ?? "" };
|
|
2670
|
+
const protocol = attr(node, "protocol");
|
|
2671
|
+
const auth = attr(node, "auth");
|
|
2672
|
+
const description = text(child(node, "description"));
|
|
2673
|
+
if (protocol !== void 0) api.protocol = protocol;
|
|
2674
|
+
if (auth !== void 0) api.auth = auth;
|
|
2675
|
+
if (description !== void 0) api.description = description;
|
|
2676
|
+
const endpoints = asArray(child(node, "endpoint")).map(parseEndpoint);
|
|
2677
|
+
if (endpoints.length > 0) api.endpoints = endpoints;
|
|
2678
|
+
return api;
|
|
2679
|
+
}
|
|
2680
|
+
function parseEvent(node) {
|
|
2681
|
+
const ev = { id: attr(node, "id") ?? "", name: attr(node, "name") ?? "" };
|
|
2682
|
+
const description = text(child(node, "description"));
|
|
2683
|
+
const payload = text(child(node, "payload"));
|
|
2684
|
+
if (description !== void 0) ev.description = description;
|
|
2685
|
+
if (payload !== void 0) ev.payload = payload;
|
|
2686
|
+
return ev;
|
|
2687
|
+
}
|
|
2688
|
+
function parseInterfaces(node) {
|
|
2689
|
+
if (!isNode(node)) return void 0;
|
|
2690
|
+
const i = {};
|
|
2691
|
+
const apis = asArray(node.api).map(parseApi);
|
|
2692
|
+
const events = asArray(node.event).map(parseEvent);
|
|
2693
|
+
if (apis.length > 0) i.apis = apis;
|
|
2694
|
+
if (events.length > 0) i.events = events;
|
|
2695
|
+
return Object.keys(i).length > 0 ? i : void 0;
|
|
2696
|
+
}
|
|
2697
|
+
function parseTestSuite(node) {
|
|
2698
|
+
const ts = {
|
|
2699
|
+
id: attr(node, "id") ?? "",
|
|
2700
|
+
title: attr(node, "title") ?? ""
|
|
2701
|
+
};
|
|
2702
|
+
const description = text(child(node, "description"));
|
|
2703
|
+
if (description !== void 0) ts.description = description;
|
|
2704
|
+
return ts;
|
|
2705
|
+
}
|
|
2706
|
+
function parseTestCase(node) {
|
|
2707
|
+
const tc = {
|
|
2708
|
+
id: attr(node, "id") ?? "",
|
|
2709
|
+
type: attr(node, "type") ?? "acceptance",
|
|
2710
|
+
title: attr(node, "title") ?? ""
|
|
2711
|
+
};
|
|
2712
|
+
const purpose = text(child(node, "purpose"));
|
|
2713
|
+
const steps = text(child(node, "steps"));
|
|
2714
|
+
const expected = text(child(node, "expected"));
|
|
2715
|
+
if (purpose !== void 0) tc.purpose = purpose;
|
|
2716
|
+
if (steps !== void 0) tc.steps = steps;
|
|
2717
|
+
if (expected !== void 0) tc.expected = expected;
|
|
2718
|
+
return tc;
|
|
2719
|
+
}
|
|
2720
|
+
function parseVerification(node) {
|
|
2721
|
+
if (!isNode(node)) return void 0;
|
|
2722
|
+
const v = {};
|
|
2723
|
+
const testSuites = asArray(node.testSuite).map(parseTestSuite);
|
|
2724
|
+
const testCases = asArray(node.testCase).map(parseTestCase);
|
|
2725
|
+
if (testSuites.length > 0) v.testSuites = testSuites;
|
|
2726
|
+
if (testCases.length > 0) v.testCases = testCases;
|
|
2727
|
+
return Object.keys(v).length > 0 ? v : void 0;
|
|
2728
|
+
}
|
|
2729
|
+
function parseLocator(parent) {
|
|
2730
|
+
const loc = child(parent, "locator");
|
|
2731
|
+
if (!isNode(loc)) return void 0;
|
|
2732
|
+
if (isNode(loc.local)) {
|
|
2733
|
+
const out = { kind: "local", id: attr(loc.local, "id") ?? "" };
|
|
2734
|
+
const hintKind = attr(loc.local, "kind");
|
|
2735
|
+
const title = attr(loc.local, "title");
|
|
2736
|
+
if (hintKind !== void 0) out.hintKind = hintKind;
|
|
2737
|
+
if (title !== void 0) out.title = title;
|
|
2738
|
+
return out;
|
|
2739
|
+
}
|
|
2740
|
+
if (isNode(loc.doc)) {
|
|
2741
|
+
const out = {
|
|
2742
|
+
kind: "doc",
|
|
2743
|
+
uri: attr(loc.doc, "uri") ?? "",
|
|
2744
|
+
id: attr(loc.doc, "id") ?? ""
|
|
2745
|
+
};
|
|
2746
|
+
const docId = attr(loc.doc, "docId");
|
|
2747
|
+
const version = attr(loc.doc, "version");
|
|
2748
|
+
const git = attr(loc.doc, "git");
|
|
2749
|
+
const hintKind = attr(loc.doc, "kind");
|
|
2750
|
+
const title = attr(loc.doc, "title");
|
|
2751
|
+
if (docId !== void 0) out.docId = docId;
|
|
2752
|
+
if (version !== void 0) out.version = version;
|
|
2753
|
+
if (git !== void 0) out.git = git;
|
|
2754
|
+
if (hintKind !== void 0) out.hintKind = hintKind;
|
|
2755
|
+
if (title !== void 0) out.title = title;
|
|
2756
|
+
return out;
|
|
2757
|
+
}
|
|
2758
|
+
if (isNode(loc.external)) {
|
|
2759
|
+
const out = {
|
|
2760
|
+
kind: "external",
|
|
2761
|
+
uri: attr(loc.external, "uri") ?? ""
|
|
2762
|
+
};
|
|
2763
|
+
const hintKind = attr(loc.external, "kind");
|
|
2764
|
+
const title = attr(loc.external, "title");
|
|
2765
|
+
if (hintKind !== void 0) out.hintKind = hintKind;
|
|
2766
|
+
if (title !== void 0) out.title = title;
|
|
2767
|
+
return out;
|
|
2768
|
+
}
|
|
2769
|
+
return void 0;
|
|
2770
|
+
}
|
|
2771
|
+
function applyEdgeMeta(edge, node) {
|
|
2772
|
+
const confidence = numAttr(node, "confidence");
|
|
2773
|
+
const status = attr(node, "status");
|
|
2774
|
+
const createdBy = attr(node, "createdBy");
|
|
2775
|
+
const createdAt = attr(node, "createdAt");
|
|
2776
|
+
const tags = attr(node, "tags");
|
|
2777
|
+
const notes = text(child(node, "notes"));
|
|
2778
|
+
if (confidence !== void 0) edge.confidence = confidence;
|
|
2779
|
+
if (status !== void 0) edge.status = status;
|
|
2780
|
+
if (createdBy !== void 0) edge.createdBy = createdBy;
|
|
2781
|
+
if (createdAt !== void 0) edge.createdAt = createdAt;
|
|
2782
|
+
if (tags !== void 0) {
|
|
2783
|
+
const arr = tags.split(/\s+/).filter((t) => t.length > 0);
|
|
2784
|
+
if (arr.length > 0) edge.tags = arr;
|
|
2785
|
+
}
|
|
2786
|
+
if (notes !== void 0) edge.notes = notes;
|
|
2787
|
+
}
|
|
2788
|
+
function parseEdge(node) {
|
|
2789
|
+
const from = parseLocator(child(node, "from"));
|
|
2790
|
+
const to = parseLocator(child(node, "to"));
|
|
2791
|
+
if (!from || !to) return void 0;
|
|
2792
|
+
const edge = {
|
|
2793
|
+
id: attr(node, "id") ?? "",
|
|
2794
|
+
type: attr(node, "type") ?? "satisfies",
|
|
2795
|
+
from,
|
|
2796
|
+
to
|
|
2797
|
+
};
|
|
2798
|
+
applyEdgeMeta(edge, node);
|
|
2799
|
+
return edge;
|
|
2800
|
+
}
|
|
2801
|
+
function parseFlatEdge(node) {
|
|
2802
|
+
const fromId = attr(node, "from");
|
|
2803
|
+
const toId = attr(node, "to");
|
|
2804
|
+
const fromUri = attr(node, "fromUri");
|
|
2805
|
+
const toUri = attr(node, "toUri");
|
|
2806
|
+
let from;
|
|
2807
|
+
let to;
|
|
2808
|
+
if (fromId !== void 0) from = { kind: "local", id: fromId };
|
|
2809
|
+
else if (fromUri !== void 0) from = { kind: "external", uri: fromUri };
|
|
2810
|
+
if (toId !== void 0) to = { kind: "local", id: toId };
|
|
2811
|
+
else if (toUri !== void 0) to = { kind: "external", uri: toUri };
|
|
2812
|
+
if (!from || !to) return void 0;
|
|
2813
|
+
const edge = {
|
|
2814
|
+
id: attr(node, "id") ?? "",
|
|
2815
|
+
type: attr(node, "type") ?? "satisfies",
|
|
2816
|
+
from,
|
|
2817
|
+
to
|
|
2818
|
+
};
|
|
2819
|
+
applyEdgeMeta(edge, node);
|
|
2820
|
+
return edge;
|
|
2821
|
+
}
|
|
2822
|
+
function parseTrace(root) {
|
|
2823
|
+
const traceNode = child(root, "trace");
|
|
2824
|
+
if (!isNode(traceNode)) return [];
|
|
2825
|
+
const edges = [];
|
|
2826
|
+
for (const e of asArray(traceNode.edge)) {
|
|
2827
|
+
const parsed = parseEdge(e);
|
|
2828
|
+
if (parsed) edges.push(parsed);
|
|
2829
|
+
}
|
|
2830
|
+
for (const e of asArray(traceNode.traceEdge)) {
|
|
2831
|
+
const parsed = parseFlatEdge(e);
|
|
2832
|
+
if (parsed) edges.push(parsed);
|
|
2833
|
+
}
|
|
2834
|
+
return edges;
|
|
2835
|
+
}
|
|
2836
|
+
function parseIssue(node) {
|
|
2837
|
+
const iss = {
|
|
2838
|
+
id: attr(node, "id") ?? "",
|
|
2839
|
+
statement: text(child(node, "statement")) ?? ""
|
|
2840
|
+
};
|
|
2841
|
+
const status = attr(node, "status");
|
|
2842
|
+
const owner = attr(node, "owner");
|
|
2843
|
+
const notes = text(child(node, "notes"));
|
|
2844
|
+
if (status !== void 0) iss.status = status;
|
|
2845
|
+
if (owner !== void 0) iss.owner = owner;
|
|
2846
|
+
if (notes !== void 0) iss.notes = notes;
|
|
2847
|
+
return iss;
|
|
2848
|
+
}
|
|
2849
|
+
function parseApproval(node) {
|
|
2850
|
+
const ap = { id: attr(node, "id") ?? "", role: attr(node, "role") ?? "" };
|
|
2851
|
+
const status = attr(node, "status");
|
|
2852
|
+
const description = text(child(node, "description"));
|
|
2853
|
+
if (status !== void 0) ap.status = status;
|
|
2854
|
+
if (description !== void 0) ap.description = description;
|
|
2855
|
+
return ap;
|
|
2856
|
+
}
|
|
2857
|
+
function parseGovernance(node) {
|
|
2858
|
+
if (!isNode(node)) return void 0;
|
|
2859
|
+
const g = {};
|
|
2860
|
+
const issues = asArray(node.issue).map(parseIssue);
|
|
2861
|
+
const approvals = asArray(node.approval).map(parseApproval);
|
|
2862
|
+
if (issues.length > 0) g.issues = issues;
|
|
2863
|
+
if (approvals.length > 0) g.approvals = approvals;
|
|
2864
|
+
return Object.keys(g).length > 0 ? g : void 0;
|
|
2865
|
+
}
|
|
2866
|
+
function parse(xml) {
|
|
2867
|
+
const wellFormed = import_fast_xml_parser.XMLValidator.validate(xml, { allowBooleanAttributes: true });
|
|
2868
|
+
if (wellFormed !== true) {
|
|
2869
|
+
const err = wellFormed.err;
|
|
2870
|
+
const diag = {
|
|
2871
|
+
source: "parse",
|
|
2872
|
+
severity: "error",
|
|
2873
|
+
message: err.msg
|
|
2874
|
+
};
|
|
2875
|
+
if (typeof err.line === "number") diag.line = err.line;
|
|
2876
|
+
if (typeof err.col === "number") diag.column = err.col;
|
|
2877
|
+
return { ok: false, error: diag };
|
|
2878
|
+
}
|
|
2879
|
+
let obj;
|
|
2880
|
+
try {
|
|
2881
|
+
obj = parser.parse(xml);
|
|
2882
|
+
} catch (e) {
|
|
2883
|
+
return {
|
|
2884
|
+
ok: false,
|
|
2885
|
+
error: {
|
|
2886
|
+
source: "parse",
|
|
2887
|
+
severity: "error",
|
|
2888
|
+
message: e instanceof Error ? e.message : String(e)
|
|
2889
|
+
}
|
|
2890
|
+
};
|
|
2891
|
+
}
|
|
2892
|
+
const root = obj.rqml;
|
|
2893
|
+
if (!isNode(root)) {
|
|
2894
|
+
return {
|
|
2895
|
+
ok: false,
|
|
2896
|
+
error: {
|
|
2897
|
+
source: "parse",
|
|
2898
|
+
severity: "error",
|
|
2899
|
+
message: "Missing root <rqml> element."
|
|
2900
|
+
}
|
|
2901
|
+
};
|
|
2902
|
+
}
|
|
2903
|
+
const requirements = isNode(root.requirements) ? root.requirements : {};
|
|
2904
|
+
const document = {
|
|
2905
|
+
version: attr(root, "version") ?? "",
|
|
2906
|
+
docId: attr(root, "docId") ?? "",
|
|
2907
|
+
status: attr(root, "status") ?? "draft",
|
|
2908
|
+
meta: parseMeta(root.meta),
|
|
2909
|
+
packages: asArray(requirements.reqPackage).map(parsePackage),
|
|
2910
|
+
looseRequirements: asArray(requirements.req).map(parseRequirement),
|
|
2911
|
+
trace: parseTrace(root)
|
|
2912
|
+
};
|
|
2913
|
+
const catalogs = parseCatalogs(root.catalogs);
|
|
2914
|
+
if (catalogs) document.catalogs = catalogs;
|
|
2915
|
+
const domain = parseDomain(root.domain);
|
|
2916
|
+
if (domain) document.domain = domain;
|
|
2917
|
+
const goals = parseGoals(root.goals);
|
|
2918
|
+
if (goals) document.goals = goals;
|
|
2919
|
+
const scenarios = parseScenarios(root.scenarios);
|
|
2920
|
+
if (scenarios) document.scenarios = scenarios;
|
|
2921
|
+
const behavior = parseBehavior(root.behavior);
|
|
2922
|
+
if (behavior) document.behavior = behavior;
|
|
2923
|
+
const interfaces = parseInterfaces(root.interfaces);
|
|
2924
|
+
if (interfaces) document.interfaces = interfaces;
|
|
2925
|
+
const verification = parseVerification(root.verification);
|
|
2926
|
+
if (verification) document.verification = verification;
|
|
2927
|
+
const governance = parseGovernance(root.governance);
|
|
2928
|
+
if (governance) document.governance = governance;
|
|
2929
|
+
const raw = {};
|
|
2930
|
+
for (const [key, value] of Object.entries(root)) {
|
|
2931
|
+
if (key.startsWith(ATTR_PREFIX)) {
|
|
2932
|
+
if (!KNOWN_ROOT_ATTRS.has(key)) raw[key] = value;
|
|
2933
|
+
} else if (!MODELED_SECTIONS.has(key)) {
|
|
2934
|
+
raw[key] = value;
|
|
2935
|
+
}
|
|
2936
|
+
}
|
|
2937
|
+
setRawSections(document, raw);
|
|
2938
|
+
return { ok: true, document };
|
|
2939
|
+
}
|
|
2940
|
+
var ATTR_PREFIX2 = "@_";
|
|
2941
|
+
new import_fast_xml_parser.XMLBuilder({
|
|
2942
|
+
ignoreAttributes: false,
|
|
2943
|
+
attributeNamePrefix: ATTR_PREFIX2,
|
|
2944
|
+
format: true,
|
|
2945
|
+
suppressEmptyNode: true,
|
|
2946
|
+
// Keep value="true" attributes intact; otherwise XMLBuilder collapses them to
|
|
2947
|
+
// valueless attributes (e.g. `required`), which the parser then drops.
|
|
2948
|
+
suppressBooleanAttributes: false
|
|
2949
|
+
});
|
|
2950
|
+
function scaleSeverity(nominal, strictness) {
|
|
2951
|
+
const ladder = ["info", "warning", "error"];
|
|
2952
|
+
const base = ladder.indexOf(nominal);
|
|
2953
|
+
const shift = 0;
|
|
2954
|
+
const next = base + shift;
|
|
2955
|
+
if (next < 0) return void 0;
|
|
2956
|
+
return ladder[Math.min(next, ladder.length - 1)];
|
|
2957
|
+
}
|
|
2958
|
+
function missingAcceptance(doc, strictness) {
|
|
2959
|
+
const severity = scaleSeverity("warning");
|
|
2960
|
+
if (severity === void 0) return [];
|
|
2961
|
+
return allRequirements(doc).filter((req) => req.acceptance.length === 0).map((req) => ({
|
|
2962
|
+
source: "lint",
|
|
2963
|
+
severity,
|
|
2964
|
+
rule: "missing-acceptance",
|
|
2965
|
+
message: `Requirement "${req.id}" has no acceptance criteria.`
|
|
2966
|
+
}));
|
|
2967
|
+
}
|
|
2968
|
+
function lint(doc, options) {
|
|
2969
|
+
return [...missingAcceptance(doc)];
|
|
2970
|
+
}
|
|
2971
|
+
function requirementIndex(doc) {
|
|
2972
|
+
const index = /* @__PURE__ */ new Map();
|
|
2973
|
+
for (const req of allRequirements(doc)) index.set(req.id, req);
|
|
2974
|
+
return index;
|
|
2975
|
+
}
|
|
2976
|
+
function declaredIdIndex(doc) {
|
|
2977
|
+
const index = /* @__PURE__ */ new Map();
|
|
2978
|
+
for (const ref of declaredElements(doc)) {
|
|
2979
|
+
if (!index.has(ref.id)) index.set(ref.id, ref);
|
|
2980
|
+
}
|
|
2981
|
+
return index;
|
|
2982
|
+
}
|
|
2983
|
+
function resolveTrace(doc) {
|
|
2984
|
+
const idIndex = declaredIdIndex(doc);
|
|
2985
|
+
const reqIndex = requirementIndex(doc);
|
|
2986
|
+
const diagnostics = [];
|
|
2987
|
+
const resolveEndpoint = (locator, edge, side) => {
|
|
2988
|
+
if (locator.kind !== "local") return { locator };
|
|
2989
|
+
const target = idIndex.get(locator.id);
|
|
2990
|
+
if (target === void 0) {
|
|
2991
|
+
diagnostics.push({
|
|
2992
|
+
source: "trace",
|
|
2993
|
+
severity: "error",
|
|
2994
|
+
rule: "unresolved-local-ref",
|
|
2995
|
+
message: `Trace edge "${edge.id}" (${side}) references unknown local id "${locator.id}".`
|
|
2996
|
+
});
|
|
2997
|
+
return { locator };
|
|
2998
|
+
}
|
|
2999
|
+
const resolved = { locator, target };
|
|
3000
|
+
const requirement = reqIndex.get(locator.id);
|
|
3001
|
+
if (requirement !== void 0) resolved.requirement = requirement;
|
|
3002
|
+
return resolved;
|
|
3003
|
+
};
|
|
3004
|
+
const edges = doc.trace.map((edge) => ({
|
|
3005
|
+
edge,
|
|
3006
|
+
from: resolveEndpoint(edge.from, edge, "from"),
|
|
3007
|
+
to: resolveEndpoint(edge.to, edge, "to")
|
|
3008
|
+
}));
|
|
3009
|
+
return { edges, diagnostics };
|
|
3010
|
+
}
|
|
3011
|
+
var ATTR_PREFIX3 = "@_";
|
|
3012
|
+
var REFERENCE_ELEMENTS = /* @__PURE__ */ new Set(["local", "doc"]);
|
|
3013
|
+
var parser2 = new import_fast_xml_parser.XMLParser({
|
|
3014
|
+
ignoreAttributes: false,
|
|
3015
|
+
attributeNamePrefix: ATTR_PREFIX3,
|
|
3016
|
+
parseAttributeValue: false,
|
|
3017
|
+
parseTagValue: false,
|
|
3018
|
+
trimValues: true
|
|
3019
|
+
});
|
|
3020
|
+
function isNode2(v) {
|
|
3021
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
3022
|
+
}
|
|
3023
|
+
function asArray2(v) {
|
|
3024
|
+
if (v == null) return [];
|
|
3025
|
+
return Array.isArray(v) ? v : [v];
|
|
3026
|
+
}
|
|
3027
|
+
function str(v) {
|
|
3028
|
+
return v == null ? void 0 : String(v);
|
|
3029
|
+
}
|
|
3030
|
+
function attr2(node, name) {
|
|
3031
|
+
return str(node[ATTR_PREFIX3 + name]);
|
|
3032
|
+
}
|
|
3033
|
+
function nestedRefs(edge, out) {
|
|
3034
|
+
const edgeId = attr2(edge, "id") ?? "";
|
|
3035
|
+
for (const side of ["from", "to"]) {
|
|
3036
|
+
const endpoint = edge[side];
|
|
3037
|
+
const locator = isNode2(endpoint) ? endpoint.locator : void 0;
|
|
3038
|
+
const local = isNode2(locator) ? locator.local : void 0;
|
|
3039
|
+
const refId = isNode2(local) ? attr2(local, "id") : void 0;
|
|
3040
|
+
if (refId !== void 0) out.push({ refId, edgeId, side, flat: false });
|
|
3041
|
+
}
|
|
3042
|
+
}
|
|
3043
|
+
function flatRefs(edge, out) {
|
|
3044
|
+
const edgeId = attr2(edge, "id") ?? "";
|
|
3045
|
+
const from = attr2(edge, "from");
|
|
3046
|
+
const to = attr2(edge, "to");
|
|
3047
|
+
if (from !== void 0) out.push({ refId: from, edgeId, side: "from", flat: true });
|
|
3048
|
+
if (to !== void 0) out.push({ refId: to, edgeId, side: "to", flat: true });
|
|
3049
|
+
}
|
|
3050
|
+
function walk(node, declared, refs) {
|
|
3051
|
+
for (const [key, value] of Object.entries(node)) {
|
|
3052
|
+
if (key.startsWith(ATTR_PREFIX3) || key === "#text") continue;
|
|
3053
|
+
for (const item of asArray2(value)) {
|
|
3054
|
+
if (!isNode2(item)) continue;
|
|
3055
|
+
const id = attr2(item, "id");
|
|
3056
|
+
if (id !== void 0 && !REFERENCE_ELEMENTS.has(key)) declared.push(id);
|
|
3057
|
+
if (key === "edge") nestedRefs(item, refs);
|
|
3058
|
+
else if (key === "traceEdge") flatRefs(item, refs);
|
|
3059
|
+
walk(item, declared, refs);
|
|
3060
|
+
}
|
|
3061
|
+
}
|
|
3062
|
+
}
|
|
3063
|
+
function escapeRegExp(s) {
|
|
3064
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3065
|
+
}
|
|
3066
|
+
function lineStarts(xml) {
|
|
3067
|
+
const starts = [0];
|
|
3068
|
+
for (let i = 0; i < xml.length; i++) if (xml[i] === "\n") starts.push(i + 1);
|
|
3069
|
+
return starts;
|
|
3070
|
+
}
|
|
3071
|
+
function lineAtOffset(starts, offset) {
|
|
3072
|
+
let lo = 0;
|
|
3073
|
+
let hi = starts.length - 1;
|
|
3074
|
+
let ans = 0;
|
|
3075
|
+
while (lo <= hi) {
|
|
3076
|
+
const mid = lo + hi >> 1;
|
|
3077
|
+
const start = starts[mid];
|
|
3078
|
+
if (start !== void 0 && start <= offset) {
|
|
3079
|
+
ans = mid;
|
|
3080
|
+
lo = mid + 1;
|
|
3081
|
+
} else {
|
|
3082
|
+
hi = mid - 1;
|
|
3083
|
+
}
|
|
3084
|
+
}
|
|
3085
|
+
return ans + 1;
|
|
3086
|
+
}
|
|
3087
|
+
function matchLines(xml, starts, re) {
|
|
3088
|
+
const lines = [];
|
|
3089
|
+
re.lastIndex = 0;
|
|
3090
|
+
let m;
|
|
3091
|
+
while ((m = re.exec(xml)) !== null) {
|
|
3092
|
+
lines.push(lineAtOffset(starts, m.index));
|
|
3093
|
+
if (m.index === re.lastIndex) re.lastIndex++;
|
|
3094
|
+
}
|
|
3095
|
+
return lines;
|
|
3096
|
+
}
|
|
3097
|
+
function checkIntegrity(xml) {
|
|
3098
|
+
let root;
|
|
3099
|
+
try {
|
|
3100
|
+
const obj = parser2.parse(xml);
|
|
3101
|
+
root = isNode2(obj.rqml) ? obj.rqml : void 0;
|
|
3102
|
+
} catch {
|
|
3103
|
+
return [];
|
|
3104
|
+
}
|
|
3105
|
+
if (!root) return [];
|
|
3106
|
+
const declared = [];
|
|
3107
|
+
const refs = [];
|
|
3108
|
+
walk(root, declared, refs);
|
|
3109
|
+
const starts = lineStarts(xml);
|
|
3110
|
+
const diagnostics = [];
|
|
3111
|
+
const counts = /* @__PURE__ */ new Map();
|
|
3112
|
+
for (const id of declared) counts.set(id, (counts.get(id) ?? 0) + 1);
|
|
3113
|
+
for (const [id, count] of counts) {
|
|
3114
|
+
if (id === "" || count < 2) continue;
|
|
3115
|
+
const re = new RegExp(
|
|
3116
|
+
`<(?!local\\b|doc\\b)[A-Za-z][\\w.:-]*\\b[^>]*?\\sid\\s*=\\s*"${escapeRegExp(id)}"`,
|
|
3117
|
+
"g"
|
|
3118
|
+
);
|
|
3119
|
+
const lines = matchLines(xml, starts, re);
|
|
3120
|
+
const redeclLines = lines.length >= 2 ? lines.slice(1) : [void 0];
|
|
3121
|
+
for (const line of redeclLines) {
|
|
3122
|
+
const diag = {
|
|
3123
|
+
source: "validate",
|
|
3124
|
+
severity: "error",
|
|
3125
|
+
rule: "duplicate-id",
|
|
3126
|
+
message: `Duplicate id "${id}": this id is already declared elsewhere in the document.`
|
|
3127
|
+
};
|
|
3128
|
+
if (typeof line === "number") diag.line = line;
|
|
3129
|
+
diagnostics.push(diag);
|
|
3130
|
+
}
|
|
3131
|
+
}
|
|
3132
|
+
const declaredSet = new Set(declared);
|
|
3133
|
+
for (const ref of refs) {
|
|
3134
|
+
if (ref.refId === "" || declaredSet.has(ref.refId)) continue;
|
|
3135
|
+
const re = ref.flat ? new RegExp(
|
|
3136
|
+
`<traceEdge\\b[^>]*?\\s${ref.side}\\s*=\\s*"${escapeRegExp(ref.refId)}"`,
|
|
3137
|
+
"g"
|
|
3138
|
+
) : new RegExp(`<local\\b[^>]*?\\sid\\s*=\\s*"${escapeRegExp(ref.refId)}"`, "g");
|
|
3139
|
+
const lines = matchLines(xml, starts, re);
|
|
3140
|
+
const diag = {
|
|
3141
|
+
source: "trace",
|
|
3142
|
+
severity: "error",
|
|
3143
|
+
rule: "unresolved-local-ref",
|
|
3144
|
+
message: `Trace edge "${ref.edgeId}" (${ref.side}) references unknown id "${ref.refId}".`
|
|
3145
|
+
};
|
|
3146
|
+
if (lines.length > 0) diag.line = lines[0];
|
|
3147
|
+
diagnostics.push(diag);
|
|
3148
|
+
}
|
|
3149
|
+
return diagnostics;
|
|
3150
|
+
}
|
|
3151
|
+
var UPWARD_TARGET_KINDS = /* @__PURE__ */ new Set([
|
|
3152
|
+
"goal",
|
|
3153
|
+
"qgoal",
|
|
3154
|
+
"scenario",
|
|
3155
|
+
"misuseCase",
|
|
3156
|
+
"edgeCase"
|
|
3157
|
+
]);
|
|
3158
|
+
function add(group, type, edgeId) {
|
|
3159
|
+
const existing = group[type];
|
|
3160
|
+
if (existing) {
|
|
3161
|
+
existing.push(edgeId);
|
|
3162
|
+
} else {
|
|
3163
|
+
group[type] = [edgeId];
|
|
3164
|
+
}
|
|
3165
|
+
}
|
|
3166
|
+
function sortGroups(group) {
|
|
3167
|
+
for (const key of Object.keys(group)) {
|
|
3168
|
+
group[key] = [...new Set(group[key])].sort();
|
|
3169
|
+
}
|
|
3170
|
+
}
|
|
3171
|
+
function computeCoverage(doc) {
|
|
3172
|
+
const idIndex = declaredIdIndex(doc);
|
|
3173
|
+
const reqs = allRequirements(doc);
|
|
3174
|
+
const reqIds = new Set(reqs.map((r) => r.id));
|
|
3175
|
+
const outgoing = /* @__PURE__ */ new Map();
|
|
3176
|
+
const incoming = /* @__PURE__ */ new Map();
|
|
3177
|
+
const ensure = (m, id) => {
|
|
3178
|
+
let g = m.get(id);
|
|
3179
|
+
if (g === void 0) {
|
|
3180
|
+
g = {};
|
|
3181
|
+
m.set(id, g);
|
|
3182
|
+
}
|
|
3183
|
+
return g;
|
|
3184
|
+
};
|
|
3185
|
+
for (const edge of doc.trace) {
|
|
3186
|
+
if (edge.from.kind === "local")
|
|
3187
|
+
add(ensure(outgoing, edge.from.id), edge.type, edge.id);
|
|
3188
|
+
if (edge.to.kind === "local") add(ensure(incoming, edge.to.id), edge.type, edge.id);
|
|
3189
|
+
}
|
|
3190
|
+
const requirements = [...reqIds].sort().map((id) => {
|
|
3191
|
+
const out = outgoing.get(id) ?? {};
|
|
3192
|
+
const inc = incoming.get(id) ?? {};
|
|
3193
|
+
sortGroups(out);
|
|
3194
|
+
sortGroups(inc);
|
|
3195
|
+
return { id, outgoing: out, incoming: inc };
|
|
3196
|
+
});
|
|
3197
|
+
const uncoveredGoals = [];
|
|
3198
|
+
for (const [id, ref] of idIndex) {
|
|
3199
|
+
if (ref.kind !== "goal" && ref.kind !== "qgoal") continue;
|
|
3200
|
+
if (!(incoming.get(id)?.satisfies?.length ?? 0)) uncoveredGoals.push(id);
|
|
3201
|
+
}
|
|
3202
|
+
uncoveredGoals.sort();
|
|
3203
|
+
const unverifiedRequirements = [];
|
|
3204
|
+
const unimplementedRequirements = [];
|
|
3205
|
+
const orphanRequirements = [];
|
|
3206
|
+
for (const id of [...reqIds].sort()) {
|
|
3207
|
+
const out = outgoing.get(id) ?? {};
|
|
3208
|
+
const inc = incoming.get(id) ?? {};
|
|
3209
|
+
const verified = (out.verifiedBy?.length ?? 0) > 0 || (inc.covers?.length ?? 0) > 0;
|
|
3210
|
+
if (!verified) unverifiedRequirements.push(id);
|
|
3211
|
+
if (!(inc.implements?.length ?? 0)) unimplementedRequirements.push(id);
|
|
3212
|
+
const satisfiesUpward = (out.satisfies ?? []).some((edgeId) => {
|
|
3213
|
+
const edge = doc.trace.find((e) => e.id === edgeId);
|
|
3214
|
+
const to = edge?.to;
|
|
3215
|
+
if (to?.kind !== "local") return false;
|
|
3216
|
+
const target = idIndex.get(to.id);
|
|
3217
|
+
return target !== void 0 && UPWARD_TARGET_KINDS.has(target.kind);
|
|
3218
|
+
});
|
|
3219
|
+
if (!satisfiesUpward) orphanRequirements.push(id);
|
|
3220
|
+
}
|
|
3221
|
+
const diagnostics = [];
|
|
3222
|
+
for (const id of uncoveredGoals)
|
|
3223
|
+
diagnostics.push(
|
|
3224
|
+
finding(
|
|
3225
|
+
"coverage",
|
|
3226
|
+
"uncovered-goal",
|
|
3227
|
+
`Goal "${id}" has no satisfying requirement.`
|
|
3228
|
+
)
|
|
3229
|
+
);
|
|
3230
|
+
for (const id of unverifiedRequirements)
|
|
3231
|
+
diagnostics.push(
|
|
3232
|
+
finding(
|
|
3233
|
+
"coverage",
|
|
3234
|
+
"unverified-requirement",
|
|
3235
|
+
`Requirement "${id}" has no verification edge.`
|
|
3236
|
+
)
|
|
3237
|
+
);
|
|
3238
|
+
for (const id of unimplementedRequirements)
|
|
3239
|
+
diagnostics.push(
|
|
3240
|
+
finding(
|
|
3241
|
+
"coverage",
|
|
3242
|
+
"unimplemented-requirement",
|
|
3243
|
+
`Requirement "${id}" has no implementation link.`
|
|
3244
|
+
)
|
|
3245
|
+
);
|
|
3246
|
+
for (const id of orphanRequirements)
|
|
3247
|
+
diagnostics.push(
|
|
3248
|
+
finding(
|
|
3249
|
+
"coverage",
|
|
3250
|
+
"orphan-requirement",
|
|
3251
|
+
`Requirement "${id}" satisfies no goal or scenario.`
|
|
3252
|
+
)
|
|
3253
|
+
);
|
|
3254
|
+
diagnostics.push(...resolveTrace(doc).diagnostics);
|
|
3255
|
+
return {
|
|
3256
|
+
requirements,
|
|
3257
|
+
uncoveredGoals,
|
|
3258
|
+
unverifiedRequirements,
|
|
3259
|
+
unimplementedRequirements,
|
|
3260
|
+
orphanRequirements,
|
|
3261
|
+
diagnostics
|
|
3262
|
+
};
|
|
3263
|
+
}
|
|
3264
|
+
function finding(source, rule, message) {
|
|
3265
|
+
return { source, severity: "warning", rule, message };
|
|
3266
|
+
}
|
|
3267
|
+
function implementsLinks(doc) {
|
|
3268
|
+
const out = [];
|
|
3269
|
+
for (const edge of doc.trace) {
|
|
3270
|
+
if (edge.type !== "implements") continue;
|
|
3271
|
+
const external = edge.from.kind === "external" ? edge.from : edge.to.kind === "external" ? edge.to : void 0;
|
|
3272
|
+
if (external === void 0) continue;
|
|
3273
|
+
const local = edge.from.kind === "local" ? edge.from.id : edge.to.kind === "local" ? edge.to.id : void 0;
|
|
3274
|
+
const link = { edgeId: edge.id, uri: external.uri };
|
|
3275
|
+
if (local !== void 0) link.requirementId = local;
|
|
3276
|
+
out.push(link);
|
|
3277
|
+
}
|
|
3278
|
+
return out.sort((a, b) => a.edgeId.localeCompare(b.edgeId));
|
|
3279
|
+
}
|
|
3280
|
+
function filePathFromUri(uri, baseDir) {
|
|
3281
|
+
const noFragment = uri.split("#")[0] ?? uri;
|
|
3282
|
+
if (noFragment.startsWith("file://")) return fileURLToPath(noFragment);
|
|
3283
|
+
if (noFragment.startsWith("file:")) {
|
|
3284
|
+
const path = noFragment.slice("file:".length);
|
|
3285
|
+
return isAbsolute(path) ? path : resolve(baseDir, path);
|
|
3286
|
+
}
|
|
3287
|
+
if (!/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(noFragment)) {
|
|
3288
|
+
return isAbsolute(noFragment) ? noFragment : resolve(baseDir, noFragment);
|
|
3289
|
+
}
|
|
3290
|
+
return void 0;
|
|
3291
|
+
}
|
|
3292
|
+
function filesystemResolver(baseDir) {
|
|
3293
|
+
return (link) => {
|
|
3294
|
+
const filePath = filePathFromUri(link.uri, baseDir);
|
|
3295
|
+
if (filePath === void 0) return "present";
|
|
3296
|
+
return existsSync(filePath) ? "present" : "missing";
|
|
3297
|
+
};
|
|
3298
|
+
}
|
|
3299
|
+
function detectDrift(doc, options = {}) {
|
|
3300
|
+
const baseDir = options.baseDir ?? process.cwd();
|
|
3301
|
+
const resolve4 = options.resolve ?? filesystemResolver(baseDir);
|
|
3302
|
+
const links = implementsLinks(doc);
|
|
3303
|
+
const drifted = [];
|
|
3304
|
+
const diagnostics = [];
|
|
3305
|
+
for (const link of links) {
|
|
3306
|
+
const status = resolve4(link);
|
|
3307
|
+
if (status === "present") continue;
|
|
3308
|
+
drifted.push({ ...link, status });
|
|
3309
|
+
diagnostics.push({
|
|
3310
|
+
source: "drift",
|
|
3311
|
+
severity: "error",
|
|
3312
|
+
rule: status === "missing" ? "missing-implementation" : "changed-implementation",
|
|
3313
|
+
message: status === "missing" ? `implements edge "${link.edgeId}" points at "${link.uri}", which does not exist.` : `implements edge "${link.edgeId}" points at "${link.uri}", which has changed since approval.`
|
|
3314
|
+
});
|
|
3315
|
+
}
|
|
3316
|
+
return { links, drifted, diagnostics };
|
|
3317
|
+
}
|
|
3318
|
+
|
|
3319
|
+
// src/report.ts
|
|
3320
|
+
function formatDiagnostic(d) {
|
|
3321
|
+
const loc = d.line !== void 0 ? `:${d.line}${d.column !== void 0 ? `:${d.column}` : ""}` : "";
|
|
3322
|
+
const rule = d.rule !== void 0 ? ` [${d.rule}]` : "";
|
|
3323
|
+
return ` ${d.severity}${loc} (${d.source})${rule}: ${d.message}`;
|
|
3324
|
+
}
|
|
3325
|
+
function printDiagnostics(diags) {
|
|
3326
|
+
for (const d of diags) process.stdout.write(`${formatDiagnostic(d)}
|
|
3327
|
+
`);
|
|
3328
|
+
}
|
|
3329
|
+
var EXIT = {
|
|
3330
|
+
OK: 0,
|
|
3331
|
+
/** The document is not well-formed, schema-invalid, or fails integrity. */
|
|
3332
|
+
VALIDATION: 1,
|
|
3333
|
+
/** The check gate failed on blocking drift or coverage. */
|
|
3334
|
+
CHECK: 2,
|
|
3335
|
+
/** The command was invoked incorrectly. */
|
|
3336
|
+
USAGE: 64
|
|
3337
|
+
};
|
|
3338
|
+
var UsageError = class extends Error {
|
|
3339
|
+
};
|
|
3340
|
+
var STRICTNESS = /* @__PURE__ */ new Set(["relaxed", "standard", "strict", "certified"]);
|
|
3341
|
+
function parseArgs(rest) {
|
|
3342
|
+
const positionals = [];
|
|
3343
|
+
const flags = /* @__PURE__ */ new Map();
|
|
3344
|
+
for (let i = 0; i < rest.length; i++) {
|
|
3345
|
+
const a = rest[i];
|
|
3346
|
+
if (a.startsWith("--")) {
|
|
3347
|
+
const eq = a.indexOf("=");
|
|
3348
|
+
if (eq >= 0) {
|
|
3349
|
+
flags.set(a.slice(2, eq), a.slice(eq + 1));
|
|
3350
|
+
} else {
|
|
3351
|
+
const next = rest[i + 1];
|
|
3352
|
+
if (next !== void 0 && !next.startsWith("-")) {
|
|
3353
|
+
flags.set(a.slice(2), next);
|
|
3354
|
+
i++;
|
|
3355
|
+
} else {
|
|
3356
|
+
flags.set(a.slice(2), true);
|
|
3357
|
+
}
|
|
3358
|
+
}
|
|
3359
|
+
} else {
|
|
3360
|
+
positionals.push(a);
|
|
3361
|
+
}
|
|
3362
|
+
}
|
|
3363
|
+
const strictness = String(flags.get("strictness") ?? "standard");
|
|
3364
|
+
if (!STRICTNESS.has(strictness)) {
|
|
3365
|
+
throw new UsageError(
|
|
3366
|
+
`unknown strictness "${strictness}" (relaxed|standard|strict|certified)`
|
|
3367
|
+
);
|
|
3368
|
+
}
|
|
3369
|
+
return {
|
|
3370
|
+
positionals,
|
|
3371
|
+
json: flags.get("json") === true || flags.get("json") === "true",
|
|
3372
|
+
strictness,
|
|
3373
|
+
baseDir: resolve(String(flags.get("base-dir") ?? process.cwd()))
|
|
3374
|
+
};
|
|
3375
|
+
}
|
|
3376
|
+
function resolveSpecPath(args) {
|
|
3377
|
+
const explicit = args.positionals[0];
|
|
3378
|
+
if (explicit !== void 0) {
|
|
3379
|
+
const p = resolve(args.baseDir, explicit);
|
|
3380
|
+
if (!existsSync(p)) throw new UsageError(`spec file not found: ${explicit}`);
|
|
3381
|
+
return p;
|
|
3382
|
+
}
|
|
3383
|
+
const candidates = readdirSync(args.baseDir).filter((f) => f.endsWith(".rqml")).sort();
|
|
3384
|
+
if (candidates.length === 0) {
|
|
3385
|
+
throw new UsageError("no .rqml document found in this directory; pass a path");
|
|
3386
|
+
}
|
|
3387
|
+
const preferred = candidates.includes("requirements.rqml") ? "requirements.rqml" : candidates[0];
|
|
3388
|
+
return resolve(args.baseDir, preferred);
|
|
3389
|
+
}
|
|
3390
|
+
function readSpec(args) {
|
|
3391
|
+
const path = resolveSpecPath(args);
|
|
3392
|
+
return { path, xml: readFileSync(path, "utf8") };
|
|
3393
|
+
}
|
|
3394
|
+
|
|
3395
|
+
// src/commands/check.ts
|
|
3396
|
+
function coverageBlocks(strictness) {
|
|
3397
|
+
return strictness === "strict" || strictness === "certified";
|
|
3398
|
+
}
|
|
3399
|
+
async function runCheck(rest) {
|
|
3400
|
+
const args = parseArgs(rest);
|
|
3401
|
+
const { path, xml } = readSpec(args);
|
|
3402
|
+
const { validate } = await import('./validate-O3LLP44J.js');
|
|
3403
|
+
const validation = validate(xml);
|
|
3404
|
+
const integrity = validation.valid ? checkIntegrity(xml) : [];
|
|
3405
|
+
const parsed = parse(xml);
|
|
3406
|
+
const coverage = parsed.ok ? computeCoverage(parsed.document) : void 0;
|
|
3407
|
+
const drift = parsed.ok ? detectDrift(parsed.document, { baseDir: args.baseDir }) : void 0;
|
|
3408
|
+
const validationFailed = !validation.valid || integrity.length > 0;
|
|
3409
|
+
const driftFailed = (drift?.drifted.length ?? 0) > 0;
|
|
3410
|
+
const coverageProblemCount = (coverage?.uncoveredGoals.length ?? 0) + (coverage?.unverifiedRequirements.length ?? 0) + (coverage?.orphanRequirements.length ?? 0);
|
|
3411
|
+
const coverageFailed = coverageBlocks(args.strictness) && coverageProblemCount > 0;
|
|
3412
|
+
const verdict = validationFailed || driftFailed || coverageFailed ? "fail" : "pass";
|
|
3413
|
+
const diagnostics = [
|
|
3414
|
+
...validation.diagnostics,
|
|
3415
|
+
...integrity,
|
|
3416
|
+
...drift?.diagnostics ?? [],
|
|
3417
|
+
...coverageFailed ? coverage?.diagnostics ?? [] : []
|
|
3418
|
+
];
|
|
3419
|
+
const report = {
|
|
3420
|
+
path,
|
|
3421
|
+
verdict,
|
|
3422
|
+
strictness: args.strictness,
|
|
3423
|
+
schemaVersion: validation.schemaVersion,
|
|
3424
|
+
valid: !validationFailed,
|
|
3425
|
+
drift: drift?.drifted ?? [],
|
|
3426
|
+
coverage: coverage ? {
|
|
3427
|
+
uncoveredGoals: coverage.uncoveredGoals,
|
|
3428
|
+
unverifiedRequirements: coverage.unverifiedRequirements,
|
|
3429
|
+
unimplementedRequirements: coverage.unimplementedRequirements,
|
|
3430
|
+
orphanRequirements: coverage.orphanRequirements
|
|
3431
|
+
} : null,
|
|
3432
|
+
diagnostics
|
|
3433
|
+
};
|
|
3434
|
+
if (args.json) {
|
|
3435
|
+
process.stdout.write(`${JSON.stringify(report, null, 2)}
|
|
3436
|
+
`);
|
|
3437
|
+
} else {
|
|
3438
|
+
if (diagnostics.length > 0) printDiagnostics(diagnostics);
|
|
3439
|
+
process.stdout.write(
|
|
3440
|
+
`${verdict === "pass" ? "\u2713" : "\u2717"} check ${verdict} (${args.strictness}) \u2014 ${path}
|
|
3441
|
+
`
|
|
3442
|
+
);
|
|
3443
|
+
}
|
|
3444
|
+
if (validationFailed) return EXIT.VALIDATION;
|
|
3445
|
+
if (driftFailed || coverageFailed) return EXIT.CHECK;
|
|
3446
|
+
return EXIT.OK;
|
|
3447
|
+
}
|
|
3448
|
+
|
|
3449
|
+
// ../schema/dist/index.js
|
|
3450
|
+
var AGENTS_default = "# RQML Agent Guidelines\n\n## Strictness: `standard`\n\n| Level | Description |\n|-------|-------------|\n| `relaxed` | Prototyping. Spec is advisory. Quick iteration allowed. |\n| `standard` | Production default. Spec-first for features. Core traces. |\n| `strict` | Full traceability. All behavior specified. No ghost features. |\n| `certified` | Regulated/safety-critical. Audit-grade traces with metadata. |\n\n---\n\nThis project uses **RQML** as the single source of truth for system intent. Familiarize yourself with the documentation at https://rqml.org/docs/user-guide/\n\n**Specification file:** Specification lives in a single .rqml file in the root of the project - convention is `requirements.rqml`. Multiple .rqml files may be employed in multirepo projects, in such cases a .rqml spec applies to everything that is higher in the project tree, unless overridden by another .rqml file.\n\n**Schema file:**\nThe RQML XSD schema is at https://rqml.org/schema/rqml-2.1.0.xsd (insert correct version number). Make sure to adhere to the schema at all times and follow guidelines in schema comments. Use as much of the RQML tagset as is necessary to capture and describe high quality requirements.\n\n---\n\n## Core Principle: Spec-First Development\n\n```\n[Elicit] \u2192 [Specify] \u2192 [Implement] \u2192 [Verify] \u2192 [Trace]\n \u2191____________________\u2190______________________|\n```\n\nCode follows specification, not the reverse. If code and spec diverge, the spec is authoritative\u2014update the code or negotiate a spec change with the developer.\n\n---\n\n## Workflow\n\n### 1. Elicit\nAsk clarifying questions until you understand the goal, scope, acceptance criteria, and constraints. Don't assume\u2014capture assumptions as `<notes>` or `<issue>` elements.\n\n### 2. Specify\n**Never implement unspecified behavior.** Update the `.rqml` file before coding:\n- Add a `<req>` with statement and acceptance criteria\n- Set appropriate `type`, `priority`, and `status=\"draft\"`\n- Get developer confirmation before proceeding\n\n### 3. Implement\nReference requirement IDs in code comments. If you discover missing requirements, stop and add them to the spec first.\n\n### 4. Verify\nAdd tests that reference requirement IDs. Update `<trace>` section with verification links.\n\n---\n\n## When Code and Spec Diverge\n\n1. **Spec gap** (code has behavior not in spec): Propose adding the requirement, mark as `status=\"review\"`\n2. **Code bug** (code doesn't match spec): Fix the code\n3. **Spec bug** (spec is wrong): Propose correction, wait for developer confirmation\n\n**Never silently change the spec to match code.**\n\n---\n\n## Strictness Reference\n\n| Aspect | relaxed | standard | strict | certified |\n|--------|---------|----------|--------|-----------|\n| Elicitation | Major features | Testable reqs | Edge cases | Formal |\n| Spec-first | Recommended | Required | Required | Approved first |\n| Code traces | Optional | New features | All changes | With metadata |\n| Test traces | Optional | New reqs | All reqs | Full matrix |\n| Ghost features | Allowed | Blocked | Blocked | Blocked |\n\n---\n\n## Change Summary Template\n\nFor PRs and commits:\n\n```\n## RQML Trace Summary\n\n**Requirements:** REQ-xxx (added/modified/implemented)\n**Implementation:** `path/to/file` \u2014 what changed\n**Verification:** `path/to/test` \u2014 what it verifies\n**Open items:** gaps, assumptions, follow-ups\n```\n\n---\n\n## Schema Validation\n\nThe `.rqml` file must remain valid XML conforming to the version of RQML referenced in the version attribute in the spec document.\n\n**To validate:** Try xmllint first (pre-installed on macOS/Linux):\n```bash\nxmllint --schema https://rqml.org/schema/rqml-2.1.0.xsd <rqml-file-name> --noout\n```\n\nIf xmllint is unavailable, use Python with lxml:\n```bash\npip install lxml\npython -c \"from lxml import etree; s=etree.XMLSchema(etree.parse('https://rqml.org/schema/rqml-2.1.0.xsd')); print('Valid' if s.validate(etree.parse('<rqml-file-name>')) else s.error_log)\"\n```\n\n**IDE validation:** If the `.rqml` file includes `xsi:schemaLocation`, XML-aware editors (VS Code with XML extension, IntelliJ) validate automatically.\n\nThe schema comments contain detailed guidance on document structure, ID conventions, and requirement quality criteria.\n\n**If unsure:** Ask the developer before making structural changes to the spec.\n";
|
|
3451
|
+
var AGENTS_TEMPLATE = AGENTS_default;
|
|
3452
|
+
|
|
3453
|
+
// src/commands/init.ts
|
|
3454
|
+
var STARTER_SPEC = `<?xml version="1.0" encoding="UTF-8"?>
|
|
3455
|
+
<rqml xmlns="https://rqml.org/schema/2.1.0" version="2.1.0" docId="PROJECT-001" status="draft">
|
|
3456
|
+
<meta>
|
|
3457
|
+
<title>My Project</title>
|
|
3458
|
+
<system>my-system</system>
|
|
3459
|
+
</meta>
|
|
3460
|
+
<requirements>
|
|
3461
|
+
<req id="REQ-EXAMPLE" type="FR" title="Example requirement" priority="must" status="draft">
|
|
3462
|
+
<statement>The system SHALL do something useful.</statement>
|
|
3463
|
+
</req>
|
|
3464
|
+
</requirements>
|
|
3465
|
+
</rqml>
|
|
3466
|
+
`;
|
|
3467
|
+
async function runInit(rest) {
|
|
3468
|
+
const args = parseArgs(rest);
|
|
3469
|
+
const specPath = resolve(args.baseDir, args.positionals[0] ?? "requirements.rqml");
|
|
3470
|
+
const agentsPath = resolve(args.baseDir, "AGENTS.md");
|
|
3471
|
+
let wrote = false;
|
|
3472
|
+
if (existsSync(specPath)) {
|
|
3473
|
+
process.stdout.write(`skip (exists) ${specPath}
|
|
3474
|
+
`);
|
|
3475
|
+
} else {
|
|
3476
|
+
writeFileSync(specPath, STARTER_SPEC);
|
|
3477
|
+
process.stdout.write(`created ${specPath}
|
|
3478
|
+
`);
|
|
3479
|
+
wrote = true;
|
|
3480
|
+
}
|
|
3481
|
+
if (existsSync(agentsPath)) {
|
|
3482
|
+
process.stdout.write(`skip (exists) ${agentsPath}
|
|
3483
|
+
`);
|
|
3484
|
+
} else {
|
|
3485
|
+
writeFileSync(agentsPath, AGENTS_TEMPLATE);
|
|
3486
|
+
process.stdout.write(`created ${agentsPath}
|
|
3487
|
+
`);
|
|
3488
|
+
wrote = true;
|
|
3489
|
+
}
|
|
3490
|
+
if (!wrote) process.stdout.write("nothing to do; project already initialized\n");
|
|
3491
|
+
return EXIT.OK;
|
|
3492
|
+
}
|
|
3493
|
+
|
|
3494
|
+
// src/commands/status.ts
|
|
3495
|
+
async function runStatus(rest) {
|
|
3496
|
+
const args = parseArgs(rest);
|
|
3497
|
+
const { path, xml } = readSpec(args);
|
|
3498
|
+
const parsed = parse(xml);
|
|
3499
|
+
if (!parsed.ok) {
|
|
3500
|
+
process.stderr.write(`\u2717 ${path}: ${parsed.error.message}
|
|
3501
|
+
`);
|
|
3502
|
+
return EXIT.VALIDATION;
|
|
3503
|
+
}
|
|
3504
|
+
const doc = parsed.document;
|
|
3505
|
+
const coverage = computeCoverage(doc);
|
|
3506
|
+
const lintDiags = lint(doc);
|
|
3507
|
+
const trace = resolveTrace(doc);
|
|
3508
|
+
const reqCount = doc.packages.reduce((n, p) => n + p.requirements.length, 0) + doc.looseRequirements.length;
|
|
3509
|
+
const summary = {
|
|
3510
|
+
path,
|
|
3511
|
+
docId: doc.docId,
|
|
3512
|
+
version: doc.version,
|
|
3513
|
+
status: doc.status,
|
|
3514
|
+
requirements: reqCount,
|
|
3515
|
+
edges: doc.trace.length,
|
|
3516
|
+
uncoveredGoals: coverage.uncoveredGoals,
|
|
3517
|
+
unverifiedRequirements: coverage.unverifiedRequirements,
|
|
3518
|
+
unimplementedRequirements: coverage.unimplementedRequirements,
|
|
3519
|
+
orphanRequirements: coverage.orphanRequirements,
|
|
3520
|
+
danglingReferences: trace.diagnostics.length,
|
|
3521
|
+
lintFindings: lintDiags.length
|
|
3522
|
+
};
|
|
3523
|
+
if (args.json) {
|
|
3524
|
+
process.stdout.write(`${JSON.stringify(summary, null, 2)}
|
|
3525
|
+
`);
|
|
3526
|
+
} else {
|
|
3527
|
+
process.stdout.write(
|
|
3528
|
+
`RQML status \u2014 ${doc.docId} (${doc.version}, ${doc.status})
|
|
3529
|
+
spec: ${path}
|
|
3530
|
+
requirements: ${reqCount} trace edges: ${doc.trace.length}
|
|
3531
|
+
uncovered goals: ${coverage.uncoveredGoals.length}
|
|
3532
|
+
unverified reqs: ${coverage.unverifiedRequirements.length}
|
|
3533
|
+
unimplemented reqs: ${coverage.unimplementedRequirements.length}
|
|
3534
|
+
dangling refs: ${trace.diagnostics.length} lint findings: ${lintDiags.length}
|
|
3535
|
+
`
|
|
3536
|
+
);
|
|
3537
|
+
}
|
|
3538
|
+
return EXIT.OK;
|
|
3539
|
+
}
|
|
3540
|
+
|
|
3541
|
+
// src/commands/validate.ts
|
|
3542
|
+
async function runValidate(rest) {
|
|
3543
|
+
const args = parseArgs(rest);
|
|
3544
|
+
const { path, xml } = readSpec(args);
|
|
3545
|
+
const { validate } = await import('./validate-O3LLP44J.js');
|
|
3546
|
+
const result = validate(xml);
|
|
3547
|
+
const integrity = result.valid ? checkIntegrity(xml) : [];
|
|
3548
|
+
const diagnostics = [...result.diagnostics, ...integrity];
|
|
3549
|
+
const ok = result.valid && integrity.length === 0;
|
|
3550
|
+
if (args.json) {
|
|
3551
|
+
process.stdout.write(
|
|
3552
|
+
`${JSON.stringify({ path, valid: ok, schemaVersion: result.schemaVersion, diagnostics }, null, 2)}
|
|
3553
|
+
`
|
|
3554
|
+
);
|
|
3555
|
+
} else {
|
|
3556
|
+
if (diagnostics.length > 0) printDiagnostics(diagnostics);
|
|
3557
|
+
process.stdout.write(
|
|
3558
|
+
ok ? `\u2713 ${path} is valid (schema ${result.schemaVersion})
|
|
3559
|
+
` : `\u2717 ${path}: ${diagnostics.length} problem(s)
|
|
3560
|
+
`
|
|
3561
|
+
);
|
|
3562
|
+
}
|
|
3563
|
+
return ok ? EXIT.OK : EXIT.VALIDATION;
|
|
3564
|
+
}
|
|
3565
|
+
|
|
3566
|
+
// src/index.ts
|
|
3567
|
+
var VERSION = "0.1.0";
|
|
3568
|
+
var HELP = `rqml \u2014 RQML reference CLI (v${VERSION})
|
|
3569
|
+
|
|
3570
|
+
Usage:
|
|
3571
|
+
rqml <command> [spec.rqml] [options]
|
|
3572
|
+
|
|
3573
|
+
Commands:
|
|
3574
|
+
init [path] Scaffold a starter spec and AGENTS.md project marker
|
|
3575
|
+
validate [path] Validate XML well-formedness, XSD, and referential integrity
|
|
3576
|
+
status [path] Show spec, coverage, and lint summary
|
|
3577
|
+
check [path] Deterministic enforcement gate (validation + coverage + drift)
|
|
3578
|
+
|
|
3579
|
+
Options:
|
|
3580
|
+
--json Emit machine-readable JSON (status, check, validate)
|
|
3581
|
+
--strictness <level> relaxed | standard | strict | certified (default: standard)
|
|
3582
|
+
--base-dir <dir> Directory to resolve the spec and code links against
|
|
3583
|
+
-h, --help Show this help
|
|
3584
|
+
-v, --version Show version
|
|
3585
|
+
|
|
3586
|
+
Exit codes: 0 ok \xB7 1 validation failure \xB7 2 check (drift/coverage) failure \xB7 64 usage
|
|
3587
|
+
`;
|
|
3588
|
+
async function main(argv) {
|
|
3589
|
+
const [cmd, ...rest] = argv;
|
|
3590
|
+
switch (cmd) {
|
|
3591
|
+
case "validate":
|
|
3592
|
+
return runValidate(rest);
|
|
3593
|
+
case "status":
|
|
3594
|
+
return runStatus(rest);
|
|
3595
|
+
case "check":
|
|
3596
|
+
return runCheck(rest);
|
|
3597
|
+
case "init":
|
|
3598
|
+
return runInit(rest);
|
|
3599
|
+
case "-v":
|
|
3600
|
+
case "--version":
|
|
3601
|
+
process.stdout.write(`${VERSION}
|
|
3602
|
+
`);
|
|
3603
|
+
return EXIT.OK;
|
|
3604
|
+
case void 0:
|
|
3605
|
+
case "-h":
|
|
3606
|
+
case "--help":
|
|
3607
|
+
process.stdout.write(HELP);
|
|
3608
|
+
return EXIT.OK;
|
|
3609
|
+
default:
|
|
3610
|
+
process.stderr.write(`rqml: unknown command "${cmd}"
|
|
3611
|
+
|
|
3612
|
+
${HELP}`);
|
|
3613
|
+
return EXIT.USAGE;
|
|
3614
|
+
}
|
|
3615
|
+
}
|
|
3616
|
+
main(process.argv.slice(2)).then((code) => {
|
|
3617
|
+
process.exitCode = code;
|
|
3618
|
+
}).catch((err) => {
|
|
3619
|
+
const isUsage = err instanceof UsageError;
|
|
3620
|
+
process.stderr.write(`rqml: ${err instanceof Error ? err.message : String(err)}
|
|
3621
|
+
`);
|
|
3622
|
+
process.exitCode = isUsage ? EXIT.USAGE : EXIT.VALIDATION;
|
|
3623
|
+
});
|
|
3624
|
+
//# sourceMappingURL=index.js.map
|
|
3625
|
+
//# sourceMappingURL=index.js.map
|