yaml 2.8.2 → 3.0.0-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (238) hide show
  1. package/README.md +65 -85
  2. package/{bin.mjs → bin.js} +1 -1
  3. package/dist/chunk-BYypO7fO.js +18 -0
  4. package/dist/cli.d.ts +10 -7
  5. package/dist/cli.js +181 -0
  6. package/dist/directives-CG6n4xSM.js +2856 -0
  7. package/dist/index.d.ts +335 -25
  8. package/dist/index.js +4 -49
  9. package/dist/line-counter-TFl552k_.js +3098 -0
  10. package/dist/public-api-BE74JyVm.js +79 -0
  11. package/dist/stringifyString-S_ITVLTO.d.ts +1306 -0
  12. package/dist/test-events.d.ts +6 -3
  13. package/dist/test-events.js +98 -124
  14. package/dist/util.d.ts +2 -16
  15. package/dist/util.js +2 -27
  16. package/package.json +20 -44
  17. package/browser/dist/compose/compose-collection.js +0 -88
  18. package/browser/dist/compose/compose-doc.js +0 -43
  19. package/browser/dist/compose/compose-node.js +0 -102
  20. package/browser/dist/compose/compose-scalar.js +0 -86
  21. package/browser/dist/compose/composer.js +0 -217
  22. package/browser/dist/compose/resolve-block-map.js +0 -115
  23. package/browser/dist/compose/resolve-block-scalar.js +0 -198
  24. package/browser/dist/compose/resolve-block-seq.js +0 -49
  25. package/browser/dist/compose/resolve-end.js +0 -37
  26. package/browser/dist/compose/resolve-flow-collection.js +0 -207
  27. package/browser/dist/compose/resolve-flow-scalar.js +0 -223
  28. package/browser/dist/compose/resolve-props.js +0 -146
  29. package/browser/dist/compose/util-contains-newline.js +0 -34
  30. package/browser/dist/compose/util-empty-scalar-position.js +0 -26
  31. package/browser/dist/compose/util-flow-indent-check.js +0 -15
  32. package/browser/dist/compose/util-map-includes.js +0 -13
  33. package/browser/dist/doc/Document.js +0 -335
  34. package/browser/dist/doc/anchors.js +0 -71
  35. package/browser/dist/doc/applyReviver.js +0 -55
  36. package/browser/dist/doc/createNode.js +0 -88
  37. package/browser/dist/doc/directives.js +0 -176
  38. package/browser/dist/errors.js +0 -57
  39. package/browser/dist/index.js +0 -17
  40. package/browser/dist/log.js +0 -11
  41. package/browser/dist/nodes/Alias.js +0 -114
  42. package/browser/dist/nodes/Collection.js +0 -147
  43. package/browser/dist/nodes/Node.js +0 -38
  44. package/browser/dist/nodes/Pair.js +0 -36
  45. package/browser/dist/nodes/Scalar.js +0 -24
  46. package/browser/dist/nodes/YAMLMap.js +0 -144
  47. package/browser/dist/nodes/YAMLSeq.js +0 -113
  48. package/browser/dist/nodes/addPairToJSMap.js +0 -63
  49. package/browser/dist/nodes/identity.js +0 -36
  50. package/browser/dist/nodes/toJS.js +0 -37
  51. package/browser/dist/parse/cst-scalar.js +0 -214
  52. package/browser/dist/parse/cst-stringify.js +0 -61
  53. package/browser/dist/parse/cst-visit.js +0 -97
  54. package/browser/dist/parse/cst.js +0 -98
  55. package/browser/dist/parse/lexer.js +0 -717
  56. package/browser/dist/parse/line-counter.js +0 -39
  57. package/browser/dist/parse/parser.js +0 -967
  58. package/browser/dist/public-api.js +0 -102
  59. package/browser/dist/schema/Schema.js +0 -37
  60. package/browser/dist/schema/common/map.js +0 -17
  61. package/browser/dist/schema/common/null.js +0 -15
  62. package/browser/dist/schema/common/seq.js +0 -17
  63. package/browser/dist/schema/common/string.js +0 -14
  64. package/browser/dist/schema/core/bool.js +0 -19
  65. package/browser/dist/schema/core/float.js +0 -43
  66. package/browser/dist/schema/core/int.js +0 -38
  67. package/browser/dist/schema/core/schema.js +0 -23
  68. package/browser/dist/schema/json/schema.js +0 -62
  69. package/browser/dist/schema/tags.js +0 -96
  70. package/browser/dist/schema/yaml-1.1/binary.js +0 -58
  71. package/browser/dist/schema/yaml-1.1/bool.js +0 -26
  72. package/browser/dist/schema/yaml-1.1/float.js +0 -46
  73. package/browser/dist/schema/yaml-1.1/int.js +0 -71
  74. package/browser/dist/schema/yaml-1.1/merge.js +0 -64
  75. package/browser/dist/schema/yaml-1.1/omap.js +0 -74
  76. package/browser/dist/schema/yaml-1.1/pairs.js +0 -78
  77. package/browser/dist/schema/yaml-1.1/schema.js +0 -39
  78. package/browser/dist/schema/yaml-1.1/set.js +0 -93
  79. package/browser/dist/schema/yaml-1.1/timestamp.js +0 -101
  80. package/browser/dist/stringify/foldFlowLines.js +0 -146
  81. package/browser/dist/stringify/stringify.js +0 -128
  82. package/browser/dist/stringify/stringifyCollection.js +0 -143
  83. package/browser/dist/stringify/stringifyComment.js +0 -20
  84. package/browser/dist/stringify/stringifyDocument.js +0 -85
  85. package/browser/dist/stringify/stringifyNumber.js +0 -24
  86. package/browser/dist/stringify/stringifyPair.js +0 -150
  87. package/browser/dist/stringify/stringifyString.js +0 -336
  88. package/browser/dist/util.js +0 -11
  89. package/browser/dist/visit.js +0 -233
  90. package/browser/index.js +0 -5
  91. package/browser/package.json +0 -3
  92. package/dist/cli.mjs +0 -201
  93. package/dist/compose/compose-collection.d.ts +0 -11
  94. package/dist/compose/compose-collection.js +0 -90
  95. package/dist/compose/compose-doc.d.ts +0 -7
  96. package/dist/compose/compose-doc.js +0 -45
  97. package/dist/compose/compose-node.d.ts +0 -29
  98. package/dist/compose/compose-node.js +0 -105
  99. package/dist/compose/compose-scalar.d.ts +0 -5
  100. package/dist/compose/compose-scalar.js +0 -88
  101. package/dist/compose/composer.d.ts +0 -63
  102. package/dist/compose/composer.js +0 -222
  103. package/dist/compose/resolve-block-map.d.ts +0 -6
  104. package/dist/compose/resolve-block-map.js +0 -117
  105. package/dist/compose/resolve-block-scalar.d.ts +0 -11
  106. package/dist/compose/resolve-block-scalar.js +0 -200
  107. package/dist/compose/resolve-block-seq.d.ts +0 -6
  108. package/dist/compose/resolve-block-seq.js +0 -51
  109. package/dist/compose/resolve-end.d.ts +0 -6
  110. package/dist/compose/resolve-end.js +0 -39
  111. package/dist/compose/resolve-flow-collection.d.ts +0 -7
  112. package/dist/compose/resolve-flow-collection.js +0 -209
  113. package/dist/compose/resolve-flow-scalar.d.ts +0 -10
  114. package/dist/compose/resolve-flow-scalar.js +0 -225
  115. package/dist/compose/resolve-props.d.ts +0 -23
  116. package/dist/compose/resolve-props.js +0 -148
  117. package/dist/compose/util-contains-newline.d.ts +0 -2
  118. package/dist/compose/util-contains-newline.js +0 -36
  119. package/dist/compose/util-empty-scalar-position.d.ts +0 -2
  120. package/dist/compose/util-empty-scalar-position.js +0 -28
  121. package/dist/compose/util-flow-indent-check.d.ts +0 -3
  122. package/dist/compose/util-flow-indent-check.js +0 -17
  123. package/dist/compose/util-map-includes.d.ts +0 -4
  124. package/dist/compose/util-map-includes.js +0 -15
  125. package/dist/doc/Document.d.ts +0 -141
  126. package/dist/doc/Document.js +0 -337
  127. package/dist/doc/anchors.d.ts +0 -24
  128. package/dist/doc/anchors.js +0 -76
  129. package/dist/doc/applyReviver.d.ts +0 -9
  130. package/dist/doc/applyReviver.js +0 -57
  131. package/dist/doc/createNode.d.ts +0 -17
  132. package/dist/doc/createNode.js +0 -90
  133. package/dist/doc/directives.d.ts +0 -49
  134. package/dist/doc/directives.js +0 -178
  135. package/dist/errors.d.ts +0 -21
  136. package/dist/errors.js +0 -62
  137. package/dist/log.d.ts +0 -3
  138. package/dist/log.js +0 -19
  139. package/dist/nodes/Alias.d.ts +0 -29
  140. package/dist/nodes/Alias.js +0 -116
  141. package/dist/nodes/Collection.d.ts +0 -73
  142. package/dist/nodes/Collection.js +0 -151
  143. package/dist/nodes/Node.d.ts +0 -53
  144. package/dist/nodes/Node.js +0 -40
  145. package/dist/nodes/Pair.d.ts +0 -22
  146. package/dist/nodes/Pair.js +0 -39
  147. package/dist/nodes/Scalar.d.ts +0 -43
  148. package/dist/nodes/Scalar.js +0 -27
  149. package/dist/nodes/YAMLMap.d.ts +0 -53
  150. package/dist/nodes/YAMLMap.js +0 -147
  151. package/dist/nodes/YAMLSeq.d.ts +0 -60
  152. package/dist/nodes/YAMLSeq.js +0 -115
  153. package/dist/nodes/addPairToJSMap.d.ts +0 -4
  154. package/dist/nodes/addPairToJSMap.js +0 -65
  155. package/dist/nodes/identity.d.ts +0 -23
  156. package/dist/nodes/identity.js +0 -53
  157. package/dist/nodes/toJS.d.ts +0 -29
  158. package/dist/nodes/toJS.js +0 -39
  159. package/dist/options.d.ts +0 -344
  160. package/dist/parse/cst-scalar.d.ts +0 -64
  161. package/dist/parse/cst-scalar.js +0 -218
  162. package/dist/parse/cst-stringify.d.ts +0 -8
  163. package/dist/parse/cst-stringify.js +0 -63
  164. package/dist/parse/cst-visit.d.ts +0 -39
  165. package/dist/parse/cst-visit.js +0 -99
  166. package/dist/parse/cst.d.ts +0 -109
  167. package/dist/parse/cst.js +0 -112
  168. package/dist/parse/lexer.d.ts +0 -87
  169. package/dist/parse/lexer.js +0 -719
  170. package/dist/parse/line-counter.d.ts +0 -22
  171. package/dist/parse/line-counter.js +0 -41
  172. package/dist/parse/parser.d.ts +0 -84
  173. package/dist/parse/parser.js +0 -972
  174. package/dist/public-api.d.ts +0 -44
  175. package/dist/public-api.js +0 -107
  176. package/dist/schema/Schema.d.ts +0 -17
  177. package/dist/schema/Schema.js +0 -39
  178. package/dist/schema/common/map.d.ts +0 -2
  179. package/dist/schema/common/map.js +0 -19
  180. package/dist/schema/common/null.d.ts +0 -4
  181. package/dist/schema/common/null.js +0 -17
  182. package/dist/schema/common/seq.d.ts +0 -2
  183. package/dist/schema/common/seq.js +0 -19
  184. package/dist/schema/common/string.d.ts +0 -2
  185. package/dist/schema/common/string.js +0 -16
  186. package/dist/schema/core/bool.d.ts +0 -4
  187. package/dist/schema/core/bool.js +0 -21
  188. package/dist/schema/core/float.d.ts +0 -4
  189. package/dist/schema/core/float.js +0 -47
  190. package/dist/schema/core/int.d.ts +0 -4
  191. package/dist/schema/core/int.js +0 -42
  192. package/dist/schema/core/schema.d.ts +0 -1
  193. package/dist/schema/core/schema.js +0 -25
  194. package/dist/schema/json/schema.d.ts +0 -2
  195. package/dist/schema/json/schema.js +0 -64
  196. package/dist/schema/json-schema.d.ts +0 -69
  197. package/dist/schema/tags.d.ts +0 -48
  198. package/dist/schema/tags.js +0 -99
  199. package/dist/schema/types.d.ts +0 -92
  200. package/dist/schema/yaml-1.1/binary.d.ts +0 -2
  201. package/dist/schema/yaml-1.1/binary.js +0 -70
  202. package/dist/schema/yaml-1.1/bool.d.ts +0 -7
  203. package/dist/schema/yaml-1.1/bool.js +0 -29
  204. package/dist/schema/yaml-1.1/float.d.ts +0 -4
  205. package/dist/schema/yaml-1.1/float.js +0 -50
  206. package/dist/schema/yaml-1.1/int.d.ts +0 -5
  207. package/dist/schema/yaml-1.1/int.js +0 -76
  208. package/dist/schema/yaml-1.1/merge.d.ts +0 -9
  209. package/dist/schema/yaml-1.1/merge.js +0 -68
  210. package/dist/schema/yaml-1.1/omap.d.ts +0 -22
  211. package/dist/schema/yaml-1.1/omap.js +0 -77
  212. package/dist/schema/yaml-1.1/pairs.d.ts +0 -10
  213. package/dist/schema/yaml-1.1/pairs.js +0 -82
  214. package/dist/schema/yaml-1.1/schema.d.ts +0 -1
  215. package/dist/schema/yaml-1.1/schema.js +0 -41
  216. package/dist/schema/yaml-1.1/set.d.ts +0 -28
  217. package/dist/schema/yaml-1.1/set.js +0 -96
  218. package/dist/schema/yaml-1.1/timestamp.d.ts +0 -6
  219. package/dist/schema/yaml-1.1/timestamp.js +0 -105
  220. package/dist/stringify/foldFlowLines.d.ts +0 -34
  221. package/dist/stringify/foldFlowLines.js +0 -151
  222. package/dist/stringify/stringify.d.ts +0 -21
  223. package/dist/stringify/stringify.js +0 -131
  224. package/dist/stringify/stringifyCollection.d.ts +0 -17
  225. package/dist/stringify/stringifyCollection.js +0 -145
  226. package/dist/stringify/stringifyComment.d.ts +0 -10
  227. package/dist/stringify/stringifyComment.js +0 -24
  228. package/dist/stringify/stringifyDocument.d.ts +0 -4
  229. package/dist/stringify/stringifyDocument.js +0 -87
  230. package/dist/stringify/stringifyNumber.d.ts +0 -2
  231. package/dist/stringify/stringifyNumber.js +0 -26
  232. package/dist/stringify/stringifyPair.d.ts +0 -3
  233. package/dist/stringify/stringifyPair.js +0 -152
  234. package/dist/stringify/stringifyString.d.ts +0 -9
  235. package/dist/stringify/stringifyString.js +0 -338
  236. package/dist/visit.d.ts +0 -102
  237. package/dist/visit.js +0 -236
  238. package/util.js +0 -2
