yaml 2.8.1 → 2.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/browser/dist/compose/compose-collection.js +1 -1
- package/browser/dist/compose/compose-node.js +11 -4
- package/browser/dist/compose/resolve-block-seq.js +1 -1
- package/browser/dist/compose/resolve-flow-collection.js +2 -2
- package/browser/dist/errors.js +1 -1
- package/browser/dist/nodes/Alias.js +1 -1
- package/browser/dist/parse/parser.js +2 -2
- package/browser/dist/stringify/stringify.js +1 -0
- package/browser/dist/stringify/stringifyCollection.js +13 -3
- package/browser/dist/stringify/stringifyNumber.js +1 -1
- package/browser/dist/stringify/stringifyPair.js +1 -1
- package/dist/compose/compose-collection.js +1 -1
- package/dist/compose/compose-node.js +11 -4
- package/dist/compose/resolve-block-seq.js +1 -1
- package/dist/compose/resolve-flow-collection.js +2 -2
- package/dist/errors.d.ts +1 -1
- package/dist/errors.js +1 -1
- package/dist/nodes/Alias.js +1 -1
- package/dist/options.d.ts +6 -0
- package/dist/parse/parser.js +2 -2
- package/dist/stringify/stringify.js +1 -0
- package/dist/stringify/stringifyCollection.js +13 -3
- package/dist/stringify/stringifyNumber.js +1 -1
- package/dist/stringify/stringifyPair.js +1 -1
- package/package.json +4 -4
|
@@ -59,7 +59,7 @@ function composeCollection(CN, ctx, token, props, onError) {
|
|
|
59
59
|
let tag = ctx.schema.tags.find(t => t.tag === tagName && t.collection === expType);
|
|
60
60
|
if (!tag) {
|
|
61
61
|
const kt = ctx.schema.knownTags[tagName];
|
|
62
|
-
if (kt
|
|
62
|
+
if (kt?.collection === expType) {
|
|
63
63
|
ctx.schema.tags.push(Object.assign({}, kt, { default: false }));
|
|
64
64
|
tag = kt;
|
|
65
65
|
}
|
|
@@ -28,19 +28,26 @@ function composeNode(ctx, token, props, onError) {
|
|
|
28
28
|
case 'block-map':
|
|
29
29
|
case 'block-seq':
|
|
30
30
|
case 'flow-collection':
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
try {
|
|
32
|
+
node = composeCollection(CN, ctx, token, props, onError);
|
|
33
|
+
if (anchor)
|
|
34
|
+
node.anchor = anchor.source.substring(1);
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
// Almost certainly here due to a stack overflow
|
|
38
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
39
|
+
onError(token, 'RESOURCE_EXHAUSTION', message);
|
|
40
|
+
}
|
|
34
41
|
break;
|
|
35
42
|
default: {
|
|
36
43
|
const message = token.type === 'error'
|
|
37
44
|
? token.message
|
|
38
45
|
: `Unsupported token (type: ${token.type})`;
|
|
39
46
|
onError(token, 'UNEXPECTED_TOKEN', message);
|
|
40
|
-
node = composeEmptyNode(ctx, token.offset, undefined, null, props, onError);
|
|
41
47
|
isSrcToken = false;
|
|
42
48
|
}
|
|
43
49
|
}
|
|
50
|
+
node ?? (node = composeEmptyNode(ctx, token.offset, undefined, null, props, onError));
|
|
44
51
|
if (anchor && node.anchor === '')
|
|
45
52
|
onError(anchor, 'BAD_ALIAS', 'Anchor cannot be an empty string');
|
|
46
53
|
if (atKey &&
|
|
@@ -22,7 +22,7 @@ function resolveBlockSeq({ composeNode, composeEmptyNode }, ctx, bs, onError, ta
|
|
|
22
22
|
});
|
|
23
23
|
if (!props.found) {
|
|
24
24
|
if (props.anchor || props.tag || value) {
|
|
25
|
-
if (value
|
|
25
|
+
if (value?.type === 'block-seq')
|
|
26
26
|
onError(props.end, 'BAD_INDENT', 'All sequence items must start at the same column');
|
|
27
27
|
else
|
|
28
28
|
onError(offset, 'MISSING_CHAR', 'Sequence item without - indicator');
|
|
@@ -133,7 +133,7 @@ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onErr
|
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
135
|
else if (value) {
|
|
136
|
-
if ('source' in value && value.source
|
|
136
|
+
if ('source' in value && value.source?.[0] === ':')
|
|
137
137
|
onError(value, 'MISSING_CHAR', `Missing space after : in ${fcName}`);
|
|
138
138
|
else
|
|
139
139
|
onError(valueProps.start, 'MISSING_CHAR', `Missing , or : between ${fcName} items`);
|
|
@@ -177,7 +177,7 @@ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onErr
|
|
|
177
177
|
const expectedEnd = isMap ? '}' : ']';
|
|
178
178
|
const [ce, ...ee] = fc.end;
|
|
179
179
|
let cePos = offset;
|
|
180
|
-
if (ce
|
|
180
|
+
if (ce?.source === expectedEnd)
|
|
181
181
|
cePos = ce.offset + ce.source.length;
|
|
182
182
|
else {
|
|
183
183
|
const name = fcName[0].toUpperCase() + fcName.substring(1);
|
package/browser/dist/errors.js
CHANGED
|
@@ -46,7 +46,7 @@ const prettifyError = (src, lc) => (error) => {
|
|
|
46
46
|
if (/[^ ]/.test(lineStr)) {
|
|
47
47
|
let count = 1;
|
|
48
48
|
const end = error.linePos[1];
|
|
49
|
-
if (end
|
|
49
|
+
if (end?.line === line && end.col > col) {
|
|
50
50
|
count = Math.max(1, Math.min(end.col - col, 80 - ci));
|
|
51
51
|
}
|
|
52
52
|
const pointer = ' '.repeat(ci) + '^'.repeat(count);
|
|
@@ -59,7 +59,7 @@ class Alias extends NodeBase {
|
|
|
59
59
|
data = anchors.get(source);
|
|
60
60
|
}
|
|
61
61
|
/* istanbul ignore if */
|
|
62
|
-
if (
|
|
62
|
+
if (data?.res === undefined) {
|
|
63
63
|
const msg = 'This should not happen: Alias anchor was not resolved?';
|
|
64
64
|
throw new ReferenceError(msg);
|
|
65
65
|
}
|
|
@@ -226,7 +226,7 @@ class Parser {
|
|
|
226
226
|
}
|
|
227
227
|
*step() {
|
|
228
228
|
const top = this.peek(1);
|
|
229
|
-
if (this.type === 'doc-end' &&
|
|
229
|
+
if (this.type === 'doc-end' && top?.type !== 'doc-end') {
|
|
230
230
|
while (this.stack.length > 0)
|
|
231
231
|
yield* this.pop();
|
|
232
232
|
this.stack.push({
|
|
@@ -758,7 +758,7 @@ class Parser {
|
|
|
758
758
|
do {
|
|
759
759
|
yield* this.pop();
|
|
760
760
|
top = this.peek(1);
|
|
761
|
-
} while (top
|
|
761
|
+
} while (top?.type === 'flow-collection');
|
|
762
762
|
}
|
|
763
763
|
else if (fc.end.length === 0) {
|
|
764
764
|
switch (this.type) {
|
|
@@ -102,12 +102,22 @@ function stringifyFlowCollection({ items }, ctx, { flowChars, itemIndent }) {
|
|
|
102
102
|
if (comment)
|
|
103
103
|
reqNewline = true;
|
|
104
104
|
let str = stringify(item, itemCtx, () => (comment = null));
|
|
105
|
-
|
|
105
|
+
reqNewline || (reqNewline = lines.length > linesAtValue || str.includes('\n'));
|
|
106
|
+
if (i < items.length - 1) {
|
|
106
107
|
str += ',';
|
|
108
|
+
}
|
|
109
|
+
else if (ctx.options.trailingComma) {
|
|
110
|
+
if (ctx.options.lineWidth > 0) {
|
|
111
|
+
reqNewline || (reqNewline = lines.reduce((sum, line) => sum + line.length + 2, 2) +
|
|
112
|
+
(str.length + 2) >
|
|
113
|
+
ctx.options.lineWidth);
|
|
114
|
+
}
|
|
115
|
+
if (reqNewline) {
|
|
116
|
+
str += ',';
|
|
117
|
+
}
|
|
118
|
+
}
|
|
107
119
|
if (comment)
|
|
108
120
|
str += lineComment(str, itemIndent, commentString(comment));
|
|
109
|
-
if (!reqNewline && (lines.length > linesAtValue || str.includes('\n')))
|
|
110
|
-
reqNewline = true;
|
|
111
121
|
lines.push(str);
|
|
112
122
|
linesAtValue = lines.length;
|
|
113
123
|
}
|
|
@@ -4,7 +4,7 @@ function stringifyNumber({ format, minFractionDigits, tag, value }) {
|
|
|
4
4
|
const num = typeof value === 'number' ? value : Number(value);
|
|
5
5
|
if (!isFinite(num))
|
|
6
6
|
return isNaN(num) ? '.nan' : num < 0 ? '-.inf' : '.inf';
|
|
7
|
-
let n = JSON.stringify(value);
|
|
7
|
+
let n = Object.is(value, -0) ? '-0' : JSON.stringify(value);
|
|
8
8
|
if (!format &&
|
|
9
9
|
minFractionDigits &&
|
|
10
10
|
(!tag || tag === 'tag:yaml.org,2002:float') &&
|
|
@@ -101,7 +101,7 @@ function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
|
|
|
101
101
|
ws += `\n${indentComment(cs, ctx.indent)}`;
|
|
102
102
|
}
|
|
103
103
|
if (valueStr === '' && !ctx.inFlow) {
|
|
104
|
-
if (ws === '\n')
|
|
104
|
+
if (ws === '\n' && valueComment)
|
|
105
105
|
ws = '\n\n';
|
|
106
106
|
}
|
|
107
107
|
else {
|
|
@@ -61,7 +61,7 @@ function composeCollection(CN, ctx, token, props, onError) {
|
|
|
61
61
|
let tag = ctx.schema.tags.find(t => t.tag === tagName && t.collection === expType);
|
|
62
62
|
if (!tag) {
|
|
63
63
|
const kt = ctx.schema.knownTags[tagName];
|
|
64
|
-
if (kt
|
|
64
|
+
if (kt?.collection === expType) {
|
|
65
65
|
ctx.schema.tags.push(Object.assign({}, kt, { default: false }));
|
|
66
66
|
tag = kt;
|
|
67
67
|
}
|
|
@@ -30,19 +30,26 @@ function composeNode(ctx, token, props, onError) {
|
|
|
30
30
|
case 'block-map':
|
|
31
31
|
case 'block-seq':
|
|
32
32
|
case 'flow-collection':
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
try {
|
|
34
|
+
node = composeCollection.composeCollection(CN, ctx, token, props, onError);
|
|
35
|
+
if (anchor)
|
|
36
|
+
node.anchor = anchor.source.substring(1);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
// Almost certainly here due to a stack overflow
|
|
40
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
41
|
+
onError(token, 'RESOURCE_EXHAUSTION', message);
|
|
42
|
+
}
|
|
36
43
|
break;
|
|
37
44
|
default: {
|
|
38
45
|
const message = token.type === 'error'
|
|
39
46
|
? token.message
|
|
40
47
|
: `Unsupported token (type: ${token.type})`;
|
|
41
48
|
onError(token, 'UNEXPECTED_TOKEN', message);
|
|
42
|
-
node = composeEmptyNode(ctx, token.offset, undefined, null, props, onError);
|
|
43
49
|
isSrcToken = false;
|
|
44
50
|
}
|
|
45
51
|
}
|
|
52
|
+
node ?? (node = composeEmptyNode(ctx, token.offset, undefined, null, props, onError));
|
|
46
53
|
if (anchor && node.anchor === '')
|
|
47
54
|
onError(anchor, 'BAD_ALIAS', 'Anchor cannot be an empty string');
|
|
48
55
|
if (atKey &&
|
|
@@ -24,7 +24,7 @@ function resolveBlockSeq({ composeNode, composeEmptyNode }, ctx, bs, onError, ta
|
|
|
24
24
|
});
|
|
25
25
|
if (!props.found) {
|
|
26
26
|
if (props.anchor || props.tag || value) {
|
|
27
|
-
if (value
|
|
27
|
+
if (value?.type === 'block-seq')
|
|
28
28
|
onError(props.end, 'BAD_INDENT', 'All sequence items must start at the same column');
|
|
29
29
|
else
|
|
30
30
|
onError(offset, 'MISSING_CHAR', 'Sequence item without - indicator');
|
|
@@ -135,7 +135,7 @@ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onErr
|
|
|
135
135
|
}
|
|
136
136
|
}
|
|
137
137
|
else if (value) {
|
|
138
|
-
if ('source' in value && value.source
|
|
138
|
+
if ('source' in value && value.source?.[0] === ':')
|
|
139
139
|
onError(value, 'MISSING_CHAR', `Missing space after : in ${fcName}`);
|
|
140
140
|
else
|
|
141
141
|
onError(valueProps.start, 'MISSING_CHAR', `Missing , or : between ${fcName} items`);
|
|
@@ -179,7 +179,7 @@ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onErr
|
|
|
179
179
|
const expectedEnd = isMap ? '}' : ']';
|
|
180
180
|
const [ce, ...ee] = fc.end;
|
|
181
181
|
let cePos = offset;
|
|
182
|
-
if (ce
|
|
182
|
+
if (ce?.source === expectedEnd)
|
|
183
183
|
cePos = ce.offset + ce.source.length;
|
|
184
184
|
else {
|
|
185
185
|
const name = fcName[0].toUpperCase() + fcName.substring(1);
|
package/dist/errors.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { LineCounter } from './parse/line-counter';
|
|
2
|
-
export type ErrorCode = 'ALIAS_PROPS' | 'BAD_ALIAS' | 'BAD_DIRECTIVE' | 'BAD_DQ_ESCAPE' | 'BAD_INDENT' | 'BAD_PROP_ORDER' | 'BAD_SCALAR_START' | 'BLOCK_AS_IMPLICIT_KEY' | 'BLOCK_IN_FLOW' | 'DUPLICATE_KEY' | 'IMPOSSIBLE' | 'KEY_OVER_1024_CHARS' | 'MISSING_CHAR' | 'MULTILINE_IMPLICIT_KEY' | 'MULTIPLE_ANCHORS' | 'MULTIPLE_DOCS' | 'MULTIPLE_TAGS' | 'NON_STRING_KEY' | 'TAB_AS_INDENT' | 'TAG_RESOLVE_FAILED' | 'UNEXPECTED_TOKEN' | 'BAD_COLLECTION_TYPE';
|
|
2
|
+
export type ErrorCode = 'ALIAS_PROPS' | 'BAD_ALIAS' | 'BAD_DIRECTIVE' | 'BAD_DQ_ESCAPE' | 'BAD_INDENT' | 'BAD_PROP_ORDER' | 'BAD_SCALAR_START' | 'BLOCK_AS_IMPLICIT_KEY' | 'BLOCK_IN_FLOW' | 'DUPLICATE_KEY' | 'IMPOSSIBLE' | 'KEY_OVER_1024_CHARS' | 'MISSING_CHAR' | 'MULTILINE_IMPLICIT_KEY' | 'MULTIPLE_ANCHORS' | 'MULTIPLE_DOCS' | 'MULTIPLE_TAGS' | 'NON_STRING_KEY' | 'RESOURCE_EXHAUSTION' | 'TAB_AS_INDENT' | 'TAG_RESOLVE_FAILED' | 'UNEXPECTED_TOKEN' | 'BAD_COLLECTION_TYPE';
|
|
3
3
|
export type LinePos = {
|
|
4
4
|
line: number;
|
|
5
5
|
col: number;
|
package/dist/errors.js
CHANGED
|
@@ -48,7 +48,7 @@ const prettifyError = (src, lc) => (error) => {
|
|
|
48
48
|
if (/[^ ]/.test(lineStr)) {
|
|
49
49
|
let count = 1;
|
|
50
50
|
const end = error.linePos[1];
|
|
51
|
-
if (end
|
|
51
|
+
if (end?.line === line && end.col > col) {
|
|
52
52
|
count = Math.max(1, Math.min(end.col - col, 80 - ci));
|
|
53
53
|
}
|
|
54
54
|
const pointer = ' '.repeat(ci) + '^'.repeat(count);
|
package/dist/nodes/Alias.js
CHANGED
|
@@ -61,7 +61,7 @@ class Alias extends Node.NodeBase {
|
|
|
61
61
|
data = anchors.get(source);
|
|
62
62
|
}
|
|
63
63
|
/* istanbul ignore if */
|
|
64
|
-
if (
|
|
64
|
+
if (data?.res === undefined) {
|
|
65
65
|
const msg = 'This should not happen: Alias anchor was not resolved?';
|
|
66
66
|
throw new ReferenceError(msg);
|
|
67
67
|
}
|
package/dist/options.d.ts
CHANGED
|
@@ -326,6 +326,12 @@ export type ToStringOptions = {
|
|
|
326
326
|
* Default: `null`
|
|
327
327
|
*/
|
|
328
328
|
singleQuote?: boolean | null;
|
|
329
|
+
/**
|
|
330
|
+
* Add a trailing comma after the last entry in a flow map or flow sequence that's split across multiple lines.
|
|
331
|
+
*
|
|
332
|
+
* Default: `'false'`
|
|
333
|
+
*/
|
|
334
|
+
trailingComma?: boolean;
|
|
329
335
|
/**
|
|
330
336
|
* String representation for `true`.
|
|
331
337
|
* With the core schema, use `'true'`, `'True'`, or `'TRUE'`.
|
package/dist/parse/parser.js
CHANGED
|
@@ -231,7 +231,7 @@ class Parser {
|
|
|
231
231
|
}
|
|
232
232
|
*step() {
|
|
233
233
|
const top = this.peek(1);
|
|
234
|
-
if (this.type === 'doc-end' &&
|
|
234
|
+
if (this.type === 'doc-end' && top?.type !== 'doc-end') {
|
|
235
235
|
while (this.stack.length > 0)
|
|
236
236
|
yield* this.pop();
|
|
237
237
|
this.stack.push({
|
|
@@ -763,7 +763,7 @@ class Parser {
|
|
|
763
763
|
do {
|
|
764
764
|
yield* this.pop();
|
|
765
765
|
top = this.peek(1);
|
|
766
|
-
} while (top
|
|
766
|
+
} while (top?.type === 'flow-collection');
|
|
767
767
|
}
|
|
768
768
|
else if (fc.end.length === 0) {
|
|
769
769
|
switch (this.type) {
|
|
@@ -104,12 +104,22 @@ function stringifyFlowCollection({ items }, ctx, { flowChars, itemIndent }) {
|
|
|
104
104
|
if (comment)
|
|
105
105
|
reqNewline = true;
|
|
106
106
|
let str = stringify.stringify(item, itemCtx, () => (comment = null));
|
|
107
|
-
|
|
107
|
+
reqNewline || (reqNewline = lines.length > linesAtValue || str.includes('\n'));
|
|
108
|
+
if (i < items.length - 1) {
|
|
108
109
|
str += ',';
|
|
110
|
+
}
|
|
111
|
+
else if (ctx.options.trailingComma) {
|
|
112
|
+
if (ctx.options.lineWidth > 0) {
|
|
113
|
+
reqNewline || (reqNewline = lines.reduce((sum, line) => sum + line.length + 2, 2) +
|
|
114
|
+
(str.length + 2) >
|
|
115
|
+
ctx.options.lineWidth);
|
|
116
|
+
}
|
|
117
|
+
if (reqNewline) {
|
|
118
|
+
str += ',';
|
|
119
|
+
}
|
|
120
|
+
}
|
|
109
121
|
if (comment)
|
|
110
122
|
str += stringifyComment.lineComment(str, itemIndent, commentString(comment));
|
|
111
|
-
if (!reqNewline && (lines.length > linesAtValue || str.includes('\n')))
|
|
112
|
-
reqNewline = true;
|
|
113
123
|
lines.push(str);
|
|
114
124
|
linesAtValue = lines.length;
|
|
115
125
|
}
|
|
@@ -6,7 +6,7 @@ function stringifyNumber({ format, minFractionDigits, tag, value }) {
|
|
|
6
6
|
const num = typeof value === 'number' ? value : Number(value);
|
|
7
7
|
if (!isFinite(num))
|
|
8
8
|
return isNaN(num) ? '.nan' : num < 0 ? '-.inf' : '.inf';
|
|
9
|
-
let n = JSON.stringify(value);
|
|
9
|
+
let n = Object.is(value, -0) ? '-0' : JSON.stringify(value);
|
|
10
10
|
if (!format &&
|
|
11
11
|
minFractionDigits &&
|
|
12
12
|
(!tag || tag === 'tag:yaml.org,2002:float') &&
|
|
@@ -103,7 +103,7 @@ function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
|
|
|
103
103
|
ws += `\n${stringifyComment.indentComment(cs, ctx.indent)}`;
|
|
104
104
|
}
|
|
105
105
|
if (valueStr === '' && !ctx.inFlow) {
|
|
106
|
-
if (ws === '\n')
|
|
106
|
+
if (ws === '\n' && valueComment)
|
|
107
107
|
ws = '\n\n';
|
|
108
108
|
}
|
|
109
109
|
else {
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yaml",
|
|
3
|
-
"version": "2.8.
|
|
3
|
+
"version": "2.8.3",
|
|
4
4
|
"license": "ISC",
|
|
5
5
|
"author": "Eemeli Aro <eemeli@gmail.com>",
|
|
6
|
+
"funding": "https://github.com/sponsors/eemeli",
|
|
6
7
|
"repository": "github:eemeli/yaml",
|
|
7
8
|
"description": "JavaScript parser and stringifier for YAML",
|
|
8
9
|
"keywords": [
|
|
@@ -73,14 +74,13 @@
|
|
|
73
74
|
"@babel/preset-env": "^7.12.11",
|
|
74
75
|
"@eslint/js": "^9.9.1",
|
|
75
76
|
"@rollup/plugin-babel": "^6.0.3",
|
|
76
|
-
"@rollup/plugin-replace": "^
|
|
77
|
+
"@rollup/plugin-replace": "^6.0.3",
|
|
77
78
|
"@rollup/plugin-typescript": "^12.1.1",
|
|
78
79
|
"@types/jest": "^29.2.4",
|
|
79
80
|
"@types/node": "^20.11.20",
|
|
80
81
|
"babel-jest": "^29.0.1",
|
|
81
|
-
"cross-env": "^7.0.3",
|
|
82
82
|
"eslint": "^9.9.1",
|
|
83
|
-
"eslint-config-prettier": "^
|
|
83
|
+
"eslint-config-prettier": "^10.1.8",
|
|
84
84
|
"fast-check": "^2.12.0",
|
|
85
85
|
"jest": "^29.0.1",
|
|
86
86
|
"jest-resolve": "^29.7.0",
|