yaml 2.8.4 → 3.0.0-1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -85
- package/{bin.mjs → bin.js} +1 -1
- package/dist/chunk-pbuEa-1d.js +13 -0
- package/dist/cli.d.ts +10 -7
- package/dist/cli.js +180 -0
- package/dist/directives-CiM56lHW.js +2963 -0
- package/dist/directives-DlYEVlkC.d.ts +1396 -0
- package/dist/index.d.ts +320 -25
- package/dist/index.js +4 -50
- package/dist/line-counter-bmCJ4fGy.js +3086 -0
- package/dist/public-api-BTMehGT6.js +77 -0
- package/dist/test-events.d.ts +6 -3
- package/dist/test-events.js +105 -126
- package/dist/util.d.ts +2 -16
- package/dist/util.js +2 -28
- package/package.json +20 -44
- package/browser/dist/compose/compose-collection.js +0 -88
- package/browser/dist/compose/compose-doc.js +0 -43
- package/browser/dist/compose/compose-node.js +0 -109
- package/browser/dist/compose/compose-scalar.js +0 -86
- package/browser/dist/compose/composer.js +0 -217
- package/browser/dist/compose/resolve-block-map.js +0 -115
- package/browser/dist/compose/resolve-block-scalar.js +0 -198
- package/browser/dist/compose/resolve-block-seq.js +0 -49
- package/browser/dist/compose/resolve-end.js +0 -37
- package/browser/dist/compose/resolve-flow-collection.js +0 -207
- package/browser/dist/compose/resolve-flow-scalar.js +0 -225
- package/browser/dist/compose/resolve-props.js +0 -146
- package/browser/dist/compose/util-contains-newline.js +0 -34
- package/browser/dist/compose/util-empty-scalar-position.js +0 -26
- package/browser/dist/compose/util-flow-indent-check.js +0 -15
- package/browser/dist/compose/util-map-includes.js +0 -13
- package/browser/dist/doc/Document.js +0 -335
- package/browser/dist/doc/anchors.js +0 -71
- package/browser/dist/doc/applyReviver.js +0 -55
- package/browser/dist/doc/createNode.js +0 -88
- package/browser/dist/doc/directives.js +0 -176
- package/browser/dist/errors.js +0 -57
- package/browser/dist/index.js +0 -17
- package/browser/dist/log.js +0 -11
- package/browser/dist/nodes/Alias.js +0 -116
- package/browser/dist/nodes/Collection.js +0 -147
- package/browser/dist/nodes/Node.js +0 -38
- package/browser/dist/nodes/Pair.js +0 -36
- package/browser/dist/nodes/Scalar.js +0 -24
- package/browser/dist/nodes/YAMLMap.js +0 -144
- package/browser/dist/nodes/YAMLSeq.js +0 -113
- package/browser/dist/nodes/addPairToJSMap.js +0 -63
- package/browser/dist/nodes/identity.js +0 -36
- package/browser/dist/nodes/toJS.js +0 -37
- package/browser/dist/parse/cst-scalar.js +0 -214
- package/browser/dist/parse/cst-stringify.js +0 -61
- package/browser/dist/parse/cst-visit.js +0 -97
- package/browser/dist/parse/cst.js +0 -98
- package/browser/dist/parse/lexer.js +0 -717
- package/browser/dist/parse/line-counter.js +0 -39
- package/browser/dist/parse/parser.js +0 -967
- package/browser/dist/public-api.js +0 -102
- package/browser/dist/schema/Schema.js +0 -37
- package/browser/dist/schema/common/map.js +0 -17
- package/browser/dist/schema/common/null.js +0 -15
- package/browser/dist/schema/common/seq.js +0 -17
- package/browser/dist/schema/common/string.js +0 -14
- package/browser/dist/schema/core/bool.js +0 -19
- package/browser/dist/schema/core/float.js +0 -43
- package/browser/dist/schema/core/int.js +0 -38
- package/browser/dist/schema/core/schema.js +0 -23
- package/browser/dist/schema/json/schema.js +0 -62
- package/browser/dist/schema/tags.js +0 -96
- package/browser/dist/schema/yaml-1.1/binary.js +0 -58
- package/browser/dist/schema/yaml-1.1/bool.js +0 -26
- package/browser/dist/schema/yaml-1.1/float.js +0 -46
- package/browser/dist/schema/yaml-1.1/int.js +0 -71
- package/browser/dist/schema/yaml-1.1/merge.js +0 -67
- package/browser/dist/schema/yaml-1.1/omap.js +0 -74
- package/browser/dist/schema/yaml-1.1/pairs.js +0 -78
- package/browser/dist/schema/yaml-1.1/schema.js +0 -39
- package/browser/dist/schema/yaml-1.1/set.js +0 -93
- package/browser/dist/schema/yaml-1.1/timestamp.js +0 -101
- package/browser/dist/stringify/foldFlowLines.js +0 -146
- package/browser/dist/stringify/stringify.js +0 -129
- package/browser/dist/stringify/stringifyCollection.js +0 -153
- package/browser/dist/stringify/stringifyComment.js +0 -20
- package/browser/dist/stringify/stringifyDocument.js +0 -85
- package/browser/dist/stringify/stringifyNumber.js +0 -25
- package/browser/dist/stringify/stringifyPair.js +0 -150
- package/browser/dist/stringify/stringifyString.js +0 -336
- package/browser/dist/util.js +0 -11
- package/browser/dist/visit.js +0 -233
- package/browser/index.js +0 -5
- package/browser/package.json +0 -3
- package/dist/cli.mjs +0 -201
- package/dist/compose/compose-collection.d.ts +0 -11
- package/dist/compose/compose-collection.js +0 -90
- package/dist/compose/compose-doc.d.ts +0 -7
- package/dist/compose/compose-doc.js +0 -45
- package/dist/compose/compose-node.d.ts +0 -29
- package/dist/compose/compose-node.js +0 -112
- package/dist/compose/compose-scalar.d.ts +0 -5
- package/dist/compose/compose-scalar.js +0 -88
- package/dist/compose/composer.d.ts +0 -63
- package/dist/compose/composer.js +0 -222
- package/dist/compose/resolve-block-map.d.ts +0 -6
- package/dist/compose/resolve-block-map.js +0 -117
- package/dist/compose/resolve-block-scalar.d.ts +0 -11
- package/dist/compose/resolve-block-scalar.js +0 -200
- package/dist/compose/resolve-block-seq.d.ts +0 -6
- package/dist/compose/resolve-block-seq.js +0 -51
- package/dist/compose/resolve-end.d.ts +0 -6
- package/dist/compose/resolve-end.js +0 -39
- package/dist/compose/resolve-flow-collection.d.ts +0 -7
- package/dist/compose/resolve-flow-collection.js +0 -209
- package/dist/compose/resolve-flow-scalar.d.ts +0 -10
- package/dist/compose/resolve-flow-scalar.js +0 -227
- package/dist/compose/resolve-props.d.ts +0 -23
- package/dist/compose/resolve-props.js +0 -148
- package/dist/compose/util-contains-newline.d.ts +0 -2
- package/dist/compose/util-contains-newline.js +0 -36
- package/dist/compose/util-empty-scalar-position.d.ts +0 -2
- package/dist/compose/util-empty-scalar-position.js +0 -28
- package/dist/compose/util-flow-indent-check.d.ts +0 -3
- package/dist/compose/util-flow-indent-check.js +0 -17
- package/dist/compose/util-map-includes.d.ts +0 -4
- package/dist/compose/util-map-includes.js +0 -15
- package/dist/doc/Document.d.ts +0 -141
- package/dist/doc/Document.js +0 -337
- package/dist/doc/anchors.d.ts +0 -24
- package/dist/doc/anchors.js +0 -76
- package/dist/doc/applyReviver.d.ts +0 -9
- package/dist/doc/applyReviver.js +0 -57
- package/dist/doc/createNode.d.ts +0 -17
- package/dist/doc/createNode.js +0 -90
- package/dist/doc/directives.d.ts +0 -49
- package/dist/doc/directives.js +0 -178
- package/dist/errors.d.ts +0 -21
- package/dist/errors.js +0 -62
- package/dist/log.d.ts +0 -3
- package/dist/log.js +0 -19
- package/dist/nodes/Alias.d.ts +0 -29
- package/dist/nodes/Alias.js +0 -118
- package/dist/nodes/Collection.d.ts +0 -73
- package/dist/nodes/Collection.js +0 -151
- package/dist/nodes/Node.d.ts +0 -53
- package/dist/nodes/Node.js +0 -40
- package/dist/nodes/Pair.d.ts +0 -22
- package/dist/nodes/Pair.js +0 -39
- package/dist/nodes/Scalar.d.ts +0 -47
- package/dist/nodes/Scalar.js +0 -27
- package/dist/nodes/YAMLMap.d.ts +0 -53
- package/dist/nodes/YAMLMap.js +0 -147
- package/dist/nodes/YAMLSeq.d.ts +0 -60
- package/dist/nodes/YAMLSeq.js +0 -115
- package/dist/nodes/addPairToJSMap.d.ts +0 -4
- package/dist/nodes/addPairToJSMap.js +0 -65
- package/dist/nodes/identity.d.ts +0 -23
- package/dist/nodes/identity.js +0 -53
- package/dist/nodes/toJS.d.ts +0 -29
- package/dist/nodes/toJS.js +0 -39
- package/dist/options.d.ts +0 -350
- package/dist/parse/cst-scalar.d.ts +0 -64
- package/dist/parse/cst-scalar.js +0 -218
- package/dist/parse/cst-stringify.d.ts +0 -8
- package/dist/parse/cst-stringify.js +0 -63
- package/dist/parse/cst-visit.d.ts +0 -39
- package/dist/parse/cst-visit.js +0 -99
- package/dist/parse/cst.d.ts +0 -109
- package/dist/parse/cst.js +0 -112
- package/dist/parse/lexer.d.ts +0 -87
- package/dist/parse/lexer.js +0 -719
- package/dist/parse/line-counter.d.ts +0 -22
- package/dist/parse/line-counter.js +0 -41
- package/dist/parse/parser.d.ts +0 -84
- package/dist/parse/parser.js +0 -972
- package/dist/public-api.d.ts +0 -44
- package/dist/public-api.js +0 -107
- package/dist/schema/Schema.d.ts +0 -17
- package/dist/schema/Schema.js +0 -39
- package/dist/schema/common/map.d.ts +0 -2
- package/dist/schema/common/map.js +0 -19
- package/dist/schema/common/null.d.ts +0 -4
- package/dist/schema/common/null.js +0 -17
- package/dist/schema/common/seq.d.ts +0 -2
- package/dist/schema/common/seq.js +0 -19
- package/dist/schema/common/string.d.ts +0 -2
- package/dist/schema/common/string.js +0 -16
- package/dist/schema/core/bool.d.ts +0 -4
- package/dist/schema/core/bool.js +0 -21
- package/dist/schema/core/float.d.ts +0 -4
- package/dist/schema/core/float.js +0 -47
- package/dist/schema/core/int.d.ts +0 -4
- package/dist/schema/core/int.js +0 -42
- package/dist/schema/core/schema.d.ts +0 -1
- package/dist/schema/core/schema.js +0 -25
- package/dist/schema/json/schema.d.ts +0 -2
- package/dist/schema/json/schema.js +0 -64
- package/dist/schema/json-schema.d.ts +0 -69
- package/dist/schema/tags.d.ts +0 -48
- package/dist/schema/tags.js +0 -99
- package/dist/schema/types.d.ts +0 -92
- package/dist/schema/yaml-1.1/binary.d.ts +0 -2
- package/dist/schema/yaml-1.1/binary.js +0 -70
- package/dist/schema/yaml-1.1/bool.d.ts +0 -7
- package/dist/schema/yaml-1.1/bool.js +0 -29
- package/dist/schema/yaml-1.1/float.d.ts +0 -4
- package/dist/schema/yaml-1.1/float.js +0 -50
- package/dist/schema/yaml-1.1/int.d.ts +0 -5
- package/dist/schema/yaml-1.1/int.js +0 -76
- package/dist/schema/yaml-1.1/merge.d.ts +0 -9
- package/dist/schema/yaml-1.1/merge.js +0 -71
- package/dist/schema/yaml-1.1/omap.d.ts +0 -22
- package/dist/schema/yaml-1.1/omap.js +0 -77
- package/dist/schema/yaml-1.1/pairs.d.ts +0 -10
- package/dist/schema/yaml-1.1/pairs.js +0 -82
- package/dist/schema/yaml-1.1/schema.d.ts +0 -1
- package/dist/schema/yaml-1.1/schema.js +0 -41
- package/dist/schema/yaml-1.1/set.d.ts +0 -28
- package/dist/schema/yaml-1.1/set.js +0 -96
- package/dist/schema/yaml-1.1/timestamp.d.ts +0 -6
- package/dist/schema/yaml-1.1/timestamp.js +0 -105
- package/dist/stringify/foldFlowLines.d.ts +0 -34
- package/dist/stringify/foldFlowLines.js +0 -151
- package/dist/stringify/stringify.d.ts +0 -21
- package/dist/stringify/stringify.js +0 -132
- package/dist/stringify/stringifyCollection.d.ts +0 -17
- package/dist/stringify/stringifyCollection.js +0 -155
- package/dist/stringify/stringifyComment.d.ts +0 -10
- package/dist/stringify/stringifyComment.js +0 -24
- package/dist/stringify/stringifyDocument.d.ts +0 -4
- package/dist/stringify/stringifyDocument.js +0 -87
- package/dist/stringify/stringifyNumber.d.ts +0 -2
- package/dist/stringify/stringifyNumber.js +0 -27
- package/dist/stringify/stringifyPair.d.ts +0 -3
- package/dist/stringify/stringifyPair.js +0 -152
- package/dist/stringify/stringifyString.d.ts +0 -9
- package/dist/stringify/stringifyString.js +0 -338
- package/dist/visit.d.ts +0 -102
- package/dist/visit.js +0 -236
- package/util.js +0 -2
|
@@ -0,0 +1,2963 @@
|
|
|
1
|
+
//#region src/nodes/Scalar.ts
|
|
2
|
+
var Scalar = class {
|
|
3
|
+
static BLOCK_FOLDED = "BLOCK_FOLDED";
|
|
4
|
+
static BLOCK_LITERAL = "BLOCK_LITERAL";
|
|
5
|
+
static PLAIN = "PLAIN";
|
|
6
|
+
static QUOTE_DOUBLE = "QUOTE_DOUBLE";
|
|
7
|
+
static QUOTE_SINGLE = "QUOTE_SINGLE";
|
|
8
|
+
value;
|
|
9
|
+
constructor(value) {
|
|
10
|
+
this.value = value;
|
|
11
|
+
}
|
|
12
|
+
/** Create a copy of this node. */
|
|
13
|
+
clone() {
|
|
14
|
+
const copy = Object.create(Object.getPrototypeOf(this), Object.getOwnPropertyDescriptors(this));
|
|
15
|
+
if (this.range) copy.range = [...this.range];
|
|
16
|
+
return copy;
|
|
17
|
+
}
|
|
18
|
+
/** A plain JavaScript representation of this node. */
|
|
19
|
+
toJS(_doc, ctx) {
|
|
20
|
+
if (ctx && this.anchor) ctx.anchors.set(this, {
|
|
21
|
+
aliasCount: 0,
|
|
22
|
+
count: 1,
|
|
23
|
+
res: this.value
|
|
24
|
+
});
|
|
25
|
+
return this.value;
|
|
26
|
+
}
|
|
27
|
+
toString() {
|
|
28
|
+
return String(this.value);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
//#endregion
|
|
32
|
+
//#region src/stringify/foldFlowLines.ts
|
|
33
|
+
const FOLD_FLOW = "flow";
|
|
34
|
+
const FOLD_BLOCK = "block";
|
|
35
|
+
const FOLD_QUOTED = "quoted";
|
|
36
|
+
/**
|
|
37
|
+
* Tries to keep input at up to `lineWidth` characters, splitting only on spaces
|
|
38
|
+
* not followed by newlines or spaces unless `mode` is `'quoted'`. Lines are
|
|
39
|
+
* terminated with `\n` and started with `indent`.
|
|
40
|
+
*/
|
|
41
|
+
function foldFlowLines(text, indent, mode = "flow", { indentAtStart, lineWidth = 80, minContentWidth = 20, onFold, onOverflow } = {}) {
|
|
42
|
+
if (!lineWidth || lineWidth < 0) return text;
|
|
43
|
+
if (lineWidth < minContentWidth) minContentWidth = 0;
|
|
44
|
+
const endStep = Math.max(1 + minContentWidth, 1 + lineWidth - indent.length);
|
|
45
|
+
if (text.length <= endStep) return text;
|
|
46
|
+
const folds = [];
|
|
47
|
+
const escapedFolds = {};
|
|
48
|
+
let end = lineWidth - indent.length;
|
|
49
|
+
if (typeof indentAtStart === "number") if (indentAtStart > lineWidth - Math.max(2, minContentWidth)) folds.push(0);
|
|
50
|
+
else end = lineWidth - indentAtStart;
|
|
51
|
+
let split = void 0;
|
|
52
|
+
let prev = void 0;
|
|
53
|
+
let overflow = false;
|
|
54
|
+
let i = -1;
|
|
55
|
+
let escStart = -1;
|
|
56
|
+
let escEnd = -1;
|
|
57
|
+
if (mode === "block") {
|
|
58
|
+
i = consumeMoreIndentedLines(text, i, indent.length);
|
|
59
|
+
if (i !== -1) end = i + endStep;
|
|
60
|
+
}
|
|
61
|
+
for (let ch; ch = text[i += 1];) {
|
|
62
|
+
if (mode === "quoted" && ch === "\\") {
|
|
63
|
+
escStart = i;
|
|
64
|
+
switch (text[i + 1]) {
|
|
65
|
+
case "x":
|
|
66
|
+
i += 3;
|
|
67
|
+
break;
|
|
68
|
+
case "u":
|
|
69
|
+
i += 5;
|
|
70
|
+
break;
|
|
71
|
+
case "U":
|
|
72
|
+
i += 9;
|
|
73
|
+
break;
|
|
74
|
+
default: i += 1;
|
|
75
|
+
}
|
|
76
|
+
escEnd = i;
|
|
77
|
+
}
|
|
78
|
+
if (ch === "\n") {
|
|
79
|
+
if (mode === "block") i = consumeMoreIndentedLines(text, i, indent.length);
|
|
80
|
+
end = i + indent.length + endStep;
|
|
81
|
+
split = void 0;
|
|
82
|
+
} else {
|
|
83
|
+
if (ch === " " && prev && prev !== " " && prev !== "\n" && prev !== " ") {
|
|
84
|
+
const next = text[i + 1];
|
|
85
|
+
if (next && next !== " " && next !== "\n" && next !== " ") split = i;
|
|
86
|
+
}
|
|
87
|
+
if (i >= end) if (split) {
|
|
88
|
+
folds.push(split);
|
|
89
|
+
end = split + endStep;
|
|
90
|
+
split = void 0;
|
|
91
|
+
} else if (mode === "quoted") {
|
|
92
|
+
while (prev === " " || prev === " ") {
|
|
93
|
+
prev = ch;
|
|
94
|
+
ch = text[i += 1];
|
|
95
|
+
overflow = true;
|
|
96
|
+
}
|
|
97
|
+
const j = i > escEnd + 1 ? i - 2 : escStart - 1;
|
|
98
|
+
if (escapedFolds[j]) return text;
|
|
99
|
+
folds.push(j);
|
|
100
|
+
escapedFolds[j] = true;
|
|
101
|
+
end = j + endStep;
|
|
102
|
+
split = void 0;
|
|
103
|
+
} else overflow = true;
|
|
104
|
+
}
|
|
105
|
+
prev = ch;
|
|
106
|
+
}
|
|
107
|
+
if (overflow && onOverflow) onOverflow();
|
|
108
|
+
if (folds.length === 0) return text;
|
|
109
|
+
if (onFold) onFold();
|
|
110
|
+
let res = text.slice(0, folds[0]);
|
|
111
|
+
for (let i = 0; i < folds.length; ++i) {
|
|
112
|
+
const fold = folds[i];
|
|
113
|
+
const end = folds[i + 1] || text.length;
|
|
114
|
+
if (fold === 0) res = `\n${indent}${text.slice(0, end)}`;
|
|
115
|
+
else {
|
|
116
|
+
if (mode === "quoted" && escapedFolds[fold]) res += `${text[fold]}\\`;
|
|
117
|
+
res += `\n${indent}${text.slice(fold + 1, end)}`;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return res;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Presumes `i + 1` is at the start of a line
|
|
124
|
+
* @returns index of last newline in more-indented block
|
|
125
|
+
*/
|
|
126
|
+
function consumeMoreIndentedLines(text, i, indent) {
|
|
127
|
+
let end = i;
|
|
128
|
+
let start = i + 1;
|
|
129
|
+
let ch = text[start];
|
|
130
|
+
while (ch === " " || ch === " ") if (i < start + indent) ch = text[++i];
|
|
131
|
+
else {
|
|
132
|
+
do
|
|
133
|
+
ch = text[++i];
|
|
134
|
+
while (ch && ch !== "\n");
|
|
135
|
+
end = i;
|
|
136
|
+
start = i + 1;
|
|
137
|
+
ch = text[start];
|
|
138
|
+
}
|
|
139
|
+
return end;
|
|
140
|
+
}
|
|
141
|
+
//#endregion
|
|
142
|
+
//#region src/stringify/stringifyString.ts
|
|
143
|
+
const getFoldOptions = (ctx, isBlock) => ({
|
|
144
|
+
indentAtStart: isBlock ? ctx.indent.length : ctx.indentAtStart,
|
|
145
|
+
lineWidth: ctx.options.lineWidth,
|
|
146
|
+
minContentWidth: ctx.options.minContentWidth
|
|
147
|
+
});
|
|
148
|
+
const containsDocumentMarker = (str) => /^(%|---|\.\.\.)/m.test(str);
|
|
149
|
+
function lineLengthOverLimit(str, lineWidth, indentLength) {
|
|
150
|
+
if (!lineWidth || lineWidth < 0) return false;
|
|
151
|
+
const limit = lineWidth - indentLength;
|
|
152
|
+
const strLen = str.length;
|
|
153
|
+
if (strLen <= limit) return false;
|
|
154
|
+
for (let i = 0, start = 0; i < strLen; ++i) if (str[i] === "\n") {
|
|
155
|
+
if (i - start > limit) return true;
|
|
156
|
+
start = i + 1;
|
|
157
|
+
if (strLen - start <= limit) return false;
|
|
158
|
+
}
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
161
|
+
function doubleQuotedString(value, ctx) {
|
|
162
|
+
const json = JSON.stringify(value);
|
|
163
|
+
if (ctx.options.doubleQuotedAsJSON) return json;
|
|
164
|
+
const { implicitKey } = ctx;
|
|
165
|
+
const minMultiLineLength = ctx.options.doubleQuotedMinMultiLineLength;
|
|
166
|
+
const indent = ctx.indent || (containsDocumentMarker(value) ? " " : "");
|
|
167
|
+
let str = "";
|
|
168
|
+
let start = 0;
|
|
169
|
+
for (let i = 0, ch = json[i]; ch; ch = json[++i]) {
|
|
170
|
+
if (ch === " " && json[i + 1] === "\\" && json[i + 2] === "n") {
|
|
171
|
+
str += json.slice(start, i) + "\\ ";
|
|
172
|
+
i += 1;
|
|
173
|
+
start = i;
|
|
174
|
+
ch = "\\";
|
|
175
|
+
}
|
|
176
|
+
if (ch === "\\") switch (json[i + 1]) {
|
|
177
|
+
case "u":
|
|
178
|
+
{
|
|
179
|
+
str += json.slice(start, i);
|
|
180
|
+
const code = json.substr(i + 2, 4);
|
|
181
|
+
switch (code) {
|
|
182
|
+
case "0000":
|
|
183
|
+
str += "\\0";
|
|
184
|
+
break;
|
|
185
|
+
case "0007":
|
|
186
|
+
str += "\\a";
|
|
187
|
+
break;
|
|
188
|
+
case "000b":
|
|
189
|
+
str += "\\v";
|
|
190
|
+
break;
|
|
191
|
+
case "001b":
|
|
192
|
+
str += "\\e";
|
|
193
|
+
break;
|
|
194
|
+
case "0085":
|
|
195
|
+
str += "\\N";
|
|
196
|
+
break;
|
|
197
|
+
case "00a0":
|
|
198
|
+
str += "\\_";
|
|
199
|
+
break;
|
|
200
|
+
case "2028":
|
|
201
|
+
str += "\\L";
|
|
202
|
+
break;
|
|
203
|
+
case "2029":
|
|
204
|
+
str += "\\P";
|
|
205
|
+
break;
|
|
206
|
+
default: if (code.substr(0, 2) === "00") str += "\\x" + code.substr(2);
|
|
207
|
+
else str += json.substr(i, 6);
|
|
208
|
+
}
|
|
209
|
+
i += 5;
|
|
210
|
+
start = i + 1;
|
|
211
|
+
}
|
|
212
|
+
break;
|
|
213
|
+
case "n":
|
|
214
|
+
if (implicitKey || json[i + 2] === "\"" || json.length < minMultiLineLength) i += 1;
|
|
215
|
+
else {
|
|
216
|
+
str += json.slice(start, i) + "\n\n";
|
|
217
|
+
while (json[i + 2] === "\\" && json[i + 3] === "n" && json[i + 4] !== "\"") {
|
|
218
|
+
str += "\n";
|
|
219
|
+
i += 2;
|
|
220
|
+
}
|
|
221
|
+
str += indent;
|
|
222
|
+
if (json[i + 2] === " ") str += "\\";
|
|
223
|
+
i += 1;
|
|
224
|
+
start = i + 1;
|
|
225
|
+
}
|
|
226
|
+
break;
|
|
227
|
+
default: i += 1;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
str = start ? str + json.slice(start) : json;
|
|
231
|
+
return implicitKey ? str : foldFlowLines(str, indent, FOLD_QUOTED, getFoldOptions(ctx, false));
|
|
232
|
+
}
|
|
233
|
+
function singleQuotedString(value, ctx) {
|
|
234
|
+
if (ctx.options.singleQuote === false || ctx.implicitKey && value.includes("\n") || /[ \t]\n|\n[ \t]/.test(value)) return doubleQuotedString(value, ctx);
|
|
235
|
+
const indent = ctx.indent || (containsDocumentMarker(value) ? " " : "");
|
|
236
|
+
const res = "'" + value.replace(/'/g, "''").replace(/\n+/g, `$&\n${indent}`) + "'";
|
|
237
|
+
return ctx.implicitKey ? res : foldFlowLines(res, indent, FOLD_FLOW, getFoldOptions(ctx, false));
|
|
238
|
+
}
|
|
239
|
+
function quotedString(value, ctx) {
|
|
240
|
+
const { singleQuote } = ctx.options;
|
|
241
|
+
let qs;
|
|
242
|
+
if (singleQuote === false) qs = doubleQuotedString;
|
|
243
|
+
else {
|
|
244
|
+
const hasDouble = value.includes("\"");
|
|
245
|
+
const hasSingle = value.includes("'");
|
|
246
|
+
if (hasDouble && !hasSingle) qs = singleQuotedString;
|
|
247
|
+
else if (hasSingle && !hasDouble) qs = doubleQuotedString;
|
|
248
|
+
else qs = singleQuote ? singleQuotedString : doubleQuotedString;
|
|
249
|
+
}
|
|
250
|
+
return qs(value, ctx);
|
|
251
|
+
}
|
|
252
|
+
let blockEndNewlines;
|
|
253
|
+
try {
|
|
254
|
+
blockEndNewlines = /* @__PURE__ */ new RegExp("(^|(?<!\n))\n+(?!\n|$)", "g");
|
|
255
|
+
} catch {
|
|
256
|
+
blockEndNewlines = /\n+(?!\n|$)/g;
|
|
257
|
+
}
|
|
258
|
+
function blockString({ comment, type, value }, ctx, onComment, onChompKeep) {
|
|
259
|
+
const { blockQuote, commentString, lineWidth } = ctx.options;
|
|
260
|
+
if (!blockQuote || /\n[\t ]+$/.test(value)) return quotedString(value, ctx);
|
|
261
|
+
const indent = ctx.indent || (ctx.forceBlockIndent || containsDocumentMarker(value) ? " " : "");
|
|
262
|
+
const literal = blockQuote === "literal" ? true : blockQuote === "folded" || type === Scalar.BLOCK_FOLDED ? false : type === Scalar.BLOCK_LITERAL ? true : !lineLengthOverLimit(value, lineWidth, indent.length);
|
|
263
|
+
if (!value) return literal ? "|\n" : ">\n";
|
|
264
|
+
let chomp;
|
|
265
|
+
let endStart;
|
|
266
|
+
for (endStart = value.length; endStart > 0; --endStart) {
|
|
267
|
+
const ch = value[endStart - 1];
|
|
268
|
+
if (ch !== "\n" && ch !== " " && ch !== " ") break;
|
|
269
|
+
}
|
|
270
|
+
let end = value.substring(endStart);
|
|
271
|
+
const endNlPos = end.indexOf("\n");
|
|
272
|
+
if (endNlPos === -1) chomp = "-";
|
|
273
|
+
else if (value === end || endNlPos !== end.length - 1) {
|
|
274
|
+
chomp = "+";
|
|
275
|
+
if (onChompKeep) onChompKeep();
|
|
276
|
+
} else chomp = "";
|
|
277
|
+
if (end) {
|
|
278
|
+
value = value.slice(0, -end.length);
|
|
279
|
+
if (end[end.length - 1] === "\n") end = end.slice(0, -1);
|
|
280
|
+
end = end.replace(blockEndNewlines, `$&${indent}`);
|
|
281
|
+
}
|
|
282
|
+
let startWithSpace = false;
|
|
283
|
+
let startEnd;
|
|
284
|
+
let startNlPos = -1;
|
|
285
|
+
for (startEnd = 0; startEnd < value.length; ++startEnd) {
|
|
286
|
+
const ch = value[startEnd];
|
|
287
|
+
if (ch === " ") startWithSpace = true;
|
|
288
|
+
else if (ch === "\n") startNlPos = startEnd;
|
|
289
|
+
else break;
|
|
290
|
+
}
|
|
291
|
+
let start = value.substring(0, startNlPos < startEnd ? startNlPos + 1 : startEnd);
|
|
292
|
+
if (start) {
|
|
293
|
+
value = value.substring(start.length);
|
|
294
|
+
start = start.replace(/\n+/g, `$&${indent}`);
|
|
295
|
+
}
|
|
296
|
+
let header = (startWithSpace ? indent ? "2" : "1" : "") + chomp;
|
|
297
|
+
if (comment) {
|
|
298
|
+
header += " " + commentString(comment.replace(/ ?[\r\n]+/g, " "));
|
|
299
|
+
if (onComment) onComment();
|
|
300
|
+
}
|
|
301
|
+
if (!literal) {
|
|
302
|
+
const foldedValue = value.replace(/\n+/g, "\n$&").replace(/(?:^|\n)([\t ].*)(?:([\n\t ]*)\n(?![\n\t ]))?/g, "$1$2").replace(/\n+/g, `$&${indent}`);
|
|
303
|
+
let literalFallback = false;
|
|
304
|
+
const foldOptions = getFoldOptions(ctx, true);
|
|
305
|
+
if (blockQuote !== "folded" && type !== Scalar.BLOCK_FOLDED) foldOptions.onOverflow = () => {
|
|
306
|
+
literalFallback = true;
|
|
307
|
+
};
|
|
308
|
+
const body = foldFlowLines(`${start}${foldedValue}${end}`, indent, FOLD_BLOCK, foldOptions);
|
|
309
|
+
if (!literalFallback) return `>${header}\n${indent}${body}`;
|
|
310
|
+
}
|
|
311
|
+
value = value.replace(/\n+/g, `$&${indent}`);
|
|
312
|
+
return `|${header}\n${indent}${start}${value}${end}`;
|
|
313
|
+
}
|
|
314
|
+
function plainString(item, ctx, onComment, onChompKeep) {
|
|
315
|
+
const { type, value } = item;
|
|
316
|
+
const { actualString, implicitKey, indent, indentStep, inFlow } = ctx;
|
|
317
|
+
if (implicitKey && value.includes("\n") || inFlow && /[[\]{},]/.test(value)) return quotedString(value, ctx);
|
|
318
|
+
if (/^[\n\t ,[\]{}#&*!|>'"%@`]|^[?-]$|^[?-][ \t]|[\n:][ \t]|[ \t]\n|[\n\t ]#|[\n\t :]$/.test(value)) return implicitKey || inFlow || !value.includes("\n") ? quotedString(value, ctx) : blockString(item, ctx, onComment, onChompKeep);
|
|
319
|
+
if (!implicitKey && !inFlow && type !== Scalar.PLAIN && value.includes("\n")) return blockString(item, ctx, onComment, onChompKeep);
|
|
320
|
+
if (containsDocumentMarker(value)) {
|
|
321
|
+
if (indent === "") {
|
|
322
|
+
ctx.forceBlockIndent = true;
|
|
323
|
+
return blockString(item, ctx, onComment, onChompKeep);
|
|
324
|
+
} else if (implicitKey && indent === indentStep) return quotedString(value, ctx);
|
|
325
|
+
}
|
|
326
|
+
const str = value.replace(/\n+/g, `$&\n${indent}`);
|
|
327
|
+
if (actualString) {
|
|
328
|
+
const test = (tag) => tag.default && tag.tag !== "tag:yaml.org,2002:str" && tag.test?.test(str);
|
|
329
|
+
const { compat, tags } = ctx.doc.schema;
|
|
330
|
+
if (tags.some(test) || compat?.some(test)) return quotedString(value, ctx);
|
|
331
|
+
}
|
|
332
|
+
return implicitKey ? str : foldFlowLines(str, indent, FOLD_FLOW, getFoldOptions(ctx, false));
|
|
333
|
+
}
|
|
334
|
+
function stringifyString(item, ctx, onComment, onChompKeep) {
|
|
335
|
+
const { implicitKey, inFlow } = ctx;
|
|
336
|
+
const ss = typeof item.value === "string" ? item : Object.assign({}, item, { value: String(item.value) });
|
|
337
|
+
let { type } = item;
|
|
338
|
+
if (type !== Scalar.QUOTE_DOUBLE) {
|
|
339
|
+
if (/[\x00-\x08\x0b-\x1f\x7f-\x9f\u{D800}-\u{DFFF}]/u.test(ss.value)) type = Scalar.QUOTE_DOUBLE;
|
|
340
|
+
}
|
|
341
|
+
const _stringify = (_type) => {
|
|
342
|
+
switch (_type) {
|
|
343
|
+
case Scalar.BLOCK_FOLDED:
|
|
344
|
+
case Scalar.BLOCK_LITERAL: return implicitKey || inFlow ? quotedString(ss.value, ctx) : blockString(ss, ctx, onComment, onChompKeep);
|
|
345
|
+
case Scalar.QUOTE_DOUBLE: return doubleQuotedString(ss.value, ctx);
|
|
346
|
+
case Scalar.QUOTE_SINGLE: return singleQuotedString(ss.value, ctx);
|
|
347
|
+
case Scalar.PLAIN: return plainString(ss, ctx, onComment, onChompKeep);
|
|
348
|
+
default: return null;
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
let res = _stringify(type);
|
|
352
|
+
if (res === null) {
|
|
353
|
+
const { defaultKeyType, defaultStringType } = ctx.options;
|
|
354
|
+
const t = implicitKey && defaultKeyType || defaultStringType;
|
|
355
|
+
res = _stringify(t);
|
|
356
|
+
if (res === null) throw new Error(`Unsupported default string type ${t}`);
|
|
357
|
+
}
|
|
358
|
+
return res;
|
|
359
|
+
}
|
|
360
|
+
//#endregion
|
|
361
|
+
//#region src/doc/anchors.ts
|
|
362
|
+
/**
|
|
363
|
+
* Verify that the input string is a valid anchor.
|
|
364
|
+
*
|
|
365
|
+
* Will throw on errors.
|
|
366
|
+
*/
|
|
367
|
+
function anchorIsValid(anchor) {
|
|
368
|
+
if (/[\x00-\x19\s,[\]{}]/.test(anchor)) {
|
|
369
|
+
const msg = `Anchor must not contain whitespace or control characters: ${JSON.stringify(anchor)}`;
|
|
370
|
+
throw new Error(msg);
|
|
371
|
+
}
|
|
372
|
+
return true;
|
|
373
|
+
}
|
|
374
|
+
function anchorNames(root) {
|
|
375
|
+
const anchors = /* @__PURE__ */ new Set();
|
|
376
|
+
visit(root, { Value(_key, node) {
|
|
377
|
+
if (node.anchor) anchors.add(node.anchor);
|
|
378
|
+
} });
|
|
379
|
+
return anchors;
|
|
380
|
+
}
|
|
381
|
+
/** Find a new anchor name with the given `prefix` and a one-indexed suffix. */
|
|
382
|
+
function findNewAnchor(prefix, exclude) {
|
|
383
|
+
for (let i = 1;; ++i) {
|
|
384
|
+
const name = `${prefix}${i}`;
|
|
385
|
+
if (!exclude.has(name)) return name;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
//#endregion
|
|
389
|
+
//#region src/doc/NodeCreator.ts
|
|
390
|
+
const defaultTagPrefix = "tag:yaml.org,2002:";
|
|
391
|
+
var NodeCreator = class {
|
|
392
|
+
keepUndefined;
|
|
393
|
+
replacer;
|
|
394
|
+
schema;
|
|
395
|
+
#anchorPrefix;
|
|
396
|
+
#aliasObjects = [];
|
|
397
|
+
#doc;
|
|
398
|
+
#flow;
|
|
399
|
+
#onTagObj;
|
|
400
|
+
#prevAnchors = null;
|
|
401
|
+
#sourceObjects = /* @__PURE__ */ new Map();
|
|
402
|
+
constructor(docOrSchema, options = {}, replacer) {
|
|
403
|
+
this.keepUndefined = options.keepUndefined ?? false;
|
|
404
|
+
this.replacer = replacer;
|
|
405
|
+
this.#flow = options.flow ?? false;
|
|
406
|
+
this.#onTagObj = options.onTagObj;
|
|
407
|
+
this.#anchorPrefix = options.anchorPrefix || "a";
|
|
408
|
+
if (docOrSchema instanceof Document) {
|
|
409
|
+
if (options.aliasDuplicateObjects ?? true) this.#doc = docOrSchema;
|
|
410
|
+
this.schema = docOrSchema.schema;
|
|
411
|
+
} else this.schema = docOrSchema;
|
|
412
|
+
}
|
|
413
|
+
create(value, tagName) {
|
|
414
|
+
if (value instanceof Document) value = value.value;
|
|
415
|
+
if (isNode(value)) return value;
|
|
416
|
+
if (value instanceof Pair) return this.schema.map.createNode(this, null).set(value);
|
|
417
|
+
if (value instanceof String || value instanceof Number || value instanceof Boolean || typeof BigInt !== "undefined" && value instanceof BigInt) value = value.valueOf();
|
|
418
|
+
let ref = void 0;
|
|
419
|
+
if (this.#doc && value && typeof value === "object") {
|
|
420
|
+
ref = this.#sourceObjects.get(value);
|
|
421
|
+
if (ref) {
|
|
422
|
+
if (!ref.anchor) {
|
|
423
|
+
this.#aliasObjects.push(value);
|
|
424
|
+
this.#prevAnchors ??= anchorNames(this.#doc);
|
|
425
|
+
ref.anchor = findNewAnchor(this.#anchorPrefix, this.#prevAnchors);
|
|
426
|
+
this.#prevAnchors.add(ref.anchor);
|
|
427
|
+
}
|
|
428
|
+
return new Alias(ref.anchor);
|
|
429
|
+
} else {
|
|
430
|
+
ref = {
|
|
431
|
+
anchor: null,
|
|
432
|
+
node: null
|
|
433
|
+
};
|
|
434
|
+
this.#sourceObjects.set(value, ref);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
let tagObj;
|
|
438
|
+
if (tagName) {
|
|
439
|
+
if (tagName.startsWith("!!")) tagName = defaultTagPrefix + tagName.slice(2);
|
|
440
|
+
const match = this.schema.tags.filter((t) => t.tag === tagName);
|
|
441
|
+
tagObj = match.find((t) => !t.format) ?? match[0];
|
|
442
|
+
if (!tagObj) throw new Error(`Tag ${tagName} not found`);
|
|
443
|
+
} else tagObj = this.schema.tags.find((t) => t.identify?.(value) && !t.format);
|
|
444
|
+
if (!tagObj) {
|
|
445
|
+
if (value && typeof value.toJSON === "function") value = value.toJSON();
|
|
446
|
+
if (!value || typeof value !== "object") {
|
|
447
|
+
const node = new Scalar(value);
|
|
448
|
+
if (ref) ref.node = node;
|
|
449
|
+
return node;
|
|
450
|
+
}
|
|
451
|
+
tagObj = value instanceof Map ? this.schema.map : Symbol.iterator in Object(value) ? this.schema.seq : this.schema.map;
|
|
452
|
+
}
|
|
453
|
+
if (this.#onTagObj) {
|
|
454
|
+
this.#onTagObj(tagObj);
|
|
455
|
+
this.#onTagObj = void 0;
|
|
456
|
+
}
|
|
457
|
+
const node = tagObj?.createNode?.(this, value) ?? new Scalar(value);
|
|
458
|
+
if (tagName) node.tag = tagName;
|
|
459
|
+
else if (!tagObj.default) node.tag = tagObj.tag;
|
|
460
|
+
if (ref) ref.node = node;
|
|
461
|
+
if (this.#flow && isCollection(node)) node.flow = true;
|
|
462
|
+
return node;
|
|
463
|
+
}
|
|
464
|
+
createPair(key, value) {
|
|
465
|
+
return new Pair(this.create(key), value == null ? null : this.create(value));
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* With circular references, the source node is only resolved after all
|
|
469
|
+
* of its child nodes are. This is why anchors are set only after all of
|
|
470
|
+
* the nodes have been created.
|
|
471
|
+
*/
|
|
472
|
+
setAnchors() {
|
|
473
|
+
for (const source of this.#aliasObjects) {
|
|
474
|
+
const ref = this.#sourceObjects.get(source);
|
|
475
|
+
if (typeof ref === "object" && ref.anchor && (ref.node instanceof Scalar || isCollection(ref.node))) ref.node.anchor = ref.anchor;
|
|
476
|
+
else throw Object.assign(/* @__PURE__ */ new Error("Failed to resolve repeated object (this should not happen)"), { source });
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
};
|
|
480
|
+
//#endregion
|
|
481
|
+
//#region src/stringify/stringifyComment.ts
|
|
482
|
+
/**
|
|
483
|
+
* Stringifies a comment.
|
|
484
|
+
*
|
|
485
|
+
* Empty comment lines are left empty,
|
|
486
|
+
* lines consisting of a single space are replaced by `#`,
|
|
487
|
+
* and all other lines are prefixed with a `#`.
|
|
488
|
+
*/
|
|
489
|
+
const stringifyComment = (str) => str.replace(/^(?!$)(?: $)?/gm, "#");
|
|
490
|
+
function indentComment(comment, indent) {
|
|
491
|
+
if (/^\n+$/.test(comment)) return comment.substring(1);
|
|
492
|
+
return indent ? comment.replace(/^(?! *$)/gm, indent) : comment;
|
|
493
|
+
}
|
|
494
|
+
const lineComment = (str, indent, comment) => str.endsWith("\n") ? indentComment(comment, indent) : comment.includes("\n") ? "\n" + indentComment(comment, indent) : (str.endsWith(" ") ? "" : " ") + comment;
|
|
495
|
+
//#endregion
|
|
496
|
+
//#region src/log.ts
|
|
497
|
+
function debug(logLevel, ...messages) {
|
|
498
|
+
if (logLevel === "debug") console.log(...messages);
|
|
499
|
+
}
|
|
500
|
+
function warn(logLevel, warning) {
|
|
501
|
+
if (logLevel === "debug" || logLevel === "warn") if (typeof process !== "undefined" && typeof process.emitWarning === "function") process.emitWarning(warning);
|
|
502
|
+
else console.warn(warning);
|
|
503
|
+
}
|
|
504
|
+
//#endregion
|
|
505
|
+
//#region src/schema/yaml-1.1/merge.ts
|
|
506
|
+
const MERGE_KEY = "<<";
|
|
507
|
+
const merge = {
|
|
508
|
+
identify: (value) => value === MERGE_KEY || typeof value === "symbol" && value.description === MERGE_KEY,
|
|
509
|
+
default: "key",
|
|
510
|
+
tag: "tag:yaml.org,2002:merge",
|
|
511
|
+
test: /^<<$/,
|
|
512
|
+
resolve: () => Object.assign(new Scalar(Symbol(MERGE_KEY)), { addToJSMap: addMergeToJSMap }),
|
|
513
|
+
stringify: () => MERGE_KEY
|
|
514
|
+
};
|
|
515
|
+
const isMergeKey = (doc, key) => (merge.identify(key) || key instanceof Scalar && (!key.type || key.type === Scalar.PLAIN) && merge.identify(key.value)) && Boolean(doc.schema.tags.some((tag) => tag.tag === merge.tag && tag.default));
|
|
516
|
+
function addMergeToJSMap(doc, ctx, map, value) {
|
|
517
|
+
value = ctx && value instanceof Alias ? value.resolve(doc, ctx) : value;
|
|
518
|
+
if (Array.isArray(value) && !(value instanceof YAMLMap)) for (const it of value) mergeValue(doc, ctx, map, it);
|
|
519
|
+
else mergeValue(doc, ctx, map, value);
|
|
520
|
+
}
|
|
521
|
+
function mergeValue(doc, ctx, map, value) {
|
|
522
|
+
const srcMap = (value instanceof Alias ? value.resolve(doc, ctx) : value).toJS(doc, ctx, Map);
|
|
523
|
+
if (!(srcMap instanceof Map)) throw new Error("Merge sources must be maps or map aliases");
|
|
524
|
+
for (const [key, value] of srcMap) if (map instanceof Map) {
|
|
525
|
+
if (!map.has(key)) map.set(key, value);
|
|
526
|
+
} else if (map instanceof Set) map.add(key);
|
|
527
|
+
else if (!Object.prototype.hasOwnProperty.call(map, key)) Object.defineProperty(map, key, {
|
|
528
|
+
value,
|
|
529
|
+
writable: true,
|
|
530
|
+
enumerable: true,
|
|
531
|
+
configurable: true
|
|
532
|
+
});
|
|
533
|
+
return map;
|
|
534
|
+
}
|
|
535
|
+
//#endregion
|
|
536
|
+
//#region src/stringify/stringify.ts
|
|
537
|
+
const sortMapEntriesByKey = (a, b) => a.key < b.key ? -1 : a.key > b.key ? 1 : 0;
|
|
538
|
+
function createStringifyContext(doc, options) {
|
|
539
|
+
const opt = Object.assign({
|
|
540
|
+
blockQuote: true,
|
|
541
|
+
commentString: stringifyComment,
|
|
542
|
+
defaultKeyType: null,
|
|
543
|
+
defaultStringType: "PLAIN",
|
|
544
|
+
directives: null,
|
|
545
|
+
doubleQuotedAsJSON: false,
|
|
546
|
+
doubleQuotedMinMultiLineLength: 40,
|
|
547
|
+
falseStr: "false",
|
|
548
|
+
flowCollectionPadding: true,
|
|
549
|
+
indentSeq: true,
|
|
550
|
+
lineWidth: 80,
|
|
551
|
+
minContentWidth: 20,
|
|
552
|
+
nullStr: "null",
|
|
553
|
+
simpleKeys: false,
|
|
554
|
+
singleQuote: null,
|
|
555
|
+
sortMapEntries: false,
|
|
556
|
+
trailingComma: false,
|
|
557
|
+
trueStr: "true",
|
|
558
|
+
verifyAliasOrder: true
|
|
559
|
+
}, doc.schema.toStringOptions, options);
|
|
560
|
+
let inFlow;
|
|
561
|
+
switch (opt.collectionStyle) {
|
|
562
|
+
case "block":
|
|
563
|
+
inFlow = false;
|
|
564
|
+
break;
|
|
565
|
+
case "flow":
|
|
566
|
+
inFlow = true;
|
|
567
|
+
break;
|
|
568
|
+
default: inFlow = null;
|
|
569
|
+
}
|
|
570
|
+
const sortMapEntries = typeof opt.sortMapEntries === "function" ? opt.sortMapEntries : opt.sortMapEntries === true ? sortMapEntriesByKey : null;
|
|
571
|
+
return {
|
|
572
|
+
anchors: /* @__PURE__ */ new Set(),
|
|
573
|
+
doc,
|
|
574
|
+
flowCollectionPadding: opt.flowCollectionPadding ? " " : "",
|
|
575
|
+
indent: "",
|
|
576
|
+
indentStep: typeof opt.indent === "number" ? " ".repeat(opt.indent) : " ",
|
|
577
|
+
inFlow,
|
|
578
|
+
options: opt,
|
|
579
|
+
sortMapEntries
|
|
580
|
+
};
|
|
581
|
+
}
|
|
582
|
+
function getTagObject(tags, item) {
|
|
583
|
+
if (item.tag) {
|
|
584
|
+
const match = tags.filter((t) => t.tag === item.tag);
|
|
585
|
+
if (match.length > 0) return match.find((t) => t.format === item.format) ?? match[0];
|
|
586
|
+
}
|
|
587
|
+
let tagObj = void 0;
|
|
588
|
+
let obj;
|
|
589
|
+
if (item instanceof Scalar) {
|
|
590
|
+
obj = item.value;
|
|
591
|
+
let match = tags.filter((t) => t.identify?.(obj));
|
|
592
|
+
if (match.length > 1) {
|
|
593
|
+
const testMatch = match.filter((t) => t.test);
|
|
594
|
+
if (testMatch.length > 0) match = testMatch;
|
|
595
|
+
}
|
|
596
|
+
tagObj = match.find((t) => t.format === item.format) ?? match.find((t) => !t.format);
|
|
597
|
+
} else {
|
|
598
|
+
obj = item;
|
|
599
|
+
tagObj = tags.find((t) => t.nodeClass && obj instanceof t.nodeClass);
|
|
600
|
+
}
|
|
601
|
+
if (!tagObj) {
|
|
602
|
+
const name = obj?.constructor?.name ?? (obj === null ? "null" : typeof obj);
|
|
603
|
+
throw new Error(`Tag not resolved for ${name} value`);
|
|
604
|
+
}
|
|
605
|
+
return tagObj;
|
|
606
|
+
}
|
|
607
|
+
function stringifyProps(node, tagObj, { anchors, doc }) {
|
|
608
|
+
if (!doc.directives) return "";
|
|
609
|
+
const props = [];
|
|
610
|
+
const anchor = node.anchor;
|
|
611
|
+
if (anchor && anchorIsValid(anchor)) {
|
|
612
|
+
anchors.add(anchor);
|
|
613
|
+
props.push(`&${anchor}`);
|
|
614
|
+
}
|
|
615
|
+
const tag = node.tag ?? (tagObj.default ? null : tagObj.tag);
|
|
616
|
+
if (tag) props.push(doc.directives.tagString(tag));
|
|
617
|
+
return props.join(" ");
|
|
618
|
+
}
|
|
619
|
+
function stringify(node, ctx, onComment, onChompKeep) {
|
|
620
|
+
if (node instanceof Pair) return node.toString(ctx, onComment, onChompKeep);
|
|
621
|
+
if (node instanceof Alias) {
|
|
622
|
+
if (ctx.doc.directives) return node.toString(ctx);
|
|
623
|
+
if (ctx.resolvedAliases?.has(node)) throw new TypeError("Cannot stringify circular structure without alias nodes");
|
|
624
|
+
if (ctx.resolvedAliases) ctx.resolvedAliases.add(node);
|
|
625
|
+
else ctx.resolvedAliases = new Set([node]);
|
|
626
|
+
node = node.resolve(ctx.doc) ?? null;
|
|
627
|
+
}
|
|
628
|
+
let tagObj = void 0;
|
|
629
|
+
node ??= ctx.doc.createNode(null, { onTagObj: (o) => tagObj = o });
|
|
630
|
+
tagObj ??= getTagObject(ctx.doc.schema.tags, node);
|
|
631
|
+
const props = stringifyProps(node, tagObj, ctx);
|
|
632
|
+
if (props.length > 0) ctx.indentAtStart = (ctx.indentAtStart ?? 0) + props.length + 1;
|
|
633
|
+
const str = typeof tagObj.stringify === "function" ? tagObj.stringify(node, ctx, onComment, onChompKeep) : node instanceof Scalar ? stringifyString(node, ctx, onComment, onChompKeep) : node.toString(ctx, onComment, onChompKeep);
|
|
634
|
+
if (!props) return str;
|
|
635
|
+
return node instanceof Scalar || str[0] === "{" || str[0] === "[" ? `${props} ${str}` : `${props}\n${ctx.indent}${str}`;
|
|
636
|
+
}
|
|
637
|
+
//#endregion
|
|
638
|
+
//#region src/nodes/addPairToJSMap.ts
|
|
639
|
+
function addPairToJSMap(doc, ctx, map, { key, value }) {
|
|
640
|
+
if ("addToJSMap" in key) key.addToJSMap?.(doc, ctx, map, value);
|
|
641
|
+
else if (isMergeKey(doc, key)) addMergeToJSMap(doc, ctx, map, value);
|
|
642
|
+
else {
|
|
643
|
+
const jsKey = key.toJS(doc, ctx);
|
|
644
|
+
if (map instanceof Map) map.set(jsKey, value ? value.toJS(doc, ctx) : value);
|
|
645
|
+
else if (map instanceof Set) map.add(jsKey);
|
|
646
|
+
else {
|
|
647
|
+
const stringKey = stringifyKey(doc, ctx, key, jsKey);
|
|
648
|
+
const jsValue = value ? value.toJS(doc, ctx) : value;
|
|
649
|
+
if (stringKey in map) Object.defineProperty(map, stringKey, {
|
|
650
|
+
value: jsValue,
|
|
651
|
+
writable: true,
|
|
652
|
+
enumerable: true,
|
|
653
|
+
configurable: true
|
|
654
|
+
});
|
|
655
|
+
else map[stringKey] = jsValue;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
return map;
|
|
659
|
+
}
|
|
660
|
+
function stringifyKey(doc, ctx, key, jsKey) {
|
|
661
|
+
if (jsKey === null) return "";
|
|
662
|
+
if (typeof jsKey !== "object") return String(jsKey);
|
|
663
|
+
const strCtx = createStringifyContext(doc, {});
|
|
664
|
+
strCtx.anchors = /* @__PURE__ */ new Set();
|
|
665
|
+
for (const node of ctx.anchors.keys()) strCtx.anchors.add(node.anchor);
|
|
666
|
+
strCtx.inFlow = true;
|
|
667
|
+
strCtx.inStringifyKey = true;
|
|
668
|
+
const strKey = key.toString(strCtx);
|
|
669
|
+
if (!ctx.mapKeyWarned) {
|
|
670
|
+
let jsonStr = JSON.stringify(strKey);
|
|
671
|
+
if (jsonStr.length > 40) jsonStr = jsonStr.substring(0, 36) + "...\"";
|
|
672
|
+
const msg = `Keys with collection values will be stringified due to JS Object restrictions: ${jsonStr}. Set mapAsMap: true to use a Map instead.`;
|
|
673
|
+
warn(doc.options.logLevel, msg);
|
|
674
|
+
ctx.mapKeyWarned = true;
|
|
675
|
+
}
|
|
676
|
+
return strKey;
|
|
677
|
+
}
|
|
678
|
+
//#endregion
|
|
679
|
+
//#region src/nodes/toJS.ts
|
|
680
|
+
/** A context used in `node.toJS()` implementations */
|
|
681
|
+
var ToJSContext = class {
|
|
682
|
+
anchors = /* @__PURE__ */ new Map();
|
|
683
|
+
/** Cached anchor and alias nodes in the order they occur in the document */
|
|
684
|
+
aliasResolveCache;
|
|
685
|
+
mapAsMap;
|
|
686
|
+
mapKeyWarned = false;
|
|
687
|
+
maxAliasCount;
|
|
688
|
+
constructor(opt) {
|
|
689
|
+
this.mapAsMap = opt?.mapAsMap === true;
|
|
690
|
+
this.maxAliasCount = opt?.maxAliasCount ?? 100;
|
|
691
|
+
}
|
|
692
|
+
setAnchor(node, res) {
|
|
693
|
+
this.anchors.set(node, {
|
|
694
|
+
aliasCount: 0,
|
|
695
|
+
count: 1,
|
|
696
|
+
res
|
|
697
|
+
});
|
|
698
|
+
}
|
|
699
|
+
};
|
|
700
|
+
//#endregion
|
|
701
|
+
//#region src/nodes/util-clone-map-or-set.ts
|
|
702
|
+
function cloneMapOrSet(coll, schema) {
|
|
703
|
+
schema ??= coll.schema;
|
|
704
|
+
const copy = new coll.constructor(schema);
|
|
705
|
+
for (const [key, value] of coll.values) copy.values.set(key, value.clone(schema));
|
|
706
|
+
if (coll.range) copy.range = [...coll.range];
|
|
707
|
+
const propDesc = Object.getOwnPropertyDescriptors(coll);
|
|
708
|
+
for (const [name, prop] of Object.entries(propDesc)) if (!(name in copy)) Object.defineProperty(copy, name, prop);
|
|
709
|
+
return copy;
|
|
710
|
+
}
|
|
711
|
+
//#endregion
|
|
712
|
+
//#region src/nodes/YAMLMap.ts
|
|
713
|
+
var YAMLMap = class {
|
|
714
|
+
static tagName = "tag:yaml.org,2002:map";
|
|
715
|
+
values = /* @__PURE__ */ new Map();
|
|
716
|
+
/**
|
|
717
|
+
* A generic collection factory method that can be used
|
|
718
|
+
* by other node classes that inherit from YAMLMap
|
|
719
|
+
*/
|
|
720
|
+
static create(nc, obj) {
|
|
721
|
+
const { replacer } = nc;
|
|
722
|
+
const map = new this(nc.schema);
|
|
723
|
+
if (obj && typeof obj === "object") {
|
|
724
|
+
const iter = obj instanceof Map ? obj : Object.entries(obj);
|
|
725
|
+
for (let [key, value] of iter) {
|
|
726
|
+
if (replacer) {
|
|
727
|
+
if (typeof replacer === "function") value = replacer.call(obj, key, value);
|
|
728
|
+
else if (Array.isArray(replacer) && !replacer.includes(key)) continue;
|
|
729
|
+
}
|
|
730
|
+
if (value !== void 0 || nc.keepUndefined) {
|
|
731
|
+
const mk = nc.schema.mapKey(key);
|
|
732
|
+
const pair = nc.createPair(key, value);
|
|
733
|
+
map.values.set(mk, pair);
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
return map;
|
|
738
|
+
}
|
|
739
|
+
constructor(schema, elements) {
|
|
740
|
+
Object.defineProperty(this, "schema", {
|
|
741
|
+
value: schema,
|
|
742
|
+
configurable: true,
|
|
743
|
+
enumerable: false,
|
|
744
|
+
writable: true
|
|
745
|
+
});
|
|
746
|
+
this.values = new Map(elements?.map((pair) => [this.schema.mapKey(pair), pair]));
|
|
747
|
+
}
|
|
748
|
+
get size() {
|
|
749
|
+
return this.values.size;
|
|
750
|
+
}
|
|
751
|
+
/**
|
|
752
|
+
* Create a copy of this map.
|
|
753
|
+
*
|
|
754
|
+
* @param schema - If defined, overwrites the original's schema
|
|
755
|
+
*/
|
|
756
|
+
clone(schema) {
|
|
757
|
+
return cloneMapOrSet(this, schema);
|
|
758
|
+
}
|
|
759
|
+
/**
|
|
760
|
+
* Remove a value from the mapping.
|
|
761
|
+
* @returns `true` if the item was found and removed.
|
|
762
|
+
*/
|
|
763
|
+
delete(key) {
|
|
764
|
+
let mk = this.schema.mapKey(key);
|
|
765
|
+
if (this.values.delete(mk)) return true;
|
|
766
|
+
mk = key instanceof Pair ? key.key : isNode(key) ? key : null;
|
|
767
|
+
if (mk) {
|
|
768
|
+
for (const [k, p] of this.values) if (p.key === mk) return this.values.delete(k);
|
|
769
|
+
}
|
|
770
|
+
return false;
|
|
771
|
+
}
|
|
772
|
+
/** Return value at `key`, or `undefined` if not found. */
|
|
773
|
+
get(key) {
|
|
774
|
+
return this.getPair(key)?.value;
|
|
775
|
+
}
|
|
776
|
+
/** Return pair at `key`, or `undefined` if not found. */
|
|
777
|
+
getPair(key) {
|
|
778
|
+
let mk = this.schema.mapKey(key);
|
|
779
|
+
const pair = this.values.get(mk);
|
|
780
|
+
if (pair) return pair;
|
|
781
|
+
mk = key instanceof Pair ? key.key : isNode(key) ? key : null;
|
|
782
|
+
if (mk) {
|
|
783
|
+
for (const p of this.values.values()) if (p.key === mk) return p;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
/** Check if the mapping includes a value with the key `key`. */
|
|
787
|
+
has(key) {
|
|
788
|
+
let mk = this.schema.mapKey(key);
|
|
789
|
+
if (this.values.has(mk)) return true;
|
|
790
|
+
mk = key instanceof Pair ? key.key : isNode(key) ? key : null;
|
|
791
|
+
if (mk) {
|
|
792
|
+
for (const p of this.values.values()) if (p.key === mk) return true;
|
|
793
|
+
}
|
|
794
|
+
return false;
|
|
795
|
+
}
|
|
796
|
+
/**
|
|
797
|
+
* Return the internal Map key matching `key`, or `undefined` if not found.
|
|
798
|
+
*
|
|
799
|
+
* @param allowMissing - If `true`, a key is always returned,
|
|
800
|
+
* even if the key is not in the map.
|
|
801
|
+
*/
|
|
802
|
+
keyOf(key, allowMissing = false) {
|
|
803
|
+
let mk = this.schema.mapKey(key);
|
|
804
|
+
if (allowMissing || this.values.has(mk)) return mk;
|
|
805
|
+
mk = key instanceof Pair ? key.key : isNode(key) ? key : null;
|
|
806
|
+
if (mk) {
|
|
807
|
+
for (const [k, v] of this.values) if (v.key === mk) return k;
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
pairs() {
|
|
811
|
+
return this.values.values();
|
|
812
|
+
}
|
|
813
|
+
set(keyOrPair, value, options) {
|
|
814
|
+
const mk = this.schema.mapKey(keyOrPair);
|
|
815
|
+
let pair;
|
|
816
|
+
if (keyOrPair instanceof Pair) pair = keyOrPair;
|
|
817
|
+
else if (isNode(keyOrPair) && (value == null || isNode(value))) pair = new Pair(keyOrPair, value ?? null);
|
|
818
|
+
else pair = new NodeCreator(this.schema, options).createPair(keyOrPair, value);
|
|
819
|
+
if (pair.value instanceof Scalar) {
|
|
820
|
+
const prev = this.values.get(mk);
|
|
821
|
+
if (prev) {
|
|
822
|
+
if (!prev.value) {
|
|
823
|
+
prev.value = pair.value;
|
|
824
|
+
return this;
|
|
825
|
+
}
|
|
826
|
+
if (prev.value instanceof Scalar) {
|
|
827
|
+
Object.assign(prev.value, pair.value);
|
|
828
|
+
return this;
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
this.values.set(mk, pair);
|
|
833
|
+
return this;
|
|
834
|
+
}
|
|
835
|
+
toJS(doc, ctx, Type) {
|
|
836
|
+
ctx ??= new ToJSContext();
|
|
837
|
+
const map = Type ? new Type() : ctx?.mapAsMap ? /* @__PURE__ */ new Map() : {};
|
|
838
|
+
if (this.anchor) ctx.setAnchor(this, map);
|
|
839
|
+
for (const pair of this.values.values()) addPairToJSMap(doc, ctx, map, pair);
|
|
840
|
+
return map;
|
|
841
|
+
}
|
|
842
|
+
toString(ctx, onComment, onChompKeep) {
|
|
843
|
+
if (!ctx) return JSON.stringify(this);
|
|
844
|
+
let pairs = this.values.values();
|
|
845
|
+
if (ctx.sortMapEntries) pairs = Array.from(pairs).sort(ctx.sortMapEntries);
|
|
846
|
+
return ctx.inFlow ?? this.flow ? this.#stringifyFlowMap(ctx, pairs) : this.#stringifyBlockMap(ctx, pairs, onComment, onChompKeep);
|
|
847
|
+
}
|
|
848
|
+
#stringifyBlockMap(ctx, pairs, onComment, onChompKeep) {
|
|
849
|
+
const { indent, options: { commentString } } = ctx;
|
|
850
|
+
let chompKeep = false;
|
|
851
|
+
const lines = [];
|
|
852
|
+
for (const pair of pairs) {
|
|
853
|
+
let comment = null;
|
|
854
|
+
if (!chompKeep && pair.key.spaceBefore) lines.push("");
|
|
855
|
+
let cb = pair.key.commentBefore;
|
|
856
|
+
if (cb && chompKeep) cb = cb.replace(/^\n+/, "");
|
|
857
|
+
if (cb) {
|
|
858
|
+
const ic = indentComment(commentString(cb), indent).trimStart();
|
|
859
|
+
lines.push(ic);
|
|
860
|
+
}
|
|
861
|
+
chompKeep = false;
|
|
862
|
+
let str = stringifyPair(pair, ctx, () => comment = null, () => chompKeep = true);
|
|
863
|
+
if (comment) str += lineComment(str, indent, commentString(comment));
|
|
864
|
+
if (chompKeep && comment) chompKeep = false;
|
|
865
|
+
lines.push(str);
|
|
866
|
+
}
|
|
867
|
+
let str;
|
|
868
|
+
if (lines.length === 0) str = "{}";
|
|
869
|
+
else {
|
|
870
|
+
str = lines[0];
|
|
871
|
+
for (let i = 1; i < lines.length; ++i) {
|
|
872
|
+
const line = lines[i];
|
|
873
|
+
str += line ? `\n${indent}${line}` : "\n";
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
if (this.comment) {
|
|
877
|
+
str += "\n" + indentComment(commentString(this.comment), indent);
|
|
878
|
+
onComment?.();
|
|
879
|
+
} else if (chompKeep) onChompKeep?.();
|
|
880
|
+
return str;
|
|
881
|
+
}
|
|
882
|
+
#stringifyFlowMap(ctx, pairs) {
|
|
883
|
+
const { indent, indentStep, flowCollectionPadding: fcPadding, options: { commentString, lineWidth, trailingComma } } = ctx;
|
|
884
|
+
const itemIndent = indent + indentStep;
|
|
885
|
+
const itemCtx = {
|
|
886
|
+
...ctx,
|
|
887
|
+
indent: itemIndent,
|
|
888
|
+
inFlow: true
|
|
889
|
+
};
|
|
890
|
+
let reqNewline = false;
|
|
891
|
+
let linesAtValue = 0;
|
|
892
|
+
const lines = [];
|
|
893
|
+
let itemsLeft = this.values.size;
|
|
894
|
+
for (const pair of pairs) {
|
|
895
|
+
itemsLeft -= 1;
|
|
896
|
+
let comment = null;
|
|
897
|
+
const ik = pair.key;
|
|
898
|
+
if (ik.spaceBefore) {
|
|
899
|
+
lines.push("");
|
|
900
|
+
reqNewline = true;
|
|
901
|
+
}
|
|
902
|
+
if (ik.commentBefore) {
|
|
903
|
+
const ic = indentComment(commentString(ik.commentBefore), indent);
|
|
904
|
+
lines.push(ic.trimStart());
|
|
905
|
+
reqNewline = true;
|
|
906
|
+
}
|
|
907
|
+
if (ik.comment) reqNewline = true;
|
|
908
|
+
const iv = pair.value;
|
|
909
|
+
if (iv) {
|
|
910
|
+
if (iv.comment) comment = iv.comment;
|
|
911
|
+
if (iv.commentBefore) reqNewline = true;
|
|
912
|
+
} else if (ik?.comment) comment = ik.comment;
|
|
913
|
+
if (comment) reqNewline = true;
|
|
914
|
+
let str = stringifyPair(pair, itemCtx, () => comment = null);
|
|
915
|
+
reqNewline ||= lines.length > linesAtValue || str.includes("\n");
|
|
916
|
+
if (itemsLeft > 0) str += ",";
|
|
917
|
+
else if (trailingComma) {
|
|
918
|
+
if (!reqNewline && lineWidth > 0) reqNewline = lines.reduce((sum, line) => sum + line.length + 2, 2) + (str.length + 2) > lineWidth;
|
|
919
|
+
if (reqNewline) str += ",";
|
|
920
|
+
}
|
|
921
|
+
if (comment) str += lineComment(str, itemIndent, commentString(comment));
|
|
922
|
+
lines.push(str);
|
|
923
|
+
linesAtValue = lines.length;
|
|
924
|
+
}
|
|
925
|
+
if (lines.length === 0) return "{}";
|
|
926
|
+
if (!reqNewline) {
|
|
927
|
+
const len = lines.reduce((sum, line) => sum + line.length + 2, 2);
|
|
928
|
+
reqNewline = ctx.options.lineWidth > 0 && len > ctx.options.lineWidth;
|
|
929
|
+
}
|
|
930
|
+
if (reqNewline) {
|
|
931
|
+
let str = "{";
|
|
932
|
+
for (const line of lines) str += line ? `\n${indentStep}${indent}${line}` : "\n";
|
|
933
|
+
return `${str}\n${indent}}`;
|
|
934
|
+
}
|
|
935
|
+
return `{${fcPadding}${lines.join(" ")}${fcPadding}}`;
|
|
936
|
+
}
|
|
937
|
+
};
|
|
938
|
+
//#endregion
|
|
939
|
+
//#region src/nodes/YAMLSeq.ts
|
|
940
|
+
const isScalarValue = (value) => !value || typeof value !== "function" && typeof value !== "object";
|
|
941
|
+
var YAMLSeq = class extends Array {
|
|
942
|
+
static get tagName() {
|
|
943
|
+
return "tag:yaml.org,2002:seq";
|
|
944
|
+
}
|
|
945
|
+
/**
|
|
946
|
+
* A generic collection factory method that can be extended
|
|
947
|
+
* to other node classes that inherit from YAMLSeq
|
|
948
|
+
*/
|
|
949
|
+
static create(nc, obj) {
|
|
950
|
+
const seq = new this(nc.schema);
|
|
951
|
+
if (obj && Symbol.iterator in Object(obj)) {
|
|
952
|
+
let i = 0;
|
|
953
|
+
for (let it of obj) {
|
|
954
|
+
if (typeof nc.replacer === "function") {
|
|
955
|
+
const key = obj instanceof Set ? it : String(i++);
|
|
956
|
+
it = nc.replacer.call(obj, key, it);
|
|
957
|
+
}
|
|
958
|
+
seq.push(nc.create(it));
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
return seq;
|
|
962
|
+
}
|
|
963
|
+
constructor(schema, elements = []) {
|
|
964
|
+
super(...nodeValues(schema, elements));
|
|
965
|
+
Object.defineProperty(this, "schema", {
|
|
966
|
+
value: schema,
|
|
967
|
+
configurable: true,
|
|
968
|
+
enumerable: false,
|
|
969
|
+
writable: true
|
|
970
|
+
});
|
|
971
|
+
}
|
|
972
|
+
get size() {
|
|
973
|
+
return this.length;
|
|
974
|
+
}
|
|
975
|
+
/**
|
|
976
|
+
* Create a copy of this collection.
|
|
977
|
+
*
|
|
978
|
+
* @param schema - If defined, overwrites the original's schema
|
|
979
|
+
*/
|
|
980
|
+
clone(schema) {
|
|
981
|
+
const copy = this.constructor.from(this, (it) => it.clone(schema));
|
|
982
|
+
if (this.range) copy.range = [...this.range];
|
|
983
|
+
const propDesc = Object.getOwnPropertyDescriptors(this);
|
|
984
|
+
for (const [name, prop] of Object.entries(propDesc)) if (!(name in copy)) Object.defineProperty(copy, name, prop);
|
|
985
|
+
if (schema) copy.schema = schema;
|
|
986
|
+
return copy;
|
|
987
|
+
}
|
|
988
|
+
/**
|
|
989
|
+
* Change all elements within a range of indices in this sequence to a static value.
|
|
990
|
+
*
|
|
991
|
+
* Non-node values are converted to Node values.
|
|
992
|
+
*/
|
|
993
|
+
fill(value, start, end) {
|
|
994
|
+
return super.fill(nodeValue(this.schema, value), start, end);
|
|
995
|
+
}
|
|
996
|
+
/** @private */
|
|
997
|
+
_push(item) {
|
|
998
|
+
super.push(item);
|
|
999
|
+
}
|
|
1000
|
+
/**
|
|
1001
|
+
* Append new elements to this sequence, and return its new length.
|
|
1002
|
+
*
|
|
1003
|
+
* Non-node values are converted to Node values.
|
|
1004
|
+
*/
|
|
1005
|
+
push(...values) {
|
|
1006
|
+
return super.push(...nodeValues(this.schema, values));
|
|
1007
|
+
}
|
|
1008
|
+
/**
|
|
1009
|
+
* Set a value in this sequence.
|
|
1010
|
+
*
|
|
1011
|
+
* Non-node values are converted to Node values.
|
|
1012
|
+
*/
|
|
1013
|
+
set(idx, value, options) {
|
|
1014
|
+
if (!Number.isInteger(idx)) throw new TypeError(`Expected an integer, not ${JSON.stringify(idx)}.`);
|
|
1015
|
+
const prev = this.at(idx);
|
|
1016
|
+
if (prev instanceof Scalar && isScalarValue(value)) prev.value = value;
|
|
1017
|
+
else {
|
|
1018
|
+
if (idx < 0) {
|
|
1019
|
+
if (idx < -this.length) throw new RangeError(`Invalid index ${idx}`);
|
|
1020
|
+
idx += this.length;
|
|
1021
|
+
}
|
|
1022
|
+
this[idx] = nodeValue(this.schema, value, options);
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
/**
|
|
1026
|
+
* Changes the contents of this sequence by removing or replacing existing elements
|
|
1027
|
+
* and/or adding new elements in place.
|
|
1028
|
+
*
|
|
1029
|
+
* Non-node values are converted to Node values.
|
|
1030
|
+
*/
|
|
1031
|
+
splice(start, deleteCount, ...values) {
|
|
1032
|
+
const nv = nodeValues(this.schema, values);
|
|
1033
|
+
return arguments.length < 2 ? super.splice(start) : super.splice(start, Number(deleteCount), ...nv);
|
|
1034
|
+
}
|
|
1035
|
+
/**
|
|
1036
|
+
* Prepend new elements to this sequence, and return its new length.
|
|
1037
|
+
*
|
|
1038
|
+
* Non-node values are converted to Node values.
|
|
1039
|
+
*/
|
|
1040
|
+
unshift(...values) {
|
|
1041
|
+
return super.unshift(...nodeValues(this.schema, values));
|
|
1042
|
+
}
|
|
1043
|
+
/** A plain JavaScript representation of this node. */
|
|
1044
|
+
toJS(doc, ctx) {
|
|
1045
|
+
ctx ??= new ToJSContext();
|
|
1046
|
+
if (this.anchor) {
|
|
1047
|
+
const res = [];
|
|
1048
|
+
if (this.anchor) ctx.setAnchor(this, res);
|
|
1049
|
+
for (const item of this) res.push(item.toJS(doc, ctx));
|
|
1050
|
+
return res;
|
|
1051
|
+
}
|
|
1052
|
+
return Array.from(this, (item) => item.toJS(doc, ctx));
|
|
1053
|
+
}
|
|
1054
|
+
toString(ctx, onComment, onChompKeep) {
|
|
1055
|
+
if (!ctx) return JSON.stringify(this);
|
|
1056
|
+
return ctx.inFlow ?? this.flow ? this.#stringifyFlowSeq(ctx) : this.#stringifyBlockSeq(ctx, onComment, onChompKeep);
|
|
1057
|
+
}
|
|
1058
|
+
#stringifyBlockSeq(ctx, onComment, onChompKeep) {
|
|
1059
|
+
const { indent, options: { commentString } } = ctx;
|
|
1060
|
+
const itemIndent = indent + " ";
|
|
1061
|
+
const itemCtx = {
|
|
1062
|
+
...ctx,
|
|
1063
|
+
indent: itemIndent
|
|
1064
|
+
};
|
|
1065
|
+
let chompKeep = false;
|
|
1066
|
+
const lines = [];
|
|
1067
|
+
for (let i = 0; i < this.length; ++i) {
|
|
1068
|
+
const item = this[i];
|
|
1069
|
+
let comment = null;
|
|
1070
|
+
if (item instanceof Pair) {
|
|
1071
|
+
if (!chompKeep && item.key.spaceBefore) lines.push("");
|
|
1072
|
+
addCommentBefore(ctx, lines, item.key.commentBefore, chompKeep);
|
|
1073
|
+
} else if (item) {
|
|
1074
|
+
if (!chompKeep && item.spaceBefore) lines.push("");
|
|
1075
|
+
addCommentBefore(ctx, lines, item.commentBefore, chompKeep);
|
|
1076
|
+
if (item.comment) comment = item.comment;
|
|
1077
|
+
}
|
|
1078
|
+
chompKeep = false;
|
|
1079
|
+
let str = stringify(item, itemCtx, () => comment = null, () => chompKeep = true);
|
|
1080
|
+
if (comment) str += lineComment(str, itemIndent, commentString(comment));
|
|
1081
|
+
if (chompKeep && comment) chompKeep = false;
|
|
1082
|
+
lines.push(`- ${str}`);
|
|
1083
|
+
}
|
|
1084
|
+
let str;
|
|
1085
|
+
if (lines.length === 0) str = "[]";
|
|
1086
|
+
else {
|
|
1087
|
+
str = lines[0];
|
|
1088
|
+
for (let i = 1; i < lines.length; ++i) {
|
|
1089
|
+
const line = lines[i];
|
|
1090
|
+
str += line ? `\n${indent}${line}` : "\n";
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
if (this.comment) {
|
|
1094
|
+
str += "\n" + indentComment(commentString(this.comment), indent);
|
|
1095
|
+
onComment?.();
|
|
1096
|
+
} else if (chompKeep) onChompKeep?.();
|
|
1097
|
+
return str;
|
|
1098
|
+
}
|
|
1099
|
+
#stringifyFlowSeq(ctx) {
|
|
1100
|
+
const { indent, indentStep, flowCollectionPadding: fcPadding, options: { commentString } } = ctx;
|
|
1101
|
+
const itemIndent = indent + " " + indentStep;
|
|
1102
|
+
const itemCtx = {
|
|
1103
|
+
...ctx,
|
|
1104
|
+
indent: itemIndent,
|
|
1105
|
+
inFlow: true
|
|
1106
|
+
};
|
|
1107
|
+
let reqNewline = false;
|
|
1108
|
+
let linesAtValue = 0;
|
|
1109
|
+
const lines = [];
|
|
1110
|
+
for (let i = 0; i < this.length; ++i) {
|
|
1111
|
+
const item = this[i];
|
|
1112
|
+
let comment = null;
|
|
1113
|
+
if (item instanceof Pair) {
|
|
1114
|
+
const ik = item.key;
|
|
1115
|
+
if (ik.spaceBefore) lines.push("");
|
|
1116
|
+
addCommentBefore(ctx, lines, ik.commentBefore, false);
|
|
1117
|
+
if (ik.comment) reqNewline = true;
|
|
1118
|
+
const iv = item.value;
|
|
1119
|
+
if (iv) {
|
|
1120
|
+
if (iv.comment) comment = iv.comment;
|
|
1121
|
+
if (iv.commentBefore) reqNewline = true;
|
|
1122
|
+
} else if (ik?.comment) comment = ik.comment;
|
|
1123
|
+
} else if (item) {
|
|
1124
|
+
if (item.spaceBefore) lines.push("");
|
|
1125
|
+
addCommentBefore(ctx, lines, item.commentBefore, false);
|
|
1126
|
+
if (item.comment) comment = item.comment;
|
|
1127
|
+
}
|
|
1128
|
+
if (comment) reqNewline = true;
|
|
1129
|
+
let str = stringify(item, itemCtx, () => comment = null);
|
|
1130
|
+
reqNewline ||= lines.length > linesAtValue || str.includes("\n");
|
|
1131
|
+
if (i < this.length - 1) str += ",";
|
|
1132
|
+
else if (ctx.options.trailingComma) {
|
|
1133
|
+
if (ctx.options.lineWidth > 0) reqNewline ||= lines.reduce((sum, line) => sum + line.length + 2, 2) + (str.length + 2) > ctx.options.lineWidth;
|
|
1134
|
+
if (reqNewline) str += ",";
|
|
1135
|
+
}
|
|
1136
|
+
if (comment) str += lineComment(str, itemIndent, commentString(comment));
|
|
1137
|
+
lines.push(str);
|
|
1138
|
+
linesAtValue = lines.length;
|
|
1139
|
+
}
|
|
1140
|
+
if (lines.length === 0) return "[]";
|
|
1141
|
+
if (!reqNewline) {
|
|
1142
|
+
const len = lines.reduce((sum, line) => sum + line.length + 2, 2);
|
|
1143
|
+
reqNewline = ctx.options.lineWidth > 0 && len > ctx.options.lineWidth;
|
|
1144
|
+
}
|
|
1145
|
+
if (reqNewline) {
|
|
1146
|
+
let str = "[";
|
|
1147
|
+
for (const line of lines) str += line ? `\n${indentStep}${indent}${line}` : "\n";
|
|
1148
|
+
return `${str}\n${indent}]`;
|
|
1149
|
+
}
|
|
1150
|
+
return `[${fcPadding}${lines.join(" ")}${fcPadding}]`;
|
|
1151
|
+
}
|
|
1152
|
+
};
|
|
1153
|
+
function nodeValue(schema, value, options) {
|
|
1154
|
+
if (isNode(value) || value instanceof Pair) return value;
|
|
1155
|
+
return new NodeCreator(schema, options).create(value);
|
|
1156
|
+
}
|
|
1157
|
+
function nodeValues(schema, values) {
|
|
1158
|
+
let nc;
|
|
1159
|
+
return values.map((value) => {
|
|
1160
|
+
if (isNode(value) || value instanceof Pair) return value;
|
|
1161
|
+
nc ??= new NodeCreator(schema);
|
|
1162
|
+
return nc.create(value);
|
|
1163
|
+
});
|
|
1164
|
+
}
|
|
1165
|
+
function addCommentBefore({ indent, options: { commentString } }, lines, comment, chompKeep) {
|
|
1166
|
+
if (comment && chompKeep) comment = comment.replace(/^\n+/, "");
|
|
1167
|
+
if (comment) {
|
|
1168
|
+
const ic = indentComment(commentString(comment), indent);
|
|
1169
|
+
lines.push(ic.trimStart());
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
//#endregion
|
|
1173
|
+
//#region src/nodes/YAMLSet.ts
|
|
1174
|
+
var YAMLSet = class {
|
|
1175
|
+
static tagName = "tag:yaml.org,2002:set";
|
|
1176
|
+
/** A fully qualified tag */
|
|
1177
|
+
tag = "tag:yaml.org,2002:set";
|
|
1178
|
+
values = /* @__PURE__ */ new Map();
|
|
1179
|
+
constructor(schema) {
|
|
1180
|
+
Object.defineProperty(this, "schema", {
|
|
1181
|
+
value: schema,
|
|
1182
|
+
configurable: true,
|
|
1183
|
+
enumerable: false,
|
|
1184
|
+
writable: true
|
|
1185
|
+
});
|
|
1186
|
+
}
|
|
1187
|
+
get size() {
|
|
1188
|
+
return this.values.size;
|
|
1189
|
+
}
|
|
1190
|
+
add(value, options) {
|
|
1191
|
+
if (this.has(value)) return this;
|
|
1192
|
+
const mk = this.schema.mapKey(value);
|
|
1193
|
+
const node = isNode(value) ? value : new NodeCreator(this.schema, options).create(value);
|
|
1194
|
+
this.values.set(mk, node);
|
|
1195
|
+
return this;
|
|
1196
|
+
}
|
|
1197
|
+
/**
|
|
1198
|
+
* Create a copy of this set.
|
|
1199
|
+
*
|
|
1200
|
+
* @param schema - If defined, overwrites the original's schema
|
|
1201
|
+
*/
|
|
1202
|
+
clone(schema) {
|
|
1203
|
+
return cloneMapOrSet(this, schema);
|
|
1204
|
+
}
|
|
1205
|
+
/**
|
|
1206
|
+
* Remove `value` from the set.
|
|
1207
|
+
* @returns `true` if the item was found and removed.
|
|
1208
|
+
*/
|
|
1209
|
+
delete(value) {
|
|
1210
|
+
const mk = this.schema.mapKey(value);
|
|
1211
|
+
if (this.values.delete(mk)) return true;
|
|
1212
|
+
if (isNode(value)) {
|
|
1213
|
+
for (const [k, v] of this.values) if (v === value) return this.values.delete(k);
|
|
1214
|
+
}
|
|
1215
|
+
return false;
|
|
1216
|
+
}
|
|
1217
|
+
/** Return the node matching `value`, if the set includes it. */
|
|
1218
|
+
get(value) {
|
|
1219
|
+
const mk = this.schema.mapKey(value);
|
|
1220
|
+
const node = this.values.get(mk);
|
|
1221
|
+
if (node) return node;
|
|
1222
|
+
if (isNode(value)) {
|
|
1223
|
+
for (const v of this.values.values()) if (v === value) return v;
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
/** Check if the set includes `value`. */
|
|
1227
|
+
has(value) {
|
|
1228
|
+
const mk = this.schema.mapKey(value);
|
|
1229
|
+
if (this.values.has(mk)) return true;
|
|
1230
|
+
if (isNode(value)) {
|
|
1231
|
+
for (const v of this.values.values()) if (v === value) return true;
|
|
1232
|
+
}
|
|
1233
|
+
return false;
|
|
1234
|
+
}
|
|
1235
|
+
/**
|
|
1236
|
+
* Return the internal Map key matching `value`, or `undefined` if not found.
|
|
1237
|
+
*
|
|
1238
|
+
* @param allowMissing - If `true`, a key is always returned,
|
|
1239
|
+
* even if the value is not in the set.
|
|
1240
|
+
*/
|
|
1241
|
+
keyOf(value, allowMissing = false) {
|
|
1242
|
+
const mk = this.schema.mapKey(value);
|
|
1243
|
+
if (allowMissing || this.values.has(mk)) return mk;
|
|
1244
|
+
if (isNode(value)) {
|
|
1245
|
+
for (const [k, v] of this.values) if (v === value) return k;
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
/** A plain JavaScript representation of this set. */
|
|
1249
|
+
toJS(doc, ctx) {
|
|
1250
|
+
ctx ??= new ToJSContext();
|
|
1251
|
+
const set = /* @__PURE__ */ new Set();
|
|
1252
|
+
if (this.anchor) ctx.setAnchor(this, set);
|
|
1253
|
+
for (const item of this.values.values()) set.add(item.toJS(doc, ctx));
|
|
1254
|
+
return set;
|
|
1255
|
+
}
|
|
1256
|
+
toString(ctx, onComment, onChompKeep) {
|
|
1257
|
+
if (!ctx) return JSON.stringify(this);
|
|
1258
|
+
let items = this.values.values();
|
|
1259
|
+
if (ctx.sortMapEntries) items = Array.from(items, (item) => new Pair(item)).sort(ctx.sortMapEntries).map((pair) => pair.key);
|
|
1260
|
+
if (ctx.inFlow ?? this.flow) return this.#stringifyFlowSet(ctx, items);
|
|
1261
|
+
else return this.#stringifyBlockSet(ctx, items, onComment, onChompKeep);
|
|
1262
|
+
}
|
|
1263
|
+
#stringifyBlockSet(ctx, items, onComment, onChompKeep) {
|
|
1264
|
+
const { indent, indentStep, options: { commentString } } = ctx;
|
|
1265
|
+
const itemCtx = {
|
|
1266
|
+
...ctx,
|
|
1267
|
+
implicitKey: false,
|
|
1268
|
+
indent: indent + indentStep
|
|
1269
|
+
};
|
|
1270
|
+
let chompKeep = false;
|
|
1271
|
+
let res = null;
|
|
1272
|
+
for (const item of items) {
|
|
1273
|
+
if (!chompKeep && item.spaceBefore) if (typeof res === "string") res += "\n";
|
|
1274
|
+
else res = "";
|
|
1275
|
+
let cb = item.commentBefore;
|
|
1276
|
+
if (cb && chompKeep) cb = cb.replace(/^\n+/, "");
|
|
1277
|
+
if (cb) {
|
|
1278
|
+
const ic = indentComment(commentString(cb), indent).trimStart();
|
|
1279
|
+
if (typeof res === "string") res += `\n${indent}${ic}`;
|
|
1280
|
+
else res = ic;
|
|
1281
|
+
}
|
|
1282
|
+
chompKeep = false;
|
|
1283
|
+
let comment = item.comment;
|
|
1284
|
+
let str = stringify(item, itemCtx, () => comment = null, () => chompKeep = true);
|
|
1285
|
+
str = str ? `? ${str}` : "?";
|
|
1286
|
+
if (comment) {
|
|
1287
|
+
str += lineComment(str, itemCtx.indent, commentString(comment));
|
|
1288
|
+
chompKeep = false;
|
|
1289
|
+
}
|
|
1290
|
+
if (typeof res === "string") res += `\n${indent}${str}`;
|
|
1291
|
+
else res = str;
|
|
1292
|
+
}
|
|
1293
|
+
if (this.comment) {
|
|
1294
|
+
const cs = commentString(this.comment);
|
|
1295
|
+
if (typeof res === "string") res += "\n" + indentComment(cs, indent);
|
|
1296
|
+
else res = "{}" + lineComment("", indent, cs);
|
|
1297
|
+
onComment?.();
|
|
1298
|
+
} else if (chompKeep) onChompKeep?.();
|
|
1299
|
+
return res ?? "{}";
|
|
1300
|
+
}
|
|
1301
|
+
#stringifyFlowSet(ctx, items) {
|
|
1302
|
+
const { indent, indentStep, flowCollectionPadding: fcPadding, options: { commentString, lineWidth, trailingComma } } = ctx;
|
|
1303
|
+
const itemCtx = {
|
|
1304
|
+
...ctx,
|
|
1305
|
+
indent: indent + indentStep + indentStep,
|
|
1306
|
+
inFlow: true
|
|
1307
|
+
};
|
|
1308
|
+
let reqNewline = false;
|
|
1309
|
+
const lines = [];
|
|
1310
|
+
let itemsLeft = this.values.size;
|
|
1311
|
+
let singleLineWidth = 2 * fcPadding.length;
|
|
1312
|
+
for (const item of items) {
|
|
1313
|
+
itemsLeft -= 1;
|
|
1314
|
+
if (item.spaceBefore) {
|
|
1315
|
+
lines.push("");
|
|
1316
|
+
reqNewline = true;
|
|
1317
|
+
}
|
|
1318
|
+
if (item.commentBefore) {
|
|
1319
|
+
const ic = indentComment(commentString(item.commentBefore), indent);
|
|
1320
|
+
lines.push(ic.trimStart());
|
|
1321
|
+
reqNewline = true;
|
|
1322
|
+
}
|
|
1323
|
+
let comment = item.comment;
|
|
1324
|
+
if (comment) reqNewline = true;
|
|
1325
|
+
itemCtx.implicitKey = !isCollection(item);
|
|
1326
|
+
let str = stringify(item, itemCtx, () => comment = null) || "?";
|
|
1327
|
+
if (isCollection(item)) str = `? ${str}`;
|
|
1328
|
+
reqNewline ||= str.includes("\n");
|
|
1329
|
+
if (!reqNewline && lineWidth > 0) {
|
|
1330
|
+
singleLineWidth += str.length + 2;
|
|
1331
|
+
if (singleLineWidth > lineWidth) reqNewline = true;
|
|
1332
|
+
}
|
|
1333
|
+
if (itemsLeft > 0 || trailingComma && reqNewline) str += ",";
|
|
1334
|
+
if (comment) str += lineComment(str, indent + indentStep, commentString(comment));
|
|
1335
|
+
lines.push(str);
|
|
1336
|
+
}
|
|
1337
|
+
if (lines.length === 0) return "{}";
|
|
1338
|
+
if (!reqNewline) return `{${fcPadding}${lines.join(" ")}${fcPadding}}`;
|
|
1339
|
+
let str = "{";
|
|
1340
|
+
for (const line of lines) str += line ? `\n${indentStep}${indent}${line}` : "\n";
|
|
1341
|
+
return `${str}\n${indent}}`;
|
|
1342
|
+
}
|
|
1343
|
+
};
|
|
1344
|
+
//#endregion
|
|
1345
|
+
//#region src/nodes/identity.ts
|
|
1346
|
+
/** Type predicate for collections */
|
|
1347
|
+
const isCollection = (node) => node instanceof YAMLMap || node instanceof YAMLSeq || node instanceof YAMLSet;
|
|
1348
|
+
/** Type predicate for `Node` values */
|
|
1349
|
+
const isNode = (node) => node instanceof Scalar || node instanceof Alias || node instanceof YAMLMap || node instanceof YAMLSeq || node instanceof YAMLSet;
|
|
1350
|
+
//#endregion
|
|
1351
|
+
//#region src/stringify/stringifyPair.ts
|
|
1352
|
+
function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
|
|
1353
|
+
const { indent, indentStep, options: { commentString, indentSeq, simpleKeys } } = ctx;
|
|
1354
|
+
if (simpleKeys) {
|
|
1355
|
+
if (key.comment) throw new Error("With simple keys, key nodes cannot have comments");
|
|
1356
|
+
if (isCollection(key)) throw new Error("With simple keys, collection cannot be used as a key value");
|
|
1357
|
+
}
|
|
1358
|
+
let explicitKey = !simpleKeys && (!(key instanceof Scalar) || key.type === Scalar.BLOCK_FOLDED || key.type === Scalar.BLOCK_LITERAL);
|
|
1359
|
+
ctx = {
|
|
1360
|
+
...ctx,
|
|
1361
|
+
implicitKey: !explicitKey,
|
|
1362
|
+
indent: indent + indentStep
|
|
1363
|
+
};
|
|
1364
|
+
let keyComment = key.comment;
|
|
1365
|
+
let keyCommentDone = false;
|
|
1366
|
+
let chompKeep = false;
|
|
1367
|
+
let str = stringify(key, ctx, () => keyCommentDone = true, () => chompKeep = true);
|
|
1368
|
+
if (!explicitKey && !ctx.inFlow && str.length > 1024) {
|
|
1369
|
+
if (simpleKeys) throw new Error("With simple keys, single line scalar must not span more than 1024 characters");
|
|
1370
|
+
explicitKey = true;
|
|
1371
|
+
}
|
|
1372
|
+
if (ctx.inFlow) {
|
|
1373
|
+
if (value == null) {
|
|
1374
|
+
if (keyCommentDone && onComment) onComment();
|
|
1375
|
+
return str === "" ? "?" : explicitKey ? `? ${str}` : `${str}:`;
|
|
1376
|
+
}
|
|
1377
|
+
} else if (value == null && explicitKey) {
|
|
1378
|
+
str = `? ${str}`;
|
|
1379
|
+
if (keyComment && !keyCommentDone) str += lineComment(str, ctx.indent, commentString(keyComment));
|
|
1380
|
+
else if (chompKeep && onChompKeep) onChompKeep();
|
|
1381
|
+
return str;
|
|
1382
|
+
}
|
|
1383
|
+
if (keyCommentDone) keyComment = null;
|
|
1384
|
+
if (explicitKey) {
|
|
1385
|
+
if (keyComment) str += lineComment(str, ctx.indent, commentString(keyComment));
|
|
1386
|
+
str = `? ${str}\n${indent}:`;
|
|
1387
|
+
} else {
|
|
1388
|
+
str = `${str}:`;
|
|
1389
|
+
if (keyComment) str += lineComment(str, ctx.indent, commentString(keyComment));
|
|
1390
|
+
}
|
|
1391
|
+
let vsb, vcb, valueComment;
|
|
1392
|
+
if (value) {
|
|
1393
|
+
vsb = !!value.spaceBefore;
|
|
1394
|
+
vcb = value.commentBefore;
|
|
1395
|
+
valueComment = value.comment;
|
|
1396
|
+
} else {
|
|
1397
|
+
vsb = false;
|
|
1398
|
+
vcb = null;
|
|
1399
|
+
valueComment = null;
|
|
1400
|
+
}
|
|
1401
|
+
ctx.implicitKey = false;
|
|
1402
|
+
if (!explicitKey && !keyComment && value instanceof Scalar) ctx.indentAtStart = str.length + 1;
|
|
1403
|
+
chompKeep = false;
|
|
1404
|
+
if (!indentSeq && indentStep.length >= 2 && !ctx.inFlow && !explicitKey && value instanceof YAMLSeq && !value.flow && !value.tag && !value.anchor) ctx.indent = ctx.indent.substring(2);
|
|
1405
|
+
let valueCommentDone = false;
|
|
1406
|
+
const valueStr = stringify(value, ctx, () => valueCommentDone = true, () => chompKeep = true);
|
|
1407
|
+
let ws = " ";
|
|
1408
|
+
if (keyComment || vsb || vcb) {
|
|
1409
|
+
ws = vsb ? "\n" : "";
|
|
1410
|
+
if (vcb) {
|
|
1411
|
+
const cs = commentString(vcb);
|
|
1412
|
+
ws += `\n${indentComment(cs, ctx.indent)}`;
|
|
1413
|
+
}
|
|
1414
|
+
if (valueStr === "" && !ctx.inFlow) {
|
|
1415
|
+
if (ws === "\n" && valueComment) ws = "\n\n";
|
|
1416
|
+
} else ws += `\n${ctx.indent}`;
|
|
1417
|
+
} else if (!explicitKey && isCollection(value)) {
|
|
1418
|
+
const vs0 = valueStr[0];
|
|
1419
|
+
const nl0 = valueStr.indexOf("\n");
|
|
1420
|
+
const hasNewline = nl0 !== -1;
|
|
1421
|
+
const flow = ctx.inFlow ?? value.flow ?? value.size === 0;
|
|
1422
|
+
if (hasNewline || !flow) {
|
|
1423
|
+
let hasPropsLine = false;
|
|
1424
|
+
if (hasNewline && (vs0 === "&" || vs0 === "!")) {
|
|
1425
|
+
let sp0 = valueStr.indexOf(" ");
|
|
1426
|
+
if (vs0 === "&" && sp0 !== -1 && sp0 < nl0 && valueStr[sp0 + 1] === "!") sp0 = valueStr.indexOf(" ", sp0 + 1);
|
|
1427
|
+
if (sp0 === -1 || nl0 < sp0) hasPropsLine = true;
|
|
1428
|
+
}
|
|
1429
|
+
if (!hasPropsLine) ws = `\n${ctx.indent}`;
|
|
1430
|
+
}
|
|
1431
|
+
} else if (valueStr === "" || valueStr[0] === "\n") ws = "";
|
|
1432
|
+
str += ws + valueStr;
|
|
1433
|
+
if (ctx.inFlow) {
|
|
1434
|
+
if (valueCommentDone && onComment) onComment();
|
|
1435
|
+
} else if (valueComment && !valueCommentDone) str += lineComment(str, ctx.indent, commentString(valueComment));
|
|
1436
|
+
else if (chompKeep && onChompKeep) onChompKeep();
|
|
1437
|
+
return str;
|
|
1438
|
+
}
|
|
1439
|
+
//#endregion
|
|
1440
|
+
//#region src/nodes/Pair.ts
|
|
1441
|
+
var Pair = class Pair {
|
|
1442
|
+
key;
|
|
1443
|
+
value;
|
|
1444
|
+
constructor(key, value = null) {
|
|
1445
|
+
this.key = key;
|
|
1446
|
+
this.value = value;
|
|
1447
|
+
}
|
|
1448
|
+
clone(schema) {
|
|
1449
|
+
return new Pair(this.key.clone(schema), this.value?.clone(schema) ?? null);
|
|
1450
|
+
}
|
|
1451
|
+
toJS(doc, ctx) {
|
|
1452
|
+
return addPairToJSMap(doc, ctx, ctx.mapAsMap ? /* @__PURE__ */ new Map() : {}, this);
|
|
1453
|
+
}
|
|
1454
|
+
toString(ctx, onComment, onChompKeep) {
|
|
1455
|
+
return ctx?.doc ? stringifyPair(this, ctx, onComment, onChompKeep) : JSON.stringify(this);
|
|
1456
|
+
}
|
|
1457
|
+
};
|
|
1458
|
+
//#endregion
|
|
1459
|
+
//#region src/nodes/Alias.ts
|
|
1460
|
+
var Alias = class Alias {
|
|
1461
|
+
source;
|
|
1462
|
+
constructor(source) {
|
|
1463
|
+
this.source = source;
|
|
1464
|
+
Object.defineProperty(this, "tag", { set() {
|
|
1465
|
+
throw new Error("Alias nodes cannot have tags");
|
|
1466
|
+
} });
|
|
1467
|
+
}
|
|
1468
|
+
/** Create a copy of this node. */
|
|
1469
|
+
clone() {
|
|
1470
|
+
const copy = Object.create(Object.getPrototypeOf(this), Object.getOwnPropertyDescriptors(this));
|
|
1471
|
+
if (this.range) copy.range = [...this.range];
|
|
1472
|
+
return copy;
|
|
1473
|
+
}
|
|
1474
|
+
/**
|
|
1475
|
+
* Resolve the value of this alias within `doc`, finding the last
|
|
1476
|
+
* instance of the `source` anchor before this node.
|
|
1477
|
+
*/
|
|
1478
|
+
resolve(doc, ctx) {
|
|
1479
|
+
if (ctx?.maxAliasCount === 0) throw new ReferenceError("Alias resolution is disabled");
|
|
1480
|
+
let nodes;
|
|
1481
|
+
if (ctx?.aliasResolveCache) nodes = ctx.aliasResolveCache;
|
|
1482
|
+
else {
|
|
1483
|
+
nodes = [];
|
|
1484
|
+
visit(doc, { Node: (_key, node) => {
|
|
1485
|
+
if (node instanceof Alias || node.anchor) nodes.push(node);
|
|
1486
|
+
} });
|
|
1487
|
+
if (ctx) ctx.aliasResolveCache = nodes;
|
|
1488
|
+
}
|
|
1489
|
+
let found = void 0;
|
|
1490
|
+
for (const node of nodes) {
|
|
1491
|
+
if (node === this) break;
|
|
1492
|
+
if (node.anchor === this.source) found = node;
|
|
1493
|
+
}
|
|
1494
|
+
return found;
|
|
1495
|
+
}
|
|
1496
|
+
/** A plain JavaScript representation of the resolved value of this alias. */
|
|
1497
|
+
toJS(doc, ctx) {
|
|
1498
|
+
if (!doc?.schema) throw new TypeError("A document argument is required");
|
|
1499
|
+
ctx ??= new ToJSContext();
|
|
1500
|
+
const { anchors, maxAliasCount } = ctx;
|
|
1501
|
+
const source = this.resolve(doc, ctx);
|
|
1502
|
+
if (!source) {
|
|
1503
|
+
const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`;
|
|
1504
|
+
throw new ReferenceError(msg);
|
|
1505
|
+
}
|
|
1506
|
+
let data = anchors.get(source);
|
|
1507
|
+
if (!data) {
|
|
1508
|
+
source.toJS(doc, ctx);
|
|
1509
|
+
data = anchors.get(source);
|
|
1510
|
+
}
|
|
1511
|
+
/* istanbul ignore if */
|
|
1512
|
+
if (data?.res === void 0) throw new ReferenceError("This should not happen: Alias anchor was not resolved?");
|
|
1513
|
+
if (maxAliasCount >= 0) {
|
|
1514
|
+
data.count += 1;
|
|
1515
|
+
data.aliasCount ||= getAliasCount(doc, ctx, source, anchors);
|
|
1516
|
+
if (data.count * data.aliasCount > maxAliasCount) throw new ReferenceError("Excessive alias count indicates a resource exhaustion attack");
|
|
1517
|
+
}
|
|
1518
|
+
return data.res;
|
|
1519
|
+
}
|
|
1520
|
+
toString(ctx, _onComment, _onChompKeep) {
|
|
1521
|
+
const src = `*${this.source}`;
|
|
1522
|
+
if (ctx) {
|
|
1523
|
+
anchorIsValid(this.source);
|
|
1524
|
+
if (ctx.options.verifyAliasOrder && !ctx.anchors.has(this.source)) {
|
|
1525
|
+
const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`;
|
|
1526
|
+
throw new Error(msg);
|
|
1527
|
+
}
|
|
1528
|
+
if (ctx.implicitKey) return `${src} `;
|
|
1529
|
+
}
|
|
1530
|
+
return src;
|
|
1531
|
+
}
|
|
1532
|
+
};
|
|
1533
|
+
function getAliasCount(doc, ctx, node, anchors) {
|
|
1534
|
+
if (node instanceof Alias) {
|
|
1535
|
+
const source = node.resolve(doc, ctx);
|
|
1536
|
+
const anchor = anchors && source && anchors.get(source);
|
|
1537
|
+
return anchor ? anchor.count * anchor.aliasCount : 0;
|
|
1538
|
+
} else if (node instanceof Pair) {
|
|
1539
|
+
const kc = getAliasCount(doc, ctx, node.key, anchors);
|
|
1540
|
+
const vc = getAliasCount(doc, ctx, node.value, anchors);
|
|
1541
|
+
return Math.max(kc, vc);
|
|
1542
|
+
} else if (Array.isArray(node)) {
|
|
1543
|
+
let count = 0;
|
|
1544
|
+
for (const item of node) {
|
|
1545
|
+
const c = getAliasCount(doc, ctx, item, anchors);
|
|
1546
|
+
if (c > count) count = c;
|
|
1547
|
+
}
|
|
1548
|
+
return count;
|
|
1549
|
+
}
|
|
1550
|
+
return 1;
|
|
1551
|
+
}
|
|
1552
|
+
//#endregion
|
|
1553
|
+
//#region src/schema/common/map.ts
|
|
1554
|
+
const map = {
|
|
1555
|
+
collection: "map",
|
|
1556
|
+
default: true,
|
|
1557
|
+
nodeClass: YAMLMap,
|
|
1558
|
+
tag: "tag:yaml.org,2002:map",
|
|
1559
|
+
createNode(nc, obj) {
|
|
1560
|
+
return YAMLMap.create(nc, obj);
|
|
1561
|
+
},
|
|
1562
|
+
resolve(map, onError) {
|
|
1563
|
+
if (!(map instanceof YAMLMap)) onError("Expected a mapping for this tag");
|
|
1564
|
+
return map;
|
|
1565
|
+
}
|
|
1566
|
+
};
|
|
1567
|
+
//#endregion
|
|
1568
|
+
//#region src/schema/common/seq.ts
|
|
1569
|
+
const seq = {
|
|
1570
|
+
collection: "seq",
|
|
1571
|
+
default: true,
|
|
1572
|
+
nodeClass: YAMLSeq,
|
|
1573
|
+
tag: "tag:yaml.org,2002:seq",
|
|
1574
|
+
createNode(nc, obj) {
|
|
1575
|
+
return YAMLSeq.create(nc, obj);
|
|
1576
|
+
},
|
|
1577
|
+
resolve(seq, onError) {
|
|
1578
|
+
if (!(seq instanceof YAMLSeq)) onError("Expected a sequence for this tag");
|
|
1579
|
+
return seq;
|
|
1580
|
+
}
|
|
1581
|
+
};
|
|
1582
|
+
//#endregion
|
|
1583
|
+
//#region src/schema/common/string.ts
|
|
1584
|
+
const string = {
|
|
1585
|
+
identify: (value) => typeof value === "string",
|
|
1586
|
+
default: true,
|
|
1587
|
+
tag: "tag:yaml.org,2002:str",
|
|
1588
|
+
resolve: (str) => str,
|
|
1589
|
+
stringify(item, ctx, onComment, onChompKeep) {
|
|
1590
|
+
ctx = Object.assign({ actualString: true }, ctx);
|
|
1591
|
+
return stringifyString(item, ctx, onComment, onChompKeep);
|
|
1592
|
+
}
|
|
1593
|
+
};
|
|
1594
|
+
//#endregion
|
|
1595
|
+
//#region src/schema/common/null.ts
|
|
1596
|
+
const nullTag = {
|
|
1597
|
+
identify: (value) => value == null,
|
|
1598
|
+
createNode: () => new Scalar(null),
|
|
1599
|
+
default: true,
|
|
1600
|
+
tag: "tag:yaml.org,2002:null",
|
|
1601
|
+
test: /^(?:~|[Nn]ull|NULL)?$/,
|
|
1602
|
+
resolve: () => new Scalar(null),
|
|
1603
|
+
stringify: ({ source }, ctx) => typeof source === "string" && nullTag.test.test(source) ? source : ctx.options.nullStr
|
|
1604
|
+
};
|
|
1605
|
+
//#endregion
|
|
1606
|
+
//#region src/schema/core/bool.ts
|
|
1607
|
+
const boolTag = {
|
|
1608
|
+
identify: (value) => typeof value === "boolean",
|
|
1609
|
+
default: true,
|
|
1610
|
+
tag: "tag:yaml.org,2002:bool",
|
|
1611
|
+
test: /^(?:[Tt]rue|TRUE|[Ff]alse|FALSE)$/,
|
|
1612
|
+
resolve: (str) => new Scalar(str[0] === "t" || str[0] === "T"),
|
|
1613
|
+
stringify({ source, value }, ctx) {
|
|
1614
|
+
if (source && boolTag.test.test(source)) {
|
|
1615
|
+
if (value === (source[0] === "t" || source[0] === "T")) return source;
|
|
1616
|
+
}
|
|
1617
|
+
return value ? ctx.options.trueStr : ctx.options.falseStr;
|
|
1618
|
+
}
|
|
1619
|
+
};
|
|
1620
|
+
//#endregion
|
|
1621
|
+
//#region src/stringify/stringifyNumber.ts
|
|
1622
|
+
function stringifyNumber({ format, minFractionDigits, tag, value }) {
|
|
1623
|
+
if (typeof value === "bigint") return String(value);
|
|
1624
|
+
const num = typeof value === "number" ? value : Number(value);
|
|
1625
|
+
if (!isFinite(num)) return isNaN(num) ? ".nan" : num < 0 ? "-.inf" : ".inf";
|
|
1626
|
+
let n = Object.is(value, -0) ? "-0" : JSON.stringify(value);
|
|
1627
|
+
if (!format && minFractionDigits && (!tag || tag === "tag:yaml.org,2002:float") && /^-?\d/.test(n) && !n.includes("e")) {
|
|
1628
|
+
let i = n.indexOf(".");
|
|
1629
|
+
if (i < 0) {
|
|
1630
|
+
i = n.length;
|
|
1631
|
+
n += ".";
|
|
1632
|
+
}
|
|
1633
|
+
let d = minFractionDigits - (n.length - i - 1);
|
|
1634
|
+
while (d-- > 0) n += "0";
|
|
1635
|
+
}
|
|
1636
|
+
return n;
|
|
1637
|
+
}
|
|
1638
|
+
//#endregion
|
|
1639
|
+
//#region src/schema/core/float.ts
|
|
1640
|
+
const floatNaN$1 = {
|
|
1641
|
+
identify: (value) => typeof value === "number",
|
|
1642
|
+
default: true,
|
|
1643
|
+
tag: "tag:yaml.org,2002:float",
|
|
1644
|
+
test: /^(?:[-+]?\.(?:inf|Inf|INF)|\.nan|\.NaN|\.NAN)$/,
|
|
1645
|
+
resolve: (str) => str.slice(-3).toLowerCase() === "nan" ? NaN : str[0] === "-" ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY,
|
|
1646
|
+
stringify: stringifyNumber
|
|
1647
|
+
};
|
|
1648
|
+
const floatExp$1 = {
|
|
1649
|
+
identify: (value) => typeof value === "number",
|
|
1650
|
+
default: true,
|
|
1651
|
+
tag: "tag:yaml.org,2002:float",
|
|
1652
|
+
format: "EXP",
|
|
1653
|
+
test: /^[-+]?(?:\.[0-9]+|[0-9]+(?:\.[0-9]*)?)[eE][-+]?[0-9]+$/,
|
|
1654
|
+
resolve: (str) => parseFloat(str),
|
|
1655
|
+
stringify(node) {
|
|
1656
|
+
const num = Number(node.value);
|
|
1657
|
+
return isFinite(num) ? num.toExponential() : stringifyNumber(node);
|
|
1658
|
+
}
|
|
1659
|
+
};
|
|
1660
|
+
const float$1 = {
|
|
1661
|
+
identify: (value) => typeof value === "number",
|
|
1662
|
+
default: true,
|
|
1663
|
+
tag: "tag:yaml.org,2002:float",
|
|
1664
|
+
test: /^[-+]?(?:\.[0-9]+|[0-9]+\.[0-9]*)$/,
|
|
1665
|
+
resolve(str) {
|
|
1666
|
+
const node = new Scalar(parseFloat(str));
|
|
1667
|
+
const dot = str.indexOf(".");
|
|
1668
|
+
if (dot !== -1 && str[str.length - 1] === "0") node.minFractionDigits = str.length - dot - 1;
|
|
1669
|
+
return node;
|
|
1670
|
+
},
|
|
1671
|
+
stringify: stringifyNumber
|
|
1672
|
+
};
|
|
1673
|
+
//#endregion
|
|
1674
|
+
//#region src/schema/core/int.ts
|
|
1675
|
+
const intIdentify$2 = (value) => typeof value === "bigint" || Number.isInteger(value);
|
|
1676
|
+
const intResolve$1 = (str, offset, radix, { intAsBigInt }) => intAsBigInt ? BigInt(str) : parseInt(str.substring(offset), radix);
|
|
1677
|
+
function intStringify$1(node, radix, prefix) {
|
|
1678
|
+
const { value } = node;
|
|
1679
|
+
if (intIdentify$2(value) && value >= 0) return prefix + value.toString(radix);
|
|
1680
|
+
return stringifyNumber(node);
|
|
1681
|
+
}
|
|
1682
|
+
const intOct$1 = {
|
|
1683
|
+
identify: (value) => intIdentify$2(value) && value >= 0,
|
|
1684
|
+
default: true,
|
|
1685
|
+
tag: "tag:yaml.org,2002:int",
|
|
1686
|
+
format: "OCT",
|
|
1687
|
+
test: /^0o[0-7]+$/,
|
|
1688
|
+
resolve: (str, _onError, opt) => intResolve$1(str, 2, 8, opt),
|
|
1689
|
+
stringify: (node) => intStringify$1(node, 8, "0o")
|
|
1690
|
+
};
|
|
1691
|
+
const int$1 = {
|
|
1692
|
+
identify: intIdentify$2,
|
|
1693
|
+
default: true,
|
|
1694
|
+
tag: "tag:yaml.org,2002:int",
|
|
1695
|
+
test: /^[-+]?[0-9]+$/,
|
|
1696
|
+
resolve: (str, _onError, opt) => intResolve$1(str, 0, 10, opt),
|
|
1697
|
+
stringify: stringifyNumber
|
|
1698
|
+
};
|
|
1699
|
+
const intHex$1 = {
|
|
1700
|
+
identify: (value) => intIdentify$2(value) && value >= 0,
|
|
1701
|
+
default: true,
|
|
1702
|
+
tag: "tag:yaml.org,2002:int",
|
|
1703
|
+
format: "HEX",
|
|
1704
|
+
test: /^0x[0-9a-fA-F]+$/,
|
|
1705
|
+
resolve: (str, _onError, opt) => intResolve$1(str, 2, 16, opt),
|
|
1706
|
+
stringify: (node) => intStringify$1(node, 16, "0x")
|
|
1707
|
+
};
|
|
1708
|
+
//#endregion
|
|
1709
|
+
//#region src/schema/core/schema.ts
|
|
1710
|
+
const schema$2 = [
|
|
1711
|
+
map,
|
|
1712
|
+
seq,
|
|
1713
|
+
string,
|
|
1714
|
+
nullTag,
|
|
1715
|
+
boolTag,
|
|
1716
|
+
intOct$1,
|
|
1717
|
+
int$1,
|
|
1718
|
+
intHex$1,
|
|
1719
|
+
floatNaN$1,
|
|
1720
|
+
floatExp$1,
|
|
1721
|
+
float$1
|
|
1722
|
+
];
|
|
1723
|
+
//#endregion
|
|
1724
|
+
//#region src/schema/json/schema.ts
|
|
1725
|
+
function intIdentify$1(value) {
|
|
1726
|
+
return typeof value === "bigint" || Number.isInteger(value);
|
|
1727
|
+
}
|
|
1728
|
+
const stringifyJSON = ({ value }) => JSON.stringify(value);
|
|
1729
|
+
const jsonScalars = [
|
|
1730
|
+
{
|
|
1731
|
+
identify: (value) => typeof value === "string",
|
|
1732
|
+
default: true,
|
|
1733
|
+
tag: "tag:yaml.org,2002:str",
|
|
1734
|
+
resolve: (str) => str,
|
|
1735
|
+
stringify: stringifyJSON
|
|
1736
|
+
},
|
|
1737
|
+
{
|
|
1738
|
+
identify: (value) => value == null,
|
|
1739
|
+
createNode: () => new Scalar(null),
|
|
1740
|
+
default: true,
|
|
1741
|
+
tag: "tag:yaml.org,2002:null",
|
|
1742
|
+
test: /^null$/,
|
|
1743
|
+
resolve: () => null,
|
|
1744
|
+
stringify: stringifyJSON
|
|
1745
|
+
},
|
|
1746
|
+
{
|
|
1747
|
+
identify: (value) => typeof value === "boolean",
|
|
1748
|
+
default: true,
|
|
1749
|
+
tag: "tag:yaml.org,2002:bool",
|
|
1750
|
+
test: /^true$|^false$/,
|
|
1751
|
+
resolve: (str) => str === "true",
|
|
1752
|
+
stringify: stringifyJSON
|
|
1753
|
+
},
|
|
1754
|
+
{
|
|
1755
|
+
identify: intIdentify$1,
|
|
1756
|
+
default: true,
|
|
1757
|
+
tag: "tag:yaml.org,2002:int",
|
|
1758
|
+
test: /^-?(?:0|[1-9][0-9]*)$/,
|
|
1759
|
+
resolve: (str, _onError, { intAsBigInt }) => intAsBigInt ? BigInt(str) : parseInt(str, 10),
|
|
1760
|
+
stringify: ({ value }) => intIdentify$1(value) ? value.toString() : JSON.stringify(value)
|
|
1761
|
+
},
|
|
1762
|
+
{
|
|
1763
|
+
identify: (value) => typeof value === "number",
|
|
1764
|
+
default: true,
|
|
1765
|
+
tag: "tag:yaml.org,2002:float",
|
|
1766
|
+
test: /^-?(?:0|[1-9][0-9]*)(?:\.[0-9]*)?(?:[eE][-+]?[0-9]+)?$/,
|
|
1767
|
+
resolve: (str) => parseFloat(str),
|
|
1768
|
+
stringify: stringifyJSON
|
|
1769
|
+
}
|
|
1770
|
+
];
|
|
1771
|
+
const jsonError = {
|
|
1772
|
+
default: true,
|
|
1773
|
+
tag: "",
|
|
1774
|
+
test: /^/,
|
|
1775
|
+
resolve(str, onError) {
|
|
1776
|
+
onError(`Unresolved plain scalar ${JSON.stringify(str)}`);
|
|
1777
|
+
return str;
|
|
1778
|
+
}
|
|
1779
|
+
};
|
|
1780
|
+
const schema$1 = [
|
|
1781
|
+
map,
|
|
1782
|
+
seq,
|
|
1783
|
+
...jsonScalars,
|
|
1784
|
+
jsonError
|
|
1785
|
+
];
|
|
1786
|
+
//#endregion
|
|
1787
|
+
//#region src/schema/yaml-1.1/binary.ts
|
|
1788
|
+
const binary = {
|
|
1789
|
+
identify: (value) => value instanceof Uint8Array,
|
|
1790
|
+
default: false,
|
|
1791
|
+
tag: "tag:yaml.org,2002:binary",
|
|
1792
|
+
resolve(src, onError) {
|
|
1793
|
+
if (typeof Buffer === "function") return Buffer.from(src, "base64");
|
|
1794
|
+
else if (typeof Uint8Array.fromBase64 === "function") return Uint8Array.fromBase64(src);
|
|
1795
|
+
else if (typeof atob === "function") {
|
|
1796
|
+
const str = atob(src.replace(/[\n\r]/g, ""));
|
|
1797
|
+
const buffer = new Uint8Array(str.length);
|
|
1798
|
+
for (let i = 0; i < str.length; ++i) buffer[i] = str.charCodeAt(i);
|
|
1799
|
+
return buffer;
|
|
1800
|
+
} else {
|
|
1801
|
+
onError("This environment does not support reading binary tags; either Buffer or atob is required");
|
|
1802
|
+
return src;
|
|
1803
|
+
}
|
|
1804
|
+
},
|
|
1805
|
+
stringify({ comment, type, value }, ctx, onComment, onChompKeep) {
|
|
1806
|
+
if (!value) return "";
|
|
1807
|
+
const buf = value;
|
|
1808
|
+
let str;
|
|
1809
|
+
if (typeof buf.toBase64 === "function") str = buf.toBase64();
|
|
1810
|
+
else if (typeof Buffer === "function") str = buf instanceof Buffer ? buf.toString("base64") : Buffer.from(buf.buffer).toString("base64");
|
|
1811
|
+
else if (typeof btoa === "function") {
|
|
1812
|
+
let s = "";
|
|
1813
|
+
for (let i = 0; i < buf.length; ++i) s += String.fromCharCode(buf[i]);
|
|
1814
|
+
str = btoa(s);
|
|
1815
|
+
} else throw new Error("This environment does not support writing binary tags; either Buffer or btoa is required");
|
|
1816
|
+
type ??= Scalar.BLOCK_LITERAL;
|
|
1817
|
+
if (type !== Scalar.QUOTE_DOUBLE) {
|
|
1818
|
+
const lineWidth = Math.max(ctx.options.lineWidth - ctx.indent.length, ctx.options.minContentWidth);
|
|
1819
|
+
const n = Math.ceil(str.length / lineWidth);
|
|
1820
|
+
const lines = new Array(n);
|
|
1821
|
+
for (let i = 0, o = 0; i < n; ++i, o += lineWidth) lines[i] = str.substr(o, lineWidth);
|
|
1822
|
+
str = lines.join(type === Scalar.BLOCK_LITERAL ? "\n" : " ");
|
|
1823
|
+
}
|
|
1824
|
+
return stringifyString({
|
|
1825
|
+
comment,
|
|
1826
|
+
type,
|
|
1827
|
+
value: str
|
|
1828
|
+
}, ctx, onComment, onChompKeep);
|
|
1829
|
+
}
|
|
1830
|
+
};
|
|
1831
|
+
//#endregion
|
|
1832
|
+
//#region src/schema/yaml-1.1/pairs.ts
|
|
1833
|
+
function resolvePairs(seq, onError) {
|
|
1834
|
+
if (seq instanceof YAMLSeq) for (let i = 0; i < seq.length; ++i) {
|
|
1835
|
+
const item = seq[i];
|
|
1836
|
+
if (item instanceof Pair) continue;
|
|
1837
|
+
if (item instanceof YAMLMap) {
|
|
1838
|
+
if (item.size > 1) onError("Each pair must have its own sequence indicator");
|
|
1839
|
+
const pair = item.values.values().next().value ?? new Pair(new Scalar(null));
|
|
1840
|
+
if (item.commentBefore) pair.key.commentBefore = pair.key.commentBefore ? `${item.commentBefore}\n${pair.key.commentBefore}` : item.commentBefore;
|
|
1841
|
+
if (item.comment) {
|
|
1842
|
+
const cn = pair.value ?? pair.key;
|
|
1843
|
+
cn.comment = cn.comment ? `${item.comment}\n${cn.comment}` : item.comment;
|
|
1844
|
+
}
|
|
1845
|
+
seq[i] = pair;
|
|
1846
|
+
} else seq[i] = new Pair(item, null);
|
|
1847
|
+
}
|
|
1848
|
+
else onError("Expected a sequence for this tag");
|
|
1849
|
+
return seq;
|
|
1850
|
+
}
|
|
1851
|
+
function createPairs(nc, iterable) {
|
|
1852
|
+
const pairs = new YAMLSeq(nc.schema);
|
|
1853
|
+
pairs.tag = "tag:yaml.org,2002:pairs";
|
|
1854
|
+
let i = 0;
|
|
1855
|
+
if (iterable && Symbol.iterator in Object(iterable)) for (let it of iterable) {
|
|
1856
|
+
if (typeof nc.replacer === "function") it = nc.replacer.call(iterable, String(i++), it);
|
|
1857
|
+
let key, value;
|
|
1858
|
+
if (Array.isArray(it)) if (it.length === 2) {
|
|
1859
|
+
key = it[0];
|
|
1860
|
+
value = it[1];
|
|
1861
|
+
} else throw new TypeError(`Expected [key, value] tuple: ${it}`);
|
|
1862
|
+
else if (it && it instanceof Object) {
|
|
1863
|
+
const keys = Object.keys(it);
|
|
1864
|
+
if (keys.length === 1) {
|
|
1865
|
+
key = keys[0];
|
|
1866
|
+
value = it[key];
|
|
1867
|
+
} else throw new TypeError(`Expected tuple with one key, not ${keys.length} keys`);
|
|
1868
|
+
} else key = it;
|
|
1869
|
+
pairs.push(nc.createPair(key, value));
|
|
1870
|
+
}
|
|
1871
|
+
return pairs;
|
|
1872
|
+
}
|
|
1873
|
+
const pairs = {
|
|
1874
|
+
collection: "seq",
|
|
1875
|
+
default: false,
|
|
1876
|
+
tag: "tag:yaml.org,2002:pairs",
|
|
1877
|
+
resolve: resolvePairs,
|
|
1878
|
+
createNode: createPairs
|
|
1879
|
+
};
|
|
1880
|
+
//#endregion
|
|
1881
|
+
//#region src/schema/yaml-1.1/omap.ts
|
|
1882
|
+
var YAMLOMap = class extends YAMLSeq {
|
|
1883
|
+
constructor(schema, elements) {
|
|
1884
|
+
super(schema, elements);
|
|
1885
|
+
this.tag = omap.tag;
|
|
1886
|
+
}
|
|
1887
|
+
/**
|
|
1888
|
+
* Append new pairs to the omap, and return its new length.
|
|
1889
|
+
*/
|
|
1890
|
+
push(...pairs) {
|
|
1891
|
+
for (const pair of pairs) if (pair instanceof Pair) super.push(pair);
|
|
1892
|
+
else throw new Error("Omap only supports Pair values");
|
|
1893
|
+
return this.length;
|
|
1894
|
+
}
|
|
1895
|
+
/**
|
|
1896
|
+
* Set a pair in this omap.
|
|
1897
|
+
*
|
|
1898
|
+
* Throws if `idx` is not an integer.
|
|
1899
|
+
*/
|
|
1900
|
+
set(idx, pair) {
|
|
1901
|
+
if (!Number.isInteger(idx)) throw new TypeError(`Expected an integer, not ${JSON.stringify(idx)}.`);
|
|
1902
|
+
if (idx < 0) {
|
|
1903
|
+
if (idx < -this.length) throw new RangeError(`Invalid index ${idx}`);
|
|
1904
|
+
idx += this.length;
|
|
1905
|
+
}
|
|
1906
|
+
this[idx] = pair;
|
|
1907
|
+
}
|
|
1908
|
+
/**
|
|
1909
|
+
* The returned value actually has type `Map<unknown, unknown>`,
|
|
1910
|
+
* but TypeScript won't allow widening the signature of a child method.
|
|
1911
|
+
*/
|
|
1912
|
+
toJS(doc, ctx) {
|
|
1913
|
+
if (!ctx) return super.toJS(doc);
|
|
1914
|
+
const map = /* @__PURE__ */ new Map();
|
|
1915
|
+
if (this.anchor) ctx.anchors.set(this, {
|
|
1916
|
+
aliasCount: 0,
|
|
1917
|
+
count: 1,
|
|
1918
|
+
res: map
|
|
1919
|
+
});
|
|
1920
|
+
for (const pair of this) {
|
|
1921
|
+
const key = pair.key.toJS(doc, ctx);
|
|
1922
|
+
const value = pair.value ? pair.value.toJS(doc, ctx) : null;
|
|
1923
|
+
if (map.has(key)) throw new Error("Ordered maps must not include duplicate keys");
|
|
1924
|
+
map.set(key, value);
|
|
1925
|
+
}
|
|
1926
|
+
return map;
|
|
1927
|
+
}
|
|
1928
|
+
toString(ctx, onComment, onChompKeep) {
|
|
1929
|
+
const keys = /* @__PURE__ */ new Set();
|
|
1930
|
+
for (const pair of this) {
|
|
1931
|
+
const key = this.schema.mapKey(pair);
|
|
1932
|
+
if (keys.has(key)) throw new Error("Ordered maps must not include duplicate keys");
|
|
1933
|
+
keys.add(key);
|
|
1934
|
+
}
|
|
1935
|
+
return super.toString(ctx, onComment, onChompKeep);
|
|
1936
|
+
}
|
|
1937
|
+
};
|
|
1938
|
+
const omap = {
|
|
1939
|
+
collection: "seq",
|
|
1940
|
+
identify: (value) => value instanceof Map,
|
|
1941
|
+
nodeClass: YAMLOMap,
|
|
1942
|
+
default: false,
|
|
1943
|
+
tag: "tag:yaml.org,2002:omap",
|
|
1944
|
+
createNode(nc, iterable) {
|
|
1945
|
+
const pairs = createPairs(nc, iterable);
|
|
1946
|
+
return new YAMLOMap(nc.schema, pairs);
|
|
1947
|
+
},
|
|
1948
|
+
resolve(seq, onError) {
|
|
1949
|
+
const pairs = resolvePairs(seq, onError);
|
|
1950
|
+
const seenKeys = [];
|
|
1951
|
+
for (const { key } of pairs) if (key instanceof Scalar) if (seenKeys.includes(key.value)) onError(`Ordered maps must not include duplicate keys: ${key.value}`);
|
|
1952
|
+
else seenKeys.push(key.value);
|
|
1953
|
+
return Object.assign(new YAMLOMap(seq.schema), pairs);
|
|
1954
|
+
}
|
|
1955
|
+
};
|
|
1956
|
+
//#endregion
|
|
1957
|
+
//#region src/schema/yaml-1.1/bool.ts
|
|
1958
|
+
function boolStringify({ value, source }, ctx) {
|
|
1959
|
+
if (source && (value ? trueTag : falseTag).test.test(source)) return source;
|
|
1960
|
+
return value ? ctx.options.trueStr : ctx.options.falseStr;
|
|
1961
|
+
}
|
|
1962
|
+
const trueTag = {
|
|
1963
|
+
identify: (value) => value === true,
|
|
1964
|
+
default: true,
|
|
1965
|
+
tag: "tag:yaml.org,2002:bool",
|
|
1966
|
+
test: /^(?:Y|y|[Yy]es|YES|[Tt]rue|TRUE|[Oo]n|ON)$/,
|
|
1967
|
+
resolve: () => new Scalar(true),
|
|
1968
|
+
stringify: boolStringify
|
|
1969
|
+
};
|
|
1970
|
+
const falseTag = {
|
|
1971
|
+
identify: (value) => value === false,
|
|
1972
|
+
default: true,
|
|
1973
|
+
tag: "tag:yaml.org,2002:bool",
|
|
1974
|
+
test: /^(?:N|n|[Nn]o|NO|[Ff]alse|FALSE|[Oo]ff|OFF)$/,
|
|
1975
|
+
resolve: () => new Scalar(false),
|
|
1976
|
+
stringify: boolStringify
|
|
1977
|
+
};
|
|
1978
|
+
//#endregion
|
|
1979
|
+
//#region src/schema/yaml-1.1/float.ts
|
|
1980
|
+
const floatNaN = {
|
|
1981
|
+
identify: (value) => typeof value === "number",
|
|
1982
|
+
default: true,
|
|
1983
|
+
tag: "tag:yaml.org,2002:float",
|
|
1984
|
+
test: /^(?:[-+]?\.(?:inf|Inf|INF)|\.nan|\.NaN|\.NAN)$/,
|
|
1985
|
+
resolve: (str) => str.slice(-3).toLowerCase() === "nan" ? NaN : str[0] === "-" ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY,
|
|
1986
|
+
stringify: stringifyNumber
|
|
1987
|
+
};
|
|
1988
|
+
const floatExp = {
|
|
1989
|
+
identify: (value) => typeof value === "number",
|
|
1990
|
+
default: true,
|
|
1991
|
+
tag: "tag:yaml.org,2002:float",
|
|
1992
|
+
format: "EXP",
|
|
1993
|
+
test: /^[-+]?(?:[0-9][0-9_]*)?(?:\.[0-9_]*)?[eE][-+]?[0-9]+$/,
|
|
1994
|
+
resolve: (str) => parseFloat(str.replace(/_/g, "")),
|
|
1995
|
+
stringify(node) {
|
|
1996
|
+
const num = Number(node.value);
|
|
1997
|
+
return isFinite(num) ? num.toExponential() : stringifyNumber(node);
|
|
1998
|
+
}
|
|
1999
|
+
};
|
|
2000
|
+
const float = {
|
|
2001
|
+
identify: (value) => typeof value === "number",
|
|
2002
|
+
default: true,
|
|
2003
|
+
tag: "tag:yaml.org,2002:float",
|
|
2004
|
+
test: /^[-+]?(?:[0-9][0-9_]*)?\.[0-9_]*$/,
|
|
2005
|
+
resolve(str) {
|
|
2006
|
+
const node = new Scalar(parseFloat(str.replace(/_/g, "")));
|
|
2007
|
+
const dot = str.indexOf(".");
|
|
2008
|
+
if (dot !== -1) {
|
|
2009
|
+
const f = str.substring(dot + 1).replace(/_/g, "");
|
|
2010
|
+
if (f[f.length - 1] === "0") node.minFractionDigits = f.length;
|
|
2011
|
+
}
|
|
2012
|
+
return node;
|
|
2013
|
+
},
|
|
2014
|
+
stringify: stringifyNumber
|
|
2015
|
+
};
|
|
2016
|
+
//#endregion
|
|
2017
|
+
//#region src/schema/yaml-1.1/int.ts
|
|
2018
|
+
const intIdentify = (value) => typeof value === "bigint" || Number.isInteger(value);
|
|
2019
|
+
function intResolve(str, offset, radix, { intAsBigInt }) {
|
|
2020
|
+
const sign = str[0];
|
|
2021
|
+
if (sign === "-" || sign === "+") offset += 1;
|
|
2022
|
+
str = str.substring(offset).replace(/_/g, "");
|
|
2023
|
+
if (intAsBigInt) {
|
|
2024
|
+
switch (radix) {
|
|
2025
|
+
case 2:
|
|
2026
|
+
str = `0b${str}`;
|
|
2027
|
+
break;
|
|
2028
|
+
case 8:
|
|
2029
|
+
str = `0o${str}`;
|
|
2030
|
+
break;
|
|
2031
|
+
case 16:
|
|
2032
|
+
str = `0x${str}`;
|
|
2033
|
+
break;
|
|
2034
|
+
}
|
|
2035
|
+
const n = BigInt(str);
|
|
2036
|
+
return sign === "-" ? BigInt(-1) * n : n;
|
|
2037
|
+
}
|
|
2038
|
+
const n = parseInt(str, radix);
|
|
2039
|
+
return sign === "-" ? -1 * n : n;
|
|
2040
|
+
}
|
|
2041
|
+
function intStringify(node, radix, prefix) {
|
|
2042
|
+
const { value } = node;
|
|
2043
|
+
if (intIdentify(value)) {
|
|
2044
|
+
const str = value.toString(radix);
|
|
2045
|
+
return value < 0 ? "-" + prefix + str.substr(1) : prefix + str;
|
|
2046
|
+
}
|
|
2047
|
+
return stringifyNumber(node);
|
|
2048
|
+
}
|
|
2049
|
+
const intBin = {
|
|
2050
|
+
identify: intIdentify,
|
|
2051
|
+
default: true,
|
|
2052
|
+
tag: "tag:yaml.org,2002:int",
|
|
2053
|
+
format: "BIN",
|
|
2054
|
+
test: /^[-+]?0b[0-1_]+$/,
|
|
2055
|
+
resolve: (str, _onError, opt) => intResolve(str, 2, 2, opt),
|
|
2056
|
+
stringify: (node) => intStringify(node, 2, "0b")
|
|
2057
|
+
};
|
|
2058
|
+
const intOct = {
|
|
2059
|
+
identify: intIdentify,
|
|
2060
|
+
default: true,
|
|
2061
|
+
tag: "tag:yaml.org,2002:int",
|
|
2062
|
+
format: "OCT",
|
|
2063
|
+
test: /^[-+]?0[0-7_]+$/,
|
|
2064
|
+
resolve: (str, _onError, opt) => intResolve(str, 1, 8, opt),
|
|
2065
|
+
stringify: (node) => intStringify(node, 8, "0")
|
|
2066
|
+
};
|
|
2067
|
+
const int = {
|
|
2068
|
+
identify: intIdentify,
|
|
2069
|
+
default: true,
|
|
2070
|
+
tag: "tag:yaml.org,2002:int",
|
|
2071
|
+
test: /^[-+]?[0-9][0-9_]*$/,
|
|
2072
|
+
resolve: (str, _onError, opt) => intResolve(str, 0, 10, opt),
|
|
2073
|
+
stringify: stringifyNumber
|
|
2074
|
+
};
|
|
2075
|
+
const intHex = {
|
|
2076
|
+
identify: intIdentify,
|
|
2077
|
+
default: true,
|
|
2078
|
+
tag: "tag:yaml.org,2002:int",
|
|
2079
|
+
format: "HEX",
|
|
2080
|
+
test: /^[-+]?0x[0-9a-fA-F_]+$/,
|
|
2081
|
+
resolve: (str, _onError, opt) => intResolve(str, 2, 16, opt),
|
|
2082
|
+
stringify: (node) => intStringify(node, 16, "0x")
|
|
2083
|
+
};
|
|
2084
|
+
//#endregion
|
|
2085
|
+
//#region src/schema/yaml-1.1/set.ts
|
|
2086
|
+
const set = {
|
|
2087
|
+
collection: "map",
|
|
2088
|
+
identify: (value) => value instanceof Set,
|
|
2089
|
+
nodeClass: YAMLSet,
|
|
2090
|
+
default: false,
|
|
2091
|
+
tag: "tag:yaml.org,2002:set",
|
|
2092
|
+
createNode(nc, iterable) {
|
|
2093
|
+
const set = new YAMLSet(nc.schema);
|
|
2094
|
+
if (iterable && Symbol.iterator in Object(iterable)) for (let value of iterable) {
|
|
2095
|
+
if (typeof nc.replacer === "function") value = nc.replacer.call(iterable, value, value);
|
|
2096
|
+
const mk = nc.schema.mapKey(value);
|
|
2097
|
+
set.values.set(mk, nc.create(value));
|
|
2098
|
+
}
|
|
2099
|
+
return set;
|
|
2100
|
+
},
|
|
2101
|
+
resolve(set, onError) {
|
|
2102
|
+
if (!(set instanceof YAMLSet)) onError("Expected a set for this tag");
|
|
2103
|
+
return set;
|
|
2104
|
+
}
|
|
2105
|
+
};
|
|
2106
|
+
//#endregion
|
|
2107
|
+
//#region src/schema/yaml-1.1/timestamp.ts
|
|
2108
|
+
/** Internal types handle bigint as number, because TS can't figure it out. */
|
|
2109
|
+
function parseSexagesimal(str, asBigInt) {
|
|
2110
|
+
const sign = str[0];
|
|
2111
|
+
const parts = sign === "-" || sign === "+" ? str.substring(1) : str;
|
|
2112
|
+
const num = (n) => asBigInt ? BigInt(n) : Number(n);
|
|
2113
|
+
const res = parts.replace(/_/g, "").split(":").reduce((res, p) => res * num(60) + num(p), num(0));
|
|
2114
|
+
return sign === "-" ? num(-1) * res : res;
|
|
2115
|
+
}
|
|
2116
|
+
/**
|
|
2117
|
+
* hhhh:mm:ss.sss
|
|
2118
|
+
*
|
|
2119
|
+
* Internal types handle bigint as number, because TS can't figure it out.
|
|
2120
|
+
*/
|
|
2121
|
+
function stringifySexagesimal(node) {
|
|
2122
|
+
let { value } = node;
|
|
2123
|
+
let num = (n) => n;
|
|
2124
|
+
if (typeof value === "bigint") num = (n) => BigInt(n);
|
|
2125
|
+
else if (isNaN(value) || !isFinite(value)) return stringifyNumber(node);
|
|
2126
|
+
let sign = "";
|
|
2127
|
+
if (value < 0) {
|
|
2128
|
+
sign = "-";
|
|
2129
|
+
value *= num(-1);
|
|
2130
|
+
}
|
|
2131
|
+
const _60 = num(60);
|
|
2132
|
+
const parts = [value % _60];
|
|
2133
|
+
if (value < 60) parts.unshift(0);
|
|
2134
|
+
else {
|
|
2135
|
+
value = (value - parts[0]) / _60;
|
|
2136
|
+
parts.unshift(value % _60);
|
|
2137
|
+
if (value >= 60) {
|
|
2138
|
+
value = (value - parts[0]) / _60;
|
|
2139
|
+
parts.unshift(value);
|
|
2140
|
+
}
|
|
2141
|
+
}
|
|
2142
|
+
return sign + parts.map((n) => String(n).padStart(2, "0")).join(":").replace(/000000\d*$/, "");
|
|
2143
|
+
}
|
|
2144
|
+
const intTime = {
|
|
2145
|
+
identify: (value) => typeof value === "bigint" || Number.isInteger(value),
|
|
2146
|
+
default: true,
|
|
2147
|
+
tag: "tag:yaml.org,2002:int",
|
|
2148
|
+
format: "TIME",
|
|
2149
|
+
test: /^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+$/,
|
|
2150
|
+
resolve: (str, _onError, { intAsBigInt }) => parseSexagesimal(str, intAsBigInt),
|
|
2151
|
+
stringify: stringifySexagesimal
|
|
2152
|
+
};
|
|
2153
|
+
const floatTime = {
|
|
2154
|
+
identify: (value) => typeof value === "number",
|
|
2155
|
+
default: true,
|
|
2156
|
+
tag: "tag:yaml.org,2002:float",
|
|
2157
|
+
format: "TIME",
|
|
2158
|
+
test: /^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\.[0-9_]*$/,
|
|
2159
|
+
resolve: (str) => parseSexagesimal(str, false),
|
|
2160
|
+
stringify: stringifySexagesimal
|
|
2161
|
+
};
|
|
2162
|
+
const timestamp = {
|
|
2163
|
+
identify: (value) => value instanceof Date,
|
|
2164
|
+
default: true,
|
|
2165
|
+
tag: "tag:yaml.org,2002:timestamp",
|
|
2166
|
+
test: RegExp("^([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})(?:(?:t|T|[ \\t]+)([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2}(\\.[0-9]+)?)(?:[ \\t]*(Z|[-+][012]?[0-9](?::[0-9]{2})?))?)?$"),
|
|
2167
|
+
resolve(str) {
|
|
2168
|
+
const match = str.match(timestamp.test);
|
|
2169
|
+
if (!match) throw new Error("!!timestamp expects a date, starting with yyyy-mm-dd");
|
|
2170
|
+
const [, year, month, day, hour, minute, second] = match.map(Number);
|
|
2171
|
+
const millisec = match[7] ? Number((match[7] + "00").substr(1, 3)) : 0;
|
|
2172
|
+
let date = Date.UTC(year, month - 1, day, hour || 0, minute || 0, second || 0, millisec);
|
|
2173
|
+
const tz = match[8];
|
|
2174
|
+
if (tz && tz !== "Z") {
|
|
2175
|
+
let d = parseSexagesimal(tz, false);
|
|
2176
|
+
if (Math.abs(d) < 30) d *= 60;
|
|
2177
|
+
date -= 6e4 * d;
|
|
2178
|
+
}
|
|
2179
|
+
return new Date(date);
|
|
2180
|
+
},
|
|
2181
|
+
stringify: ({ value }) => value?.toISOString().replace(/(T00:00:00)?\.000Z$/, "") ?? ""
|
|
2182
|
+
};
|
|
2183
|
+
//#endregion
|
|
2184
|
+
//#region src/schema/yaml-1.1/schema.ts
|
|
2185
|
+
const schema = [
|
|
2186
|
+
map,
|
|
2187
|
+
seq,
|
|
2188
|
+
string,
|
|
2189
|
+
nullTag,
|
|
2190
|
+
trueTag,
|
|
2191
|
+
falseTag,
|
|
2192
|
+
intBin,
|
|
2193
|
+
intOct,
|
|
2194
|
+
int,
|
|
2195
|
+
intHex,
|
|
2196
|
+
floatNaN,
|
|
2197
|
+
floatExp,
|
|
2198
|
+
float,
|
|
2199
|
+
binary,
|
|
2200
|
+
merge,
|
|
2201
|
+
omap,
|
|
2202
|
+
pairs,
|
|
2203
|
+
set,
|
|
2204
|
+
intTime,
|
|
2205
|
+
floatTime,
|
|
2206
|
+
timestamp
|
|
2207
|
+
];
|
|
2208
|
+
//#endregion
|
|
2209
|
+
//#region src/schema/tags.ts
|
|
2210
|
+
const schemas = new Map([
|
|
2211
|
+
["core", schema$2],
|
|
2212
|
+
["failsafe", [
|
|
2213
|
+
map,
|
|
2214
|
+
seq,
|
|
2215
|
+
string
|
|
2216
|
+
]],
|
|
2217
|
+
["json", schema$1],
|
|
2218
|
+
["yaml11", schema],
|
|
2219
|
+
["yaml-1.1", schema]
|
|
2220
|
+
]);
|
|
2221
|
+
const tagsByName = {
|
|
2222
|
+
binary,
|
|
2223
|
+
bool: boolTag,
|
|
2224
|
+
float: float$1,
|
|
2225
|
+
floatExp: floatExp$1,
|
|
2226
|
+
floatNaN: floatNaN$1,
|
|
2227
|
+
floatTime,
|
|
2228
|
+
int: int$1,
|
|
2229
|
+
intHex: intHex$1,
|
|
2230
|
+
intOct: intOct$1,
|
|
2231
|
+
intTime,
|
|
2232
|
+
map,
|
|
2233
|
+
merge,
|
|
2234
|
+
null: nullTag,
|
|
2235
|
+
omap,
|
|
2236
|
+
pairs,
|
|
2237
|
+
seq,
|
|
2238
|
+
set,
|
|
2239
|
+
timestamp
|
|
2240
|
+
};
|
|
2241
|
+
const coreKnownTags = {
|
|
2242
|
+
"tag:yaml.org,2002:binary": binary,
|
|
2243
|
+
"tag:yaml.org,2002:merge": merge,
|
|
2244
|
+
"tag:yaml.org,2002:omap": omap,
|
|
2245
|
+
"tag:yaml.org,2002:pairs": pairs,
|
|
2246
|
+
"tag:yaml.org,2002:set": set,
|
|
2247
|
+
"tag:yaml.org,2002:timestamp": timestamp
|
|
2248
|
+
};
|
|
2249
|
+
function getTags(customTags, schemaName, addMergeTag) {
|
|
2250
|
+
const schemaTags = schemas.get(schemaName);
|
|
2251
|
+
if (schemaTags && !customTags) return addMergeTag && !schemaTags.includes(merge) ? [...schemaTags, merge] : schemaTags.slice();
|
|
2252
|
+
let tags = schemaTags;
|
|
2253
|
+
if (!tags) if (Array.isArray(customTags)) tags = [];
|
|
2254
|
+
else {
|
|
2255
|
+
const keys = Array.from(schemas.keys()).filter((key) => key !== "yaml11").map((key) => JSON.stringify(key)).join(", ");
|
|
2256
|
+
throw new Error(`Unknown schema "${schemaName}"; use one of ${keys} or define customTags array`);
|
|
2257
|
+
}
|
|
2258
|
+
if (Array.isArray(customTags)) for (const tag of customTags) tags = tags.concat(tag);
|
|
2259
|
+
else if (typeof customTags === "function") tags = customTags(tags.slice());
|
|
2260
|
+
if (addMergeTag) tags = [...tags, merge];
|
|
2261
|
+
return tags.reduce((tags, tag) => {
|
|
2262
|
+
const tagObj = typeof tag === "string" ? tagsByName[tag] : tag;
|
|
2263
|
+
if (!tagObj) {
|
|
2264
|
+
const tagName = JSON.stringify(tag);
|
|
2265
|
+
const keys = Object.keys(tagsByName).map((key) => JSON.stringify(key)).join(", ");
|
|
2266
|
+
throw new Error(`Unknown custom tag ${tagName}; use one of ${keys}`);
|
|
2267
|
+
}
|
|
2268
|
+
if (!tags.includes(tagObj)) tags.push(tagObj);
|
|
2269
|
+
return tags;
|
|
2270
|
+
}, []);
|
|
2271
|
+
}
|
|
2272
|
+
//#endregion
|
|
2273
|
+
//#region src/schema/Schema.ts
|
|
2274
|
+
var Schema = class Schema {
|
|
2275
|
+
compat;
|
|
2276
|
+
knownTags;
|
|
2277
|
+
mapKey;
|
|
2278
|
+
name;
|
|
2279
|
+
tags;
|
|
2280
|
+
toStringOptions;
|
|
2281
|
+
constructor({ compat, customTags, mapKey, merge, resolveKnownTags, schema, toStringDefaults }) {
|
|
2282
|
+
this.compat = Array.isArray(compat) ? getTags(compat, "compat") : compat ? getTags(null, compat) : null;
|
|
2283
|
+
this.mapKey = mapKey ?? defaultMapKey;
|
|
2284
|
+
this.name = typeof schema === "string" && schema || "core";
|
|
2285
|
+
this.knownTags = resolveKnownTags ? coreKnownTags : {};
|
|
2286
|
+
this.tags = getTags(customTags, this.name, merge);
|
|
2287
|
+
this.toStringOptions = toStringDefaults ?? null;
|
|
2288
|
+
Object.defineProperty(this, "map", { value: map });
|
|
2289
|
+
Object.defineProperty(this, "scalar", { value: string });
|
|
2290
|
+
Object.defineProperty(this, "seq", { value: seq });
|
|
2291
|
+
}
|
|
2292
|
+
clone() {
|
|
2293
|
+
const copy = Object.create(Schema.prototype, Object.getOwnPropertyDescriptors(this));
|
|
2294
|
+
copy.tags = this.tags.slice();
|
|
2295
|
+
return copy;
|
|
2296
|
+
}
|
|
2297
|
+
};
|
|
2298
|
+
function defaultMapKey(value) {
|
|
2299
|
+
if (value instanceof Pair) value = value.key;
|
|
2300
|
+
if (value instanceof Scalar) value = value.value;
|
|
2301
|
+
return value ?? null;
|
|
2302
|
+
}
|
|
2303
|
+
//#endregion
|
|
2304
|
+
//#region src/stringify/stringifyDocument.ts
|
|
2305
|
+
function stringifyDocument(doc, options) {
|
|
2306
|
+
const lines = [];
|
|
2307
|
+
let hasDirectives = options.directives === true;
|
|
2308
|
+
if (options.directives !== false && doc.directives) {
|
|
2309
|
+
const dir = doc.directives.toString(doc);
|
|
2310
|
+
if (dir) {
|
|
2311
|
+
lines.push(dir);
|
|
2312
|
+
hasDirectives = true;
|
|
2313
|
+
} else if (doc.directives.docStart) hasDirectives = true;
|
|
2314
|
+
}
|
|
2315
|
+
if (hasDirectives) lines.push("---");
|
|
2316
|
+
const ctx = createStringifyContext(doc, options);
|
|
2317
|
+
const { commentString } = ctx.options;
|
|
2318
|
+
if (doc.commentBefore) {
|
|
2319
|
+
if (lines.length !== 1) lines.unshift("");
|
|
2320
|
+
const cs = commentString(doc.commentBefore);
|
|
2321
|
+
lines.unshift(indentComment(cs, ""));
|
|
2322
|
+
}
|
|
2323
|
+
let chompKeep = false;
|
|
2324
|
+
let contentComment = null;
|
|
2325
|
+
if (doc.value.spaceBefore && hasDirectives) lines.push("");
|
|
2326
|
+
if (doc.value.commentBefore) {
|
|
2327
|
+
const cs = commentString(doc.value.commentBefore);
|
|
2328
|
+
lines.push(indentComment(cs, ""));
|
|
2329
|
+
}
|
|
2330
|
+
ctx.forceBlockIndent = !!doc.comment;
|
|
2331
|
+
contentComment = doc.value.comment;
|
|
2332
|
+
const onChompKeep = contentComment ? void 0 : () => chompKeep = true;
|
|
2333
|
+
let body = stringify(doc.value, ctx, () => contentComment = null, onChompKeep);
|
|
2334
|
+
if (contentComment) body += lineComment(body, "", commentString(contentComment));
|
|
2335
|
+
if ((body[0] === "|" || body[0] === ">") && lines[lines.length - 1] === "---") lines[lines.length - 1] = `--- ${body}`;
|
|
2336
|
+
else lines.push(body);
|
|
2337
|
+
if (doc.directives?.docEnd) if (doc.comment) {
|
|
2338
|
+
const cs = commentString(doc.comment);
|
|
2339
|
+
if (cs.includes("\n")) {
|
|
2340
|
+
lines.push("...");
|
|
2341
|
+
lines.push(indentComment(cs, ""));
|
|
2342
|
+
} else lines.push(`... ${cs}`);
|
|
2343
|
+
} else lines.push("...");
|
|
2344
|
+
else {
|
|
2345
|
+
let dc = doc.comment;
|
|
2346
|
+
if (dc && chompKeep) dc = dc.replace(/^\n+/, "");
|
|
2347
|
+
if (dc) {
|
|
2348
|
+
if ((!chompKeep || contentComment) && lines[lines.length - 1] !== "") lines.push("");
|
|
2349
|
+
lines.push(indentComment(commentString(dc), ""));
|
|
2350
|
+
}
|
|
2351
|
+
}
|
|
2352
|
+
return lines.join("\n") + "\n";
|
|
2353
|
+
}
|
|
2354
|
+
//#endregion
|
|
2355
|
+
//#region src/doc/applyReviver.ts
|
|
2356
|
+
function applyReviver(reviver, obj, key, val) {
|
|
2357
|
+
if (val && typeof val === "object") if (Array.isArray(val)) for (let i = 0, len = val.length; i < len; ++i) {
|
|
2358
|
+
const v0 = val[i];
|
|
2359
|
+
const v1 = applyReviver(reviver, val, String(i), v0);
|
|
2360
|
+
if (v1 === void 0) delete val[i];
|
|
2361
|
+
else if (v1 !== v0) val[i] = v1;
|
|
2362
|
+
}
|
|
2363
|
+
else if (val instanceof Map) for (const k of Array.from(val.keys())) {
|
|
2364
|
+
const v0 = val.get(k);
|
|
2365
|
+
const v1 = applyReviver(reviver, val, k, v0);
|
|
2366
|
+
if (v1 === void 0) val.delete(k);
|
|
2367
|
+
else if (v1 !== v0) val.set(k, v1);
|
|
2368
|
+
}
|
|
2369
|
+
else if (val instanceof Set) for (const v0 of Array.from(val)) {
|
|
2370
|
+
const v1 = applyReviver(reviver, val, v0, v0);
|
|
2371
|
+
if (v1 === void 0) val.delete(v0);
|
|
2372
|
+
else if (v1 !== v0) {
|
|
2373
|
+
val.delete(v0);
|
|
2374
|
+
val.add(v1);
|
|
2375
|
+
}
|
|
2376
|
+
}
|
|
2377
|
+
else for (const [k, v0] of Object.entries(val)) {
|
|
2378
|
+
const v1 = applyReviver(reviver, val, k, v0);
|
|
2379
|
+
if (v1 === void 0) delete val[k];
|
|
2380
|
+
else if (v1 !== v0) val[k] = v1;
|
|
2381
|
+
}
|
|
2382
|
+
return reviver.call(obj, key, val);
|
|
2383
|
+
}
|
|
2384
|
+
//#endregion
|
|
2385
|
+
//#region src/doc/Document.ts
|
|
2386
|
+
var Document = class Document {
|
|
2387
|
+
/** A comment before this Document */
|
|
2388
|
+
commentBefore = null;
|
|
2389
|
+
/** A comment immediately after this Document */
|
|
2390
|
+
comment = null;
|
|
2391
|
+
/** The document value. */
|
|
2392
|
+
value;
|
|
2393
|
+
directives;
|
|
2394
|
+
/** Errors encountered during parsing. */
|
|
2395
|
+
errors = [];
|
|
2396
|
+
options;
|
|
2397
|
+
/** Warnings encountered during parsing. */
|
|
2398
|
+
warnings = [];
|
|
2399
|
+
constructor(value, replacer, options) {
|
|
2400
|
+
let _replacer = null;
|
|
2401
|
+
if (typeof replacer === "function" || Array.isArray(replacer)) _replacer = replacer;
|
|
2402
|
+
else if (options === void 0 && replacer) {
|
|
2403
|
+
options = replacer;
|
|
2404
|
+
replacer = void 0;
|
|
2405
|
+
}
|
|
2406
|
+
const opt = Object.assign({
|
|
2407
|
+
intAsBigInt: false,
|
|
2408
|
+
keepSourceTokens: false,
|
|
2409
|
+
logLevel: "warn",
|
|
2410
|
+
prettyErrors: true,
|
|
2411
|
+
strict: true,
|
|
2412
|
+
stringKeys: false,
|
|
2413
|
+
version: "1.2"
|
|
2414
|
+
}, options);
|
|
2415
|
+
this.options = opt;
|
|
2416
|
+
let { version } = opt;
|
|
2417
|
+
if (options?._directives) {
|
|
2418
|
+
this.directives = options._directives.atDocument();
|
|
2419
|
+
if (this.directives.yaml.explicit) version = this.directives.yaml.version;
|
|
2420
|
+
} else this.directives = new Directives({ version });
|
|
2421
|
+
this.setSchema(version, options);
|
|
2422
|
+
this.value = this.createNode(value, _replacer, options);
|
|
2423
|
+
}
|
|
2424
|
+
/**
|
|
2425
|
+
* Create a deep copy of this Document and its value.
|
|
2426
|
+
*
|
|
2427
|
+
* Custom Node values that inherit from `Object` still refer to their original instances.
|
|
2428
|
+
*/
|
|
2429
|
+
clone() {
|
|
2430
|
+
const copy = Object.create(Document.prototype);
|
|
2431
|
+
copy.commentBefore = this.commentBefore;
|
|
2432
|
+
copy.comment = this.comment;
|
|
2433
|
+
copy.errors = this.errors.slice();
|
|
2434
|
+
copy.warnings = this.warnings.slice();
|
|
2435
|
+
copy.options = Object.assign({}, this.options);
|
|
2436
|
+
if (this.directives) copy.directives = this.directives.clone();
|
|
2437
|
+
copy.schema = this.schema.clone();
|
|
2438
|
+
copy.value = this.value.clone(copy.schema);
|
|
2439
|
+
if (this.range) copy.range = this.range.slice();
|
|
2440
|
+
return copy;
|
|
2441
|
+
}
|
|
2442
|
+
/**
|
|
2443
|
+
* Create a new `Alias` node, ensuring that the target `node` has the required anchor.
|
|
2444
|
+
*
|
|
2445
|
+
* If `node` already has an anchor, `name` is ignored.
|
|
2446
|
+
* Otherwise, the `node.anchor` value will be set to `name`,
|
|
2447
|
+
* or if an anchor with that name is already present in the document,
|
|
2448
|
+
* `name` will be used as a prefix for a new unique anchor.
|
|
2449
|
+
* If `name` is undefined, the generated anchor will use 'a' as a prefix.
|
|
2450
|
+
*/
|
|
2451
|
+
createAlias(node, name) {
|
|
2452
|
+
if (!node.anchor) {
|
|
2453
|
+
const prev = anchorNames(this);
|
|
2454
|
+
node.anchor = !name || prev.has(name) ? findNewAnchor(name || "a", prev) : name;
|
|
2455
|
+
}
|
|
2456
|
+
return new Alias(node.anchor);
|
|
2457
|
+
}
|
|
2458
|
+
createNode(value, replacer, options) {
|
|
2459
|
+
let nc;
|
|
2460
|
+
if (typeof replacer === "function") {
|
|
2461
|
+
value = replacer.call({ "": value }, "", value);
|
|
2462
|
+
nc = new NodeCreator(this, options, replacer);
|
|
2463
|
+
} else if (Array.isArray(replacer)) {
|
|
2464
|
+
const keyToStr = (v) => typeof v === "number" || v instanceof String || v instanceof Number;
|
|
2465
|
+
const asStr = replacer.filter(keyToStr).map(String);
|
|
2466
|
+
if (asStr.length > 0) replacer = [...replacer, ...asStr];
|
|
2467
|
+
nc = new NodeCreator(this, options, replacer);
|
|
2468
|
+
} else {
|
|
2469
|
+
options ??= replacer ?? void 0;
|
|
2470
|
+
nc = new NodeCreator(this, options);
|
|
2471
|
+
}
|
|
2472
|
+
const node = nc.create(value, options?.tag);
|
|
2473
|
+
nc.setAnchors();
|
|
2474
|
+
return node;
|
|
2475
|
+
}
|
|
2476
|
+
/**
|
|
2477
|
+
* Convert a key and a value into a `Pair` using the current schema,
|
|
2478
|
+
* recursively wrapping all values as `Scalar` or `Collection` nodes.
|
|
2479
|
+
*/
|
|
2480
|
+
createPair(key, value, options = {}) {
|
|
2481
|
+
const nc = new NodeCreator(this, options);
|
|
2482
|
+
const pair = nc.createPair(key, value);
|
|
2483
|
+
nc.setAnchors();
|
|
2484
|
+
return pair;
|
|
2485
|
+
}
|
|
2486
|
+
/**
|
|
2487
|
+
* Returns item at `key`, or `undefined` if not found.
|
|
2488
|
+
*/
|
|
2489
|
+
get(key) {
|
|
2490
|
+
if (this.value instanceof YAMLMap || this.value instanceof YAMLSet) return this.value.get(key);
|
|
2491
|
+
if (this.value instanceof YAMLSeq) {
|
|
2492
|
+
if (Number.isInteger(key)) return this.value.at(key);
|
|
2493
|
+
throw new TypeError(`Expected an integer, not ${JSON.stringify(key)}.`);
|
|
2494
|
+
}
|
|
2495
|
+
}
|
|
2496
|
+
/**
|
|
2497
|
+
* Returns pair at `key`, or `undefined` if not found.
|
|
2498
|
+
*/
|
|
2499
|
+
getPair(key) {
|
|
2500
|
+
if (this.value instanceof YAMLMap) return this.value.getPair(key);
|
|
2501
|
+
if (this.value instanceof YAMLSeq) {
|
|
2502
|
+
if (!Number.isInteger(key)) throw new TypeError(`Expected an integer, not ${JSON.stringify(key)}.`);
|
|
2503
|
+
const pair = this.value.at(key);
|
|
2504
|
+
if (pair instanceof Pair) return pair;
|
|
2505
|
+
throw new TypeError(`Value at ${key} is not a Pair`);
|
|
2506
|
+
}
|
|
2507
|
+
}
|
|
2508
|
+
/**
|
|
2509
|
+
* Sets a value in this document's top-level collection. For `!!set`, `value` is ignored.
|
|
2510
|
+
*/
|
|
2511
|
+
set(key, value) {
|
|
2512
|
+
if (this.value instanceof YAMLSet) this.value.add(key);
|
|
2513
|
+
else if (this.value instanceof YAMLMap || this.value instanceof YAMLSeq) this.value.set(key, value);
|
|
2514
|
+
else throw new Error("Expected a YAML collection as document value");
|
|
2515
|
+
}
|
|
2516
|
+
/**
|
|
2517
|
+
* Change the YAML version and schema used by the document.
|
|
2518
|
+
* A `null` version disables support for directives, explicit tags, anchors, and aliases.
|
|
2519
|
+
* It also requires the `schema` option to be given as a `Schema` instance value.
|
|
2520
|
+
*
|
|
2521
|
+
* Overrides all previously set schema options.
|
|
2522
|
+
*/
|
|
2523
|
+
setSchema(version, options = {}) {
|
|
2524
|
+
if (typeof version === "number") version = String(version);
|
|
2525
|
+
let opt;
|
|
2526
|
+
switch (version) {
|
|
2527
|
+
case "1.1":
|
|
2528
|
+
if (this.directives) this.directives.yaml.version = "1.1";
|
|
2529
|
+
else this.directives = new Directives({ version: "1.1" });
|
|
2530
|
+
opt = {
|
|
2531
|
+
resolveKnownTags: false,
|
|
2532
|
+
schema: "yaml-1.1"
|
|
2533
|
+
};
|
|
2534
|
+
break;
|
|
2535
|
+
case "1.2":
|
|
2536
|
+
case "next":
|
|
2537
|
+
if (this.directives) this.directives.yaml.version = version;
|
|
2538
|
+
else this.directives = new Directives({ version });
|
|
2539
|
+
opt = {
|
|
2540
|
+
resolveKnownTags: true,
|
|
2541
|
+
schema: "core"
|
|
2542
|
+
};
|
|
2543
|
+
break;
|
|
2544
|
+
case null:
|
|
2545
|
+
if (this.directives) delete this.directives;
|
|
2546
|
+
opt = null;
|
|
2547
|
+
break;
|
|
2548
|
+
default: {
|
|
2549
|
+
const sv = JSON.stringify(version);
|
|
2550
|
+
throw new Error(`Expected '1.1', '1.2' or null as first argument, but found: ${sv}`);
|
|
2551
|
+
}
|
|
2552
|
+
}
|
|
2553
|
+
if (options.schema instanceof Object) this.schema = options.schema;
|
|
2554
|
+
else if (opt) this.schema = new Schema(Object.assign(opt, options));
|
|
2555
|
+
else throw new Error(`With a null YAML version, the { schema: Schema } option is required`);
|
|
2556
|
+
}
|
|
2557
|
+
/** A plain JavaScript representation of the document `value`. */
|
|
2558
|
+
toJS(opt = {}) {
|
|
2559
|
+
const { onAnchor, reviver } = opt;
|
|
2560
|
+
const ctx = new ToJSContext(opt);
|
|
2561
|
+
const res = this.value.toJS(this, ctx);
|
|
2562
|
+
if (typeof onAnchor === "function") for (const { count, res } of ctx.anchors.values()) onAnchor(res, count);
|
|
2563
|
+
return typeof reviver === "function" ? applyReviver(reviver, { "": res }, "", res) : res;
|
|
2564
|
+
}
|
|
2565
|
+
/** A JSON representation of the document `value`. */
|
|
2566
|
+
toJSON() {
|
|
2567
|
+
return this.toJS({ mapAsMap: false });
|
|
2568
|
+
}
|
|
2569
|
+
/** A YAML representation of the document. */
|
|
2570
|
+
toString(options = {}) {
|
|
2571
|
+
if (this.errors.length > 0) throw new Error("Document with errors cannot be stringified");
|
|
2572
|
+
if ("indent" in options && (!Number.isInteger(options.indent) || Number(options.indent) <= 0)) {
|
|
2573
|
+
const s = JSON.stringify(options.indent);
|
|
2574
|
+
throw new Error(`"indent" option must be a positive integer, not ${s}`);
|
|
2575
|
+
}
|
|
2576
|
+
return stringifyDocument(this, options);
|
|
2577
|
+
}
|
|
2578
|
+
};
|
|
2579
|
+
//#endregion
|
|
2580
|
+
//#region src/visit.ts
|
|
2581
|
+
const BREAK = Symbol("break visit");
|
|
2582
|
+
const SKIP = Symbol("skip children");
|
|
2583
|
+
const REMOVE = Symbol("remove node");
|
|
2584
|
+
/**
|
|
2585
|
+
* Apply a visitor to an AST node or document.
|
|
2586
|
+
*
|
|
2587
|
+
* Walks through the tree (depth-first) starting from `node`, calling a
|
|
2588
|
+
* `visitor` function with three arguments:
|
|
2589
|
+
* - `key`: For sequence values and map `Pair`, the node's index in the
|
|
2590
|
+
* collection. Within a `Pair`, `'key'` or `'value'`, correspondingly.
|
|
2591
|
+
* `null` for the root node.
|
|
2592
|
+
* - `node`: The current node.
|
|
2593
|
+
* - `path`: The ancestry of the current node.
|
|
2594
|
+
*
|
|
2595
|
+
* The return value of the visitor may be used to control the traversal:
|
|
2596
|
+
* - `undefined` (default): Do nothing and continue
|
|
2597
|
+
* - `visit.SKIP`: Do not visit the children of this node, continue with next
|
|
2598
|
+
* sibling
|
|
2599
|
+
* - `visit.BREAK`: Terminate traversal completely
|
|
2600
|
+
* - `visit.REMOVE`: Remove the current node, then continue with the next one
|
|
2601
|
+
* - `Node`: Replace the current node, then continue by visiting it
|
|
2602
|
+
* - `number`: While iterating the items of a sequence or map, set the index
|
|
2603
|
+
* of the next step. This is useful especially if the index of the current
|
|
2604
|
+
* node has changed.
|
|
2605
|
+
*
|
|
2606
|
+
* If `visitor` is a single function, it will be called with all values
|
|
2607
|
+
* encountered in the tree, including e.g. `null` values. Alternatively,
|
|
2608
|
+
* separate visitor functions may be defined for each `Map`, `Pair`, `Seq`,
|
|
2609
|
+
* `Alias` and `Scalar` node. To define the same visitor function for more than
|
|
2610
|
+
* one node type, use the `Collection` (map and seq), `Value` (map, seq & scalar)
|
|
2611
|
+
* and `Node` (alias, map, seq & scalar) targets. Of all these, only the most
|
|
2612
|
+
* specific defined one will be used for each node.
|
|
2613
|
+
*/
|
|
2614
|
+
const visit = function visit(node, visitor) {
|
|
2615
|
+
const visitor_ = initVisitor(visitor);
|
|
2616
|
+
if (node instanceof Document) {
|
|
2617
|
+
if (visit_(null, node.value, visitor_, [node]) === REMOVE) node.value = new Scalar(null);
|
|
2618
|
+
} else visit_(null, node, visitor_, []);
|
|
2619
|
+
};
|
|
2620
|
+
visit.BREAK = BREAK;
|
|
2621
|
+
visit.SKIP = SKIP;
|
|
2622
|
+
visit.REMOVE = REMOVE;
|
|
2623
|
+
function visit_(key, node, visitor, path) {
|
|
2624
|
+
const ctrl = callVisitor(key, node, visitor, path);
|
|
2625
|
+
if (isNode(ctrl) || ctrl instanceof Pair) {
|
|
2626
|
+
replaceNode(key, path, ctrl);
|
|
2627
|
+
return visit_(key, ctrl, visitor, path);
|
|
2628
|
+
}
|
|
2629
|
+
if (typeof ctrl !== "symbol") {
|
|
2630
|
+
if (node instanceof YAMLSeq) {
|
|
2631
|
+
path = [...path, node];
|
|
2632
|
+
for (let i = 0; i < node.length; ++i) {
|
|
2633
|
+
const ci = visit_(i, node[i], visitor, path);
|
|
2634
|
+
if (typeof ci === "number") i = ci - 1;
|
|
2635
|
+
else if (ci === BREAK) return BREAK;
|
|
2636
|
+
else if (ci === REMOVE) {
|
|
2637
|
+
node.splice(i, 1);
|
|
2638
|
+
i -= 1;
|
|
2639
|
+
}
|
|
2640
|
+
}
|
|
2641
|
+
} else if (node instanceof YAMLMap || node instanceof YAMLSet) {
|
|
2642
|
+
path = [...path, node];
|
|
2643
|
+
const entries = Array.from(node.values);
|
|
2644
|
+
const delKeys = [];
|
|
2645
|
+
for (let i = 0; i < entries.length; ++i) {
|
|
2646
|
+
const ci = visit_(i, entries[i][1], visitor, path);
|
|
2647
|
+
if (typeof ci === "number") i = ci - 1;
|
|
2648
|
+
else if (ci === BREAK) return BREAK;
|
|
2649
|
+
else if (ci === REMOVE) delKeys.push(entries[i][0]);
|
|
2650
|
+
}
|
|
2651
|
+
for (const dk of delKeys) node.values.delete(dk);
|
|
2652
|
+
} else if (node instanceof Pair) {
|
|
2653
|
+
path = [...path, node];
|
|
2654
|
+
const ck = visit_("key", node.key, visitor, path);
|
|
2655
|
+
if (ck === BREAK) return BREAK;
|
|
2656
|
+
else if (ck === REMOVE) node.key = new Scalar(null);
|
|
2657
|
+
const cv = visit_("value", node.value, visitor, path);
|
|
2658
|
+
if (cv === BREAK) return BREAK;
|
|
2659
|
+
else if (cv === REMOVE) node.value = null;
|
|
2660
|
+
}
|
|
2661
|
+
}
|
|
2662
|
+
return ctrl;
|
|
2663
|
+
}
|
|
2664
|
+
/**
|
|
2665
|
+
* Apply an async visitor to an AST node or document.
|
|
2666
|
+
*
|
|
2667
|
+
* Walks through the tree (depth-first) starting from `node`, calling a
|
|
2668
|
+
* `visitor` function with three arguments:
|
|
2669
|
+
* - `key`: For sequence values and map `Pair`, the node's index in the
|
|
2670
|
+
* collection. Within a `Pair`, `'key'` or `'value'`, correspondingly.
|
|
2671
|
+
* `null` for the root node.
|
|
2672
|
+
* - `node`: The current node.
|
|
2673
|
+
* - `path`: The ancestry of the current node.
|
|
2674
|
+
*
|
|
2675
|
+
* The return value of the visitor may be used to control the traversal:
|
|
2676
|
+
* - `Promise`: Must resolve to one of the following values
|
|
2677
|
+
* - `undefined` (default): Do nothing and continue
|
|
2678
|
+
* - `visitAsync.SKIP`: Do not visit the children of this node,
|
|
2679
|
+
* continue with next sibling
|
|
2680
|
+
* - `visitAsync.BREAK`: Terminate traversal completely
|
|
2681
|
+
* - `visitAsync.REMOVE`: Remove the current node,
|
|
2682
|
+
* then continue with the next one
|
|
2683
|
+
* - `Node`: Replace the current node, then continue by visiting it
|
|
2684
|
+
* - `number`: While iterating the items of a sequence or map, set the index
|
|
2685
|
+
* of the next step. This is useful especially if the index of the current
|
|
2686
|
+
* node has changed.
|
|
2687
|
+
*
|
|
2688
|
+
* If `visitor` is a single function, it will be called with all values
|
|
2689
|
+
* encountered in the tree, including e.g. `null` values. Alternatively,
|
|
2690
|
+
* separate visitor functions may be defined for each `Map`, `Pair`, `Seq`,
|
|
2691
|
+
* `Alias` and `Scalar` node. To define the same visitor function for more than
|
|
2692
|
+
* one node type, use the `Collection` (map and seq), `Value` (map, seq & scalar)
|
|
2693
|
+
* and `Node` (alias, map, seq & scalar) targets. Of all these, only the most
|
|
2694
|
+
* specific defined one will be used for each node.
|
|
2695
|
+
*/
|
|
2696
|
+
const visitAsync = async function visitAsync(node, visitor) {
|
|
2697
|
+
const visitor_ = initVisitor(visitor);
|
|
2698
|
+
if (node instanceof Document) {
|
|
2699
|
+
if (await visitAsync_(null, node.value, visitor_, [node]) === REMOVE) node.value = new Scalar(null);
|
|
2700
|
+
} else await visitAsync_(null, node, visitor_, []);
|
|
2701
|
+
};
|
|
2702
|
+
visitAsync.BREAK = BREAK;
|
|
2703
|
+
visitAsync.SKIP = SKIP;
|
|
2704
|
+
visitAsync.REMOVE = REMOVE;
|
|
2705
|
+
async function visitAsync_(key, node, visitor, path) {
|
|
2706
|
+
const ctrl = await callVisitor(key, node, visitor, path);
|
|
2707
|
+
if (isNode(ctrl) || ctrl instanceof Pair) {
|
|
2708
|
+
replaceNode(key, path, ctrl);
|
|
2709
|
+
return visitAsync_(key, ctrl, visitor, path);
|
|
2710
|
+
}
|
|
2711
|
+
if (typeof ctrl !== "symbol") {
|
|
2712
|
+
if (node instanceof YAMLSeq) {
|
|
2713
|
+
path = [...path, node];
|
|
2714
|
+
for (let i = 0; i < node.length; ++i) {
|
|
2715
|
+
const ci = await visitAsync_(i, node[i], visitor, path);
|
|
2716
|
+
if (typeof ci === "number") i = ci - 1;
|
|
2717
|
+
else if (ci === BREAK) return BREAK;
|
|
2718
|
+
else if (ci === REMOVE) {
|
|
2719
|
+
node.splice(i, 1);
|
|
2720
|
+
i -= 1;
|
|
2721
|
+
}
|
|
2722
|
+
}
|
|
2723
|
+
} else if (node instanceof YAMLMap || node instanceof YAMLSet) {
|
|
2724
|
+
path = [...path, node];
|
|
2725
|
+
const entries = Array.from(node.values);
|
|
2726
|
+
const delKeys = [];
|
|
2727
|
+
for (let i = 0; i < entries.length; ++i) {
|
|
2728
|
+
const ci = await visitAsync_(i, entries[i][1], visitor, path);
|
|
2729
|
+
if (typeof ci === "number") i = ci - 1;
|
|
2730
|
+
else if (ci === BREAK) return BREAK;
|
|
2731
|
+
else if (ci === REMOVE) delKeys.push(entries[i][0]);
|
|
2732
|
+
}
|
|
2733
|
+
for (const dk of delKeys) node.values.delete(dk);
|
|
2734
|
+
} else if (node instanceof Pair) {
|
|
2735
|
+
path = [...path, node];
|
|
2736
|
+
const ck = await visitAsync_("key", node.key, visitor, path);
|
|
2737
|
+
if (ck === BREAK) return BREAK;
|
|
2738
|
+
else if (ck === REMOVE) node.key = new Scalar(null);
|
|
2739
|
+
const cv = await visitAsync_("value", node.value, visitor, path);
|
|
2740
|
+
if (cv === BREAK) return BREAK;
|
|
2741
|
+
else if (cv === REMOVE) node.value = null;
|
|
2742
|
+
}
|
|
2743
|
+
}
|
|
2744
|
+
return ctrl;
|
|
2745
|
+
}
|
|
2746
|
+
function initVisitor(visitor) {
|
|
2747
|
+
if (typeof visitor === "object" && (visitor.Collection || visitor.Node || visitor.Value)) return Object.assign({
|
|
2748
|
+
Alias: visitor.Node,
|
|
2749
|
+
Map: visitor.Node,
|
|
2750
|
+
Scalar: visitor.Node,
|
|
2751
|
+
Seq: visitor.Node
|
|
2752
|
+
}, visitor.Value && {
|
|
2753
|
+
Map: visitor.Value,
|
|
2754
|
+
Scalar: visitor.Value,
|
|
2755
|
+
Seq: visitor.Value
|
|
2756
|
+
}, visitor.Collection && {
|
|
2757
|
+
Map: visitor.Collection,
|
|
2758
|
+
Seq: visitor.Collection
|
|
2759
|
+
}, visitor);
|
|
2760
|
+
return visitor;
|
|
2761
|
+
}
|
|
2762
|
+
function callVisitor(key, node, visitor, path) {
|
|
2763
|
+
if (typeof visitor === "function") return visitor(key, node, path);
|
|
2764
|
+
if (node instanceof YAMLMap || node instanceof YAMLSet) return visitor.Map?.(key, node, path);
|
|
2765
|
+
if (node instanceof YAMLSeq) return visitor.Seq?.(key, node, path);
|
|
2766
|
+
if (node instanceof Pair) return visitor.Pair?.(key, node, path);
|
|
2767
|
+
if (node instanceof Scalar) return visitor.Scalar?.(key, node, path);
|
|
2768
|
+
if (node instanceof Alias) return visitor.Alias?.(key, node, path);
|
|
2769
|
+
}
|
|
2770
|
+
function replaceNode(key, path, node) {
|
|
2771
|
+
const parent = path[path.length - 1];
|
|
2772
|
+
if (parent instanceof YAMLSeq) parent[key] = node;
|
|
2773
|
+
else if (parent instanceof YAMLMap) if (node instanceof Pair) {
|
|
2774
|
+
const entries = Array.from(parent.values);
|
|
2775
|
+
entries[key] = [parent.keyOf(node, true), node];
|
|
2776
|
+
parent.values = new Map(entries);
|
|
2777
|
+
} else throw new Error("Cannot replace map pair with non-pair value");
|
|
2778
|
+
else if (parent instanceof YAMLSet) if (isNode(node)) {
|
|
2779
|
+
const entries = Array.from(parent.values);
|
|
2780
|
+
entries[key] = [parent.keyOf(node, true), node];
|
|
2781
|
+
parent.values = new Map(entries);
|
|
2782
|
+
} else throw new Error("Cannot replace set value with non-node value");
|
|
2783
|
+
else if (parent instanceof Pair) if (isNode(node)) if (key === "key") parent.key = node;
|
|
2784
|
+
else parent.value = node;
|
|
2785
|
+
else throw new Error(`Cannot replace pair ${key} with non-node value`);
|
|
2786
|
+
else if (parent instanceof Document) if (node instanceof Scalar || isCollection(node)) parent.value = node;
|
|
2787
|
+
else throw new Error("Cannot replace Document value with non-node value");
|
|
2788
|
+
else {
|
|
2789
|
+
const pt = parent instanceof Alias ? "alias" : "scalar";
|
|
2790
|
+
throw new Error(`Cannot replace node with ${pt} parent`);
|
|
2791
|
+
}
|
|
2792
|
+
}
|
|
2793
|
+
//#endregion
|
|
2794
|
+
//#region src/doc/directives.ts
|
|
2795
|
+
const escapeChars = {
|
|
2796
|
+
"!": "%21",
|
|
2797
|
+
",": "%2C",
|
|
2798
|
+
"[": "%5B",
|
|
2799
|
+
"]": "%5D",
|
|
2800
|
+
"{": "%7B",
|
|
2801
|
+
"}": "%7D"
|
|
2802
|
+
};
|
|
2803
|
+
const escapeTagName = (tn) => tn.replace(/[!,[\]{}]/g, (ch) => escapeChars[ch]);
|
|
2804
|
+
var Directives = class Directives {
|
|
2805
|
+
static defaultYaml = {
|
|
2806
|
+
explicit: false,
|
|
2807
|
+
version: "1.2"
|
|
2808
|
+
};
|
|
2809
|
+
static defaultTags = { "!!": "tag:yaml.org,2002:" };
|
|
2810
|
+
yaml;
|
|
2811
|
+
tags;
|
|
2812
|
+
/**
|
|
2813
|
+
* The directives-end/doc-start marker `---`. If `null`, a marker may still be
|
|
2814
|
+
* included in the document's stringified representation.
|
|
2815
|
+
*/
|
|
2816
|
+
docStart = null;
|
|
2817
|
+
/** The doc-end marker `...`. */
|
|
2818
|
+
docEnd = false;
|
|
2819
|
+
/**
|
|
2820
|
+
* Used when parsing YAML 1.1, where:
|
|
2821
|
+
* > If the document specifies no directives, it is parsed using the same
|
|
2822
|
+
* > settings as the previous document. If the document does specify any
|
|
2823
|
+
* > directives, all directives of previous documents, if any, are ignored.
|
|
2824
|
+
*/
|
|
2825
|
+
atNextDocument;
|
|
2826
|
+
constructor(yaml, tags) {
|
|
2827
|
+
this.yaml = Object.assign({}, Directives.defaultYaml, yaml);
|
|
2828
|
+
this.tags = Object.assign({}, Directives.defaultTags, tags);
|
|
2829
|
+
}
|
|
2830
|
+
clone() {
|
|
2831
|
+
const copy = new Directives(this.yaml, this.tags);
|
|
2832
|
+
copy.docStart = this.docStart;
|
|
2833
|
+
return copy;
|
|
2834
|
+
}
|
|
2835
|
+
/**
|
|
2836
|
+
* During parsing, get a Directives instance for the current document and
|
|
2837
|
+
* update the stream state according to the current version's spec.
|
|
2838
|
+
*/
|
|
2839
|
+
atDocument() {
|
|
2840
|
+
const res = new Directives(this.yaml, this.tags);
|
|
2841
|
+
switch (this.yaml.version) {
|
|
2842
|
+
case "1.1":
|
|
2843
|
+
this.atNextDocument = true;
|
|
2844
|
+
break;
|
|
2845
|
+
case "1.2":
|
|
2846
|
+
this.atNextDocument = false;
|
|
2847
|
+
this.yaml = {
|
|
2848
|
+
explicit: Directives.defaultYaml.explicit,
|
|
2849
|
+
version: "1.2"
|
|
2850
|
+
};
|
|
2851
|
+
this.tags = Object.assign({}, Directives.defaultTags);
|
|
2852
|
+
break;
|
|
2853
|
+
}
|
|
2854
|
+
return res;
|
|
2855
|
+
}
|
|
2856
|
+
/**
|
|
2857
|
+
* @param onError - May be called even if the action was successful
|
|
2858
|
+
* @returns `true` on success
|
|
2859
|
+
*/
|
|
2860
|
+
add(line, onError) {
|
|
2861
|
+
if (this.atNextDocument) {
|
|
2862
|
+
this.yaml = {
|
|
2863
|
+
explicit: Directives.defaultYaml.explicit,
|
|
2864
|
+
version: "1.1"
|
|
2865
|
+
};
|
|
2866
|
+
this.tags = Object.assign({}, Directives.defaultTags);
|
|
2867
|
+
this.atNextDocument = false;
|
|
2868
|
+
}
|
|
2869
|
+
const parts = line.trim().split(/[ \t]+/);
|
|
2870
|
+
const name = parts.shift();
|
|
2871
|
+
switch (name) {
|
|
2872
|
+
case "%TAG": {
|
|
2873
|
+
if (parts.length !== 2) {
|
|
2874
|
+
onError(0, "%TAG directive should contain exactly two parts");
|
|
2875
|
+
if (parts.length < 2) return false;
|
|
2876
|
+
}
|
|
2877
|
+
const [handle, prefix] = parts;
|
|
2878
|
+
this.tags[handle] = prefix;
|
|
2879
|
+
return true;
|
|
2880
|
+
}
|
|
2881
|
+
case "%YAML": {
|
|
2882
|
+
this.yaml.explicit = true;
|
|
2883
|
+
if (parts.length !== 1) {
|
|
2884
|
+
onError(0, "%YAML directive should contain exactly one part");
|
|
2885
|
+
return false;
|
|
2886
|
+
}
|
|
2887
|
+
const [version] = parts;
|
|
2888
|
+
if (version === "1.1" || version === "1.2") {
|
|
2889
|
+
this.yaml.version = version;
|
|
2890
|
+
return true;
|
|
2891
|
+
} else {
|
|
2892
|
+
const isValid = /^\d+\.\d+$/.test(version);
|
|
2893
|
+
onError(6, `Unsupported YAML version ${version}`, isValid);
|
|
2894
|
+
return false;
|
|
2895
|
+
}
|
|
2896
|
+
}
|
|
2897
|
+
default:
|
|
2898
|
+
onError(0, `Unknown directive ${name}`, true);
|
|
2899
|
+
return false;
|
|
2900
|
+
}
|
|
2901
|
+
}
|
|
2902
|
+
/**
|
|
2903
|
+
* Resolves a tag, matching handles to those defined in %TAG directives.
|
|
2904
|
+
*
|
|
2905
|
+
* @returns Resolved tag, which may also be the non-specific tag `'!'` or a
|
|
2906
|
+
* `'!local'` tag, or `null` if unresolvable.
|
|
2907
|
+
*/
|
|
2908
|
+
tagName(source, onError) {
|
|
2909
|
+
if (source === "!") return "!";
|
|
2910
|
+
if (source[0] !== "!") {
|
|
2911
|
+
onError(`Not a valid tag: ${source}`);
|
|
2912
|
+
return null;
|
|
2913
|
+
}
|
|
2914
|
+
if (source[1] === "<") {
|
|
2915
|
+
const verbatim = source.slice(2, -1);
|
|
2916
|
+
if (verbatim === "!" || verbatim === "!!") {
|
|
2917
|
+
onError(`Verbatim tags aren't resolved, so ${source} is invalid.`);
|
|
2918
|
+
return null;
|
|
2919
|
+
}
|
|
2920
|
+
if (source[source.length - 1] !== ">") onError("Verbatim tags must end with a >");
|
|
2921
|
+
return verbatim;
|
|
2922
|
+
}
|
|
2923
|
+
const [, handle, suffix] = source.match(/^(.*!)([^!]*)$/s);
|
|
2924
|
+
if (!suffix) onError(`The ${source} tag has no suffix`);
|
|
2925
|
+
const prefix = this.tags[handle];
|
|
2926
|
+
if (prefix) try {
|
|
2927
|
+
return prefix + decodeURIComponent(suffix);
|
|
2928
|
+
} catch (error) {
|
|
2929
|
+
onError(String(error));
|
|
2930
|
+
return null;
|
|
2931
|
+
}
|
|
2932
|
+
if (handle === "!") return source;
|
|
2933
|
+
onError(`Could not resolve tag: ${source}`);
|
|
2934
|
+
return null;
|
|
2935
|
+
}
|
|
2936
|
+
/**
|
|
2937
|
+
* Given a fully resolved tag, returns its printable string form,
|
|
2938
|
+
* taking into account current tag prefixes and defaults.
|
|
2939
|
+
*/
|
|
2940
|
+
tagString(tag) {
|
|
2941
|
+
for (const [handle, prefix] of Object.entries(this.tags)) if (tag.startsWith(prefix)) return handle + escapeTagName(tag.substring(prefix.length));
|
|
2942
|
+
return tag[0] === "!" ? tag : `!<${tag}>`;
|
|
2943
|
+
}
|
|
2944
|
+
toString(doc) {
|
|
2945
|
+
const lines = this.yaml.explicit ? [`%YAML ${this.yaml.version || "1.2"}`] : [];
|
|
2946
|
+
const tagEntries = Object.entries(this.tags);
|
|
2947
|
+
let tagNames;
|
|
2948
|
+
if (doc && tagEntries.length > 0) {
|
|
2949
|
+
const tags = {};
|
|
2950
|
+
visit(doc.value, (_key, node) => {
|
|
2951
|
+
if (node?.tag) tags[node.tag] = true;
|
|
2952
|
+
});
|
|
2953
|
+
tagNames = Object.keys(tags);
|
|
2954
|
+
} else tagNames = [];
|
|
2955
|
+
for (const [handle, prefix] of tagEntries) {
|
|
2956
|
+
if (handle === "!!" && prefix === "tag:yaml.org,2002:") continue;
|
|
2957
|
+
if (!doc || tagNames.some((tn) => tn.startsWith(prefix))) lines.push(`%TAG ${handle} ${prefix}`);
|
|
2958
|
+
}
|
|
2959
|
+
return lines.join("\n");
|
|
2960
|
+
}
|
|
2961
|
+
};
|
|
2962
|
+
//#endregion
|
|
2963
|
+
export { Scalar as S, ToJSContext as _, Schema as a, stringifyString as b, seq as c, Pair as d, isCollection as f, YAMLMap as g, YAMLSeq as h, Document as i, map as l, YAMLSet as m, visit as n, stringifyNumber as o, isNode as p, visitAsync as r, string as s, Directives as t, Alias as u, debug as v, foldFlowLines as x, warn as y };
|