@@ -0,0 +1,3098 @@
1
+ import { t as __exportAll } from "./chunk-BYypO7fO.js";
2
+ import { _ as Collection, b as Scalar, f as Alias, g as YAMLSeq, i as Document, p as Pair, t as Directives, u as YAMLMap, v as stringifyString, x as NodeBase } from "./directives-CG6n4xSM.js";
3
+
4
+ //#region src/compose/resolve-block-scalar.ts
5
+ function resolveBlockScalar(ctx, scalar, onError) {
6
+ const start = scalar.offset;
7
+ const header = parseBlockScalarHeader(scalar, ctx.options.strict, onError);
8
+ if (!header) return {
9
+ value: "",
10
+ type: null,
11
+ comment: "",
12
+ range: [
13
+ start,
14
+ start,
15
+ start
16
+ ]
17
+ };
18
+ const type = header.mode === ">" ? Scalar.BLOCK_FOLDED : Scalar.BLOCK_LITERAL;
19
+ const lines = scalar.source ? splitLines(scalar.source) : [];
20
+ let chompStart = lines.length;
21
+ for (let i = lines.length - 1; i >= 0; --i) {
22
+ const content = lines[i][1];
23
+ if (content === "" || content === "\r") chompStart = i;
24
+ else break;
25
+ }
26
+ if (chompStart === 0) {
27
+ const value = header.chomp === "+" && lines.length > 0 ? "\n".repeat(Math.max(1, lines.length - 1)) : "";
28
+ let end = start + header.length;
29
+ if (scalar.source) end += scalar.source.length;
30
+ return {
31
+ value,
32
+ type,
33
+ comment: header.comment,
34
+ range: [
35
+ start,
36
+ end,
37
+ end
38
+ ]
39
+ };
40
+ }
41
+ let trimIndent = scalar.indent + header.indent;
42
+ let offset = scalar.offset + header.length;
43
+ let contentStart = 0;
44
+ for (let i = 0; i < chompStart; ++i) {
45
+ const [indent, content] = lines[i];
46
+ if (content === "" || content === "\r") {
47
+ if (header.indent === 0 && indent.length > trimIndent) trimIndent = indent.length;
48
+ } else {
49
+ if (indent.length < trimIndent) onError(offset + indent.length, "MISSING_CHAR", "Block scalars with more-indented leading empty lines must use an explicit indentation indicator");
50
+ if (header.indent === 0) trimIndent = indent.length;
51
+ contentStart = i;
52
+ if (trimIndent === 0 && !ctx.atRoot) onError(offset, "BAD_INDENT", "Block scalar values in collections must be indented");
53
+ break;
54
+ }
55
+ offset += indent.length + content.length + 1;
56
+ }
57
+ for (let i = lines.length - 1; i >= chompStart; --i) if (lines[i][0].length > trimIndent) chompStart = i + 1;
58
+ let value = "";
59
+ let sep = "";
60
+ let prevMoreIndented = false;
61
+ for (let i = 0; i < contentStart; ++i) value += lines[i][0].slice(trimIndent) + "\n";
62
+ for (let i = contentStart; i < chompStart; ++i) {
63
+ let [indent, content] = lines[i];
64
+ offset += indent.length + content.length + 1;
65
+ const crlf = content[content.length - 1] === "\r";
66
+ if (crlf) content = content.slice(0, -1);
67
+ /* istanbul ignore if already caught in lexer */
68
+ if (content && indent.length < trimIndent) {
69
+ const message = `Block scalar lines must not be less indented than their ${header.indent ? "explicit indentation indicator" : "first line"}`;
70
+ onError(offset - content.length - (crlf ? 2 : 1), "BAD_INDENT", message);
71
+ indent = "";
72
+ }
73
+ if (type === Scalar.BLOCK_LITERAL) {
74
+ value += sep + indent.slice(trimIndent) + content;
75
+ sep = "\n";
76
+ } else if (indent.length > trimIndent || content[0] === " ") {
77
+ if (sep === " ") sep = "\n";
78
+ else if (!prevMoreIndented && sep === "\n") sep = "\n\n";
79
+ value += sep + indent.slice(trimIndent) + content;
80
+ sep = "\n";
81
+ prevMoreIndented = true;
82
+ } else if (content === "") if (sep === "\n") value += "\n";
83
+ else sep = "\n";
84
+ else {
85
+ value += sep + content;
86
+ sep = " ";
87
+ prevMoreIndented = false;
88
+ }
89
+ }
90
+ switch (header.chomp) {
91
+ case "-": break;
92
+ case "+":
93
+ for (let i = chompStart; i < lines.length; ++i) value += "\n" + lines[i][0].slice(trimIndent);
94
+ if (value[value.length - 1] !== "\n") value += "\n";
95
+ break;
96
+ default: value += "\n";
97
+ }
98
+ const end = start + header.length + scalar.source.length;
99
+ return {
100
+ value,
101
+ type,
102
+ comment: header.comment,
103
+ range: [
104
+ start,
105
+ end,
106
+ end
107
+ ]
108
+ };
109
+ }
110
+ function parseBlockScalarHeader({ offset, props }, strict, onError) {
111
+ /* istanbul ignore if should not happen */
112
+ if (props[0].type !== "block-scalar-header") {
113
+ onError(props[0], "IMPOSSIBLE", "Block scalar header not found");
114
+ return null;
115
+ }
116
+ const { source } = props[0];
117
+ const mode = source[0];
118
+ let indent = 0;
119
+ let chomp = "";
120
+ let error = -1;
121
+ for (let i = 1; i < source.length; ++i) {
122
+ const ch = source[i];
123
+ if (!chomp && (ch === "-" || ch === "+")) chomp = ch;
124
+ else {
125
+ const n = Number(ch);
126
+ if (!indent && n) indent = n;
127
+ else if (error === -1) error = offset + i;
128
+ }
129
+ }
130
+ if (error !== -1) onError(error, "UNEXPECTED_TOKEN", `Block scalar header includes extra characters: ${source}`);
131
+ let hasSpace = false;
132
+ let comment = "";
133
+ let length = source.length;
134
+ for (let i = 1; i < props.length; ++i) {
135
+ const token = props[i];
136
+ switch (token.type) {
137
+ case "space": hasSpace = true;
138
+ case "newline":
139
+ length += token.source.length;
140
+ break;
141
+ case "comment":
142
+ if (strict && !hasSpace) onError(token, "MISSING_CHAR", "Comments must be separated from other tokens by white space characters");
143
+ length += token.source.length;
144
+ comment = token.source.substring(1);
145
+ break;
146
+ case "error":
147
+ onError(token, "UNEXPECTED_TOKEN", token.message);
148
+ length += token.source.length;
149
+ break;
150
+ default: {
151
+ onError(token, "UNEXPECTED_TOKEN", `Unexpected token in block scalar header: ${token.type}`);
152
+ const ts = token.source;
153
+ if (ts && typeof ts === "string") length += ts.length;
154
+ }
155
+ }
156
+ }
157
+ return {
158
+ mode,
159
+ indent,
160
+ chomp,
161
+ comment,
162
+ length
163
+ };
164
+ }
165
+ /** @returns Array of lines split up as `[indent, content]` */
166
+ function splitLines(source) {
167
+ const split = source.split(/\n( *)/);
168
+ const first = split[0];
169
+ const m = first.match(/^( *)/);
170
+ const lines = [m?.[1] ? [m[1], first.slice(m[1].length)] : ["", first]];
171
+ for (let i = 1; i < split.length; i += 2) lines.push([split[i], split[i + 1]]);
172
+ return lines;
173
+ }
174
+
175
+ //#endregion
176
+ //#region src/compose/resolve-end.ts
177
+ function resolveEnd(end, offset, reqSpace, onError) {
178
+ let comment = "";
179
+ if (end) {
180
+ let hasSpace = false;
181
+ let sep = "";
182
+ for (const token of end) {
183
+ const { source, type } = token;
184
+ switch (type) {
185
+ case "space":
186
+ hasSpace = true;
187
+ break;
188
+ case "comment": {
189
+ if (reqSpace && !hasSpace) onError(token, "MISSING_CHAR", "Comments must be separated from other tokens by white space characters");
190
+ const cb = source.substring(1) || " ";
191
+ if (!comment) comment = cb;
192
+ else comment += sep + cb;
193
+ sep = "";
194
+ break;
195
+ }
196
+ case "newline":
197
+ if (comment) sep += source;
198
+ hasSpace = true;
199
+ break;
200
+ default: onError(token, "UNEXPECTED_TOKEN", `Unexpected ${type} at node end`);
201
+ }
202
+ offset += source.length;
203
+ }
204
+ }
205
+ return {
206
+ comment,
207
+ offset
208
+ };
209
+ }
210
+
211
+ //#endregion
212
+ //#region src/compose/resolve-flow-scalar.ts
213
+ function resolveFlowScalar(scalar, strict, onError) {
214
+ const { offset, type, source, end } = scalar;
215
+ let _type;
216
+ let value;
217
+ const _onError = (rel, code, msg) => onError(offset + rel, code, msg);
218
+ switch (type) {
219
+ case "scalar":
220
+ _type = Scalar.PLAIN;
221
+ value = plainValue(source, _onError);
222
+ break;
223
+ case "single-quoted-scalar":
224
+ _type = Scalar.QUOTE_SINGLE;
225
+ value = singleQuotedValue(source, _onError);
226
+ break;
227
+ case "double-quoted-scalar":
228
+ _type = Scalar.QUOTE_DOUBLE;
229
+ value = doubleQuotedValue(source, _onError);
230
+ break;
231
+ default:
232
+ onError(scalar, "UNEXPECTED_TOKEN", `Expected a flow scalar value, but found: ${type}`);
233
+ return {
234
+ value: "",
235
+ type: null,
236
+ comment: "",
237
+ range: [
238
+ offset,
239
+ offset + source.length,
240
+ offset + source.length
241
+ ]
242
+ };
243
+ }
244
+ const valueEnd = offset + source.length;
245
+ const re = resolveEnd(end, valueEnd, strict, onError);
246
+ return {
247
+ value,
248
+ type: _type,
249
+ comment: re.comment,
250
+ range: [
251
+ offset,
252
+ valueEnd,
253
+ re.offset
254
+ ]
255
+ };
256
+ }
257
+ function plainValue(source, onError) {
258
+ let badChar = "";
259
+ switch (source[0]) {
260
+ case " ":
261
+ badChar = "a tab character";
262
+ break;
263
+ case ",":
264
+ badChar = "flow indicator character ,";
265
+ break;
266
+ case "%":
267
+ badChar = "directive indicator character %";
268
+ break;
269
+ case "|":
270
+ case ">":
271
+ badChar = `block scalar indicator ${source[0]}`;
272
+ break;
273
+ case "@":
274
+ case "`":
275
+ badChar = `reserved character ${source[0]}`;
276
+ break;
277
+ }
278
+ if (badChar) onError(0, "BAD_SCALAR_START", `Plain value cannot start with ${badChar}`);
279
+ return foldLines(source);
280
+ }
281
+ function singleQuotedValue(source, onError) {
282
+ if (source[source.length - 1] !== "'" || source.length === 1) onError(source.length, "MISSING_CHAR", "Missing closing 'quote");
283
+ return foldLines(source.slice(1, -1)).replace(/''/g, "'");
284
+ }
285
+ function foldLines(source) {
286
+ /**
287
+ * The negative lookbehind here and in the `re` RegExp is to
288
+ * prevent causing a polynomial search time in certain cases.
289
+ *
290
+ * The try-catch is for Safari, which doesn't support this yet:
291
+ * https://caniuse.com/js-regexp-lookbehind
292
+ */
293
+ let first, line;
294
+ try {
295
+ first = /* @__PURE__ */ new RegExp("(.*?)(?<![ ])[ ]*\r?\n", "sy");
296
+ line = /* @__PURE__ */ new RegExp("[ ]*(.*?)(?:(?<![ ])[ ]*)?\r?\n", "sy");
297
+ } catch {
298
+ first = /(.*?)[ \t]*\r?\n/sy;
299
+ line = /[ \t]*(.*?)[ \t]*\r?\n/sy;
300
+ }
301
+ let match = first.exec(source);
302
+ if (!match) return source;
303
+ let res = match[1];
304
+ let sep = " ";
305
+ let pos = first.lastIndex;
306
+ line.lastIndex = pos;
307
+ while (match = line.exec(source)) {
308
+ if (match[1] === "") if (sep === "\n") res += sep;
309
+ else sep = "\n";
310
+ else {
311
+ res += sep + match[1];
312
+ sep = " ";
313
+ }
314
+ pos = line.lastIndex;
315
+ }
316
+ const last = /[ \t]*(.*)/sy;
317
+ last.lastIndex = pos;
318
+ match = last.exec(source);
319
+ return res + sep + (match?.[1] ?? "");
320
+ }
321
+ function doubleQuotedValue(source, onError) {
322
+ let res = "";
323
+ for (let i = 1; i < source.length - 1; ++i) {
324
+ const ch = source[i];
325
+ if (ch === "\r" && source[i + 1] === "\n") continue;
326
+ if (ch === "\n") {
327
+ const { fold, offset } = foldNewline(source, i);
328
+ res += fold;
329
+ i = offset;
330
+ } else if (ch === "\\") {
331
+ let next = source[++i];
332
+ const cc = escapeCodes[next];
333
+ if (cc) res += cc;
334
+ else if (next === "\n") {
335
+ next = source[i + 1];
336
+ while (next === " " || next === " ") next = source[++i + 1];
337
+ } else if (next === "\r" && source[i + 1] === "\n") {
338
+ next = source[++i + 1];
339
+ while (next === " " || next === " ") next = source[++i + 1];
340
+ } else if (next === "x" || next === "u" || next === "U") {
341
+ const length = {
342
+ x: 2,
343
+ u: 4,
344
+ U: 8
345
+ }[next];
346
+ res += parseCharCode(source, i + 1, length, onError);
347
+ i += length;
348
+ } else {
349
+ const raw = source.substr(i - 1, 2);
350
+ onError(i - 1, "BAD_DQ_ESCAPE", `Invalid escape sequence ${raw}`);
351
+ res += raw;
352
+ }
353
+ } else if (ch === " " || ch === " ") {
354
+ const wsStart = i;
355
+ let next = source[i + 1];
356
+ while (next === " " || next === " ") next = source[++i + 1];
357
+ if (next !== "\n" && !(next === "\r" && source[i + 2] === "\n")) res += i > wsStart ? source.slice(wsStart, i + 1) : ch;
358
+ } else res += ch;
359
+ }
360
+ if (source[source.length - 1] !== "\"" || source.length === 1) onError(source.length, "MISSING_CHAR", "Missing closing \"quote");
361
+ return res;
362
+ }
363
+ /**
364
+ * Fold a single newline into a space, multiple newlines to N - 1 newlines.
365
+ * Presumes `source[offset] === '\n'`
366
+ */
367
+ function foldNewline(source, offset) {
368
+ let fold = "";
369
+ let ch = source[offset + 1];
370
+ while (ch === " " || ch === " " || ch === "\n" || ch === "\r") {
371
+ if (ch === "\r" && source[offset + 2] !== "\n") break;
372
+ if (ch === "\n") fold += "\n";
373
+ offset += 1;
374
+ ch = source[offset + 1];
375
+ }
376
+ if (!fold) fold = " ";
377
+ return {
378
+ fold,
379
+ offset
380
+ };
381
+ }
382
+ const escapeCodes = {
383
+ "0": "\0",
384
+ a: "\x07",
385
+ b: "\b",
386
+ e: "\x1B",
387
+ f: "\f",
388
+ n: "\n",
389
+ r: "\r",
390
+ t: " ",
391
+ v: "\v",
392
+ N: "…",
393
+ _: "\xA0",
394
+ L: "\u2028",
395
+ P: "\u2029",
396
+ " ": " ",
397
+ "\"": "\"",
398
+ "/": "/",
399
+ "\\": "\\",
400
+ " ": " "
401
+ };
402
+ function parseCharCode(source, offset, length, onError) {
403
+ const cc = source.substr(offset, length);
404
+ const code = cc.length === length && /^[0-9a-fA-F]+$/.test(cc) ? parseInt(cc, 16) : NaN;
405
+ if (isNaN(code)) {
406
+ const raw = source.substr(offset - 2, length + 2);
407
+ onError(offset - 2, "BAD_DQ_ESCAPE", `Invalid escape sequence ${raw}`);
408
+ return raw;
409
+ }
410
+ return String.fromCodePoint(code);
411
+ }
412
+
413
+ //#endregion
414
+ //#region src/errors.ts
415
+ var YAMLError = class extends Error {
416
+ name;
417
+ code;
418
+ message;
419
+ pos;
420
+ linePos;
421
+ constructor(name, pos, code, message) {
422
+ super();
423
+ this.name = name;
424
+ this.code = code;
425
+ this.message = message;
426
+ this.pos = pos;
427
+ }
428
+ };
429
+ var YAMLParseError = class extends YAMLError {
430
+ constructor(pos, code, message) {
431
+ super("YAMLParseError", pos, code, message);
432
+ }
433
+ };
434
+ var YAMLWarning = class extends YAMLError {
435
+ constructor(pos, code, message) {
436
+ super("YAMLWarning", pos, code, message);
437
+ }
438
+ };
439
+ const prettifyError = (src, lc) => (error) => {
440
+ if (error.pos[0] === -1) return;
441
+ error.linePos = error.pos.map((pos) => lc.linePos(pos));
442
+ const { line, col } = error.linePos[0];
443
+ error.message += ` at line ${line}, column ${col}`;
444
+ let ci = col - 1;
445
+ let lineStr = src.substring(lc.lineStarts[line - 1], lc.lineStarts[line]).replace(/[\n\r]+$/, "");
446
+ if (ci >= 60 && lineStr.length > 80) {
447
+ const trimStart = Math.min(ci - 39, lineStr.length - 79);
448
+ lineStr = "…" + lineStr.substring(trimStart);
449
+ ci -= trimStart - 1;
450
+ }
451
+ if (lineStr.length > 80) lineStr = lineStr.substring(0, 79) + "…";
452
+ if (line > 1 && /^ *$/.test(lineStr.substring(0, ci))) {
453
+ let prev = src.substring(lc.lineStarts[line - 2], lc.lineStarts[line - 1]);
454
+ if (prev.length > 80) prev = prev.substring(0, 79) + "…\n";
455
+ lineStr = prev + lineStr;
456
+ }
457
+ if (/[^ ]/.test(lineStr)) {
458
+ let count = 1;
459
+ const end = error.linePos[1];
460
+ if (end?.line === line && end.col > col) count = Math.max(1, Math.min(end.col - col, 80 - ci));
461
+ const pointer = " ".repeat(ci) + "^".repeat(count);
462
+ error.message += `:\n\n${lineStr}\n${pointer}\n`;
463
+ }
464
+ };
465
+
466
+ //#endregion
467
+ //#region src/parse/cst-scalar.ts
468
+ function resolveAsScalar(token, strict = true, onError) {
469
+ if (token) {
470
+ const _onError = (pos, code, message) => {
471
+ const offset = typeof pos === "number" ? pos : Array.isArray(pos) ? pos[0] : pos.offset;
472
+ if (onError) onError(offset, code, message);
473
+ else throw new YAMLParseError([offset, offset + 1], code, message);
474
+ };
475
+ switch (token.type) {
476
+ case "scalar":
477
+ case "single-quoted-scalar":
478
+ case "double-quoted-scalar": return resolveFlowScalar(token, strict, _onError);
479
+ case "block-scalar": return resolveBlockScalar({ options: { strict } }, token, _onError);
480
+ }
481
+ }
482
+ return null;
483
+ }
484
+ /**
485
+ * Create a new scalar token with `value`
486
+ *
487
+ * Values that represent an actual string but may be parsed as a different type should use a `type` other than `'PLAIN'`,
488
+ * as this function does not support any schema operations and won't check for such conflicts.
489
+ *
490
+ * @param value The string representation of the value, which will have its content properly indented.
491
+ * @param context.end Comments and whitespace after the end of the value, or after the block scalar header. If undefined, a newline will be added.
492
+ * @param context.implicitKey Being within an implicit key may affect the resolved type of the token's value.
493
+ * @param context.indent The indent level of the token.
494
+ * @param context.inFlow Is this scalar within a flow collection? This may affect the resolved type of the token's value.
495
+ * @param context.offset The offset position of the token.
496
+ * @param context.type The preferred type of the scalar token. If undefined, the previous type of the `token` will be used, defaulting to `'PLAIN'`.
497
+ */
498
+ function createScalarToken(value, context) {
499
+ const { implicitKey = false, indent, inFlow = false, offset = -1, type = "PLAIN" } = context;
500
+ const source = stringifyString({
501
+ type,
502
+ value
503
+ }, {
504
+ implicitKey,
505
+ indent: indent > 0 ? " ".repeat(indent) : "",
506
+ inFlow,
507
+ options: {
508
+ blockQuote: true,
509
+ lineWidth: -1
510
+ }
511
+ });
512
+ const end = context.end ?? [{
513
+ type: "newline",
514
+ offset: -1,
515
+ indent,
516
+ source: "\n"
517
+ }];
518
+ switch (source[0]) {
519
+ case "|":
520
+ case ">": {
521
+ const he = source.indexOf("\n");
522
+ const head = source.substring(0, he);
523
+ const body = source.substring(he + 1) + "\n";
524
+ const props = [{
525
+ type: "block-scalar-header",
526
+ offset,
527
+ indent,
528
+ source: head
529
+ }];
530
+ if (!addEndtoBlockProps(props, end)) props.push({
531
+ type: "newline",
532
+ offset: -1,
533
+ indent,
534
+ source: "\n"
535
+ });
536
+ return {
537
+ type: "block-scalar",
538
+ offset,
539
+ indent,
540
+ props,
541
+ source: body
542
+ };
543
+ }
544
+ case "\"": return {
545
+ type: "double-quoted-scalar",
546
+ offset,
547
+ indent,
548
+ source,
549
+ end
550
+ };
551
+ case "'": return {
552
+ type: "single-quoted-scalar",
553
+ offset,
554
+ indent,
555
+ source,
556
+ end
557
+ };
558
+ default: return {
559
+ type: "scalar",
560
+ offset,
561
+ indent,
562
+ source,
563
+ end
564
+ };
565
+ }
566
+ }
567
+ /**
568
+ * Set the value of `token` to the given string `value`, overwriting any previous contents and type that it may have.
569
+ *
570
+ * Best efforts are made to retain any comments previously associated with the `token`,
571
+ * though all contents within a collection's `items` will be overwritten.
572
+ *
573
+ * Values that represent an actual string but may be parsed as a different type should use a `type` other than `'PLAIN'`,
574
+ * as this function does not support any schema operations and won't check for such conflicts.
575
+ *
576
+ * @param token Any token. If it does not include an `indent` value, the value will be stringified as if it were an implicit key.
577
+ * @param value The string representation of the value, which will have its content properly indented.
578
+ * @param context.afterKey In most cases, values after a key should have an additional level of indentation.
579
+ * @param context.implicitKey Being within an implicit key may affect the resolved type of the token's value.
580
+ * @param context.inFlow Being within a flow collection may affect the resolved type of the token's value.
581
+ * @param context.type The preferred type of the scalar token. If undefined, the previous type of the `token` will be used, defaulting to `'PLAIN'`.
582
+ */
583
+ function setScalarValue(token, value, context = {}) {
584
+ let { afterKey = false, implicitKey = false, inFlow = false, type } = context;
585
+ let indent = "indent" in token ? token.indent : null;
586
+ if (afterKey && typeof indent === "number") indent += 2;
587
+ if (!type) switch (token.type) {
588
+ case "single-quoted-scalar":
589
+ type = "QUOTE_SINGLE";
590
+ break;
591
+ case "double-quoted-scalar":
592
+ type = "QUOTE_DOUBLE";
593
+ break;
594
+ case "block-scalar": {
595
+ const header = token.props[0];
596
+ if (header.type !== "block-scalar-header") throw new Error("Invalid block scalar header");
597
+ type = header.source[0] === ">" ? "BLOCK_FOLDED" : "BLOCK_LITERAL";
598
+ break;
599
+ }
600
+ default: type = "PLAIN";
601
+ }
602
+ const source = stringifyString({
603
+ type,
604
+ value
605
+ }, {
606
+ implicitKey: implicitKey || indent === null,
607
+ indent: indent !== null && indent > 0 ? " ".repeat(indent) : "",
608
+ inFlow,
609
+ options: {
610
+ blockQuote: true,
611
+ lineWidth: -1
612
+ }
613
+ });
614
+ switch (source[0]) {
615
+ case "|":
616
+ case ">":
617
+ setBlockScalarValue(token, source);
618
+ break;
619
+ case "\"":
620
+ setFlowScalarValue(token, source, "double-quoted-scalar");
621
+ break;
622
+ case "'":
623
+ setFlowScalarValue(token, source, "single-quoted-scalar");
624
+ break;
625
+ default: setFlowScalarValue(token, source, "scalar");
626
+ }
627
+ }
628
+ function setBlockScalarValue(token, source) {
629
+ const he = source.indexOf("\n");
630
+ const head = source.substring(0, he);
631
+ const body = source.substring(he + 1) + "\n";
632
+ if (token.type === "block-scalar") {
633
+ const header = token.props[0];
634
+ if (header.type !== "block-scalar-header") throw new Error("Invalid block scalar header");
635
+ header.source = head;
636
+ token.source = body;
637
+ } else {
638
+ const { offset } = token;
639
+ const indent = "indent" in token ? token.indent : -1;
640
+ const props = [{
641
+ type: "block-scalar-header",
642
+ offset,
643
+ indent,
644
+ source: head
645
+ }];
646
+ if (!addEndtoBlockProps(props, "end" in token ? token.end : void 0)) props.push({
647
+ type: "newline",
648
+ offset: -1,
649
+ indent,
650
+ source: "\n"
651
+ });
652
+ for (const key of Object.keys(token)) if (key !== "type" && key !== "offset") delete token[key];
653
+ Object.assign(token, {
654
+ type: "block-scalar",
655
+ indent,
656
+ props,
657
+ source: body
658
+ });
659
+ }
660
+ }
661
+ /** @returns `true` if last token is a newline */
662
+ function addEndtoBlockProps(props, end) {
663
+ if (end) for (const st of end) switch (st.type) {
664
+ case "space":
665
+ case "comment":
666
+ props.push(st);
667
+ break;
668
+ case "newline":
669
+ props.push(st);
670
+ return true;
671
+ }
672
+ return false;
673
+ }
674
+ function setFlowScalarValue(token, source, type) {
675
+ switch (token.type) {
676
+ case "scalar":
677
+ case "double-quoted-scalar":
678
+ case "single-quoted-scalar":
679
+ token.type = type;
680
+ token.source = source;
681
+ break;
682
+ case "block-scalar": {
683
+ const end = token.props.slice(1);
684
+ let oa = source.length;
685
+ if (token.props[0].type === "block-scalar-header") oa -= token.props[0].source.length;
686
+ for (const tok of end) tok.offset += oa;
687
+ delete token.props;
688
+ Object.assign(token, {
689
+ type,
690
+ source,
691
+ end
692
+ });
693
+ break;
694
+ }
695
+ case "block-map":
696
+ case "block-seq": {
697
+ const nl = {
698
+ type: "newline",
699
+ offset: token.offset + source.length,
700
+ indent: token.indent,
701
+ source: "\n"
702
+ };
703
+ delete token.items;
704
+ Object.assign(token, {
705
+ type,
706
+ source,
707
+ end: [nl]
708
+ });
709
+ break;
710
+ }
711
+ default: {
712
+ const indent = "indent" in token ? token.indent : -1;
713
+ const end = "end" in token && Array.isArray(token.end) ? token.end.filter((st) => st.type === "space" || st.type === "comment" || st.type === "newline") : [];
714
+ for (const key of Object.keys(token)) if (key !== "type" && key !== "offset") delete token[key];
715
+ Object.assign(token, {
716
+ type,
717
+ indent,
718
+ source,
719
+ end
720
+ });
721
+ }
722
+ }
723
+ }
724
+
725
+ //#endregion
726
+ //#region src/parse/cst-stringify.ts
727
+ /**
728
+ * Stringify a CST document, token, or collection item
729
+ *
730
+ * Fair warning: This applies no validation whatsoever, and
731
+ * simply concatenates the sources in their logical order.
732
+ */
733
+ const stringify = (cst) => "type" in cst ? stringifyToken(cst) : stringifyItem(cst);
734
+ function stringifyToken(token) {
735
+ switch (token.type) {
736
+ case "block-scalar": {
737
+ let res = "";
738
+ for (const tok of token.props) res += stringifyToken(tok);
739
+ return res + token.source;
740
+ }
741
+ case "block-map":
742
+ case "block-seq": {
743
+ let res = "";
744
+ for (const item of token.items) res += stringifyItem(item);
745
+ return res;
746
+ }
747
+ case "flow-collection": {
748
+ let res = token.start.source;
749
+ for (const item of token.items) res += stringifyItem(item);
750
+ for (const st of token.end) res += st.source;
751
+ return res;
752
+ }
753
+ case "document": {
754
+ let res = stringifyItem(token);
755
+ if (token.end) for (const st of token.end) res += st.source;
756
+ return res;
757
+ }
758
+ default: {
759
+ let res = token.source;
760
+ if ("end" in token && token.end) for (const st of token.end) res += st.source;
761
+ return res;
762
+ }
763
+ }
764
+ }
765
+ function stringifyItem({ start, key, sep, value }) {
766
+ let res = "";
767
+ for (const st of start) res += st.source;
768
+ if (key) res += stringifyToken(key);
769
+ if (sep) for (const st of sep) res += st.source;
770
+ if (value) res += stringifyToken(value);
771
+ return res;
772
+ }
773
+
774
+ //#endregion
775
+ //#region src/parse/cst-visit.ts
776
+ const BREAK = Symbol("break visit");
777
+ const SKIP = Symbol("skip children");
778
+ const REMOVE = Symbol("remove item");
779
+ /**
780
+ * Apply a visitor to a CST document or item.
781
+ *
782
+ * Walks through the tree (depth-first) starting from the root, calling a
783
+ * `visitor` function with two arguments when entering each item:
784
+ * - `item`: The current item, which included the following members:
785
+ * - `start: SourceToken[]` – Source tokens before the key or value,
786
+ * possibly including its anchor or tag.
787
+ * - `key?: Token | null` – Set for pair values. May then be `null`, if
788
+ * the key before the `:` separator is empty.
789
+ * - `sep?: SourceToken[]` – Source tokens between the key and the value,
790
+ * which should include the `:` map value indicator if `value` is set.
791
+ * - `value?: Token` – The value of a sequence item, or of a map pair.
792
+ * - `path`: The steps from the root to the current node, as an array of
793
+ * `['key' | 'value', number]` tuples.
794
+ *
795
+ * The return value of the visitor may be used to control the traversal:
796
+ * - `undefined` (default): Do nothing and continue
797
+ * - `visit.SKIP`: Do not visit the children of this token, continue with
798
+ * next sibling
799
+ * - `visit.BREAK`: Terminate traversal completely
800
+ * - `visit.REMOVE`: Remove the current item, then continue with the next one
801
+ * - `number`: Set the index of the next step. This is useful especially if
802
+ * the index of the current token has changed.
803
+ * - `function`: Define the next visitor for this item. After the original
804
+ * visitor is called on item entry, next visitors are called after handling
805
+ * a non-empty `key` and when exiting the item.
806
+ */
807
+ const visit = function visit(cst, visitor) {
808
+ if ("type" in cst && cst.type === "document") cst = {
809
+ start: cst.start,
810
+ value: cst.value
811
+ };
812
+ _visit(Object.freeze([]), cst, visitor);
813
+ };
814
+ visit.BREAK = BREAK;
815
+ visit.SKIP = SKIP;
816
+ visit.REMOVE = REMOVE;
817
+ visit.itemAtPath = (cst, path) => {
818
+ let item = cst;
819
+ for (const [field, index] of path) {
820
+ const tok = item?.[field];
821
+ if (tok && "items" in tok) item = tok.items[index];
822
+ else return void 0;
823
+ }
824
+ return item;
825
+ };
826
+ visit.parentCollection = (cst, path) => {
827
+ const parent = visit.itemAtPath(cst, path.slice(0, -1));
828
+ const field = path[path.length - 1][0];
829
+ const coll = parent?.[field];
830
+ if (coll && "items" in coll) return coll;
831
+ throw new Error("Parent collection not found");
832
+ };
833
+ function _visit(path, item, visitor) {
834
+ let ctrl = visitor(item, path);
835
+ if (typeof ctrl === "symbol") return ctrl;
836
+ for (const field of ["key", "value"]) {
837
+ const token = item[field];
838
+ if (token && "items" in token) {
839
+ for (let i = 0; i < token.items.length; ++i) {
840
+ const ci = _visit(Object.freeze(path.concat([[field, i]])), token.items[i], visitor);
841
+ if (typeof ci === "number") i = ci - 1;
842
+ else if (ci === BREAK) return BREAK;
843
+ else if (ci === REMOVE) {
844
+ token.items.splice(i, 1);
845
+ i -= 1;
846
+ }
847
+ }
848
+ if (typeof ctrl === "function" && field === "key") ctrl = ctrl(item, path);
849
+ }
850
+ }
851
+ return typeof ctrl === "function" ? ctrl(item, path) : ctrl;
852
+ }
853
+
854
+ //#endregion
855
+ //#region src/parse/cst.ts
856
+ var cst_exports = /* @__PURE__ */ __exportAll({
857
+ BOM: () => BOM,
858
+ DOCUMENT: () => DOCUMENT,
859
+ FLOW_END: () => FLOW_END,
860
+ SCALAR: () => SCALAR,
861
+ createScalarToken: () => createScalarToken,
862
+ isCollection: () => isCollection,
863
+ isScalar: () => isScalar,
864
+ prettyToken: () => prettyToken,
865
+ resolveAsScalar: () => resolveAsScalar,
866
+ setScalarValue: () => setScalarValue,
867
+ stringify: () => stringify,
868
+ tokenType: () => tokenType,
869
+ visit: () => visit
870
+ });
871
+ /** The byte order mark */
872
+ const BOM = "";
873
+ /** Start of doc-mode */
874
+ const DOCUMENT = "";
875
+ /** Unexpected end of flow-mode */
876
+ const FLOW_END = "";
877
+ /** Next token is a scalar value */
878
+ const SCALAR = "";
879
+ /** @returns `true` if `token` is a flow or block collection */
880
+ const isCollection = (token) => !!token && "items" in token;
881
+ /** @returns `true` if `token` is a flow or block scalar; not an alias */
882
+ const isScalar = (token) => !!token && (token.type === "scalar" || token.type === "single-quoted-scalar" || token.type === "double-quoted-scalar" || token.type === "block-scalar");
883
+ /* istanbul ignore next */
884
+ /** Get a printable representation of a lexer token */
885
+ function prettyToken(token) {
886
+ switch (token) {
887
+ case BOM: return "<BOM>";
888
+ case DOCUMENT: return "<DOC>";
889
+ case FLOW_END: return "<FLOW_END>";
890
+ case SCALAR: return "<SCALAR>";
891
+ default: return JSON.stringify(token);
892
+ }
893
+ }
894
+ /** Identify the type of a lexer token. May return `null` for unknown tokens. */
895
+ function tokenType(source) {
896
+ switch (source) {
897
+ case BOM: return "byte-order-mark";
898
+ case DOCUMENT: return "doc-mode";
899
+ case FLOW_END: return "flow-error-end";
900
+ case SCALAR: return "scalar";
901
+ case "---": return "doc-start";
902
+ case "...": return "doc-end";
903
+ case "":
904
+ case "\n":
905
+ case "\r\n": return "newline";
906
+ case "-": return "seq-item-ind";
907
+ case "?": return "explicit-key-ind";
908
+ case ":": return "map-value-ind";
909
+ case "{": return "flow-map-start";
910
+ case "}": return "flow-map-end";
911
+ case "[": return "flow-seq-start";
912
+ case "]": return "flow-seq-end";
913
+ case ",": return "comma";
914
+ }
915
+ switch (source[0]) {
916
+ case " ":
917
+ case " ": return "space";
918
+ case "#": return "comment";
919
+ case "%": return "directive-line";
920
+ case "*": return "alias";
921
+ case "&": return "anchor";
922
+ case "!": return "tag";
923
+ case "'": return "single-quoted-scalar";
924
+ case "\"": return "double-quoted-scalar";
925
+ case "|":
926
+ case ">": return "block-scalar-header";
927
+ }
928
+ return null;
929
+ }
930
+
931
+ //#endregion
932
+ //#region src/parse/lexer.ts
933
+ function isEmpty(ch) {
934
+ switch (ch) {
935
+ case void 0:
936
+ case " ":
937
+ case "\n":
938
+ case "\r":
939
+ case " ": return true;
940
+ default: return false;
941
+ }
942
+ }
943
+ const flowIndicatorChars = /* @__PURE__ */ new Set(",[]{}");
944
+ const invalidAnchorChars = /* @__PURE__ */ new Set(" ,[]{}\n\r ");
945
+ const isNotAnchorChar = (ch) => !ch || invalidAnchorChars.has(ch);
946
+ const blockScalarHeader = /([|>][^\s#]*)([ \t]*)((?:.|\r(?!\n))*)$/my;
947
+ const blockStart = /([-?:])(?=[ \n\r\t]|$)([ \t]*)/y;
948
+ const directiveLine = /(%.*?)(?:([ \t]+)(#.*)?)?$/my;
949
+ const docMarker = /[-.]{3}(?=[ \n\r\t]|$)(?:([ \t]+)(#.*)?)?/y;
950
+ const emptyLineOrComment = /([ \t]*)(#.*)?$/my;
951
+ const indicator = /(?:(&[^\s,[\]{}]*|!<[^\s>]*>?|!(?:[0-9a-z-#;/?:@&=+$_.!~*'()]|%[0-9a-f]{2})*)|([-?:])(?=[ \n\r\t]|$)|([-?:])(?=[,[\]{}]|$))([ \t]*)/iy;
952
+ /**
953
+ * Splits an input `source` string into lexical YAML tokens,
954
+ * i.e. smaller strings that are easily identifiable by `tokens.tokenType()`.
955
+ *
956
+ * Lexing starts always in a "stream" context.
957
+ *
958
+ * In addition to slices of the original input, the following control characters
959
+ * may also be emitted:
960
+ *
961
+ * - `\x02` (Start of Text): A document starts with the next token
962
+ * - `\x18` (Cancel): Unexpected end of flow-mode (indicates an error)
963
+ * - `\x1f` (Unit Separator): Next token is a scalar value
964
+ * - `\u{FEFF}` (Byte order mark): Emitted separately outside documents
965
+ */
966
+ function lex(source) {
967
+ if (typeof source !== "string") throw TypeError("source is not a string");
968
+ const lexer = new Lexer(source);
969
+ const end = source.length;
970
+ let state = "stream";
971
+ while (lexer.pos < end) state = lexer[state]();
972
+ return lexer.tokens;
973
+ }
974
+ var Lexer = class {
975
+ /** Current input */
976
+ source = "";
977
+ /**
978
+ * Flag noting whether the map value indicator : can immediately follow this
979
+ * node within a flow context.
980
+ */
981
+ flowKey = false;
982
+ /** Count of surrounding flow collection levels. */
983
+ flowLevel = 0;
984
+ /**
985
+ * Minimum level of indentation required for next lines to be parsed as a
986
+ * part of the current scalar value.
987
+ */
988
+ indentNext = 0;
989
+ /** Indentation level of the current line. */
990
+ indentValue = 0;
991
+ /** A pointer to `source`; the current position of the lexer. */
992
+ pos = 0;
993
+ tokens = [];
994
+ constructor(source) {
995
+ this.source = source;
996
+ }
997
+ charAt(n) {
998
+ return this.source[this.pos + n];
999
+ }
1000
+ continueScalar(offset) {
1001
+ if (this.indentNext > 0) {
1002
+ let ch = this.source[offset];
1003
+ let indent = 0;
1004
+ while (ch === " ") ch = this.source[++indent + offset];
1005
+ if (ch === "\r") {
1006
+ if (this.source[indent + offset + 1] === "\n") return offset + indent + 1;
1007
+ }
1008
+ return ch === "\n" || indent >= this.indentNext ? offset + indent : -1;
1009
+ }
1010
+ docMarker.lastIndex = offset;
1011
+ return docMarker.test(this.source) ? -1 : offset;
1012
+ }
1013
+ stream() {
1014
+ if (this.charAt(0) === BOM) {
1015
+ this.count(1);
1016
+ return "stream";
1017
+ }
1018
+ directiveLine.lastIndex = this.pos;
1019
+ let m = directiveLine.exec(this.source);
1020
+ if (m) {
1021
+ const [line, directive, spaces, comment] = m;
1022
+ this.tokens.push(directive);
1023
+ if (spaces) this.tokens.push(spaces);
1024
+ if (comment) this.tokens.push(comment);
1025
+ this.pos += line.length;
1026
+ this.newline();
1027
+ return "stream";
1028
+ }
1029
+ emptyLineOrComment.lastIndex = this.pos;
1030
+ m = emptyLineOrComment.exec(this.source);
1031
+ if (m) {
1032
+ const [line, spaces, comment] = m;
1033
+ if (spaces) this.tokens.push(spaces);
1034
+ if (comment) this.tokens.push(comment);
1035
+ this.pos += line.length;
1036
+ this.newline();
1037
+ return "stream";
1038
+ }
1039
+ this.tokens.push(DOCUMENT);
1040
+ return this.lineStart();
1041
+ }
1042
+ lineStart() {
1043
+ docMarker.lastIndex = this.pos;
1044
+ const dmm = docMarker.exec(this.source);
1045
+ if (dmm) {
1046
+ const [line, spaces, comment] = dmm;
1047
+ this.count(3);
1048
+ if (spaces) {
1049
+ this.tokens.push(spaces);
1050
+ this.pos += spaces.length;
1051
+ }
1052
+ if (comment) {
1053
+ this.tokens.push(comment);
1054
+ this.pos += comment.length;
1055
+ }
1056
+ this.newline();
1057
+ this.indentValue = 0;
1058
+ this.indentNext = 0;
1059
+ return line.startsWith("-") ? this.lineStart() : "stream";
1060
+ }
1061
+ this.indentValue = this.spaces(false);
1062
+ if (this.indentNext > this.indentValue && !isEmpty(this.charAt(1))) this.indentNext = this.indentValue;
1063
+ blockStart.lastIndex = this.pos;
1064
+ let bsm;
1065
+ while (bsm = blockStart.exec(this.source)) {
1066
+ const [line, indicator, spaces] = bsm;
1067
+ this.tokens.push(indicator);
1068
+ if (spaces) this.tokens.push(spaces);
1069
+ this.pos += line.length;
1070
+ this.indentNext = this.indentValue + 1;
1071
+ this.indentValue += line.length;
1072
+ }
1073
+ return "document";
1074
+ }
1075
+ document() {
1076
+ this.spaces(true);
1077
+ this.indicators();
1078
+ switch (this.charAt(0)) {
1079
+ case "#": this.toLineEnd();
1080
+ case "\n":
1081
+ case void 0:
1082
+ this.newline();
1083
+ return this.lineStart();
1084
+ case "{":
1085
+ case "[":
1086
+ this.count(1);
1087
+ this.flowKey = false;
1088
+ this.flowLevel = 1;
1089
+ return "flow";
1090
+ case "}":
1091
+ case "]":
1092
+ this.count(1);
1093
+ return "document";
1094
+ case "*":
1095
+ this.until(isNotAnchorChar);
1096
+ return "document";
1097
+ case "\"":
1098
+ case "'":
1099
+ this.quotedScalar();
1100
+ return "document";
1101
+ case "|":
1102
+ case ">":
1103
+ this.blockScalar();
1104
+ return this.lineStart();
1105
+ case "\r": if (this.charAt(1) === "\n") {
1106
+ this.count(2);
1107
+ return this.lineStart();
1108
+ }
1109
+ default:
1110
+ this.plainScalar();
1111
+ return "document";
1112
+ }
1113
+ }
1114
+ flow() {
1115
+ let nl, sp;
1116
+ let indent = -1;
1117
+ do {
1118
+ nl = this.newline();
1119
+ if (nl > 0) {
1120
+ sp = this.spaces(false);
1121
+ this.indentValue = indent = sp;
1122
+ } else sp = 0;
1123
+ sp += this.spaces(true);
1124
+ } while (nl + sp > 0);
1125
+ let ch = this.charAt(0);
1126
+ if (indent !== -1 && indent < this.indentNext && ch !== "#" && !(indent === this.indentNext - 1 && this.flowLevel === 1 && (ch === "]" || ch === "}"))) {
1127
+ this.flowLevel = 0;
1128
+ this.tokens.push(FLOW_END);
1129
+ return this.lineStart();
1130
+ }
1131
+ if (indent === 0) {
1132
+ docMarker.lastIndex = this.pos;
1133
+ if (docMarker.test(this.source)) {
1134
+ this.flowLevel = 0;
1135
+ this.tokens.push(FLOW_END);
1136
+ return this.lineStart();
1137
+ }
1138
+ }
1139
+ while (ch === ",") {
1140
+ this.count(1);
1141
+ this.spaces(true);
1142
+ this.flowKey = false;
1143
+ ch = this.charAt(0);
1144
+ }
1145
+ if (this.indicators()) ch = this.charAt(0);
1146
+ switch (ch) {
1147
+ case "\n":
1148
+ case void 0: break;
1149
+ case "#":
1150
+ this.toLineEnd();
1151
+ break;
1152
+ case "{":
1153
+ case "[":
1154
+ this.count(1);
1155
+ this.flowKey = false;
1156
+ this.flowLevel += 1;
1157
+ break;
1158
+ case "}":
1159
+ case "]":
1160
+ this.count(1);
1161
+ this.flowKey = true;
1162
+ this.flowLevel -= 1;
1163
+ return this.flowLevel ? "flow" : "document";
1164
+ case "*":
1165
+ this.until(isNotAnchorChar);
1166
+ break;
1167
+ case "\"":
1168
+ case "'":
1169
+ this.flowKey = true;
1170
+ this.quotedScalar();
1171
+ break;
1172
+ case ":":
1173
+ if (this.flowKey) {
1174
+ this.flowKey = false;
1175
+ this.count(1);
1176
+ this.spaces(true);
1177
+ } else {
1178
+ const next = this.charAt(1);
1179
+ if (isEmpty(next) || next === ",") {
1180
+ this.count(1);
1181
+ this.spaces(true);
1182
+ } else this.plainScalar();
1183
+ }
1184
+ break;
1185
+ case "\r": if (this.charAt(1) === "\n") break;
1186
+ default:
1187
+ this.flowKey = false;
1188
+ this.plainScalar();
1189
+ }
1190
+ return "flow";
1191
+ }
1192
+ indicators() {
1193
+ let hasIndicators = false;
1194
+ indicator.lastIndex = this.pos;
1195
+ let m;
1196
+ while (m = indicator.exec(this.source)) {
1197
+ hasIndicators ||= true;
1198
+ const [fm, tagOrAnchor, bsEmpty, bsInFlow, spaces] = m;
1199
+ if (tagOrAnchor) this.tokens.push(tagOrAnchor);
1200
+ else if (this.flowLevel > 0) {
1201
+ this.tokens.push(bsEmpty ?? bsInFlow);
1202
+ this.flowKey &&= false;
1203
+ } else if (bsEmpty) {
1204
+ this.tokens.push(bsEmpty);
1205
+ this.indentNext = this.indentValue + 1;
1206
+ } else break;
1207
+ if (spaces) this.tokens.push(spaces);
1208
+ this.pos += fm.length;
1209
+ }
1210
+ return hasIndicators;
1211
+ }
1212
+ quotedScalar() {
1213
+ const quote = this.charAt(0);
1214
+ let end = this.source.indexOf(quote, this.pos + 1);
1215
+ if (quote === "'") while (end !== -1 && this.source[end + 1] === "'") end = this.source.indexOf("'", end + 2);
1216
+ else while (end !== -1) {
1217
+ let n = 0;
1218
+ while (this.source[end - 1 - n] === "\\") n += 1;
1219
+ if (n % 2 === 0) break;
1220
+ end = this.source.indexOf("\"", end + 1);
1221
+ }
1222
+ const qb = this.source.substring(0, end);
1223
+ let nl = qb.indexOf("\n", this.pos);
1224
+ if (nl !== -1) {
1225
+ while (nl !== -1) {
1226
+ const cs = this.continueScalar(nl + 1);
1227
+ if (cs === -1) break;
1228
+ nl = qb.indexOf("\n", cs);
1229
+ }
1230
+ if (nl !== -1) end = nl - (qb[nl - 1] === "\r" ? 2 : 1);
1231
+ }
1232
+ if (end === -1) end = this.source.length;
1233
+ this.toIndex(end + 1, false);
1234
+ }
1235
+ blockScalar() {
1236
+ let bsIndent = -1;
1237
+ let bsKeep = false;
1238
+ blockScalarHeader.lastIndex = this.pos;
1239
+ const [line, header, spaces, comment] = blockScalarHeader.exec(this.source);
1240
+ for (const ch of header) if (ch === "+") bsKeep = true;
1241
+ else if (ch > "0" && ch <= "9") bsIndent = Number(ch) - 1;
1242
+ this.tokens.push(header);
1243
+ if (spaces) this.tokens.push(spaces);
1244
+ if (comment) this.tokens.push(comment);
1245
+ this.pos += line.length;
1246
+ this.newline();
1247
+ let nl = this.pos - 1;
1248
+ let indent = 0;
1249
+ let ch;
1250
+ loop: for (let i = this.pos; ch = this.source[i]; ++i) switch (ch) {
1251
+ case " ":
1252
+ indent += 1;
1253
+ break;
1254
+ case "\n":
1255
+ nl = i;
1256
+ indent = 0;
1257
+ break;
1258
+ case "\r": if (this.source[i + 1] === "\n") break;
1259
+ default: break loop;
1260
+ }
1261
+ if (indent >= this.indentNext) {
1262
+ if (bsIndent === -1) this.indentNext = indent;
1263
+ else this.indentNext = bsIndent + (this.indentNext === 0 ? 1 : this.indentNext);
1264
+ do {
1265
+ const cs = this.continueScalar(nl + 1);
1266
+ if (cs === -1) break;
1267
+ nl = this.source.indexOf("\n", cs);
1268
+ } while (nl !== -1);
1269
+ if (nl === -1) nl = this.source.length;
1270
+ }
1271
+ let i = nl + 1;
1272
+ ch = this.source[i];
1273
+ while (ch === " ") ch = this.source[++i];
1274
+ if (ch === " ") {
1275
+ while (ch === " " || ch === " " || ch === "\r" || ch === "\n") ch = this.source[++i];
1276
+ nl = i - 1;
1277
+ } else if (!bsKeep) do {
1278
+ let i = nl - 1;
1279
+ let ch = this.source[i];
1280
+ if (ch === "\r") ch = this.source[--i];
1281
+ const lastChar = i;
1282
+ while (ch === " ") ch = this.source[--i];
1283
+ if (ch === "\n" && i >= this.pos && i + 1 + indent > lastChar) nl = i;
1284
+ else break;
1285
+ } while (true);
1286
+ this.tokens.push(SCALAR);
1287
+ this.toIndex(nl + 1, true);
1288
+ }
1289
+ plainScalar() {
1290
+ const inFlow = this.flowLevel > 0;
1291
+ let end = this.pos - 1;
1292
+ let i = this.pos - 1;
1293
+ let ch;
1294
+ while (ch = this.source[++i]) if (ch === ":") {
1295
+ const next = this.source[i + 1];
1296
+ if (isEmpty(next) || inFlow && flowIndicatorChars.has(next)) break;
1297
+ end = i;
1298
+ } else if (isEmpty(ch)) {
1299
+ let next = this.source[i + 1];
1300
+ if (ch === "\r") if (next === "\n") {
1301
+ i += 1;
1302
+ ch = "\n";
1303
+ next = this.source[i + 1];
1304
+ } else end = i;
1305
+ if (next === "#" || inFlow && flowIndicatorChars.has(next)) break;
1306
+ if (ch === "\n") {
1307
+ const cs = this.continueScalar(i + 1);
1308
+ if (cs === -1) break;
1309
+ i = Math.max(i, cs - 2);
1310
+ }
1311
+ } else {
1312
+ if (inFlow && flowIndicatorChars.has(ch)) break;
1313
+ end = i;
1314
+ }
1315
+ this.tokens.push(SCALAR);
1316
+ this.toIndex(end + 1, true);
1317
+ }
1318
+ count(n) {
1319
+ if (n > 0) {
1320
+ const s = this.source.substr(this.pos, n);
1321
+ this.tokens.push(s);
1322
+ this.pos += n;
1323
+ return n;
1324
+ }
1325
+ return 0;
1326
+ }
1327
+ toIndex(i, allowEmpty) {
1328
+ const s = this.source.slice(this.pos, i);
1329
+ if (s) {
1330
+ this.tokens.push(s);
1331
+ this.pos += s.length;
1332
+ } else if (allowEmpty) this.tokens.push("");
1333
+ return s.length;
1334
+ }
1335
+ toLineEnd() {
1336
+ let i = this.pos;
1337
+ let ch = this.source[i];
1338
+ while (ch && ch !== "\n") ch = this.source[++i];
1339
+ if (this.source[i - 1] === "\r") --i;
1340
+ return this.toIndex(i, false);
1341
+ }
1342
+ newline() {
1343
+ const ch = this.source[this.pos];
1344
+ if (ch === "\n") return this.count(1);
1345
+ else if (ch === "\r" && this.charAt(1) === "\n") return this.count(2);
1346
+ else return 0;
1347
+ }
1348
+ spaces(allowTabs) {
1349
+ let i = this.pos - 1;
1350
+ let ch;
1351
+ do
1352
+ ch = this.source[++i];
1353
+ while (ch === " " || allowTabs && ch === " ");
1354
+ const n = i - this.pos;
1355
+ if (n > 0) {
1356
+ const s = this.source.substr(this.pos, n);
1357
+ this.tokens.push(s);
1358
+ this.pos = i;
1359
+ }
1360
+ return n;
1361
+ }
1362
+ until(test) {
1363
+ let i = this.pos;
1364
+ let ch = this.source[i];
1365
+ while (!test(ch)) ch = this.source[++i];
1366
+ return this.toIndex(i, false);
1367
+ }
1368
+ };
1369
+
1370
+ //#endregion
1371
+ //#region src/parse/parser.ts
1372
+ function includesToken(list, type) {
1373
+ for (let i = 0; i < list.length; ++i) if (list[i].type === type) return true;
1374
+ return false;
1375
+ }
1376
+ const logToken$1 = typeof process !== "undefined" && process.env?.LOG_TOKENS ? (token) => console.log("|", prettyToken(token)) : () => {};
1377
+ function findNonEmptyIndex(list) {
1378
+ for (let i = 0; i < list.length; ++i) switch (list[i].type) {
1379
+ case "space":
1380
+ case "comment":
1381
+ case "newline": break;
1382
+ default: return i;
1383
+ }
1384
+ return -1;
1385
+ }
1386
+ function isFlowToken(token) {
1387
+ switch (token?.type) {
1388
+ case "alias":
1389
+ case "scalar":
1390
+ case "single-quoted-scalar":
1391
+ case "double-quoted-scalar":
1392
+ case "flow-collection": return true;
1393
+ default: return false;
1394
+ }
1395
+ }
1396
+ function getPrevProps(parent) {
1397
+ switch (parent.type) {
1398
+ case "document": return parent.start;
1399
+ case "block-map": {
1400
+ const it = parent.items[parent.items.length - 1];
1401
+ return it.sep ?? it.start;
1402
+ }
1403
+ case "block-seq": return parent.items[parent.items.length - 1].start;
1404
+ default: return [];
1405
+ }
1406
+ }
1407
+ /** Note: May modify input array */
1408
+ function getFirstKeyStartProps(prev) {
1409
+ if (prev.length === 0) return [];
1410
+ let i = prev.length;
1411
+ loop: while (--i >= 0) switch (prev[i].type) {
1412
+ case "doc-start":
1413
+ case "explicit-key-ind":
1414
+ case "map-value-ind":
1415
+ case "seq-item-ind":
1416
+ case "newline": break loop;
1417
+ }
1418
+ while (prev[++i]?.type === "space");
1419
+ return prev.splice(i, prev.length);
1420
+ }
1421
+ function fixFlowSeqItems(fc) {
1422
+ if (fc.start.type === "flow-seq-start") {
1423
+ for (const it of fc.items) if (it.sep && !it.value && !includesToken(it.start, "explicit-key-ind") && !includesToken(it.sep, "map-value-ind")) {
1424
+ if (it.key) it.value = it.key;
1425
+ delete it.key;
1426
+ if (isFlowToken(it.value)) if (it.value.end) Array.prototype.push.apply(it.value.end, it.sep);
1427
+ else it.value.end = it.sep;
1428
+ else Array.prototype.push.apply(it.start, it.sep);
1429
+ delete it.sep;
1430
+ }
1431
+ }
1432
+ }
1433
+ /**
1434
+ * A YAML concrete syntax tree (CST) parser
1435
+ *
1436
+ * ```ts
1437
+ * const src: string = ...
1438
+ * for (const token of new Parser().parse(src)) {
1439
+ * // token: Token
1440
+ * }
1441
+ * ```
1442
+ *
1443
+ * To use the parser with a user-provided lexer:
1444
+ *
1445
+ * ```ts
1446
+ * function parse(source: string, lexTokens: string[]) {
1447
+ * const parser = new Parser()
1448
+ * for (const lexeme of lexTokens) parser.next(lexeme)
1449
+ * return parser.end()
1450
+ * }
1451
+ *
1452
+ * const src: string = ...
1453
+ * for (const token of parse(src, lex(src))) {
1454
+ * // token: Token
1455
+ * }
1456
+ * ```
1457
+ */
1458
+ var Parser = class {
1459
+ onNewLine;
1460
+ /** If true, space and sequence indicators count as indentation */
1461
+ atNewLine = true;
1462
+ /** If true, next token is a scalar value */
1463
+ atScalar = false;
1464
+ /** Current indentation level */
1465
+ indent = 0;
1466
+ /** Current offset since the start of parsing */
1467
+ offset = 0;
1468
+ /** On the same line with a block map key */
1469
+ onKeyLine = false;
1470
+ /** Top indicates the node that's currently being built */
1471
+ stack = [];
1472
+ /** The source of the current token, set in parse() */
1473
+ source = "";
1474
+ /** The type of the current token, set in parse() */
1475
+ type = "";
1476
+ tokens = [];
1477
+ /**
1478
+ * @param onNewLine - If defined, called separately with the start position of
1479
+ * each new line (in `parse()`, including the start of input).
1480
+ */
1481
+ constructor(onNewLine) {
1482
+ this.onNewLine = onNewLine;
1483
+ }
1484
+ /**
1485
+ * Parse `source` as a YAML stream.
1486
+ *
1487
+ * Errors are not thrown, but included in the result as `{ type: 'error', message }` tokens.
1488
+ *
1489
+ * @returns Tokens representing each directive, document, and other structure.
1490
+ */
1491
+ parse(source) {
1492
+ if (this.onNewLine && this.offset === 0) this.onNewLine(0);
1493
+ for (const lexeme of lex(source)) this.next(lexeme);
1494
+ return this.end();
1495
+ }
1496
+ /**
1497
+ * Advance the parser by the `source` of one lexical token.
1498
+ */
1499
+ next(source) {
1500
+ this.source = source;
1501
+ logToken$1(source);
1502
+ if (this.atScalar) {
1503
+ this.atScalar = false;
1504
+ this.step();
1505
+ this.offset += source.length;
1506
+ return;
1507
+ }
1508
+ const type = tokenType(source);
1509
+ if (!type) {
1510
+ const message = `Not a YAML token: ${source}`;
1511
+ this.pop({
1512
+ type: "error",
1513
+ offset: this.offset,
1514
+ message,
1515
+ source
1516
+ });
1517
+ this.offset += source.length;
1518
+ } else if (type === "scalar") {
1519
+ this.atNewLine = false;
1520
+ this.atScalar = true;
1521
+ this.type = "scalar";
1522
+ } else {
1523
+ this.type = type;
1524
+ this.step();
1525
+ switch (type) {
1526
+ case "newline":
1527
+ this.atNewLine = true;
1528
+ this.indent = 0;
1529
+ if (this.onNewLine) this.onNewLine(this.offset + source.length);
1530
+ break;
1531
+ case "space":
1532
+ if (this.atNewLine && source[0] === " ") this.indent += source.length;
1533
+ break;
1534
+ case "explicit-key-ind":
1535
+ case "map-value-ind":
1536
+ case "seq-item-ind":
1537
+ if (this.atNewLine) this.indent += source.length;
1538
+ break;
1539
+ case "doc-mode":
1540
+ case "flow-error-end": return;
1541
+ default: this.atNewLine = false;
1542
+ }
1543
+ this.offset += source.length;
1544
+ }
1545
+ }
1546
+ /** Call at end of input to account for any remaining constructions */
1547
+ end() {
1548
+ while (this.stack.length > 0) this.pop();
1549
+ return this.tokens;
1550
+ }
1551
+ get sourceToken() {
1552
+ return {
1553
+ type: this.type,
1554
+ offset: this.offset,
1555
+ indent: this.indent,
1556
+ source: this.source
1557
+ };
1558
+ }
1559
+ step() {
1560
+ const top = this.peek(1);
1561
+ if (this.type === "doc-end" && top?.type !== "doc-end") {
1562
+ while (this.stack.length > 0) this.pop();
1563
+ this.stack.push({
1564
+ type: "doc-end",
1565
+ offset: this.offset,
1566
+ source: this.source
1567
+ });
1568
+ return;
1569
+ }
1570
+ if (!top) {
1571
+ const token = this.stream();
1572
+ if (token) this.tokens.push(token);
1573
+ return;
1574
+ }
1575
+ switch (top.type) {
1576
+ case "document": return this.document(top);
1577
+ case "alias":
1578
+ case "scalar":
1579
+ case "single-quoted-scalar":
1580
+ case "double-quoted-scalar": return this.scalar(top);
1581
+ case "block-scalar": return this.blockScalar(top);
1582
+ case "block-map": return this.blockMap(top);
1583
+ case "block-seq": return this.blockSequence(top);
1584
+ case "flow-collection": return this.flowCollection(top);
1585
+ case "doc-end": return this.documentEnd(top);
1586
+ }
1587
+ /* istanbul ignore next should not happen */
1588
+ this.pop();
1589
+ }
1590
+ peek(n) {
1591
+ return this.stack[this.stack.length - n];
1592
+ }
1593
+ pop(error) {
1594
+ const token = error ?? this.stack.pop();
1595
+ /* istanbul ignore if should not happen */
1596
+ if (!token) this.tokens.push({
1597
+ type: "error",
1598
+ offset: this.offset,
1599
+ source: "",
1600
+ message: "Tried to pop an empty stack"
1601
+ });
1602
+ else if (this.stack.length === 0) this.tokens.push(token);
1603
+ else {
1604
+ const top = this.peek(1);
1605
+ if (token.type === "block-scalar") token.indent = "indent" in top ? top.indent : 0;
1606
+ else if (token.type === "flow-collection" && top.type === "document") token.indent = 0;
1607
+ if (token.type === "flow-collection") fixFlowSeqItems(token);
1608
+ switch (top.type) {
1609
+ case "document":
1610
+ top.value = token;
1611
+ break;
1612
+ case "block-scalar":
1613
+ top.props.push(token);
1614
+ break;
1615
+ case "block-map": {
1616
+ const it = top.items[top.items.length - 1];
1617
+ if (it.value) {
1618
+ top.items.push({
1619
+ start: [],
1620
+ key: token,
1621
+ sep: []
1622
+ });
1623
+ this.onKeyLine = true;
1624
+ return;
1625
+ } else if (it.sep) it.value = token;
1626
+ else {
1627
+ Object.assign(it, {
1628
+ key: token,
1629
+ sep: []
1630
+ });
1631
+ this.onKeyLine = !it.explicitKey;
1632
+ return;
1633
+ }
1634
+ break;
1635
+ }
1636
+ case "block-seq": {
1637
+ const it = top.items[top.items.length - 1];
1638
+ if (it.value) top.items.push({
1639
+ start: [],
1640
+ value: token
1641
+ });
1642
+ else it.value = token;
1643
+ break;
1644
+ }
1645
+ case "flow-collection": {
1646
+ const it = top.items[top.items.length - 1];
1647
+ if (!it || it.value) top.items.push({
1648
+ start: [],
1649
+ key: token,
1650
+ sep: []
1651
+ });
1652
+ else if (it.sep) it.value = token;
1653
+ else Object.assign(it, {
1654
+ key: token,
1655
+ sep: []
1656
+ });
1657
+ return;
1658
+ }
1659
+ default:
1660
+ this.pop();
1661
+ this.pop(token);
1662
+ }
1663
+ if ((top.type === "document" || top.type === "block-map" || top.type === "block-seq") && (token.type === "block-map" || token.type === "block-seq")) {
1664
+ const last = token.items[token.items.length - 1];
1665
+ if (last && !last.sep && !last.value && last.start.length > 0 && findNonEmptyIndex(last.start) === -1 && (token.indent === 0 || last.start.every((st) => st.type !== "comment" || st.indent < token.indent))) {
1666
+ if (top.type === "document") top.end = last.start;
1667
+ else top.items.push({ start: last.start });
1668
+ token.items.splice(-1, 1);
1669
+ }
1670
+ }
1671
+ }
1672
+ }
1673
+ stream() {
1674
+ switch (this.type) {
1675
+ case "directive-line": return {
1676
+ type: "directive",
1677
+ offset: this.offset,
1678
+ source: this.source
1679
+ };
1680
+ case "byte-order-mark":
1681
+ case "space":
1682
+ case "comment":
1683
+ case "newline": return this.sourceToken;
1684
+ case "doc-mode":
1685
+ case "doc-start": {
1686
+ const doc = {
1687
+ type: "document",
1688
+ offset: this.offset,
1689
+ start: []
1690
+ };
1691
+ if (this.type === "doc-start") doc.start.push(this.sourceToken);
1692
+ this.stack.push(doc);
1693
+ return null;
1694
+ }
1695
+ }
1696
+ return {
1697
+ type: "error",
1698
+ offset: this.offset,
1699
+ message: `Unexpected ${this.type} token in YAML stream`,
1700
+ source: this.source
1701
+ };
1702
+ }
1703
+ document(doc) {
1704
+ if (doc.value) return this.lineEnd(doc);
1705
+ switch (this.type) {
1706
+ case "doc-start":
1707
+ if (findNonEmptyIndex(doc.start) !== -1) {
1708
+ this.pop();
1709
+ this.step();
1710
+ } else doc.start.push(this.sourceToken);
1711
+ return;
1712
+ case "anchor":
1713
+ case "tag":
1714
+ case "space":
1715
+ case "comment":
1716
+ case "newline":
1717
+ doc.start.push(this.sourceToken);
1718
+ return;
1719
+ }
1720
+ const bv = this.startBlockValue(doc);
1721
+ if (bv) this.stack.push(bv);
1722
+ else this.tokens.push({
1723
+ type: "error",
1724
+ offset: this.offset,
1725
+ message: `Unexpected ${this.type} token in YAML document`,
1726
+ source: this.source
1727
+ });
1728
+ }
1729
+ scalar(scalar) {
1730
+ if (this.type === "map-value-ind") {
1731
+ const start = getFirstKeyStartProps(getPrevProps(this.peek(2)));
1732
+ let sep;
1733
+ if (scalar.end) {
1734
+ sep = scalar.end;
1735
+ sep.push(this.sourceToken);
1736
+ delete scalar.end;
1737
+ } else sep = [this.sourceToken];
1738
+ const map = {
1739
+ type: "block-map",
1740
+ offset: scalar.offset,
1741
+ indent: scalar.indent,
1742
+ items: [{
1743
+ start,
1744
+ key: scalar,
1745
+ sep
1746
+ }]
1747
+ };
1748
+ this.onKeyLine = true;
1749
+ this.stack[this.stack.length - 1] = map;
1750
+ } else this.lineEnd(scalar);
1751
+ }
1752
+ blockScalar(scalar) {
1753
+ switch (this.type) {
1754
+ case "space":
1755
+ case "comment":
1756
+ case "newline":
1757
+ scalar.props.push(this.sourceToken);
1758
+ return;
1759
+ case "scalar":
1760
+ scalar.source = this.source;
1761
+ this.atNewLine = true;
1762
+ this.indent = 0;
1763
+ if (this.onNewLine) {
1764
+ let nl = this.source.indexOf("\n") + 1;
1765
+ while (nl !== 0) {
1766
+ this.onNewLine(this.offset + nl);
1767
+ nl = this.source.indexOf("\n", nl) + 1;
1768
+ }
1769
+ }
1770
+ this.pop();
1771
+ break;
1772
+ default:
1773
+ this.pop();
1774
+ this.step();
1775
+ }
1776
+ }
1777
+ blockMap(map) {
1778
+ const it = map.items[map.items.length - 1];
1779
+ switch (this.type) {
1780
+ case "newline":
1781
+ this.onKeyLine = false;
1782
+ if (it.value) {
1783
+ const end = "end" in it.value ? it.value.end : void 0;
1784
+ if ((Array.isArray(end) ? end[end.length - 1] : void 0)?.type === "comment") end?.push(this.sourceToken);
1785
+ else map.items.push({ start: [this.sourceToken] });
1786
+ } else if (it.sep) it.sep.push(this.sourceToken);
1787
+ else it.start.push(this.sourceToken);
1788
+ return;
1789
+ case "space":
1790
+ case "comment":
1791
+ if (it.value) map.items.push({ start: [this.sourceToken] });
1792
+ else if (it.sep) it.sep.push(this.sourceToken);
1793
+ else {
1794
+ if (this.atIndentedComment(it.start, map.indent)) {
1795
+ const end = (map.items[map.items.length - 2]?.value)?.end;
1796
+ if (Array.isArray(end)) {
1797
+ Array.prototype.push.apply(end, it.start);
1798
+ end.push(this.sourceToken);
1799
+ map.items.pop();
1800
+ return;
1801
+ }
1802
+ }
1803
+ it.start.push(this.sourceToken);
1804
+ }
1805
+ return;
1806
+ }
1807
+ if (this.indent >= map.indent) {
1808
+ const atMapIndent = !this.onKeyLine && this.indent === map.indent;
1809
+ const atNextItem = atMapIndent && (it.sep || it.explicitKey) && this.type !== "seq-item-ind";
1810
+ let start = [];
1811
+ if (atNextItem && it.sep && !it.value) {
1812
+ const nl = [];
1813
+ for (let i = 0; i < it.sep.length; ++i) {
1814
+ const st = it.sep[i];
1815
+ switch (st.type) {
1816
+ case "newline":
1817
+ nl.push(i);
1818
+ break;
1819
+ case "space": break;
1820
+ case "comment":
1821
+ if (st.indent > map.indent) nl.length = 0;
1822
+ break;
1823
+ default: nl.length = 0;
1824
+ }
1825
+ }
1826
+ if (nl.length >= 2) start = it.sep.splice(nl[1]);
1827
+ }
1828
+ switch (this.type) {
1829
+ case "anchor":
1830
+ case "tag":
1831
+ if (atNextItem || it.value) {
1832
+ start.push(this.sourceToken);
1833
+ map.items.push({ start });
1834
+ this.onKeyLine = true;
1835
+ } else if (it.sep) it.sep.push(this.sourceToken);
1836
+ else it.start.push(this.sourceToken);
1837
+ return;
1838
+ case "explicit-key-ind":
1839
+ if (!it.sep && !it.explicitKey) {
1840
+ it.start.push(this.sourceToken);
1841
+ it.explicitKey = true;
1842
+ } else if (atNextItem || it.value) {
1843
+ start.push(this.sourceToken);
1844
+ map.items.push({
1845
+ start,
1846
+ explicitKey: true
1847
+ });
1848
+ } else this.stack.push({
1849
+ type: "block-map",
1850
+ offset: this.offset,
1851
+ indent: this.indent,
1852
+ items: [{
1853
+ start: [this.sourceToken],
1854
+ explicitKey: true
1855
+ }]
1856
+ });
1857
+ this.onKeyLine = true;
1858
+ return;
1859
+ case "map-value-ind":
1860
+ if (it.explicitKey) if (!it.sep) if (includesToken(it.start, "newline")) Object.assign(it, {
1861
+ key: null,
1862
+ sep: [this.sourceToken]
1863
+ });
1864
+ else {
1865
+ const start = getFirstKeyStartProps(it.start);
1866
+ this.stack.push({
1867
+ type: "block-map",
1868
+ offset: this.offset,
1869
+ indent: this.indent,
1870
+ items: [{
1871
+ start,
1872
+ key: null,
1873
+ sep: [this.sourceToken]
1874
+ }]
1875
+ });
1876
+ }
1877
+ else if (it.value) map.items.push({
1878
+ start: [],
1879
+ key: null,
1880
+ sep: [this.sourceToken]
1881
+ });
1882
+ else if (includesToken(it.sep, "map-value-ind")) this.stack.push({
1883
+ type: "block-map",
1884
+ offset: this.offset,
1885
+ indent: this.indent,
1886
+ items: [{
1887
+ start,
1888
+ key: null,
1889
+ sep: [this.sourceToken]
1890
+ }]
1891
+ });
1892
+ else if (isFlowToken(it.key) && !includesToken(it.sep, "newline")) {
1893
+ const start = getFirstKeyStartProps(it.start);
1894
+ const key = it.key;
1895
+ const sep = it.sep;
1896
+ sep.push(this.sourceToken);
1897
+ delete it.key;
1898
+ delete it.sep;
1899
+ this.stack.push({
1900
+ type: "block-map",
1901
+ offset: this.offset,
1902
+ indent: this.indent,
1903
+ items: [{
1904
+ start,
1905
+ key,
1906
+ sep
1907
+ }]
1908
+ });
1909
+ } else if (start.length > 0) it.sep = it.sep.concat(start, this.sourceToken);
1910
+ else it.sep.push(this.sourceToken);
1911
+ else if (!it.sep) Object.assign(it, {
1912
+ key: null,
1913
+ sep: [this.sourceToken]
1914
+ });
1915
+ else if (it.value || atNextItem) map.items.push({
1916
+ start,
1917
+ key: null,
1918
+ sep: [this.sourceToken]
1919
+ });
1920
+ else if (includesToken(it.sep, "map-value-ind")) this.stack.push({
1921
+ type: "block-map",
1922
+ offset: this.offset,
1923
+ indent: this.indent,
1924
+ items: [{
1925
+ start: [],
1926
+ key: null,
1927
+ sep: [this.sourceToken]
1928
+ }]
1929
+ });
1930
+ else it.sep.push(this.sourceToken);
1931
+ this.onKeyLine = true;
1932
+ return;
1933
+ case "alias":
1934
+ case "scalar":
1935
+ case "single-quoted-scalar":
1936
+ case "double-quoted-scalar": {
1937
+ const fs = this.flowScalar(this.type);
1938
+ if (atNextItem || it.value) {
1939
+ map.items.push({
1940
+ start,
1941
+ key: fs,
1942
+ sep: []
1943
+ });
1944
+ this.onKeyLine = true;
1945
+ } else if (it.sep) this.stack.push(fs);
1946
+ else {
1947
+ Object.assign(it, {
1948
+ key: fs,
1949
+ sep: []
1950
+ });
1951
+ this.onKeyLine = true;
1952
+ }
1953
+ return;
1954
+ }
1955
+ default: {
1956
+ const bv = this.startBlockValue(map);
1957
+ if (bv) {
1958
+ if (bv.type === "block-seq") {
1959
+ if (!it.explicitKey && it.sep && !includesToken(it.sep, "newline")) {
1960
+ this.pop({
1961
+ type: "error",
1962
+ offset: this.offset,
1963
+ message: "Unexpected block-seq-ind on same line with key",
1964
+ source: this.source
1965
+ });
1966
+ return;
1967
+ }
1968
+ } else if (atMapIndent) map.items.push({ start });
1969
+ this.stack.push(bv);
1970
+ return;
1971
+ }
1972
+ }
1973
+ }
1974
+ }
1975
+ this.pop();
1976
+ this.step();
1977
+ }
1978
+ blockSequence(seq) {
1979
+ const it = seq.items[seq.items.length - 1];
1980
+ switch (this.type) {
1981
+ case "newline":
1982
+ if (it.value) {
1983
+ const end = "end" in it.value ? it.value.end : void 0;
1984
+ if ((Array.isArray(end) ? end[end.length - 1] : void 0)?.type === "comment") end?.push(this.sourceToken);
1985
+ else seq.items.push({ start: [this.sourceToken] });
1986
+ } else it.start.push(this.sourceToken);
1987
+ return;
1988
+ case "space":
1989
+ case "comment":
1990
+ if (it.value) seq.items.push({ start: [this.sourceToken] });
1991
+ else {
1992
+ if (this.atIndentedComment(it.start, seq.indent)) {
1993
+ const end = (seq.items[seq.items.length - 2]?.value)?.end;
1994
+ if (Array.isArray(end)) {
1995
+ Array.prototype.push.apply(end, it.start);
1996
+ end.push(this.sourceToken);
1997
+ seq.items.pop();
1998
+ return;
1999
+ }
2000
+ }
2001
+ it.start.push(this.sourceToken);
2002
+ }
2003
+ return;
2004
+ case "anchor":
2005
+ case "tag":
2006
+ if (it.value || this.indent <= seq.indent) break;
2007
+ it.start.push(this.sourceToken);
2008
+ return;
2009
+ case "seq-item-ind":
2010
+ if (this.indent !== seq.indent) break;
2011
+ if (it.value || includesToken(it.start, "seq-item-ind")) seq.items.push({ start: [this.sourceToken] });
2012
+ else it.start.push(this.sourceToken);
2013
+ return;
2014
+ }
2015
+ if (this.indent > seq.indent) {
2016
+ const bv = this.startBlockValue(seq);
2017
+ if (bv) {
2018
+ this.stack.push(bv);
2019
+ return;
2020
+ }
2021
+ }
2022
+ this.pop();
2023
+ this.step();
2024
+ }
2025
+ flowCollection(fc) {
2026
+ const it = fc.items[fc.items.length - 1];
2027
+ if (this.type === "flow-error-end") {
2028
+ let top;
2029
+ do {
2030
+ this.pop();
2031
+ top = this.peek(1);
2032
+ } while (top?.type === "flow-collection");
2033
+ } else if (fc.end.length === 0) {
2034
+ switch (this.type) {
2035
+ case "comma":
2036
+ case "explicit-key-ind":
2037
+ if (!it || it.sep) fc.items.push({ start: [this.sourceToken] });
2038
+ else it.start.push(this.sourceToken);
2039
+ return;
2040
+ case "map-value-ind":
2041
+ if (!it || it.value) fc.items.push({
2042
+ start: [],
2043
+ key: null,
2044
+ sep: [this.sourceToken]
2045
+ });
2046
+ else if (it.sep) it.sep.push(this.sourceToken);
2047
+ else Object.assign(it, {
2048
+ key: null,
2049
+ sep: [this.sourceToken]
2050
+ });
2051
+ return;
2052
+ case "space":
2053
+ case "comment":
2054
+ case "newline":
2055
+ case "anchor":
2056
+ case "tag":
2057
+ if (!it || it.value) fc.items.push({ start: [this.sourceToken] });
2058
+ else if (it.sep) it.sep.push(this.sourceToken);
2059
+ else it.start.push(this.sourceToken);
2060
+ return;
2061
+ case "alias":
2062
+ case "scalar":
2063
+ case "single-quoted-scalar":
2064
+ case "double-quoted-scalar": {
2065
+ const fs = this.flowScalar(this.type);
2066
+ if (!it || it.value) fc.items.push({
2067
+ start: [],
2068
+ key: fs,
2069
+ sep: []
2070
+ });
2071
+ else if (it.sep) this.stack.push(fs);
2072
+ else Object.assign(it, {
2073
+ key: fs,
2074
+ sep: []
2075
+ });
2076
+ return;
2077
+ }
2078
+ case "flow-map-end":
2079
+ case "flow-seq-end":
2080
+ fc.end.push(this.sourceToken);
2081
+ return;
2082
+ }
2083
+ const bv = this.startBlockValue(fc);
2084
+ /* istanbul ignore else should not happen */
2085
+ if (bv) this.stack.push(bv);
2086
+ else {
2087
+ this.pop();
2088
+ this.step();
2089
+ }
2090
+ } else {
2091
+ const parent = this.peek(2);
2092
+ if (parent.type === "block-map" && (this.type === "map-value-ind" && parent.indent === fc.indent || this.type === "newline" && !parent.items[parent.items.length - 1].sep)) {
2093
+ this.pop();
2094
+ this.step();
2095
+ } else if (this.type === "map-value-ind" && parent.type !== "flow-collection") {
2096
+ const start = getFirstKeyStartProps(getPrevProps(parent));
2097
+ fixFlowSeqItems(fc);
2098
+ const sep = fc.end.splice(1, fc.end.length);
2099
+ sep.push(this.sourceToken);
2100
+ const map = {
2101
+ type: "block-map",
2102
+ offset: fc.offset,
2103
+ indent: fc.indent,
2104
+ items: [{
2105
+ start,
2106
+ key: fc,
2107
+ sep
2108
+ }]
2109
+ };
2110
+ this.onKeyLine = true;
2111
+ this.stack[this.stack.length - 1] = map;
2112
+ } else this.lineEnd(fc);
2113
+ }
2114
+ }
2115
+ flowScalar(type) {
2116
+ if (this.onNewLine) {
2117
+ let nl = this.source.indexOf("\n") + 1;
2118
+ while (nl !== 0) {
2119
+ this.onNewLine(this.offset + nl);
2120
+ nl = this.source.indexOf("\n", nl) + 1;
2121
+ }
2122
+ }
2123
+ return {
2124
+ type,
2125
+ offset: this.offset,
2126
+ indent: this.indent,
2127
+ source: this.source
2128
+ };
2129
+ }
2130
+ startBlockValue(parent) {
2131
+ switch (this.type) {
2132
+ case "alias":
2133
+ case "scalar":
2134
+ case "single-quoted-scalar":
2135
+ case "double-quoted-scalar": return this.flowScalar(this.type);
2136
+ case "block-scalar-header": return {
2137
+ type: "block-scalar",
2138
+ offset: this.offset,
2139
+ indent: this.indent,
2140
+ props: [this.sourceToken],
2141
+ source: ""
2142
+ };
2143
+ case "flow-map-start":
2144
+ case "flow-seq-start": return {
2145
+ type: "flow-collection",
2146
+ offset: this.offset,
2147
+ indent: this.indent,
2148
+ start: this.sourceToken,
2149
+ items: [],
2150
+ end: []
2151
+ };
2152
+ case "seq-item-ind": return {
2153
+ type: "block-seq",
2154
+ offset: this.offset,
2155
+ indent: this.indent,
2156
+ items: [{ start: [this.sourceToken] }]
2157
+ };
2158
+ case "explicit-key-ind": {
2159
+ this.onKeyLine = true;
2160
+ const start = getFirstKeyStartProps(getPrevProps(parent));
2161
+ start.push(this.sourceToken);
2162
+ return {
2163
+ type: "block-map",
2164
+ offset: this.offset,
2165
+ indent: this.indent,
2166
+ items: [{
2167
+ start,
2168
+ explicitKey: true
2169
+ }]
2170
+ };
2171
+ }
2172
+ case "map-value-ind": {
2173
+ this.onKeyLine = true;
2174
+ const start = getFirstKeyStartProps(getPrevProps(parent));
2175
+ return {
2176
+ type: "block-map",
2177
+ offset: this.offset,
2178
+ indent: this.indent,
2179
+ items: [{
2180
+ start,
2181
+ key: null,
2182
+ sep: [this.sourceToken]
2183
+ }]
2184
+ };
2185
+ }
2186
+ }
2187
+ return null;
2188
+ }
2189
+ atIndentedComment(start, indent) {
2190
+ if (this.type !== "comment") return false;
2191
+ if (this.indent <= indent) return false;
2192
+ return start.every((st) => st.type === "newline" || st.type === "space");
2193
+ }
2194
+ documentEnd(docEnd) {
2195
+ if (this.type !== "doc-mode") {
2196
+ if (docEnd.end) docEnd.end.push(this.sourceToken);
2197
+ else docEnd.end = [this.sourceToken];
2198
+ if (this.type === "newline") this.pop();
2199
+ }
2200
+ }
2201
+ lineEnd(token) {
2202
+ switch (this.type) {
2203
+ case "comma":
2204
+ case "doc-start":
2205
+ case "doc-end":
2206
+ case "flow-seq-end":
2207
+ case "flow-map-end":
2208
+ case "map-value-ind":
2209
+ this.pop();
2210
+ this.step();
2211
+ break;
2212
+ case "newline": this.onKeyLine = false;
2213
+ default:
2214
+ if (token.end) token.end.push(this.sourceToken);
2215
+ else token.end = [this.sourceToken];
2216
+ if (this.type === "newline") this.pop();
2217
+ }
2218
+ }
2219
+ };
2220
+
2221
+ //#endregion
2222
+ //#region src/compose/resolve-props.ts
2223
+ function resolveProps(tokens, { flow, indicator, next, offset, onError, parentIndent, startOnNewline }) {
2224
+ let spaceBefore = false;
2225
+ let atNewline = startOnNewline;
2226
+ let hasSpace = startOnNewline;
2227
+ let comment = "";
2228
+ let commentSep = "";
2229
+ let hasNewline = false;
2230
+ let reqSpace = false;
2231
+ let tab = null;
2232
+ let anchor = null;
2233
+ let tag = null;
2234
+ let newlineAfterProp = null;
2235
+ let comma = null;
2236
+ let found = null;
2237
+ let start = null;
2238
+ for (const token of tokens) {
2239
+ if (reqSpace) {
2240
+ if (token.type !== "space" && token.type !== "newline" && token.type !== "comma") onError(token.offset, "MISSING_CHAR", "Tags and anchors must be separated from the next token by white space");
2241
+ reqSpace = false;
2242
+ }
2243
+ if (tab) {
2244
+ if (atNewline && token.type !== "comment" && token.type !== "newline") onError(tab, "TAB_AS_INDENT", "Tabs are not allowed as indentation");
2245
+ tab = null;
2246
+ }
2247
+ switch (token.type) {
2248
+ case "space":
2249
+ if (!flow && (indicator !== "doc-start" || next?.type !== "flow-collection") && token.source.includes(" ")) tab = token;
2250
+ hasSpace = true;
2251
+ break;
2252
+ case "comment": {
2253
+ if (!hasSpace) onError(token, "MISSING_CHAR", "Comments must be separated from other tokens by white space characters");
2254
+ const cb = token.source.substring(1) || " ";
2255
+ if (!comment) comment = cb;
2256
+ else comment += commentSep + cb;
2257
+ commentSep = "";
2258
+ atNewline = false;
2259
+ break;
2260
+ }
2261
+ case "newline":
2262
+ if (atNewline) {
2263
+ if (comment) comment += token.source;
2264
+ else if (!found || indicator !== "seq-item-ind") spaceBefore = true;
2265
+ } else commentSep += token.source;
2266
+ atNewline = true;
2267
+ hasNewline = true;
2268
+ if (anchor || tag) newlineAfterProp = token;
2269
+ hasSpace = true;
2270
+ break;
2271
+ case "anchor":
2272
+ if (anchor) onError(token, "MULTIPLE_ANCHORS", "A node can have at most one anchor");
2273
+ if (token.source.endsWith(":")) onError(token.offset + token.source.length - 1, "BAD_ALIAS", "Anchor ending in : is ambiguous", true);
2274
+ anchor = token;
2275
+ start ??= token.offset;
2276
+ atNewline = false;
2277
+ hasSpace = false;
2278
+ reqSpace = true;
2279
+ break;
2280
+ case "tag":
2281
+ if (tag) onError(token, "MULTIPLE_TAGS", "A node can have at most one tag");
2282
+ tag = token;
2283
+ start ??= token.offset;
2284
+ atNewline = false;
2285
+ hasSpace = false;
2286
+ reqSpace = true;
2287
+ break;
2288
+ case indicator:
2289
+ if (anchor || tag) onError(token, "BAD_PROP_ORDER", `Anchors and tags must be after the ${token.source} indicator`);
2290
+ if (found) onError(token, "UNEXPECTED_TOKEN", `Unexpected ${token.source} in ${flow ?? "collection"}`);
2291
+ found = token;
2292
+ atNewline = indicator === "seq-item-ind" || indicator === "explicit-key-ind";
2293
+ hasSpace = false;
2294
+ break;
2295
+ case "comma": if (flow) {
2296
+ if (comma) onError(token, "UNEXPECTED_TOKEN", `Unexpected , in ${flow}`);
2297
+ comma = token;
2298
+ atNewline = false;
2299
+ hasSpace = false;
2300
+ break;
2301
+ }
2302
+ default:
2303
+ onError(token, "UNEXPECTED_TOKEN", `Unexpected ${token.type} token`);
2304
+ atNewline = false;
2305
+ hasSpace = false;
2306
+ }
2307
+ }
2308
+ const last = tokens[tokens.length - 1];
2309
+ const end = last ? last.offset + last.source.length : offset;
2310
+ if (reqSpace && next && next.type !== "space" && next.type !== "newline" && next.type !== "comma" && (next.type !== "scalar" || next.source !== "")) onError(next.offset, "MISSING_CHAR", "Tags and anchors must be separated from the next token by white space");
2311
+ if (tab && (atNewline && tab.indent <= parentIndent || next?.type === "block-map" || next?.type === "block-seq")) onError(tab, "TAB_AS_INDENT", "Tabs are not allowed as indentation");
2312
+ return {
2313
+ comma,
2314
+ found,
2315
+ spaceBefore,
2316
+ comment,
2317
+ hasNewline,
2318
+ anchor,
2319
+ tag,
2320
+ newlineAfterProp,
2321
+ end,
2322
+ start: start ?? end
2323
+ };
2324
+ }
2325
+
2326
+ //#endregion
2327
+ //#region src/compose/util-contains-newline.ts
2328
+ function containsNewline(key) {
2329
+ if (!key) return null;
2330
+ switch (key.type) {
2331
+ case "alias":
2332
+ case "scalar":
2333
+ case "double-quoted-scalar":
2334
+ case "single-quoted-scalar":
2335
+ if (key.source.includes("\n")) return true;
2336
+ if (key.end) {
2337
+ for (const st of key.end) if (st.type === "newline") return true;
2338
+ }
2339
+ return false;
2340
+ case "flow-collection":
2341
+ for (const it of key.items) {
2342
+ for (const st of it.start) if (st.type === "newline") return true;
2343
+ if (it.sep) {
2344
+ for (const st of it.sep) if (st.type === "newline") return true;
2345
+ }
2346
+ if (containsNewline(it.key) || containsNewline(it.value)) return true;
2347
+ }
2348
+ return false;
2349
+ default: return true;
2350
+ }
2351
+ }
2352
+
2353
+ //#endregion
2354
+ //#region src/compose/util-flow-indent-check.ts
2355
+ function flowIndentCheck(indent, fc, onError) {
2356
+ if (fc?.type === "flow-collection") {
2357
+ const end = fc.end[0];
2358
+ if (end.indent === indent && (end.source === "]" || end.source === "}") && containsNewline(fc)) onError(end, "BAD_INDENT", "Flow end indicator should be more indented than parent", true);
2359
+ }
2360
+ }
2361
+
2362
+ //#endregion
2363
+ //#region src/compose/util-map-includes.ts
2364
+ function mapIncludes(ctx, items, search) {
2365
+ const { uniqueKeys } = ctx.options;
2366
+ if (uniqueKeys === false) return false;
2367
+ const isEqual = typeof uniqueKeys === "function" ? uniqueKeys : (a, b) => a === b || a instanceof Scalar && b instanceof Scalar && a.value === b.value;
2368
+ return items.some((pair) => isEqual(pair.key, search));
2369
+ }
2370
+
2371
+ //#endregion
2372
+ //#region src/compose/resolve-block-map.ts
2373
+ const startColMsg = "All mapping items must start at the same column";
2374
+ function resolveBlockMap({ composeNode, composeEmptyNode }, ctx, bm, onError, tag) {
2375
+ const map = new (tag?.nodeClass ?? YAMLMap)(ctx.schema);
2376
+ if (ctx.atRoot) ctx.atRoot = false;
2377
+ let offset = bm.offset;
2378
+ let commentEnd = null;
2379
+ for (const collItem of bm.items) {
2380
+ const { start, key, sep, value } = collItem;
2381
+ const keyProps = resolveProps(start, {
2382
+ indicator: "explicit-key-ind",
2383
+ next: key ?? sep?.[0],
2384
+ offset,
2385
+ onError,
2386
+ parentIndent: bm.indent,
2387
+ startOnNewline: true
2388
+ });
2389
+ const implicitKey = !keyProps.found;
2390
+ if (implicitKey) {
2391
+ if (key) {
2392
+ if (key.type === "block-seq") onError(offset, "BLOCK_AS_IMPLICIT_KEY", "A block sequence may not be used as an implicit map key");
2393
+ else if ("indent" in key && key.indent !== bm.indent) onError(offset, "BAD_INDENT", startColMsg);
2394
+ }
2395
+ if (!keyProps.anchor && !keyProps.tag && !sep) {
2396
+ commentEnd = keyProps.end;
2397
+ if (keyProps.comment) if (map.comment) map.comment += "\n" + keyProps.comment;
2398
+ else map.comment = keyProps.comment;
2399
+ continue;
2400
+ }
2401
+ if (keyProps.newlineAfterProp || containsNewline(key)) onError(key ?? start[start.length - 1], "MULTILINE_IMPLICIT_KEY", "Implicit keys need to be on a single line");
2402
+ } else if (keyProps.found?.indent !== bm.indent) onError(offset, "BAD_INDENT", startColMsg);
2403
+ ctx.atKey = true;
2404
+ const keyStart = keyProps.end;
2405
+ const keyNode = key ? composeNode(ctx, key, keyProps, onError) : composeEmptyNode(ctx, keyStart, start, null, keyProps, onError);
2406
+ if (ctx.schema.compat) flowIndentCheck(bm.indent, key, onError);
2407
+ ctx.atKey = false;
2408
+ if (mapIncludes(ctx, map.items, keyNode)) onError(keyStart, "DUPLICATE_KEY", "Map keys must be unique");
2409
+ const valueProps = resolveProps(sep ?? [], {
2410
+ indicator: "map-value-ind",
2411
+ next: value,
2412
+ offset: keyNode.range[2],
2413
+ onError,
2414
+ parentIndent: bm.indent,
2415
+ startOnNewline: !key || key.type === "block-scalar"
2416
+ });
2417
+ offset = valueProps.end;
2418
+ if (valueProps.found) {
2419
+ if (implicitKey) {
2420
+ if (value?.type === "block-map" && !valueProps.hasNewline) onError(offset, "BLOCK_AS_IMPLICIT_KEY", "Nested mappings are not allowed in compact mappings");
2421
+ if (ctx.options.strict && keyProps.start < valueProps.found.offset - 1024) onError(keyNode.range, "KEY_OVER_1024_CHARS", "The : indicator must be at most 1024 chars after the start of an implicit block mapping key");
2422
+ }
2423
+ const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset, sep, null, valueProps, onError);
2424
+ if (ctx.schema.compat) flowIndentCheck(bm.indent, value, onError);
2425
+ offset = valueNode.range[2];
2426
+ const pair = new Pair(keyNode, valueNode);
2427
+ if (ctx.options.keepSourceTokens) pair.srcToken = collItem;
2428
+ map.items.push(pair);
2429
+ } else {
2430
+ if (implicitKey) onError(keyNode.range, "MISSING_CHAR", "Implicit map keys need to be followed by map values");
2431
+ if (valueProps.comment) if (keyNode.comment) keyNode.comment += "\n" + valueProps.comment;
2432
+ else keyNode.comment = valueProps.comment;
2433
+ const pair = new Pair(keyNode);
2434
+ if (ctx.options.keepSourceTokens) pair.srcToken = collItem;
2435
+ map.items.push(pair);
2436
+ }
2437
+ }
2438
+ if (commentEnd && commentEnd < offset) onError(commentEnd, "IMPOSSIBLE", "Map comment with trailing content");
2439
+ map.range = [
2440
+ bm.offset,
2441
+ offset,
2442
+ commentEnd ?? offset
2443
+ ];
2444
+ return map;
2445
+ }
2446
+
2447
+ //#endregion
2448
+ //#region src/compose/resolve-block-seq.ts
2449
+ function resolveBlockSeq({ composeNode, composeEmptyNode }, ctx, bs, onError, tag) {
2450
+ const seq = new (tag?.nodeClass ?? YAMLSeq)(ctx.schema);
2451
+ if (ctx.atRoot) ctx.atRoot = false;
2452
+ if (ctx.atKey) ctx.atKey = false;
2453
+ let offset = bs.offset;
2454
+ let commentEnd = null;
2455
+ for (const { start, value } of bs.items) {
2456
+ const props = resolveProps(start, {
2457
+ indicator: "seq-item-ind",
2458
+ next: value,
2459
+ offset,
2460
+ onError,
2461
+ parentIndent: bs.indent,
2462
+ startOnNewline: true
2463
+ });
2464
+ if (!props.found) if (props.anchor || props.tag || value) if (value?.type === "block-seq") onError(props.end, "BAD_INDENT", "All sequence items must start at the same column");
2465
+ else onError(offset, "MISSING_CHAR", "Sequence item without - indicator");
2466
+ else {
2467
+ commentEnd = props.end;
2468
+ if (props.comment) seq.comment = props.comment;
2469
+ continue;
2470
+ }
2471
+ const node = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, start, null, props, onError);
2472
+ if (ctx.schema.compat) flowIndentCheck(bs.indent, value, onError);
2473
+ offset = node.range[2];
2474
+ seq.items.push(node);
2475
+ }
2476
+ seq.range = [
2477
+ bs.offset,
2478
+ offset,
2479
+ commentEnd ?? offset
2480
+ ];
2481
+ return seq;
2482
+ }
2483
+
2484
+ //#endregion
2485
+ //#region src/compose/resolve-flow-collection.ts
2486
+ const blockMsg = "Block collections are not allowed within flow collections";
2487
+ const isBlock = (token) => token && (token.type === "block-map" || token.type === "block-seq");
2488
+ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onError, tag) {
2489
+ const isMap = fc.start.source === "{";
2490
+ const fcName = isMap ? "flow map" : "flow sequence";
2491
+ const coll = new (tag?.nodeClass ?? (isMap ? YAMLMap : YAMLSeq))(ctx.schema);
2492
+ coll.flow = true;
2493
+ const atRoot = ctx.atRoot;
2494
+ if (atRoot) ctx.atRoot = false;
2495
+ if (ctx.atKey) ctx.atKey = false;
2496
+ let offset = fc.offset + fc.start.source.length;
2497
+ for (let i = 0; i < fc.items.length; ++i) {
2498
+ const collItem = fc.items[i];
2499
+ const { start, key, sep, value } = collItem;
2500
+ const props = resolveProps(start, {
2501
+ flow: fcName,
2502
+ indicator: "explicit-key-ind",
2503
+ next: key ?? sep?.[0],
2504
+ offset,
2505
+ onError,
2506
+ parentIndent: fc.indent,
2507
+ startOnNewline: false
2508
+ });
2509
+ if (!props.found) {
2510
+ if (!props.anchor && !props.tag && !sep && !value) {
2511
+ if (i === 0 && props.comma) onError(props.comma, "UNEXPECTED_TOKEN", `Unexpected , in ${fcName}`);
2512
+ else if (i < fc.items.length - 1) onError(props.start, "UNEXPECTED_TOKEN", `Unexpected empty item in ${fcName}`);
2513
+ if (props.comment) if (coll.comment) coll.comment += "\n" + props.comment;
2514
+ else coll.comment = props.comment;
2515
+ offset = props.end;
2516
+ continue;
2517
+ }
2518
+ if (!isMap && ctx.options.strict && containsNewline(key)) onError(key, "MULTILINE_IMPLICIT_KEY", "Implicit keys of flow sequence pairs need to be on a single line");
2519
+ }
2520
+ if (i === 0) {
2521
+ if (props.comma) onError(props.comma, "UNEXPECTED_TOKEN", `Unexpected , in ${fcName}`);
2522
+ } else {
2523
+ if (!props.comma) onError(props.start, "MISSING_CHAR", `Missing , between ${fcName} items`);
2524
+ if (props.comment) {
2525
+ let prevItemComment = "";
2526
+ loop: for (const st of start) switch (st.type) {
2527
+ case "comma":
2528
+ case "space": break;
2529
+ case "comment":
2530
+ prevItemComment = st.source.substring(1);
2531
+ break loop;
2532
+ default: break loop;
2533
+ }
2534
+ if (prevItemComment) {
2535
+ let prev = coll.items[coll.items.length - 1];
2536
+ if (prev instanceof Pair) prev = prev.value ?? prev.key;
2537
+ if (prev.comment) prev.comment += "\n" + prevItemComment;
2538
+ else prev.comment = prevItemComment;
2539
+ props.comment = props.comment.substring(prevItemComment.length + 1);
2540
+ }
2541
+ }
2542
+ }
2543
+ if (!isMap && !sep && !props.found) {
2544
+ const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, sep, null, props, onError);
2545
+ coll.items.push(valueNode);
2546
+ offset = valueNode.range[2];
2547
+ if (isBlock(value)) onError(valueNode.range, "BLOCK_IN_FLOW", blockMsg);
2548
+ } else {
2549
+ ctx.atKey = true;
2550
+ const keyStart = props.end;
2551
+ const keyNode = key ? composeNode(ctx, key, props, onError) : composeEmptyNode(ctx, keyStart, start, null, props, onError);
2552
+ if (isBlock(key)) onError(keyNode.range, "BLOCK_IN_FLOW", blockMsg);
2553
+ ctx.atKey = false;
2554
+ const valueProps = resolveProps(sep ?? [], {
2555
+ flow: fcName,
2556
+ indicator: "map-value-ind",
2557
+ next: value,
2558
+ offset: keyNode.range[2],
2559
+ onError,
2560
+ parentIndent: fc.indent,
2561
+ startOnNewline: false
2562
+ });
2563
+ if (valueProps.found) {
2564
+ if (!isMap && !props.found && ctx.options.strict) {
2565
+ if (sep) for (const st of sep) {
2566
+ if (st === valueProps.found) break;
2567
+ if (st.type === "newline") {
2568
+ onError(st, "MULTILINE_IMPLICIT_KEY", "Implicit keys of flow sequence pairs need to be on a single line");
2569
+ break;
2570
+ }
2571
+ }
2572
+ if (props.start < valueProps.found.offset - 1024) onError(valueProps.found, "KEY_OVER_1024_CHARS", "The : indicator must be at most 1024 chars after the start of an implicit flow sequence key");
2573
+ }
2574
+ } else if (value) if ("source" in value && value.source?.[0] === ":") onError(value, "MISSING_CHAR", `Missing space after : in ${fcName}`);
2575
+ else onError(valueProps.start, "MISSING_CHAR", `Missing , or : between ${fcName} items`);
2576
+ const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end, sep, null, valueProps, onError) : null;
2577
+ if (valueNode) {
2578
+ if (isBlock(value)) onError(valueNode.range, "BLOCK_IN_FLOW", blockMsg);
2579
+ } else if (valueProps.comment) if (keyNode.comment) keyNode.comment += "\n" + valueProps.comment;
2580
+ else keyNode.comment = valueProps.comment;
2581
+ const pair = new Pair(keyNode, valueNode);
2582
+ if (ctx.options.keepSourceTokens) pair.srcToken = collItem;
2583
+ if (isMap) {
2584
+ const map = coll;
2585
+ if (mapIncludes(ctx, map.items, keyNode)) onError(keyStart, "DUPLICATE_KEY", "Map keys must be unique");
2586
+ map.items.push(pair);
2587
+ } else {
2588
+ const map = new YAMLMap(ctx.schema);
2589
+ map.flow = true;
2590
+ map.items.push(pair);
2591
+ const endRange = (valueNode ?? keyNode).range;
2592
+ map.range = [
2593
+ keyNode.range[0],
2594
+ endRange[1],
2595
+ endRange[2]
2596
+ ];
2597
+ coll.items.push(map);
2598
+ }
2599
+ offset = valueNode ? valueNode.range[2] : valueProps.end;
2600
+ }
2601
+ }
2602
+ const expectedEnd = isMap ? "}" : "]";
2603
+ const [ce, ...ee] = fc.end;
2604
+ let cePos = offset;
2605
+ if (ce?.source === expectedEnd) cePos = ce.offset + ce.source.length;
2606
+ else {
2607
+ const name = fcName[0].toUpperCase() + fcName.substring(1);
2608
+ const msg = atRoot ? `${name} must end with a ${expectedEnd}` : `${name} in block collection must be sufficiently indented and end with a ${expectedEnd}`;
2609
+ onError(offset, atRoot ? "MISSING_CHAR" : "BAD_INDENT", msg);
2610
+ if (ce && ce.source.length !== 1) ee.unshift(ce);
2611
+ }
2612
+ if (ee.length > 0) {
2613
+ const end = resolveEnd(ee, cePos, ctx.options.strict, onError);
2614
+ if (end.comment) if (coll.comment) coll.comment += "\n" + end.comment;
2615
+ else coll.comment = end.comment;
2616
+ coll.range = [
2617
+ fc.offset,
2618
+ cePos,
2619
+ end.offset
2620
+ ];
2621
+ } else coll.range = [
2622
+ fc.offset,
2623
+ cePos,
2624
+ cePos
2625
+ ];
2626
+ return coll;
2627
+ }
2628
+
2629
+ //#endregion
2630
+ //#region src/compose/compose-collection.ts
2631
+ function resolveCollection(CN, ctx, token, onError, tagName, tag) {
2632
+ const coll = token.type === "block-map" ? resolveBlockMap(CN, ctx, token, onError, tag) : token.type === "block-seq" ? resolveBlockSeq(CN, ctx, token, onError, tag) : resolveFlowCollection(CN, ctx, token, onError, tag);
2633
+ const Coll = coll.constructor;
2634
+ if (tagName === "!" || tagName === Coll.tagName) {
2635
+ coll.tag = Coll.tagName;
2636
+ return coll;
2637
+ }
2638
+ if (tagName) coll.tag = tagName;
2639
+ return coll;
2640
+ }
2641
+ function composeCollection(CN, ctx, token, props, onError) {
2642
+ const tagToken = props.tag;
2643
+ const tagName = !tagToken ? null : ctx.directives.tagName(tagToken.source, (msg) => onError(tagToken, "TAG_RESOLVE_FAILED", msg));
2644
+ if (token.type === "block-seq") {
2645
+ const { anchor, newlineAfterProp: nl } = props;
2646
+ const lastProp = anchor && tagToken ? anchor.offset > tagToken.offset ? anchor : tagToken : anchor ?? tagToken;
2647
+ if (lastProp && (!nl || nl.offset < lastProp.offset)) onError(lastProp, "MISSING_CHAR", "Missing newline after block sequence props");
2648
+ }
2649
+ const expType = token.type === "block-map" ? "map" : token.type === "block-seq" ? "seq" : token.start.source === "{" ? "map" : "seq";
2650
+ if (!tagToken || !tagName || tagName === "!" || tagName === YAMLMap.tagName && expType === "map" || tagName === YAMLSeq.tagName && expType === "seq") return resolveCollection(CN, ctx, token, onError, tagName);
2651
+ let tag = ctx.schema.tags.find((t) => t.tag === tagName && t.collection === expType);
2652
+ if (!tag) {
2653
+ const kt = ctx.schema.knownTags[tagName];
2654
+ if (kt?.collection === expType) {
2655
+ ctx.schema.tags.push(Object.assign({}, kt, { default: false }));
2656
+ tag = kt;
2657
+ } else {
2658
+ if (kt) onError(tagToken, "BAD_COLLECTION_TYPE", `${kt.tag} used for ${expType} collection, but expects ${kt.collection ?? "scalar"}`, true);
2659
+ else onError(tagToken, "TAG_RESOLVE_FAILED", `Unresolved tag: ${tagName}`, true);
2660
+ return resolveCollection(CN, ctx, token, onError, tagName);
2661
+ }
2662
+ }
2663
+ const coll = resolveCollection(CN, ctx, token, onError, tagName, tag);
2664
+ const res = tag.resolve?.(coll, (msg) => onError(tagToken, "TAG_RESOLVE_FAILED", msg), ctx.options) ?? coll;
2665
+ const node = res instanceof NodeBase ? res : new Scalar(res);
2666
+ node.range = coll.range;
2667
+ node.tag = tagName;
2668
+ if (tag?.format) node.format = tag.format;
2669
+ return node;
2670
+ }
2671
+
2672
+ //#endregion
2673
+ //#region src/compose/compose-scalar.ts
2674
+ function composeScalar(ctx, token, tagToken, onError) {
2675
+ const { value, type, comment, range } = token.type === "block-scalar" ? resolveBlockScalar(ctx, token, onError) : resolveFlowScalar(token, ctx.options.strict, onError);
2676
+ const tagName = tagToken ? ctx.directives.tagName(tagToken.source, (msg) => onError(tagToken, "TAG_RESOLVE_FAILED", msg)) : null;
2677
+ let tag;
2678
+ if (ctx.options.stringKeys && ctx.atKey) tag = ctx.schema.scalar;
2679
+ else if (tagName) tag = findScalarTagByName(ctx.schema, value, tagName, tagToken, onError);
2680
+ else if (token.type === "scalar") tag = findScalarTagByTest(ctx, value, token, onError);
2681
+ else tag = ctx.schema.scalar;
2682
+ let scalar;
2683
+ try {
2684
+ const res = tag.resolve(value, (msg) => onError(tagToken ?? token, "TAG_RESOLVE_FAILED", msg), ctx.options);
2685
+ scalar = res instanceof Scalar ? res : new Scalar(res);
2686
+ } catch (error) {
2687
+ const msg = error instanceof Error ? error.message : String(error);
2688
+ onError(tagToken ?? token, "TAG_RESOLVE_FAILED", msg);
2689
+ scalar = new Scalar(value);
2690
+ }
2691
+ scalar.range = range;
2692
+ scalar.source = value;
2693
+ if (type) scalar.type = type;
2694
+ if (tagName) scalar.tag = tagName;
2695
+ if (tag.format) scalar.format = tag.format;
2696
+ if (comment) scalar.comment = comment;
2697
+ return scalar;
2698
+ }
2699
+ function findScalarTagByName(schema, value, tagName, tagToken, onError) {
2700
+ if (tagName === "!") return schema.scalar;
2701
+ const matchWithTest = [];
2702
+ for (const tag of schema.tags) if (!tag.collection && tag.tag === tagName) if (tag.default && tag.test) matchWithTest.push(tag);
2703
+ else return tag;
2704
+ for (const tag of matchWithTest) if (tag.test?.test(value)) return tag;
2705
+ const kt = schema.knownTags[tagName];
2706
+ if (kt && !kt.collection) {
2707
+ schema.tags.push(Object.assign({}, kt, {
2708
+ default: false,
2709
+ test: void 0
2710
+ }));
2711
+ return kt;
2712
+ }
2713
+ onError(tagToken, "TAG_RESOLVE_FAILED", `Unresolved tag: ${tagName}`, tagName !== "tag:yaml.org,2002:str");
2714
+ return schema.scalar;
2715
+ }
2716
+ function findScalarTagByTest({ atKey, directives, schema }, value, token, onError) {
2717
+ const tag = schema.tags.find((tag) => (tag.default === true || atKey && tag.default === "key") && tag.test?.test(value)) || schema.scalar;
2718
+ if (schema.compat) {
2719
+ const compat = schema.compat.find((tag) => tag.default && tag.test?.test(value)) ?? schema.scalar;
2720
+ if (tag.tag !== compat.tag) onError(token, "TAG_RESOLVE_FAILED", `Value may be parsed as either ${directives.tagString(tag.tag)} or ${directives.tagString(compat.tag)}`, true);
2721
+ }
2722
+ return tag;
2723
+ }
2724
+
2725
+ //#endregion
2726
+ //#region src/compose/util-empty-scalar-position.ts
2727
+ function emptyScalarPosition(offset, before, pos) {
2728
+ if (before) {
2729
+ pos ??= before.length;
2730
+ for (let i = pos - 1; i >= 0; --i) {
2731
+ let st = before[i];
2732
+ switch (st.type) {
2733
+ case "space":
2734
+ case "comment":
2735
+ case "newline":
2736
+ offset -= st.source.length;
2737
+ continue;
2738
+ }
2739
+ st = before[++i];
2740
+ while (st?.type === "space") {
2741
+ offset += st.source.length;
2742
+ st = before[++i];
2743
+ }
2744
+ break;
2745
+ }
2746
+ }
2747
+ return offset;
2748
+ }
2749
+
2750
+ //#endregion
2751
+ //#region src/compose/compose-node.ts
2752
+ const CN = {
2753
+ composeNode,
2754
+ composeEmptyNode
2755
+ };
2756
+ function composeNode(ctx, token, props, onError) {
2757
+ const atKey = ctx.atKey;
2758
+ const { spaceBefore, comment, anchor, tag } = props;
2759
+ let node;
2760
+ let isSrcToken = true;
2761
+ switch (token.type) {
2762
+ case "alias":
2763
+ node = composeAlias(ctx, token, onError);
2764
+ if (anchor || tag) onError(token, "ALIAS_PROPS", "An alias node must not specify any properties");
2765
+ break;
2766
+ case "scalar":
2767
+ case "single-quoted-scalar":
2768
+ case "double-quoted-scalar":
2769
+ case "block-scalar":
2770
+ node = composeScalar(ctx, token, tag, onError);
2771
+ if (anchor) node.anchor = anchor.source.substring(1);
2772
+ break;
2773
+ case "block-map":
2774
+ case "block-seq":
2775
+ case "flow-collection":
2776
+ node = composeCollection(CN, ctx, token, props, onError);
2777
+ if (anchor) node.anchor = anchor.source.substring(1);
2778
+ break;
2779
+ default:
2780
+ onError(token, "UNEXPECTED_TOKEN", token.type === "error" ? token.message : `Unsupported token (type: ${token.type})`);
2781
+ node = composeEmptyNode(ctx, token.offset, void 0, null, props, onError);
2782
+ isSrcToken = false;
2783
+ }
2784
+ if (anchor && node.anchor === "") onError(anchor, "BAD_ALIAS", "Anchor cannot be an empty string");
2785
+ if (atKey && ctx.options.stringKeys && (!(node instanceof Scalar) || typeof node.value !== "string" || node.tag && node.tag !== "tag:yaml.org,2002:str")) onError(tag ?? token, "NON_STRING_KEY", "With stringKeys, all keys must be strings");
2786
+ if (spaceBefore) node.spaceBefore = true;
2787
+ if (comment) if (token.type === "scalar" && token.source === "") node.comment = comment;
2788
+ else node.commentBefore = comment;
2789
+ if (ctx.options.keepSourceTokens && isSrcToken) node.srcToken = token;
2790
+ return node;
2791
+ }
2792
+ function composeEmptyNode(ctx, offset, before, pos, { spaceBefore, comment, anchor, tag, end }, onError) {
2793
+ const node = composeScalar(ctx, {
2794
+ type: "scalar",
2795
+ offset: emptyScalarPosition(offset, before, pos),
2796
+ indent: -1,
2797
+ source: ""
2798
+ }, tag, onError);
2799
+ if (anchor) {
2800
+ node.anchor = anchor.source.substring(1);
2801
+ if (node.anchor === "") onError(anchor, "BAD_ALIAS", "Anchor cannot be an empty string");
2802
+ }
2803
+ if (spaceBefore) node.spaceBefore = true;
2804
+ if (comment) {
2805
+ node.comment = comment;
2806
+ node.range[2] = end;
2807
+ }
2808
+ return node;
2809
+ }
2810
+ function composeAlias({ options }, { offset, source, end }, onError) {
2811
+ const alias = new Alias(source.substring(1));
2812
+ if (alias.source === "") onError(offset, "BAD_ALIAS", "Alias cannot be an empty string");
2813
+ if (alias.source.endsWith(":")) onError(offset + source.length - 1, "BAD_ALIAS", "Alias ending in : is ambiguous", true);
2814
+ const valueEnd = offset + source.length;
2815
+ const re = resolveEnd(end, valueEnd, options.strict, onError);
2816
+ alias.range = [
2817
+ offset,
2818
+ valueEnd,
2819
+ re.offset
2820
+ ];
2821
+ if (re.comment) alias.comment = re.comment;
2822
+ return alias;
2823
+ }
2824
+
2825
+ //#endregion
2826
+ //#region src/compose/compose-doc.ts
2827
+ function composeDoc(options, directives, { offset, start, value, end }, onError) {
2828
+ const doc = new Document(void 0, Object.assign({ _directives: directives }, options));
2829
+ const ctx = {
2830
+ atKey: false,
2831
+ atRoot: true,
2832
+ directives: doc.directives,
2833
+ options: doc.options,
2834
+ schema: doc.schema
2835
+ };
2836
+ const props = resolveProps(start, {
2837
+ indicator: "doc-start",
2838
+ next: value ?? end?.[0],
2839
+ offset,
2840
+ onError,
2841
+ parentIndent: 0,
2842
+ startOnNewline: true
2843
+ });
2844
+ if (props.found) {
2845
+ doc.directives.docStart = true;
2846
+ if (value && (value.type === "block-map" || value.type === "block-seq") && !props.hasNewline) onError(props.end, "MISSING_CHAR", "Block collection cannot start on same line with directives-end marker");
2847
+ }
2848
+ doc.value = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, start, null, props, onError);
2849
+ const contentEnd = doc.value.range[2];
2850
+ const re = resolveEnd(end, contentEnd, false, onError);
2851
+ if (re.comment) doc.comment = re.comment;
2852
+ doc.range = [
2853
+ offset,
2854
+ contentEnd,
2855
+ re.offset
2856
+ ];
2857
+ return doc;
2858
+ }
2859
+
2860
+ //#endregion
2861
+ //#region src/compose/composer.ts
2862
+ function getErrorPos(src) {
2863
+ if (typeof src === "number") return [src, src + 1];
2864
+ if (Array.isArray(src)) return src.length === 2 ? src : [src[0], src[1]];
2865
+ const { offset, source } = src;
2866
+ return [offset, offset + (typeof source === "string" ? source.length : 1)];
2867
+ }
2868
+ const logToken = typeof process !== "undefined" && process.env?.LOG_STREAM ? (token) => console.dir(token, { depth: null }) : () => {};
2869
+ function parsePrelude(prelude) {
2870
+ let comment = "";
2871
+ let atComment = false;
2872
+ let afterEmptyLine = false;
2873
+ for (let i = 0; i < prelude.length; ++i) {
2874
+ const source = prelude[i];
2875
+ switch (source[0]) {
2876
+ case "#":
2877
+ comment += (comment === "" ? "" : afterEmptyLine ? "\n\n" : "\n") + (source.substring(1) || " ");
2878
+ atComment = true;
2879
+ afterEmptyLine = false;
2880
+ break;
2881
+ case "%":
2882
+ if (prelude[i + 1]?.[0] !== "#") i += 1;
2883
+ atComment = false;
2884
+ break;
2885
+ default:
2886
+ if (!atComment) afterEmptyLine = true;
2887
+ atComment = false;
2888
+ }
2889
+ }
2890
+ return {
2891
+ comment,
2892
+ afterEmptyLine
2893
+ };
2894
+ }
2895
+ /**
2896
+ * Compose a stream of CST nodes into a stream of YAML Documents.
2897
+ *
2898
+ * ```ts
2899
+ * import { Composer, Parser } from 'yaml'
2900
+ *
2901
+ * const src: string = ...
2902
+ * const tokens = new Parser().parse(src)
2903
+ * const docs = new Composer().compose(tokens)
2904
+ * ```
2905
+ */
2906
+ var Composer = class {
2907
+ directives;
2908
+ doc = null;
2909
+ docs = [];
2910
+ options;
2911
+ atDirectives = false;
2912
+ prelude = [];
2913
+ errors = [];
2914
+ warnings = [];
2915
+ constructor(options = {}) {
2916
+ this.directives = new Directives({ version: options.version || "1.2" });
2917
+ this.options = options;
2918
+ }
2919
+ onError = (source, code, message, warning) => {
2920
+ const pos = getErrorPos(source);
2921
+ if (warning) this.warnings.push(new YAMLWarning(pos, code, message));
2922
+ else this.errors.push(new YAMLParseError(pos, code, message));
2923
+ };
2924
+ decorate(doc, afterDoc) {
2925
+ const { comment, afterEmptyLine } = parsePrelude(this.prelude);
2926
+ if (comment) {
2927
+ const dc = doc.value;
2928
+ if (afterDoc) doc.comment = doc.comment ? `${doc.comment}\n${comment}` : comment;
2929
+ else if (afterEmptyLine || doc.directives.docStart) doc.commentBefore = comment;
2930
+ else if (dc instanceof Collection && !dc.flow && dc.items.length > 0) {
2931
+ let it = dc.items[0];
2932
+ if (it instanceof Pair) it = it.key;
2933
+ const cb = it.commentBefore;
2934
+ it.commentBefore = cb ? `${comment}\n${cb}` : comment;
2935
+ } else {
2936
+ const cb = dc.commentBefore;
2937
+ dc.commentBefore = cb ? `${comment}\n${cb}` : comment;
2938
+ }
2939
+ }
2940
+ if (afterDoc) {
2941
+ Array.prototype.push.apply(doc.errors, this.errors);
2942
+ Array.prototype.push.apply(doc.warnings, this.warnings);
2943
+ } else {
2944
+ doc.errors = this.errors;
2945
+ doc.warnings = this.warnings;
2946
+ }
2947
+ this.prelude = [];
2948
+ this.errors = [];
2949
+ this.warnings = [];
2950
+ }
2951
+ /**
2952
+ * Current stream status information.
2953
+ *
2954
+ * Mostly useful at the end of input for an empty stream.
2955
+ */
2956
+ streamInfo() {
2957
+ return {
2958
+ comment: parsePrelude(this.prelude).comment,
2959
+ directives: this.directives,
2960
+ errors: this.errors,
2961
+ warnings: this.warnings
2962
+ };
2963
+ }
2964
+ /**
2965
+ * Compose tokens into documents.
2966
+ *
2967
+ * @param forceDoc - If the stream contains no document, still emit a final document including any comments and directives that would be applied to a subsequent document.
2968
+ * @param endOffset - Should be set if `forceDoc` is also set, to set the document range end and to indicate errors correctly.
2969
+ */
2970
+ compose(tokens, forceDoc = false, endOffset = -1) {
2971
+ this.docs = [];
2972
+ for (const token of tokens) this.next(token);
2973
+ return this.end(forceDoc, endOffset);
2974
+ }
2975
+ /** Advance the composer by one CST token. */
2976
+ next(token) {
2977
+ logToken(token);
2978
+ switch (token.type) {
2979
+ case "directive":
2980
+ this.directives.add(token.source, (offset, message, warning) => {
2981
+ const pos = getErrorPos(token);
2982
+ pos[0] += offset;
2983
+ this.onError(pos, "BAD_DIRECTIVE", message, warning);
2984
+ });
2985
+ this.prelude.push(token.source);
2986
+ this.atDirectives = true;
2987
+ break;
2988
+ case "document": {
2989
+ const doc = composeDoc(this.options, this.directives, token, this.onError);
2990
+ if (this.atDirectives && !doc.directives.docStart) this.onError(token, "MISSING_CHAR", "Missing directives-end/doc-start indicator line");
2991
+ this.decorate(doc, false);
2992
+ if (this.doc) this.docs.push(this.doc);
2993
+ this.doc = doc;
2994
+ this.atDirectives = false;
2995
+ break;
2996
+ }
2997
+ case "byte-order-mark":
2998
+ case "space": break;
2999
+ case "comment":
3000
+ case "newline":
3001
+ this.prelude.push(token.source);
3002
+ break;
3003
+ case "error": {
3004
+ const msg = token.source ? `${token.message}: ${JSON.stringify(token.source)}` : token.message;
3005
+ const error = new YAMLParseError(getErrorPos(token), "UNEXPECTED_TOKEN", msg);
3006
+ if (this.atDirectives || !this.doc) this.errors.push(error);
3007
+ else this.doc.errors.push(error);
3008
+ break;
3009
+ }
3010
+ case "doc-end": {
3011
+ if (!this.doc) {
3012
+ this.errors.push(new YAMLParseError(getErrorPos(token), "UNEXPECTED_TOKEN", "Unexpected doc-end without preceding document"));
3013
+ break;
3014
+ }
3015
+ this.doc.directives.docEnd = true;
3016
+ const end = resolveEnd(token.end, token.offset + token.source.length, this.doc.options.strict, this.onError);
3017
+ this.decorate(this.doc, true);
3018
+ if (end.comment) {
3019
+ const dc = this.doc.comment;
3020
+ this.doc.comment = dc ? `${dc}\n${end.comment}` : end.comment;
3021
+ }
3022
+ this.doc.range[2] = end.offset;
3023
+ break;
3024
+ }
3025
+ default: this.errors.push(new YAMLParseError(getErrorPos(token), "UNEXPECTED_TOKEN", `Unsupported token ${token.type}`));
3026
+ }
3027
+ }
3028
+ /**
3029
+ * Call at end of input to handle any remaining document.
3030
+ *
3031
+ * @param forceDoc - If the stream contains no document, still emit a final document including any comments and directives that would be applied to a subsequent document.
3032
+ * @param endOffset - Should be set if `forceDoc` is also set, to set the document range end and to indicate errors correctly.
3033
+ */
3034
+ end(forceDoc = false, endOffset = -1) {
3035
+ if (this.doc) {
3036
+ this.decorate(this.doc, true);
3037
+ this.docs.push(this.doc);
3038
+ this.doc = null;
3039
+ } else if (forceDoc) {
3040
+ const doc = new Document(void 0, Object.assign({ _directives: this.directives }, this.options));
3041
+ if (this.atDirectives) this.onError(endOffset, "MISSING_CHAR", "Missing directives-end indicator line");
3042
+ doc.range = [
3043
+ 0,
3044
+ endOffset,
3045
+ endOffset
3046
+ ];
3047
+ this.decorate(doc, false);
3048
+ this.docs.push(doc);
3049
+ }
3050
+ return this.docs;
3051
+ }
3052
+ };
3053
+
3054
+ //#endregion
3055
+ //#region src/parse/line-counter.ts
3056
+ /**
3057
+ * Tracks newlines during parsing in order to provide an efficient API for
3058
+ * determining the one-indexed `{ line, col }` position for any offset
3059
+ * within the input.
3060
+ */
3061
+ var LineCounter = class {
3062
+ lineStarts = [];
3063
+ /**
3064
+ * Should be called in ascending order. Otherwise, call
3065
+ * `lineCounter.lineStarts.sort()` before calling `linePos()`.
3066
+ */
3067
+ addNewLine = (offset) => this.lineStarts.push(offset);
3068
+ /**
3069
+ * Performs a binary search and returns the 1-indexed { line, col }
3070
+ * position of `offset`. If `line === 0`, `addNewLine` has never been
3071
+ * called or `offset` is before the first known newline.
3072
+ */
3073
+ linePos = (offset) => {
3074
+ let low = 0;
3075
+ let high = this.lineStarts.length;
3076
+ while (low < high) {
3077
+ const mid = low + high >> 1;
3078
+ if (this.lineStarts[mid] < offset) low = mid + 1;
3079
+ else high = mid;
3080
+ }
3081
+ if (this.lineStarts[low] === offset) return {
3082
+ line: low + 1,
3083
+ col: 1
3084
+ };
3085
+ if (low === 0) return {
3086
+ line: 0,
3087
+ col: offset
3088
+ };
3089
+ const start = this.lineStarts[low - 1];
3090
+ return {
3091
+ line: low,
3092
+ col: offset - start + 1
3093
+ };
3094
+ };
3095
+ };
3096
+
3097
+ //#endregion
3098
+ export { cst_exports as a, YAMLParseError as c, lex as i, YAMLWarning as l, Composer as n, prettyToken as o, Parser as r, YAMLError as s, LineCounter as t, prettifyError as u };