yaml 2.0.0-4 → 2.0.0-8
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 +27 -17
- package/browser/dist/compose/compose-scalar.js +21 -23
- package/browser/dist/compose/composer.js +108 -78
- package/browser/dist/compose/resolve-block-map.js +41 -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 +7 -8
- package/browser/dist/compose/resolve-flow-collection.js +158 -199
- package/browser/dist/compose/resolve-flow-scalar.js +62 -26
- package/browser/dist/compose/resolve-props.js +72 -37
- package/browser/dist/compose/util-contains-newline.js +15 -12
- package/browser/dist/compose/util-map-includes.js +17 -0
- package/browser/dist/doc/Document.js +74 -99
- package/browser/dist/doc/anchors.js +72 -0
- package/browser/dist/doc/createNode.js +35 -19
- package/browser/dist/doc/directives.js +5 -0
- 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 +23 -92
- package/browser/dist/nodes/Node.js +9 -1
- package/browser/dist/nodes/Pair.js +16 -231
- 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 +1 -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 +149 -125
- package/browser/dist/parse/parser.js +272 -196
- package/browser/dist/public-api.js +11 -14
- package/browser/dist/schema/Schema.js +28 -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/stringify.js +8 -6
- package/browser/dist/stringify/stringifyCollection.js +122 -0
- package/browser/dist/stringify/stringifyComment.js +14 -0
- package/browser/dist/stringify/stringifyDocument.js +64 -0
- package/browser/dist/stringify/stringifyPair.js +111 -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 +27 -17
- package/dist/compose/compose-scalar.d.ts +4 -3
- package/dist/compose/compose-scalar.js +20 -22
- package/dist/compose/composer.d.ts +28 -23
- package/dist/compose/composer.js +109 -79
- package/dist/compose/resolve-block-map.d.ts +5 -4
- package/dist/compose/resolve-block-map.js +41 -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 +7 -8
- package/dist/compose/resolve-flow-collection.d.ts +4 -5
- package/dist/compose/resolve-flow-collection.js +157 -198
- package/dist/compose/resolve-flow-scalar.d.ts +5 -3
- package/dist/compose/resolve-flow-scalar.js +62 -26
- package/dist/compose/resolve-props.d.ts +16 -10
- package/dist/compose/resolve-props.js +72 -37
- 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/compose/util-map-includes.d.ts +4 -0
- package/dist/compose/util-map-includes.js +19 -0
- package/dist/doc/Document.d.ts +35 -15
- package/dist/doc/Document.js +72 -97
- package/dist/doc/anchors.d.ts +24 -0
- package/dist/doc/anchors.js +77 -0
- package/dist/doc/createNode.d.ts +10 -11
- package/dist/doc/createNode.js +34 -18
- package/dist/doc/directives.d.ts +1 -0
- package/dist/doc/directives.js +5 -0
- 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 +9 -17
- package/dist/nodes/Collection.js +22 -91
- package/dist/nodes/Node.d.ts +10 -4
- package/dist/nodes/Node.js +9 -0
- package/dist/nodes/Pair.d.ts +10 -13
- package/dist/nodes/Pair.js +15 -230
- 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 +41 -25
- package/dist/options.js +1 -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 +7 -14
- package/dist/parse/lexer.js +150 -126
- package/dist/parse/parser.d.ts +31 -24
- package/dist/parse/parser.js +274 -198
- package/dist/public-api.d.ts +7 -7
- package/dist/public-api.js +11 -14
- package/dist/{doc → schema}/Schema.d.ts +6 -3
- package/dist/schema/Schema.js +30 -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/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 +124 -0
- package/dist/stringify/stringifyComment.d.ts +2 -0
- package/dist/stringify/stringifyComment.js +17 -0
- package/dist/stringify/stringifyDocument.d.ts +3 -0
- package/dist/stringify/stringifyDocument.js +66 -0
- package/dist/stringify/stringifyPair.d.ts +3 -0
- package/dist/stringify/stringifyPair.js +113 -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 +9 -8
- 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/stringify/addComment.js +0 -17
- 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/stringify/addComment.d.ts +0 -2
- package/dist/stringify/addComment.js +0 -20
- 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,90 +1,125 @@
|
|
|
1
|
-
function resolveProps(
|
|
2
|
-
let length = 0;
|
|
1
|
+
function resolveProps(tokens, { flow, indicator, next, 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 anchor =
|
|
11
|
-
let
|
|
8
|
+
let reqSpace = false;
|
|
9
|
+
let anchor = null;
|
|
10
|
+
let tag = null;
|
|
11
|
+
let comma = null;
|
|
12
12
|
let found = null;
|
|
13
13
|
let start = null;
|
|
14
14
|
for (const token of tokens) {
|
|
15
|
+
if (reqSpace) {
|
|
16
|
+
if (token.type !== 'space' &&
|
|
17
|
+
token.type !== 'newline' &&
|
|
18
|
+
token.type !== 'comma')
|
|
19
|
+
onError(token.offset, 'MISSING_CHAR', 'Tags and anchors must be separated from the next token by white space');
|
|
20
|
+
reqSpace = false;
|
|
21
|
+
}
|
|
15
22
|
switch (token.type) {
|
|
16
23
|
case 'space':
|
|
17
|
-
// At the doc level, tabs at line start may be parsed
|
|
18
|
-
// white space rather than indentation.
|
|
19
|
-
|
|
20
|
-
|
|
24
|
+
// At the doc level, tabs at line start may be parsed
|
|
25
|
+
// as leading white space rather than indentation.
|
|
26
|
+
// In a flow collection, only the parser handles indent.
|
|
27
|
+
if (!flow &&
|
|
28
|
+
atNewline &&
|
|
29
|
+
indicator !== 'doc-start' &&
|
|
30
|
+
token.source[0] === '\t')
|
|
31
|
+
onError(token, 'TAB_AS_INDENT', 'Tabs are not allowed as indentation');
|
|
21
32
|
hasSpace = true;
|
|
22
33
|
break;
|
|
23
34
|
case 'comment': {
|
|
24
|
-
if (
|
|
25
|
-
onError(
|
|
26
|
-
const cb = token.source.substring(1);
|
|
27
|
-
if (!
|
|
35
|
+
if (!hasSpace)
|
|
36
|
+
onError(token, 'MISSING_CHAR', 'Comments must be separated from other tokens by white space characters');
|
|
37
|
+
const cb = token.source.substring(1) || ' ';
|
|
38
|
+
if (!comment)
|
|
28
39
|
comment = cb;
|
|
29
40
|
else
|
|
30
|
-
comment +=
|
|
31
|
-
|
|
32
|
-
|
|
41
|
+
comment += commentSep + cb;
|
|
42
|
+
commentSep = '';
|
|
43
|
+
atNewline = false;
|
|
33
44
|
break;
|
|
34
45
|
}
|
|
35
46
|
case 'newline':
|
|
36
|
-
if (atNewline
|
|
37
|
-
|
|
47
|
+
if (atNewline) {
|
|
48
|
+
if (comment)
|
|
49
|
+
comment += token.source;
|
|
50
|
+
else
|
|
51
|
+
spaceBefore = true;
|
|
52
|
+
}
|
|
53
|
+
else
|
|
54
|
+
commentSep += token.source;
|
|
38
55
|
atNewline = true;
|
|
39
56
|
hasNewline = true;
|
|
40
57
|
hasSpace = true;
|
|
41
|
-
sep += token.source;
|
|
42
58
|
break;
|
|
43
59
|
case 'anchor':
|
|
44
60
|
if (anchor)
|
|
45
|
-
onError(
|
|
46
|
-
anchor = token
|
|
61
|
+
onError(token, 'MULTIPLE_ANCHORS', 'A node can have at most one anchor');
|
|
62
|
+
anchor = token;
|
|
47
63
|
if (start === null)
|
|
48
|
-
start = offset
|
|
64
|
+
start = token.offset;
|
|
49
65
|
atNewline = false;
|
|
50
66
|
hasSpace = false;
|
|
67
|
+
reqSpace = true;
|
|
51
68
|
break;
|
|
52
69
|
case 'tag': {
|
|
53
|
-
if (
|
|
54
|
-
onError(
|
|
55
|
-
|
|
56
|
-
if (tn)
|
|
57
|
-
tagName = tn;
|
|
70
|
+
if (tag)
|
|
71
|
+
onError(token, 'MULTIPLE_TAGS', 'A node can have at most one tag');
|
|
72
|
+
tag = token;
|
|
58
73
|
if (start === null)
|
|
59
|
-
start = offset
|
|
74
|
+
start = token.offset;
|
|
60
75
|
atNewline = false;
|
|
61
76
|
hasSpace = false;
|
|
77
|
+
reqSpace = true;
|
|
62
78
|
break;
|
|
63
79
|
}
|
|
64
80
|
case indicator:
|
|
65
81
|
// Could here handle preceding comments differently
|
|
66
|
-
|
|
82
|
+
if (anchor || tag)
|
|
83
|
+
onError(token, 'BAD_PROP_ORDER', `Anchors and tags must be after the ${token.source} indicator`);
|
|
84
|
+
found = token;
|
|
67
85
|
atNewline = false;
|
|
68
86
|
hasSpace = false;
|
|
69
87
|
break;
|
|
88
|
+
case 'comma':
|
|
89
|
+
if (flow) {
|
|
90
|
+
if (comma)
|
|
91
|
+
onError(token, 'UNEXPECTED_TOKEN', `Unexpected , in ${flow}`);
|
|
92
|
+
comma = token;
|
|
93
|
+
atNewline = false;
|
|
94
|
+
hasSpace = false;
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
// else fallthrough
|
|
70
98
|
default:
|
|
71
|
-
onError(
|
|
99
|
+
onError(token, 'UNEXPECTED_TOKEN', `Unexpected ${token.type} token`);
|
|
72
100
|
atNewline = false;
|
|
73
101
|
hasSpace = false;
|
|
74
102
|
}
|
|
75
|
-
/* istanbul ignore else should not happen */
|
|
76
|
-
if (token.source)
|
|
77
|
-
length += token.source.length;
|
|
78
103
|
}
|
|
104
|
+
const last = tokens[tokens.length - 1];
|
|
105
|
+
const end = last ? last.offset + last.source.length : offset;
|
|
106
|
+
if (reqSpace &&
|
|
107
|
+
next &&
|
|
108
|
+
next.type !== 'space' &&
|
|
109
|
+
next.type !== 'newline' &&
|
|
110
|
+
next.type !== 'comma' &&
|
|
111
|
+
(next.type !== 'scalar' || next.source !== ''))
|
|
112
|
+
onError(next.offset, 'MISSING_CHAR', 'Tags and anchors must be separated from the next token by white space');
|
|
79
113
|
return {
|
|
114
|
+
comma,
|
|
80
115
|
found,
|
|
81
116
|
spaceBefore,
|
|
82
117
|
comment,
|
|
83
118
|
hasNewline,
|
|
84
119
|
anchor,
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
start: start !== null && start !== void 0 ? start :
|
|
120
|
+
tag,
|
|
121
|
+
end,
|
|
122
|
+
start: start !== null && start !== void 0 ? start : end
|
|
88
123
|
};
|
|
89
124
|
}
|
|
90
125
|
|
|
@@ -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:
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { isScalar } from '../nodes/Node.js';
|
|
2
|
+
|
|
3
|
+
function mapIncludes(ctx, items, search) {
|
|
4
|
+
const { uniqueKeys } = ctx.options;
|
|
5
|
+
if (uniqueKeys === false)
|
|
6
|
+
return false;
|
|
7
|
+
const isEqual = typeof uniqueKeys === 'function'
|
|
8
|
+
? uniqueKeys
|
|
9
|
+
: (a, b) => a === b ||
|
|
10
|
+
(isScalar(a) &&
|
|
11
|
+
isScalar(b) &&
|
|
12
|
+
a.value === b.value &&
|
|
13
|
+
!(a.value === '<<' && ctx.schema.merge));
|
|
14
|
+
return items.some(pair => isEqual(pair.key, search));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export { mapIncludes };
|
|
@@ -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, isNode, 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,34 @@ 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
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Create a deep copy of this Document and its contents.
|
|
53
|
+
*
|
|
54
|
+
* Custom Node values that inherit from `Object` still refer to their original instances.
|
|
55
|
+
*/
|
|
56
|
+
clone() {
|
|
57
|
+
const copy = Object.create(Document.prototype, {
|
|
58
|
+
[NODE_TYPE]: { value: DOC }
|
|
59
|
+
});
|
|
60
|
+
copy.commentBefore = this.commentBefore;
|
|
61
|
+
copy.comment = this.comment;
|
|
62
|
+
copy.errors = this.errors.slice();
|
|
63
|
+
copy.warnings = this.warnings.slice();
|
|
64
|
+
copy.options = Object.assign({}, this.options);
|
|
65
|
+
copy.directives = this.directives.clone();
|
|
66
|
+
copy.schema = this.schema.clone();
|
|
67
|
+
copy.contents = isNode(this.contents)
|
|
68
|
+
? this.contents.clone(copy.schema)
|
|
69
|
+
: this.contents;
|
|
70
|
+
if (this.range)
|
|
71
|
+
copy.range = this.range.slice();
|
|
72
|
+
return copy;
|
|
50
73
|
}
|
|
51
74
|
/** Adds a value to the document. */
|
|
52
75
|
add(value) {
|
|
@@ -59,48 +82,54 @@ class Document {
|
|
|
59
82
|
this.contents.addIn(path, value);
|
|
60
83
|
}
|
|
61
84
|
/**
|
|
62
|
-
*
|
|
63
|
-
*
|
|
85
|
+
* Create a new `Alias` node, ensuring that the target `node` has the required anchor.
|
|
86
|
+
*
|
|
87
|
+
* If `node` already has an anchor, `name` is ignored.
|
|
88
|
+
* Otherwise, the `node.anchor` value will be set to `name`,
|
|
89
|
+
* or if an anchor with that name is already present in the document,
|
|
90
|
+
* `name` will be used as a prefix for a new unique anchor.
|
|
91
|
+
* If `name` is undefined, the generated anchor will use 'a' as a prefix.
|
|
64
92
|
*/
|
|
65
|
-
|
|
66
|
-
if (
|
|
93
|
+
createAlias(node, name) {
|
|
94
|
+
if (!node.anchor) {
|
|
95
|
+
const prev = anchorNames(this);
|
|
96
|
+
node.anchor =
|
|
97
|
+
!name || prev.has(name) ? findNewAnchor(name || 'a', prev) : name;
|
|
98
|
+
}
|
|
99
|
+
return new Alias(node.anchor);
|
|
100
|
+
}
|
|
101
|
+
createNode(value, replacer, options) {
|
|
102
|
+
let _replacer = undefined;
|
|
103
|
+
if (typeof replacer === 'function') {
|
|
67
104
|
value = replacer.call({ '': value }, '', value);
|
|
105
|
+
_replacer = replacer;
|
|
106
|
+
}
|
|
68
107
|
else if (Array.isArray(replacer)) {
|
|
69
108
|
const keyToStr = (v) => typeof v === 'number' || v instanceof String || v instanceof Number;
|
|
70
109
|
const asStr = replacer.filter(keyToStr).map(String);
|
|
71
110
|
if (asStr.length > 0)
|
|
72
111
|
replacer = replacer.concat(asStr);
|
|
112
|
+
_replacer = replacer;
|
|
73
113
|
}
|
|
74
|
-
if (
|
|
75
|
-
|
|
76
|
-
|
|
114
|
+
else if (options === undefined && replacer) {
|
|
115
|
+
options = replacer;
|
|
116
|
+
replacer = undefined;
|
|
117
|
+
}
|
|
118
|
+
const { aliasDuplicateObjects, anchorPrefix, flow, keepUndefined, onTagObj, tag } = options || {};
|
|
119
|
+
const { onAnchor, setAnchors, sourceObjects } = createNodeAnchors(this, anchorPrefix || 'a');
|
|
77
120
|
const ctx = {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const alias = new Alias(source);
|
|
82
|
-
aliasNodes.push(alias);
|
|
83
|
-
return alias;
|
|
84
|
-
},
|
|
121
|
+
aliasDuplicateObjects: aliasDuplicateObjects !== null && aliasDuplicateObjects !== void 0 ? aliasDuplicateObjects : true,
|
|
122
|
+
keepUndefined: keepUndefined !== null && keepUndefined !== void 0 ? keepUndefined : false,
|
|
123
|
+
onAnchor,
|
|
85
124
|
onTagObj,
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
125
|
+
replacer: _replacer,
|
|
126
|
+
schema: this.schema,
|
|
127
|
+
sourceObjects
|
|
89
128
|
};
|
|
90
129
|
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
130
|
if (flow && isCollection(node))
|
|
103
131
|
node.flow = true;
|
|
132
|
+
setAnchors();
|
|
104
133
|
return node;
|
|
105
134
|
}
|
|
106
135
|
/**
|
|
@@ -108,8 +137,8 @@ class Document {
|
|
|
108
137
|
* recursively wrapping all values as `Scalar` or `Collection` nodes.
|
|
109
138
|
*/
|
|
110
139
|
createPair(key, value, options = {}) {
|
|
111
|
-
const k = this.createNode(key, options);
|
|
112
|
-
const v = this.createNode(value, options);
|
|
140
|
+
const k = this.createNode(key, null, options);
|
|
141
|
+
const v = this.createNode(value, null, options);
|
|
113
142
|
return new Pair(k, v);
|
|
114
143
|
}
|
|
115
144
|
/**
|
|
@@ -223,10 +252,8 @@ class Document {
|
|
|
223
252
|
}
|
|
224
253
|
// json & jsonArg are only used from toJSON()
|
|
225
254
|
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
255
|
const ctx = {
|
|
229
|
-
anchors,
|
|
256
|
+
anchors: new Map(),
|
|
230
257
|
doc: this,
|
|
231
258
|
keep: !json,
|
|
232
259
|
mapAsMap: mapAsMap === true,
|
|
@@ -235,8 +262,8 @@ class Document {
|
|
|
235
262
|
stringify
|
|
236
263
|
};
|
|
237
264
|
const res = toJS(this.contents, jsonArg || '', ctx);
|
|
238
|
-
if (typeof onAnchor === 'function'
|
|
239
|
-
for (const { count, res } of anchors.values())
|
|
265
|
+
if (typeof onAnchor === 'function')
|
|
266
|
+
for (const { count, res } of ctx.anchors.values())
|
|
240
267
|
onAnchor(res, count);
|
|
241
268
|
return typeof reviver === 'function'
|
|
242
269
|
? applyReviver(reviver, { '': res }, '', res)
|
|
@@ -260,59 +287,7 @@ class Document {
|
|
|
260
287
|
const s = JSON.stringify(options.indent);
|
|
261
288
|
throw new Error(`"indent" option must be a positive integer, not ${s}`);
|
|
262
289
|
}
|
|
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';
|
|
290
|
+
return stringifyDocument(this, options);
|
|
316
291
|
}
|
|
317
292
|
}
|
|
318
293
|
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 };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Alias } from '../nodes/Alias.js';
|
|
2
|
+
import { isNode, isPair, MAP, SEQ, isDocument } from '../nodes/Node.js';
|
|
2
3
|
import { Scalar } from '../nodes/Scalar.js';
|
|
3
4
|
|
|
4
5
|
const defaultTagPrefix = 'tag:yaml.org,2002:';
|
|
@@ -14,10 +15,12 @@ function findTagObject(value, tagName, tags) {
|
|
|
14
15
|
}
|
|
15
16
|
function createNode(value, tagName, ctx) {
|
|
16
17
|
var _a, _b;
|
|
18
|
+
if (isDocument(value))
|
|
19
|
+
value = value.contents;
|
|
17
20
|
if (isNode(value))
|
|
18
21
|
return value;
|
|
19
22
|
if (isPair(value)) {
|
|
20
|
-
const map = (_b = (_a = ctx.schema
|
|
23
|
+
const map = (_b = (_a = ctx.schema[MAP]).createNode) === null || _b === void 0 ? void 0 : _b.call(_a, ctx.schema, null, ctx);
|
|
21
24
|
map.items.push(value);
|
|
22
25
|
return map;
|
|
23
26
|
}
|
|
@@ -29,39 +32,52 @@ function createNode(value, tagName, ctx) {
|
|
|
29
32
|
// https://tc39.es/ecma262/#sec-serializejsonproperty
|
|
30
33
|
value = value.valueOf();
|
|
31
34
|
}
|
|
32
|
-
const {
|
|
33
|
-
|
|
35
|
+
const { aliasDuplicateObjects, onAnchor, onTagObj, schema, sourceObjects } = ctx;
|
|
36
|
+
// Detect duplicate references to the same object & use Alias nodes for all
|
|
37
|
+
// after first. The `ref` wrapper allows for circular references to resolve.
|
|
38
|
+
let ref = undefined;
|
|
39
|
+
if (aliasDuplicateObjects && value && typeof value === 'object') {
|
|
40
|
+
ref = sourceObjects.get(value);
|
|
41
|
+
if (ref) {
|
|
42
|
+
if (!ref.anchor)
|
|
43
|
+
ref.anchor = onAnchor(value);
|
|
44
|
+
return new Alias(ref.anchor);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
ref = { anchor: null, node: null };
|
|
48
|
+
sourceObjects.set(value, ref);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
34
51
|
if (tagName && tagName.startsWith('!!'))
|
|
35
52
|
tagName = defaultTagPrefix + tagName.slice(2);
|
|
36
|
-
let tagObj = findTagObject(value, tagName, tags);
|
|
53
|
+
let tagObj = findTagObject(value, tagName, schema.tags);
|
|
37
54
|
if (!tagObj) {
|
|
38
55
|
if (value && typeof value.toJSON === 'function')
|
|
39
56
|
value = value.toJSON();
|
|
40
|
-
if (!value || typeof value !== 'object')
|
|
41
|
-
|
|
57
|
+
if (!value || typeof value !== 'object') {
|
|
58
|
+
const node = new Scalar(value);
|
|
59
|
+
if (ref)
|
|
60
|
+
ref.node = node;
|
|
61
|
+
return node;
|
|
62
|
+
}
|
|
42
63
|
tagObj =
|
|
43
|
-
value instanceof Map
|
|
64
|
+
value instanceof Map
|
|
65
|
+
? schema[MAP]
|
|
66
|
+
: Symbol.iterator in Object(value)
|
|
67
|
+
? schema[SEQ]
|
|
68
|
+
: schema[MAP];
|
|
44
69
|
}
|
|
45
70
|
if (onTagObj) {
|
|
46
71
|
onTagObj(tagObj);
|
|
47
72
|
delete ctx.onTagObj;
|
|
48
73
|
}
|
|
49
|
-
// Detect duplicate references to the same object & use Alias nodes for all
|
|
50
|
-
// after first. The `ref` wrapper allows for circular references to resolve.
|
|
51
|
-
const ref = { value: undefined, node: undefined };
|
|
52
|
-
if (value && typeof value === 'object') {
|
|
53
|
-
const prev = prevObjects.get(value);
|
|
54
|
-
if (prev)
|
|
55
|
-
return onAlias(prev);
|
|
56
|
-
ref.value = value;
|
|
57
|
-
prevObjects.set(value, ref);
|
|
58
|
-
}
|
|
59
74
|
const node = (tagObj === null || tagObj === void 0 ? void 0 : tagObj.createNode)
|
|
60
75
|
? tagObj.createNode(ctx.schema, value, ctx)
|
|
61
76
|
: new Scalar(value);
|
|
62
77
|
if (tagName)
|
|
63
78
|
node.tag = tagName;
|
|
64
|
-
ref
|
|
79
|
+
if (ref)
|
|
80
|
+
ref.node = node;
|
|
65
81
|
return node;
|
|
66
82
|
}
|
|
67
83
|
|
|
@@ -20,6 +20,11 @@ class Directives {
|
|
|
20
20
|
this.yaml = Object.assign({}, Directives.defaultYaml, yaml);
|
|
21
21
|
this.tags = Object.assign({}, Directives.defaultTags, tags);
|
|
22
22
|
}
|
|
23
|
+
clone() {
|
|
24
|
+
const copy = new Directives(this.yaml, this.tags);
|
|
25
|
+
copy.marker = this.marker;
|
|
26
|
+
return copy;
|
|
27
|
+
}
|
|
23
28
|
/**
|
|
24
29
|
* During parsing, get a Directives instance for the current document and
|
|
25
30
|
* update the stream state according to the current version's spec.
|