yaml 2.8.4 → 3.0.0-1

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