yaml 2.0.0-4 → 2.0.0-5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/browser/dist/compose/compose-collection.js +12 -9
- package/browser/dist/compose/compose-doc.js +23 -6
- package/browser/dist/compose/compose-node.js +20 -17
- package/browser/dist/compose/compose-scalar.js +20 -23
- package/browser/dist/compose/composer.js +105 -76
- package/browser/dist/compose/resolve-block-map.js +38 -29
- package/browser/dist/compose/resolve-block-scalar.js +14 -17
- package/browser/dist/compose/resolve-block-seq.js +21 -17
- package/browser/dist/compose/resolve-end.js +6 -7
- package/browser/dist/compose/resolve-flow-collection.js +153 -199
- package/browser/dist/compose/resolve-flow-scalar.js +49 -25
- package/browser/dist/compose/resolve-props.js +47 -35
- package/browser/dist/compose/util-contains-newline.js +15 -12
- package/browser/dist/doc/Document.js +50 -99
- package/browser/dist/doc/anchors.js +72 -0
- package/browser/dist/doc/createNode.js +27 -17
- package/browser/dist/errors.js +16 -12
- package/browser/dist/index.js +3 -3
- package/browser/dist/nodes/Alias.js +51 -28
- package/browser/dist/nodes/Collection.js +5 -83
- package/browser/dist/nodes/Node.js +2 -1
- package/browser/dist/nodes/Pair.js +9 -232
- package/browser/dist/nodes/YAMLMap.js +8 -4
- package/browser/dist/nodes/YAMLSeq.js +7 -4
- package/browser/dist/nodes/addPairToJSMap.js +103 -0
- package/browser/dist/nodes/toJS.js +12 -10
- package/browser/dist/options.js +0 -2
- package/browser/dist/parse/cst-scalar.js +219 -0
- package/browser/dist/parse/cst-stringify.js +61 -0
- package/browser/dist/parse/cst-visit.js +97 -0
- package/{dist/parse/tokens.js → browser/dist/parse/cst.js} +12 -7
- package/browser/dist/parse/lexer.js +99 -105
- package/browser/dist/parse/parser.js +219 -144
- package/browser/dist/public-api.js +11 -14
- package/browser/dist/schema/Schema.js +23 -0
- package/browser/dist/{tags/failsafe → schema/common}/map.js +0 -0
- package/browser/dist/schema/common/null.js +13 -0
- package/browser/dist/{tags/failsafe → schema/common}/seq.js +1 -1
- package/browser/dist/{tags/failsafe → schema/common}/string.js +0 -0
- package/browser/dist/schema/core/bool.js +19 -0
- package/browser/dist/schema/core/float.js +40 -0
- package/browser/dist/schema/core/int.js +38 -0
- package/browser/dist/schema/core/schema.js +23 -0
- package/browser/dist/{tags/json.js → schema/json/schema.js} +5 -6
- package/browser/dist/schema/tags.js +79 -0
- package/browser/dist/{tags → schema}/yaml-1.1/binary.js +0 -0
- package/browser/dist/schema/yaml-1.1/bool.js +26 -0
- package/browser/dist/schema/yaml-1.1/float.js +43 -0
- package/browser/dist/schema/yaml-1.1/int.js +71 -0
- package/browser/dist/{tags → schema}/yaml-1.1/omap.js +0 -0
- package/browser/dist/{tags → schema}/yaml-1.1/pairs.js +9 -6
- package/browser/dist/schema/yaml-1.1/schema.js +37 -0
- package/browser/dist/{tags → schema}/yaml-1.1/set.js +0 -0
- package/browser/dist/{tags → schema}/yaml-1.1/timestamp.js +0 -0
- package/browser/dist/stringify/addComment.js +1 -7
- package/browser/dist/stringify/stringify.js +8 -6
- package/browser/dist/stringify/stringifyCollection.js +108 -0
- package/browser/dist/stringify/stringifyDocument.js +61 -0
- package/browser/dist/stringify/stringifyPair.js +113 -0
- package/browser/dist/stringify/stringifyString.js +53 -52
- package/browser/dist/visit.js +20 -1
- package/dist/compose/compose-collection.d.ts +4 -4
- package/dist/compose/compose-collection.js +12 -9
- package/dist/compose/compose-doc.d.ts +4 -3
- package/dist/compose/compose-doc.js +23 -6
- package/dist/compose/compose-node.d.ts +15 -7
- package/dist/compose/compose-node.js +20 -17
- package/dist/compose/compose-scalar.d.ts +4 -3
- package/dist/compose/compose-scalar.js +19 -22
- package/dist/compose/composer.d.ts +28 -23
- package/dist/compose/composer.js +106 -77
- package/dist/compose/resolve-block-map.d.ts +4 -4
- package/dist/compose/resolve-block-map.js +38 -29
- package/dist/compose/resolve-block-scalar.d.ts +5 -3
- package/dist/compose/resolve-block-scalar.js +14 -17
- package/dist/compose/resolve-block-seq.d.ts +4 -4
- package/dist/compose/resolve-block-seq.js +21 -17
- package/dist/compose/resolve-end.d.ts +3 -2
- package/dist/compose/resolve-end.js +6 -7
- package/dist/compose/resolve-flow-collection.d.ts +4 -5
- package/dist/compose/resolve-flow-collection.js +152 -198
- package/dist/compose/resolve-flow-scalar.d.ts +5 -3
- package/dist/compose/resolve-flow-scalar.js +49 -25
- package/dist/compose/resolve-props.d.ts +17 -10
- package/dist/compose/resolve-props.js +47 -35
- package/dist/compose/util-contains-newline.d.ts +1 -1
- package/dist/compose/util-contains-newline.js +15 -12
- package/dist/compose/util-empty-scalar-position.d.ts +1 -1
- package/dist/doc/Document.d.ts +27 -15
- package/dist/doc/Document.js +48 -97
- package/dist/doc/anchors.d.ts +24 -0
- package/dist/doc/anchors.js +77 -0
- package/dist/doc/createNode.d.ts +8 -10
- package/dist/doc/createNode.js +26 -16
- package/dist/errors.d.ts +11 -8
- package/dist/errors.js +16 -12
- package/dist/index.d.ts +5 -3
- package/dist/index.js +3 -3
- package/dist/nodes/Alias.d.ts +19 -9
- package/dist/nodes/Alias.js +51 -28
- package/dist/nodes/Collection.d.ts +3 -17
- package/dist/nodes/Collection.js +4 -82
- package/dist/nodes/Node.d.ts +6 -4
- package/dist/nodes/Node.js +2 -0
- package/dist/nodes/Pair.d.ts +6 -11
- package/dist/nodes/Pair.js +8 -231
- package/dist/nodes/Scalar.d.ts +6 -3
- package/dist/nodes/YAMLMap.d.ts +3 -3
- package/dist/nodes/YAMLMap.js +8 -4
- package/dist/nodes/YAMLSeq.d.ts +3 -3
- package/dist/nodes/YAMLSeq.js +7 -4
- package/dist/nodes/addPairToJSMap.d.ts +3 -0
- package/dist/nodes/addPairToJSMap.js +105 -0
- package/dist/nodes/toJS.d.ts +4 -5
- package/dist/nodes/toJS.js +12 -10
- package/dist/options.d.ts +20 -26
- package/dist/options.js +0 -2
- package/dist/parse/cst-scalar.d.ts +58 -0
- package/dist/parse/cst-scalar.js +223 -0
- package/dist/parse/cst-stringify.d.ts +8 -0
- package/dist/parse/cst-stringify.js +63 -0
- package/dist/parse/cst-visit.d.ts +39 -0
- package/dist/parse/cst-visit.js +99 -0
- package/dist/parse/{tokens.d.ts → cst.d.ts} +23 -7
- package/{browser/dist/parse/tokens.js → dist/parse/cst.js} +27 -1
- package/dist/parse/lexer.d.ts +4 -13
- package/dist/parse/lexer.js +100 -106
- package/dist/parse/parser.d.ts +30 -24
- package/dist/parse/parser.js +221 -146
- package/dist/public-api.d.ts +7 -7
- package/dist/public-api.js +11 -14
- package/dist/{doc → schema}/Schema.d.ts +5 -3
- package/dist/schema/Schema.js +25 -0
- package/dist/{tags/failsafe → schema/common}/map.d.ts +0 -0
- package/dist/{tags/failsafe → schema/common}/map.js +0 -0
- package/dist/schema/common/null.d.ts +4 -0
- package/dist/schema/common/null.js +15 -0
- package/dist/{tags/failsafe → schema/common}/seq.d.ts +0 -0
- package/dist/{tags/failsafe → schema/common}/seq.js +1 -1
- package/dist/{tags/failsafe → schema/common}/string.d.ts +0 -0
- package/dist/{tags/failsafe → schema/common}/string.js +0 -0
- package/dist/schema/core/bool.d.ts +4 -0
- package/dist/schema/core/bool.js +21 -0
- package/dist/schema/core/float.d.ts +4 -0
- package/dist/schema/core/float.js +44 -0
- package/dist/schema/core/int.d.ts +4 -0
- package/dist/schema/core/int.js +42 -0
- package/dist/schema/core/schema.d.ts +1 -0
- package/dist/schema/core/schema.js +25 -0
- package/dist/schema/json/schema.d.ts +2 -0
- package/dist/{tags/json.js → schema/json/schema.js} +5 -6
- package/dist/schema/tags.d.ts +41 -0
- package/dist/schema/tags.js +82 -0
- package/dist/{tags → schema}/types.d.ts +3 -7
- package/dist/{tags → schema}/yaml-1.1/binary.d.ts +0 -0
- package/dist/{tags → schema}/yaml-1.1/binary.js +0 -0
- package/dist/schema/yaml-1.1/bool.d.ts +7 -0
- package/dist/schema/yaml-1.1/bool.js +29 -0
- package/dist/schema/yaml-1.1/float.d.ts +4 -0
- package/dist/schema/yaml-1.1/float.js +47 -0
- package/dist/schema/yaml-1.1/int.d.ts +5 -0
- package/dist/schema/yaml-1.1/int.js +76 -0
- package/dist/{tags → schema}/yaml-1.1/omap.d.ts +0 -0
- package/dist/{tags → schema}/yaml-1.1/omap.js +0 -0
- package/dist/{tags → schema}/yaml-1.1/pairs.d.ts +3 -2
- package/dist/{tags → schema}/yaml-1.1/pairs.js +9 -6
- package/dist/schema/yaml-1.1/schema.d.ts +1 -0
- package/dist/schema/yaml-1.1/schema.js +39 -0
- package/dist/{tags → schema}/yaml-1.1/set.d.ts +1 -1
- package/dist/{tags → schema}/yaml-1.1/set.js +0 -0
- package/dist/{tags → schema}/yaml-1.1/timestamp.d.ts +0 -0
- package/dist/{tags → schema}/yaml-1.1/timestamp.js +0 -0
- package/dist/stringify/addComment.js +0 -7
- package/dist/stringify/stringify.d.ts +1 -2
- package/dist/stringify/stringify.js +8 -6
- package/dist/stringify/stringifyCollection.d.ts +21 -0
- package/dist/stringify/stringifyCollection.js +110 -0
- package/dist/stringify/stringifyDocument.d.ts +3 -0
- package/dist/stringify/stringifyDocument.js +63 -0
- package/dist/stringify/stringifyPair.d.ts +3 -0
- package/dist/stringify/stringifyPair.js +115 -0
- package/dist/stringify/stringifyString.js +53 -52
- package/dist/test-events.d.ts +1 -2
- package/dist/test-events.js +25 -12
- package/dist/util.d.ts +1 -1
- package/dist/visit.d.ts +10 -1
- package/dist/visit.js +20 -1
- package/package.json +4 -3
- package/browser/dist/doc/Anchors.js +0 -102
- package/browser/dist/doc/Schema.js +0 -27
- package/browser/dist/doc/getSchemaTags.js +0 -30
- package/browser/dist/tags/core.js +0 -109
- package/browser/dist/tags/failsafe/index.js +0 -7
- package/browser/dist/tags/index.js +0 -34
- package/browser/dist/tags/yaml-1.1/index.js +0 -152
- package/dist/doc/Anchors.d.ts +0 -36
- package/dist/doc/Anchors.js +0 -104
- package/dist/doc/Schema.js +0 -29
- package/dist/doc/getSchemaTags.d.ts +0 -3
- package/dist/doc/getSchemaTags.js +0 -32
- package/dist/tags/core.d.ts +0 -14
- package/dist/tags/core.js +0 -119
- package/dist/tags/failsafe/index.d.ts +0 -1
- package/dist/tags/failsafe/index.js +0 -9
- package/dist/tags/index.d.ts +0 -31
- package/dist/tags/index.js +0 -37
- package/dist/tags/json.d.ts +0 -2
- package/dist/tags/yaml-1.1/index.d.ts +0 -2
- package/dist/tags/yaml-1.1/index.js +0 -154
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { Scalar } from '../nodes/Scalar.js';
|
|
2
2
|
import { resolveEnd } from './resolve-end.js';
|
|
3
3
|
|
|
4
|
-
function resolveFlowScalar(
|
|
4
|
+
function resolveFlowScalar(scalar, strict, onError) {
|
|
5
|
+
const { offset, type, source, end } = scalar;
|
|
5
6
|
let _type;
|
|
6
7
|
let value;
|
|
7
|
-
const _onError = (rel, msg) => onError(offset + rel, msg);
|
|
8
|
+
const _onError = (rel, code, msg) => onError(offset + rel, code, msg);
|
|
8
9
|
switch (type) {
|
|
9
10
|
case 'scalar':
|
|
10
11
|
_type = Scalar.PLAIN;
|
|
@@ -20,68 +21,91 @@ function resolveFlowScalar({ offset, type, source, end }, strict, onError) {
|
|
|
20
21
|
break;
|
|
21
22
|
/* istanbul ignore next should not happen */
|
|
22
23
|
default:
|
|
23
|
-
onError(
|
|
24
|
+
onError(scalar, 'UNEXPECTED_TOKEN', `Expected a flow scalar value, but found: ${type}`);
|
|
24
25
|
return {
|
|
25
26
|
value: '',
|
|
26
27
|
type: null,
|
|
27
28
|
comment: '',
|
|
28
|
-
|
|
29
|
+
range: [offset, offset + source.length, offset + source.length]
|
|
29
30
|
};
|
|
30
31
|
}
|
|
31
|
-
const
|
|
32
|
+
const valueEnd = offset + source.length;
|
|
33
|
+
const re = resolveEnd(end, valueEnd, strict, onError);
|
|
32
34
|
return {
|
|
33
35
|
value,
|
|
34
36
|
type: _type,
|
|
35
37
|
comment: re.comment,
|
|
36
|
-
|
|
38
|
+
range: [offset, valueEnd, re.offset]
|
|
37
39
|
};
|
|
38
40
|
}
|
|
39
41
|
function plainValue(source, onError) {
|
|
42
|
+
let message = '';
|
|
40
43
|
switch (source[0]) {
|
|
41
44
|
/* istanbul ignore next should not happen */
|
|
42
45
|
case '\t':
|
|
43
|
-
|
|
46
|
+
message = 'Plain value cannot start with a tab character';
|
|
44
47
|
break;
|
|
45
48
|
case '|':
|
|
46
49
|
case '>': {
|
|
47
|
-
|
|
48
|
-
onError(0, message);
|
|
50
|
+
message = `Plain value cannot start with block scalar indicator ${source[0]}`;
|
|
49
51
|
break;
|
|
50
52
|
}
|
|
51
53
|
case '@':
|
|
52
54
|
case '`': {
|
|
53
|
-
|
|
54
|
-
onError(0, message);
|
|
55
|
+
message = `Plain value cannot start with reserved character ${source[0]}`;
|
|
55
56
|
break;
|
|
56
57
|
}
|
|
57
58
|
}
|
|
58
|
-
|
|
59
|
+
if (message)
|
|
60
|
+
onError(0, 'BAD_SCALAR_START', message);
|
|
61
|
+
return foldLines(source);
|
|
59
62
|
}
|
|
60
63
|
function singleQuotedValue(source, onError) {
|
|
61
64
|
if (source[source.length - 1] !== "'" || source.length === 1)
|
|
62
|
-
onError(source.length, "Missing closing 'quote");
|
|
65
|
+
onError(source.length, 'MISSING_CHAR', "Missing closing 'quote");
|
|
63
66
|
return foldLines(source.slice(1, -1)).replace(/''/g, "'");
|
|
64
67
|
}
|
|
65
68
|
function foldLines(source) {
|
|
66
|
-
|
|
67
|
-
|
|
69
|
+
/**
|
|
70
|
+
* The negative lookbehind here and in the `re` RegExp is to
|
|
71
|
+
* prevent causing a polynomial search time in certain cases.
|
|
72
|
+
*
|
|
73
|
+
* The try-catch is for Safari, which doesn't support this yet:
|
|
74
|
+
* https://caniuse.com/js-regexp-lookbehind
|
|
75
|
+
*/
|
|
76
|
+
let first, line;
|
|
77
|
+
try {
|
|
78
|
+
first = new RegExp('(.*?)(?<![ \t])[ \t]*\r?\n', 'sy');
|
|
79
|
+
line = new RegExp('[ \t]*(.*?)(?:(?<![ \t])[ \t]*)?\r?\n', 'sy');
|
|
80
|
+
}
|
|
81
|
+
catch (_) {
|
|
82
|
+
first = /(.*?)[ \t]*\r?\n/sy;
|
|
83
|
+
line = /[ \t]*(.*?)[ \t]*\r?\n/sy;
|
|
84
|
+
}
|
|
85
|
+
let match = first.exec(source);
|
|
86
|
+
if (!match)
|
|
87
|
+
return source;
|
|
88
|
+
let res = match[1];
|
|
68
89
|
let sep = ' ';
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
90
|
+
let pos = first.lastIndex;
|
|
91
|
+
line.lastIndex = pos;
|
|
92
|
+
while ((match = line.exec(source))) {
|
|
93
|
+
if (match[1] === '') {
|
|
72
94
|
if (sep === '\n')
|
|
73
95
|
res += sep;
|
|
74
96
|
else
|
|
75
97
|
sep = '\n';
|
|
76
98
|
}
|
|
77
99
|
else {
|
|
78
|
-
res += sep +
|
|
100
|
+
res += sep + match[1];
|
|
79
101
|
sep = ' ';
|
|
80
102
|
}
|
|
103
|
+
pos = line.lastIndex;
|
|
81
104
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
105
|
+
const last = /[ \t]*(.*)/sy;
|
|
106
|
+
last.lastIndex = pos;
|
|
107
|
+
match = last.exec(source);
|
|
108
|
+
return res + sep + ((match && match[1]) || '');
|
|
85
109
|
}
|
|
86
110
|
function doubleQuotedValue(source, onError) {
|
|
87
111
|
let res = '';
|
|
@@ -112,7 +136,7 @@ function doubleQuotedValue(source, onError) {
|
|
|
112
136
|
}
|
|
113
137
|
else {
|
|
114
138
|
const raw = source.substr(i - 1, 2);
|
|
115
|
-
onError(i - 1, `Invalid escape sequence ${raw}`);
|
|
139
|
+
onError(i - 1, 'BAD_DQ_ESCAPE', `Invalid escape sequence ${raw}`);
|
|
116
140
|
res += raw;
|
|
117
141
|
}
|
|
118
142
|
}
|
|
@@ -130,7 +154,7 @@ function doubleQuotedValue(source, onError) {
|
|
|
130
154
|
}
|
|
131
155
|
}
|
|
132
156
|
if (source[source.length - 1] !== '"' || source.length === 1)
|
|
133
|
-
onError(source.length, 'Missing closing "quote');
|
|
157
|
+
onError(source.length, 'MISSING_CHAR', 'Missing closing "quote');
|
|
134
158
|
return res;
|
|
135
159
|
}
|
|
136
160
|
/**
|
|
@@ -178,7 +202,7 @@ function parseCharCode(source, offset, length, onError) {
|
|
|
178
202
|
const code = ok ? parseInt(cc, 16) : NaN;
|
|
179
203
|
if (isNaN(code)) {
|
|
180
204
|
const raw = source.substr(offset - 2, length + 2);
|
|
181
|
-
onError(offset - 2, `Invalid escape sequence ${raw}`);
|
|
205
|
+
onError(offset - 2, 'BAD_DQ_ESCAPE', `Invalid escape sequence ${raw}`);
|
|
182
206
|
return raw;
|
|
183
207
|
}
|
|
184
208
|
return String.fromCodePoint(code);
|
|
@@ -1,90 +1,102 @@
|
|
|
1
|
-
function resolveProps(
|
|
2
|
-
let length = 0;
|
|
1
|
+
function resolveProps(tokens, { ctx, flow, indicator, offset, onError, startOnNewline }) {
|
|
3
2
|
let spaceBefore = false;
|
|
4
3
|
let atNewline = startOnNewline;
|
|
5
4
|
let hasSpace = startOnNewline;
|
|
6
5
|
let comment = '';
|
|
7
|
-
let
|
|
6
|
+
let commentSep = '';
|
|
8
7
|
let hasNewline = false;
|
|
9
|
-
let
|
|
10
|
-
let
|
|
11
|
-
let
|
|
8
|
+
let anchor = null;
|
|
9
|
+
let tag = null;
|
|
10
|
+
let comma = null;
|
|
12
11
|
let found = null;
|
|
13
12
|
let start = null;
|
|
14
13
|
for (const token of tokens) {
|
|
15
14
|
switch (token.type) {
|
|
16
15
|
case 'space':
|
|
17
|
-
// At the doc level, tabs at line start may be parsed
|
|
18
|
-
// white space rather than indentation.
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
// At the doc level, tabs at line start may be parsed
|
|
17
|
+
// as leading white space rather than indentation.
|
|
18
|
+
// In a flow collection, only the parser handles indent.
|
|
19
|
+
if (!flow &&
|
|
20
|
+
atNewline &&
|
|
21
|
+
indicator !== 'doc-start' &&
|
|
22
|
+
token.source[0] === '\t')
|
|
23
|
+
onError(token, 'TAB_AS_INDENT', 'Tabs are not allowed as indentation');
|
|
21
24
|
hasSpace = true;
|
|
22
25
|
break;
|
|
23
26
|
case 'comment': {
|
|
24
|
-
if (
|
|
25
|
-
onError(
|
|
27
|
+
if (ctx.options.strict && !hasSpace)
|
|
28
|
+
onError(token, 'COMMENT_SPACE', 'Comments must be separated from other tokens by white space characters');
|
|
26
29
|
const cb = token.source.substring(1);
|
|
27
|
-
if (!
|
|
30
|
+
if (!comment)
|
|
28
31
|
comment = cb;
|
|
29
32
|
else
|
|
30
|
-
comment +=
|
|
31
|
-
|
|
32
|
-
sep = '';
|
|
33
|
+
comment += commentSep + cb;
|
|
34
|
+
commentSep = '';
|
|
33
35
|
break;
|
|
34
36
|
}
|
|
35
37
|
case 'newline':
|
|
36
|
-
if (atNewline && !
|
|
38
|
+
if (atNewline && !comment)
|
|
37
39
|
spaceBefore = true;
|
|
38
40
|
atNewline = true;
|
|
39
41
|
hasNewline = true;
|
|
40
42
|
hasSpace = true;
|
|
41
|
-
|
|
43
|
+
commentSep += token.source;
|
|
42
44
|
break;
|
|
43
45
|
case 'anchor':
|
|
44
46
|
if (anchor)
|
|
45
|
-
onError(
|
|
46
|
-
anchor = token
|
|
47
|
+
onError(token, 'MULTIPLE_ANCHORS', 'A node can have at most one anchor');
|
|
48
|
+
anchor = token;
|
|
47
49
|
if (start === null)
|
|
48
|
-
start = offset
|
|
50
|
+
start = token.offset;
|
|
49
51
|
atNewline = false;
|
|
50
52
|
hasSpace = false;
|
|
51
53
|
break;
|
|
52
54
|
case 'tag': {
|
|
53
|
-
if (
|
|
54
|
-
onError(
|
|
55
|
-
|
|
56
|
-
if (tn)
|
|
57
|
-
tagName = tn;
|
|
55
|
+
if (tag)
|
|
56
|
+
onError(token, 'MULTIPLE_TAGS', 'A node can have at most one tag');
|
|
57
|
+
tag = token;
|
|
58
58
|
if (start === null)
|
|
59
|
-
start = offset
|
|
59
|
+
start = token.offset;
|
|
60
60
|
atNewline = false;
|
|
61
61
|
hasSpace = false;
|
|
62
62
|
break;
|
|
63
63
|
}
|
|
64
64
|
case indicator:
|
|
65
65
|
// Could here handle preceding comments differently
|
|
66
|
-
|
|
66
|
+
if (anchor || tag)
|
|
67
|
+
onError(token, 'BAD_PROP_ORDER', `Anchors and tags must be after the ${token.source} indicator`);
|
|
68
|
+
found = token;
|
|
67
69
|
atNewline = false;
|
|
68
70
|
hasSpace = false;
|
|
69
71
|
break;
|
|
72
|
+
case 'comma':
|
|
73
|
+
if (flow) {
|
|
74
|
+
if (comma)
|
|
75
|
+
onError(token, 'UNEXPECTED_TOKEN', `Unexpected , in ${flow}`);
|
|
76
|
+
comma = token;
|
|
77
|
+
atNewline = false;
|
|
78
|
+
hasSpace = false;
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
// else fallthrough
|
|
70
82
|
default:
|
|
71
|
-
onError(
|
|
83
|
+
onError(token, 'UNEXPECTED_TOKEN', `Unexpected ${token.type} token`);
|
|
72
84
|
atNewline = false;
|
|
73
85
|
hasSpace = false;
|
|
74
86
|
}
|
|
75
|
-
/* istanbul ignore else should not happen */
|
|
76
|
-
if (token.source)
|
|
77
|
-
length += token.source.length;
|
|
78
87
|
}
|
|
88
|
+
const last = tokens[tokens.length - 1];
|
|
89
|
+
const end = last ? last.offset + last.source.length : offset;
|
|
79
90
|
return {
|
|
91
|
+
comma,
|
|
80
92
|
found,
|
|
81
93
|
spaceBefore,
|
|
82
94
|
comment,
|
|
83
95
|
hasNewline,
|
|
84
96
|
anchor,
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
start: start !== null && start !== void 0 ? start :
|
|
97
|
+
tag,
|
|
98
|
+
end,
|
|
99
|
+
start: start !== null && start !== void 0 ? start : end
|
|
88
100
|
};
|
|
89
101
|
}
|
|
90
102
|
|
|
@@ -6,21 +6,24 @@ function containsNewline(key) {
|
|
|
6
6
|
case 'scalar':
|
|
7
7
|
case 'double-quoted-scalar':
|
|
8
8
|
case 'single-quoted-scalar':
|
|
9
|
-
|
|
9
|
+
if (key.source.includes('\n'))
|
|
10
|
+
return true;
|
|
11
|
+
if (key.end)
|
|
12
|
+
for (const st of key.end)
|
|
13
|
+
if (st.type === 'newline')
|
|
14
|
+
return true;
|
|
15
|
+
return false;
|
|
10
16
|
case 'flow-collection':
|
|
11
|
-
for (const
|
|
12
|
-
|
|
13
|
-
|
|
17
|
+
for (const it of key.items) {
|
|
18
|
+
for (const st of it.start)
|
|
19
|
+
if (st.type === 'newline')
|
|
14
20
|
return true;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
case 'single-quoted-scalar':
|
|
19
|
-
case 'flow-collection':
|
|
20
|
-
if (containsNewline(token))
|
|
21
|
+
if (it.sep)
|
|
22
|
+
for (const st of it.sep)
|
|
23
|
+
if (st.type === 'newline')
|
|
21
24
|
return true;
|
|
22
|
-
|
|
23
|
-
|
|
25
|
+
if (containsNewline(it.key) || containsNewline(it.value))
|
|
26
|
+
return true;
|
|
24
27
|
}
|
|
25
28
|
return false;
|
|
26
29
|
default:
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { Alias } from '../nodes/Alias.js';
|
|
2
2
|
import { isEmptyPath, collectionFromPath } from '../nodes/Collection.js';
|
|
3
|
-
import { NODE_TYPE, DOC, isCollection, isScalar
|
|
3
|
+
import { NODE_TYPE, DOC, isCollection, isScalar } from '../nodes/Node.js';
|
|
4
4
|
import { Pair } from '../nodes/Pair.js';
|
|
5
5
|
import { toJS } from '../nodes/toJS.js';
|
|
6
6
|
import { defaultOptions } from '../options.js';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
7
|
+
import { Schema } from '../schema/Schema.js';
|
|
8
|
+
import { stringify } from '../stringify/stringify.js';
|
|
9
|
+
import { stringifyDocument } from '../stringify/stringifyDocument.js';
|
|
10
|
+
import { anchorNames, findNewAnchor, createNodeAnchors } from './anchors.js';
|
|
11
11
|
import { applyReviver } from './applyReviver.js';
|
|
12
12
|
import { createNode } from './createNode.js';
|
|
13
13
|
import { Directives } from './directives.js';
|
|
@@ -23,7 +23,7 @@ class Document {
|
|
|
23
23
|
/** Warnings encountered during parsing. */
|
|
24
24
|
this.warnings = [];
|
|
25
25
|
Object.defineProperty(this, NODE_TYPE, { value: DOC });
|
|
26
|
-
let _replacer =
|
|
26
|
+
let _replacer = null;
|
|
27
27
|
if (typeof replacer === 'function' || Array.isArray(replacer)) {
|
|
28
28
|
_replacer = replacer;
|
|
29
29
|
}
|
|
@@ -33,7 +33,6 @@ class Document {
|
|
|
33
33
|
}
|
|
34
34
|
const opt = Object.assign({}, defaultOptions, options);
|
|
35
35
|
this.options = opt;
|
|
36
|
-
this.anchors = new Anchors(this.options.anchorPrefix);
|
|
37
36
|
let { version } = opt;
|
|
38
37
|
if (options === null || options === void 0 ? void 0 : options.directives) {
|
|
39
38
|
this.directives = options.directives.atDocument();
|
|
@@ -43,10 +42,11 @@ class Document {
|
|
|
43
42
|
else
|
|
44
43
|
this.directives = new Directives({ version });
|
|
45
44
|
this.setSchema(version, options);
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
if (value === undefined)
|
|
46
|
+
this.contents = null;
|
|
47
|
+
else {
|
|
48
|
+
this.contents = this.createNode(value, _replacer, options);
|
|
49
|
+
}
|
|
50
50
|
}
|
|
51
51
|
/** Adds a value to the document. */
|
|
52
52
|
add(value) {
|
|
@@ -59,48 +59,53 @@ class Document {
|
|
|
59
59
|
this.contents.addIn(path, value);
|
|
60
60
|
}
|
|
61
61
|
/**
|
|
62
|
-
*
|
|
63
|
-
*
|
|
62
|
+
* Create a new `Alias` node, ensuring that the target `node` has the required anchor.
|
|
63
|
+
*
|
|
64
|
+
* If `node` already has an anchor, `name` is ignored.
|
|
65
|
+
* Otherwise, the `node.anchor` value will be set to `name`,
|
|
66
|
+
* or if an anchor with that name is already present in the document,
|
|
67
|
+
* `name` will be used as a prefix for a new unique anchor.
|
|
68
|
+
* If `name` is undefined, the generated anchor will use 'a' as a prefix.
|
|
64
69
|
*/
|
|
65
|
-
|
|
66
|
-
if (
|
|
70
|
+
createAlias(node, name) {
|
|
71
|
+
if (!node.anchor) {
|
|
72
|
+
const prev = anchorNames(this);
|
|
73
|
+
node.anchor =
|
|
74
|
+
!name || prev.has(name) ? findNewAnchor(name || 'a', prev) : name;
|
|
75
|
+
}
|
|
76
|
+
return new Alias(node.anchor);
|
|
77
|
+
}
|
|
78
|
+
createNode(value, replacer, options) {
|
|
79
|
+
let _replacer = undefined;
|
|
80
|
+
if (typeof replacer === 'function') {
|
|
67
81
|
value = replacer.call({ '': value }, '', value);
|
|
82
|
+
_replacer = replacer;
|
|
83
|
+
}
|
|
68
84
|
else if (Array.isArray(replacer)) {
|
|
69
85
|
const keyToStr = (v) => typeof v === 'number' || v instanceof String || v instanceof Number;
|
|
70
86
|
const asStr = replacer.filter(keyToStr).map(String);
|
|
71
87
|
if (asStr.length > 0)
|
|
72
88
|
replacer = replacer.concat(asStr);
|
|
89
|
+
_replacer = replacer;
|
|
90
|
+
}
|
|
91
|
+
else if (options === undefined && replacer) {
|
|
92
|
+
options = replacer;
|
|
93
|
+
replacer = undefined;
|
|
73
94
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const aliasNodes = [];
|
|
95
|
+
const { anchorPrefix, flow, keepUndefined, onTagObj, tag } = options || {};
|
|
96
|
+
const { onAnchor, setAnchors, sourceObjects } = createNodeAnchors(this, anchorPrefix || 'a');
|
|
77
97
|
const ctx = {
|
|
78
|
-
keepUndefined,
|
|
79
|
-
|
|
80
|
-
// These get fixed later in createNode()
|
|
81
|
-
const alias = new Alias(source);
|
|
82
|
-
aliasNodes.push(alias);
|
|
83
|
-
return alias;
|
|
84
|
-
},
|
|
98
|
+
keepUndefined: keepUndefined !== null && keepUndefined !== void 0 ? keepUndefined : false,
|
|
99
|
+
onAnchor,
|
|
85
100
|
onTagObj,
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
101
|
+
replacer: _replacer,
|
|
102
|
+
schema: this.schema,
|
|
103
|
+
sourceObjects
|
|
89
104
|
};
|
|
90
105
|
const node = createNode(value, tag, ctx);
|
|
91
|
-
for (const alias of aliasNodes) {
|
|
92
|
-
// With circular references, the source node is only resolved after all of
|
|
93
|
-
// its child nodes are. This is why anchors are set only after all of the
|
|
94
|
-
// nodes have been created.
|
|
95
|
-
alias.source = alias.source.node;
|
|
96
|
-
let name = this.anchors.getName(alias.source);
|
|
97
|
-
if (!name) {
|
|
98
|
-
name = this.anchors.newName();
|
|
99
|
-
this.anchors.map[name] = alias.source;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
106
|
if (flow && isCollection(node))
|
|
103
107
|
node.flow = true;
|
|
108
|
+
setAnchors();
|
|
104
109
|
return node;
|
|
105
110
|
}
|
|
106
111
|
/**
|
|
@@ -108,8 +113,8 @@ class Document {
|
|
|
108
113
|
* recursively wrapping all values as `Scalar` or `Collection` nodes.
|
|
109
114
|
*/
|
|
110
115
|
createPair(key, value, options = {}) {
|
|
111
|
-
const k = this.createNode(key, options);
|
|
112
|
-
const v = this.createNode(value, options);
|
|
116
|
+
const k = this.createNode(key, null, options);
|
|
117
|
+
const v = this.createNode(value, null, options);
|
|
113
118
|
return new Pair(k, v);
|
|
114
119
|
}
|
|
115
120
|
/**
|
|
@@ -223,10 +228,8 @@ class Document {
|
|
|
223
228
|
}
|
|
224
229
|
// json & jsonArg are only used from toJSON()
|
|
225
230
|
toJS({ json, jsonArg, mapAsMap, maxAliasCount, onAnchor, reviver } = {}) {
|
|
226
|
-
const anchorNodes = Object.values(this.anchors.map).map(node => [node, { alias: [], aliasCount: 0, count: 1 }]);
|
|
227
|
-
const anchors = anchorNodes.length > 0 ? new Map(anchorNodes) : null;
|
|
228
231
|
const ctx = {
|
|
229
|
-
anchors,
|
|
232
|
+
anchors: new Map(),
|
|
230
233
|
doc: this,
|
|
231
234
|
keep: !json,
|
|
232
235
|
mapAsMap: mapAsMap === true,
|
|
@@ -235,8 +238,8 @@ class Document {
|
|
|
235
238
|
stringify
|
|
236
239
|
};
|
|
237
240
|
const res = toJS(this.contents, jsonArg || '', ctx);
|
|
238
|
-
if (typeof onAnchor === 'function'
|
|
239
|
-
for (const { count, res } of anchors.values())
|
|
241
|
+
if (typeof onAnchor === 'function')
|
|
242
|
+
for (const { count, res } of ctx.anchors.values())
|
|
240
243
|
onAnchor(res, count);
|
|
241
244
|
return typeof reviver === 'function'
|
|
242
245
|
? applyReviver(reviver, { '': res }, '', res)
|
|
@@ -260,59 +263,7 @@ class Document {
|
|
|
260
263
|
const s = JSON.stringify(options.indent);
|
|
261
264
|
throw new Error(`"indent" option must be a positive integer, not ${s}`);
|
|
262
265
|
}
|
|
263
|
-
|
|
264
|
-
let hasDirectives = options.directives === true;
|
|
265
|
-
if (options.directives !== false) {
|
|
266
|
-
const dir = this.directives.toString(this);
|
|
267
|
-
if (dir) {
|
|
268
|
-
lines.push(dir);
|
|
269
|
-
hasDirectives = true;
|
|
270
|
-
}
|
|
271
|
-
else if (this.directives.marker)
|
|
272
|
-
hasDirectives = true;
|
|
273
|
-
}
|
|
274
|
-
if (hasDirectives)
|
|
275
|
-
lines.push('---');
|
|
276
|
-
if (this.commentBefore) {
|
|
277
|
-
if (lines.length !== 1)
|
|
278
|
-
lines.unshift('');
|
|
279
|
-
lines.unshift(this.commentBefore.replace(/^/gm, '#'));
|
|
280
|
-
}
|
|
281
|
-
const ctx = createStringifyContext(this, options);
|
|
282
|
-
let chompKeep = false;
|
|
283
|
-
let contentComment = null;
|
|
284
|
-
if (this.contents) {
|
|
285
|
-
if (isNode(this.contents)) {
|
|
286
|
-
if (this.contents.spaceBefore && hasDirectives)
|
|
287
|
-
lines.push('');
|
|
288
|
-
if (this.contents.commentBefore)
|
|
289
|
-
lines.push(this.contents.commentBefore.replace(/^/gm, '#'));
|
|
290
|
-
// top-level block scalars need to be indented if followed by a comment
|
|
291
|
-
ctx.forceBlockIndent = !!this.comment;
|
|
292
|
-
contentComment = this.contents.comment;
|
|
293
|
-
}
|
|
294
|
-
const onChompKeep = contentComment ? undefined : () => (chompKeep = true);
|
|
295
|
-
let body = stringify(this.contents, ctx, () => (contentComment = null), onChompKeep);
|
|
296
|
-
if (contentComment)
|
|
297
|
-
body = addComment(body, '', contentComment);
|
|
298
|
-
if ((body[0] === '|' || body[0] === '>') &&
|
|
299
|
-
lines[lines.length - 1] === '---') {
|
|
300
|
-
// Top-level block scalars with a preceding doc marker ought to use the
|
|
301
|
-
// same line for their header.
|
|
302
|
-
lines[lines.length - 1] = `--- ${body}`;
|
|
303
|
-
}
|
|
304
|
-
else
|
|
305
|
-
lines.push(body);
|
|
306
|
-
}
|
|
307
|
-
else {
|
|
308
|
-
lines.push(stringify(this.contents, ctx));
|
|
309
|
-
}
|
|
310
|
-
if (this.comment) {
|
|
311
|
-
if ((!chompKeep || contentComment) && lines[lines.length - 1] !== '')
|
|
312
|
-
lines.push('');
|
|
313
|
-
lines.push(this.comment.replace(/^/gm, '#'));
|
|
314
|
-
}
|
|
315
|
-
return lines.join('\n') + '\n';
|
|
266
|
+
return stringifyDocument(this, options);
|
|
316
267
|
}
|
|
317
268
|
}
|
|
318
269
|
function assertCollection(contents) {
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { isScalar, isCollection } from '../nodes/Node.js';
|
|
2
|
+
import { visit } from '../visit.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Verify that the input string is a valid anchor.
|
|
6
|
+
*
|
|
7
|
+
* Will throw on errors.
|
|
8
|
+
*/
|
|
9
|
+
function anchorIsValid(anchor) {
|
|
10
|
+
if (/[\x00-\x19\s,[\]{}]/.test(anchor)) {
|
|
11
|
+
const sa = JSON.stringify(anchor);
|
|
12
|
+
const msg = `Anchor must not contain whitespace or control characters: ${sa}`;
|
|
13
|
+
throw new Error(msg);
|
|
14
|
+
}
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
function anchorNames(root) {
|
|
18
|
+
const anchors = new Set();
|
|
19
|
+
visit(root, {
|
|
20
|
+
Value(_key, node) {
|
|
21
|
+
if (node.anchor)
|
|
22
|
+
anchors.add(node.anchor);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
return anchors;
|
|
26
|
+
}
|
|
27
|
+
/** Find a new anchor name with the given `prefix` and a one-indexed suffix. */
|
|
28
|
+
function findNewAnchor(prefix, exclude) {
|
|
29
|
+
for (let i = 1; true; ++i) {
|
|
30
|
+
const name = `${prefix}${i}`;
|
|
31
|
+
if (!exclude.has(name))
|
|
32
|
+
return name;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function createNodeAnchors(doc, prefix) {
|
|
36
|
+
const aliasObjects = [];
|
|
37
|
+
const sourceObjects = new Map();
|
|
38
|
+
let prevAnchors = null;
|
|
39
|
+
return {
|
|
40
|
+
onAnchor(source) {
|
|
41
|
+
aliasObjects.push(source);
|
|
42
|
+
if (!prevAnchors)
|
|
43
|
+
prevAnchors = anchorNames(doc);
|
|
44
|
+
const anchor = findNewAnchor(prefix, prevAnchors);
|
|
45
|
+
prevAnchors.add(anchor);
|
|
46
|
+
return anchor;
|
|
47
|
+
},
|
|
48
|
+
/**
|
|
49
|
+
* With circular references, the source node is only resolved after all
|
|
50
|
+
* of its child nodes are. This is why anchors are set only after all of
|
|
51
|
+
* the nodes have been created.
|
|
52
|
+
*/
|
|
53
|
+
setAnchors() {
|
|
54
|
+
for (const source of aliasObjects) {
|
|
55
|
+
const ref = sourceObjects.get(source);
|
|
56
|
+
if (typeof ref === 'object' &&
|
|
57
|
+
ref.anchor &&
|
|
58
|
+
(isScalar(ref.node) || isCollection(ref.node))) {
|
|
59
|
+
ref.node.anchor = ref.anchor;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
const error = new Error('Failed to resolve repeated object (this should not happen)');
|
|
63
|
+
error.source = source;
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
sourceObjects
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export { anchorIsValid, anchorNames, createNodeAnchors, findNewAnchor };
|