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
package/browser/dist/errors.js
CHANGED
|
@@ -1,28 +1,27 @@
|
|
|
1
1
|
class YAMLError extends Error {
|
|
2
|
-
constructor(name,
|
|
3
|
-
if (!message)
|
|
4
|
-
throw new Error(`Invalid arguments for new ${name}`);
|
|
2
|
+
constructor(name, pos, code, message) {
|
|
5
3
|
super();
|
|
6
4
|
this.name = name;
|
|
5
|
+
this.code = code;
|
|
7
6
|
this.message = message;
|
|
8
|
-
this.
|
|
7
|
+
this.pos = pos;
|
|
9
8
|
}
|
|
10
9
|
}
|
|
11
10
|
class YAMLParseError extends YAMLError {
|
|
12
|
-
constructor(
|
|
13
|
-
super('YAMLParseError',
|
|
11
|
+
constructor(pos, code, message) {
|
|
12
|
+
super('YAMLParseError', pos, code, message);
|
|
14
13
|
}
|
|
15
14
|
}
|
|
16
15
|
class YAMLWarning extends YAMLError {
|
|
17
|
-
constructor(
|
|
18
|
-
super('YAMLWarning',
|
|
16
|
+
constructor(pos, code, message) {
|
|
17
|
+
super('YAMLWarning', pos, code, message);
|
|
19
18
|
}
|
|
20
19
|
}
|
|
21
20
|
const prettifyError = (src, lc) => (error) => {
|
|
22
|
-
if (error.
|
|
21
|
+
if (error.pos[0] === -1)
|
|
23
22
|
return;
|
|
24
|
-
error.linePos = lc.linePos(
|
|
25
|
-
const { line, col } = error.linePos;
|
|
23
|
+
error.linePos = error.pos.map(pos => lc.linePos(pos));
|
|
24
|
+
const { line, col } = error.linePos[0];
|
|
26
25
|
error.message += ` at line ${line}, column ${col}`;
|
|
27
26
|
let ci = col - 1;
|
|
28
27
|
let lineStr = src
|
|
@@ -45,7 +44,12 @@ const prettifyError = (src, lc) => (error) => {
|
|
|
45
44
|
lineStr = prev + lineStr;
|
|
46
45
|
}
|
|
47
46
|
if (/[^ ]/.test(lineStr)) {
|
|
48
|
-
|
|
47
|
+
let count = 1;
|
|
48
|
+
const end = error.linePos[1];
|
|
49
|
+
if (end && end.line === line && end.col > col) {
|
|
50
|
+
count = Math.min(end.col - col, 80 - ci);
|
|
51
|
+
}
|
|
52
|
+
const pointer = ' '.repeat(ci) + '^'.repeat(count);
|
|
49
53
|
error.message += `:\n\n${lineStr}\n${pointer}\n`;
|
|
50
54
|
}
|
|
51
55
|
};
|
package/browser/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { Composer } from './compose/composer.js';
|
|
2
2
|
export { Document } from './doc/Document.js';
|
|
3
|
-
export { Schema } from './
|
|
3
|
+
export { Schema } from './schema/Schema.js';
|
|
4
4
|
export { YAMLError, YAMLParseError, YAMLWarning } from './errors.js';
|
|
5
5
|
export { Alias } from './nodes/Alias.js';
|
|
6
6
|
export { isAlias, isCollection, isDocument, isMap, isNode, isPair, isScalar, isSeq } from './nodes/Node.js';
|
|
@@ -9,10 +9,10 @@ export { Scalar } from './nodes/Scalar.js';
|
|
|
9
9
|
export { YAMLMap } from './nodes/YAMLMap.js';
|
|
10
10
|
export { YAMLSeq } from './nodes/YAMLSeq.js';
|
|
11
11
|
export { defaultOptions } from './options.js';
|
|
12
|
+
import * as cst from './parse/cst.js';
|
|
13
|
+
export { cst as CST };
|
|
12
14
|
export { Lexer } from './parse/lexer.js';
|
|
13
15
|
export { LineCounter } from './parse/line-counter.js';
|
|
14
16
|
export { Parser } from './parse/parser.js';
|
|
15
|
-
import * as tokens from './parse/tokens.js';
|
|
16
|
-
export { tokens };
|
|
17
17
|
export { parse, parseAllDocuments, parseDocument, stringify } from './public-api.js';
|
|
18
18
|
export { visit } from './visit.js';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { anchorIsValid } from '../doc/anchors.js';
|
|
2
|
+
import { visit } from '../visit.js';
|
|
1
3
|
import { NodeBase, ALIAS, isAlias, isCollection, isPair } from './Node.js';
|
|
2
|
-
import { toJS } from './toJS.js';
|
|
3
4
|
|
|
4
5
|
class Alias extends NodeBase {
|
|
5
6
|
constructor(source) {
|
|
@@ -11,58 +12,80 @@ class Alias extends NodeBase {
|
|
|
11
12
|
}
|
|
12
13
|
});
|
|
13
14
|
}
|
|
14
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Resolve the value of this alias within `doc`, finding the last
|
|
17
|
+
* instance of the `source` anchor before this node.
|
|
18
|
+
*/
|
|
19
|
+
resolve(doc) {
|
|
20
|
+
let found = undefined;
|
|
21
|
+
visit(doc, {
|
|
22
|
+
Node: (_key, node) => {
|
|
23
|
+
if (node === this)
|
|
24
|
+
return visit.BREAK;
|
|
25
|
+
if (node.anchor === this.source)
|
|
26
|
+
found = node;
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
return found;
|
|
30
|
+
}
|
|
31
|
+
toJSON(_arg, ctx) {
|
|
15
32
|
if (!ctx)
|
|
16
|
-
return
|
|
17
|
-
const { anchors, maxAliasCount } = ctx;
|
|
18
|
-
const
|
|
33
|
+
return { source: this.source };
|
|
34
|
+
const { anchors, doc, maxAliasCount } = ctx;
|
|
35
|
+
const source = this.resolve(doc);
|
|
36
|
+
if (!source) {
|
|
37
|
+
const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`;
|
|
38
|
+
throw new ReferenceError(msg);
|
|
39
|
+
}
|
|
40
|
+
const data = anchors.get(source);
|
|
19
41
|
/* istanbul ignore if */
|
|
20
|
-
if (!
|
|
42
|
+
if (!data || data.res === undefined) {
|
|
21
43
|
const msg = 'This should not happen: Alias anchor was not resolved?';
|
|
22
44
|
throw new ReferenceError(msg);
|
|
23
45
|
}
|
|
24
46
|
if (maxAliasCount >= 0) {
|
|
25
|
-
|
|
26
|
-
if (
|
|
27
|
-
|
|
28
|
-
if (
|
|
47
|
+
data.count += 1;
|
|
48
|
+
if (data.aliasCount === 0)
|
|
49
|
+
data.aliasCount = getAliasCount(doc, source, anchors);
|
|
50
|
+
if (data.count * data.aliasCount > maxAliasCount) {
|
|
29
51
|
const msg = 'Excessive alias count indicates a resource exhaustion attack';
|
|
30
52
|
throw new ReferenceError(msg);
|
|
31
53
|
}
|
|
32
54
|
}
|
|
33
|
-
return
|
|
55
|
+
return data.res;
|
|
34
56
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
57
|
+
toString(ctx, _onComment, _onChompKeep) {
|
|
58
|
+
const src = `*${this.source}`;
|
|
59
|
+
if (ctx) {
|
|
60
|
+
anchorIsValid(this.source);
|
|
61
|
+
if (ctx.options.verifyAliasOrder && !ctx.anchors.has(this.source)) {
|
|
62
|
+
const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`;
|
|
63
|
+
throw new Error(msg);
|
|
64
|
+
}
|
|
65
|
+
if (ctx.implicitKey)
|
|
66
|
+
return `${src} `;
|
|
67
|
+
}
|
|
68
|
+
return src;
|
|
47
69
|
}
|
|
48
70
|
}
|
|
49
|
-
function getAliasCount(node, anchors) {
|
|
71
|
+
function getAliasCount(doc, node, anchors) {
|
|
50
72
|
if (isAlias(node)) {
|
|
51
|
-
const
|
|
73
|
+
const source = node.resolve(doc);
|
|
74
|
+
const anchor = anchors && source && anchors.get(source);
|
|
52
75
|
return anchor ? anchor.count * anchor.aliasCount : 0;
|
|
53
76
|
}
|
|
54
77
|
else if (isCollection(node)) {
|
|
55
78
|
let count = 0;
|
|
56
79
|
for (const item of node.items) {
|
|
57
|
-
const c = getAliasCount(item, anchors);
|
|
80
|
+
const c = getAliasCount(doc, item, anchors);
|
|
58
81
|
if (c > count)
|
|
59
82
|
count = c;
|
|
60
83
|
}
|
|
61
84
|
return count;
|
|
62
85
|
}
|
|
63
86
|
else if (isPair(node)) {
|
|
64
|
-
const kc = getAliasCount(node.key, anchors);
|
|
65
|
-
const vc = getAliasCount(node.value, anchors);
|
|
87
|
+
const kc = getAliasCount(doc, node.key, anchors);
|
|
88
|
+
const vc = getAliasCount(doc, node.value, anchors);
|
|
66
89
|
return Math.max(kc, vc);
|
|
67
90
|
}
|
|
68
91
|
return 1;
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { createNode } from '../doc/createNode.js';
|
|
2
|
-
import {
|
|
3
|
-
import { stringify } from '../stringify/stringify.js';
|
|
4
|
-
import { NodeBase, isCollection, isScalar, isNode, isPair } from './Node.js';
|
|
2
|
+
import { NodeBase, isNode, isPair, isCollection, isScalar } from './Node.js';
|
|
5
3
|
|
|
6
4
|
function collectionFromPath(schema, path, value) {
|
|
7
5
|
let v = value;
|
|
@@ -13,22 +11,17 @@ function collectionFromPath(schema, path, value) {
|
|
|
13
11
|
v = a;
|
|
14
12
|
}
|
|
15
13
|
else {
|
|
16
|
-
|
|
17
|
-
Object.defineProperty(o, typeof k === 'symbol' ? k : String(k), {
|
|
18
|
-
value: v,
|
|
19
|
-
writable: true,
|
|
20
|
-
enumerable: true,
|
|
21
|
-
configurable: true
|
|
22
|
-
});
|
|
23
|
-
v = o;
|
|
14
|
+
v = new Map([[k, v]]);
|
|
24
15
|
}
|
|
25
16
|
}
|
|
26
17
|
return createNode(v, undefined, {
|
|
27
|
-
|
|
28
|
-
|
|
18
|
+
aliasDuplicateObjects: false,
|
|
19
|
+
keepUndefined: false,
|
|
20
|
+
onAnchor: () => {
|
|
21
|
+
throw new Error('This should not happen, please report a bug.');
|
|
29
22
|
},
|
|
30
|
-
|
|
31
|
-
|
|
23
|
+
schema,
|
|
24
|
+
sourceObjects: new Map()
|
|
32
25
|
});
|
|
33
26
|
}
|
|
34
27
|
// null, undefined, or an empty non-string iterable (e.g. [])
|
|
@@ -44,6 +37,20 @@ class Collection extends NodeBase {
|
|
|
44
37
|
writable: true
|
|
45
38
|
});
|
|
46
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Create a copy of this collection.
|
|
42
|
+
*
|
|
43
|
+
* @param schema - If defined, overwrites the original's schema
|
|
44
|
+
*/
|
|
45
|
+
clone(schema) {
|
|
46
|
+
const copy = Object.create(Object.getPrototypeOf(this), Object.getOwnPropertyDescriptors(this));
|
|
47
|
+
if (schema)
|
|
48
|
+
copy.schema = schema;
|
|
49
|
+
copy.items = copy.items.map(it => isNode(it) || isPair(it) ? it.clone(schema) : it);
|
|
50
|
+
if (this.range)
|
|
51
|
+
copy.range = this.range.slice();
|
|
52
|
+
return copy;
|
|
53
|
+
}
|
|
47
54
|
/**
|
|
48
55
|
* Adds a value to the collection. For `!!map` and `!!omap` the value must
|
|
49
56
|
* be a Pair instance or a `{ key, value }` object, which may not have a key
|
|
@@ -90,7 +97,7 @@ class Collection extends NodeBase {
|
|
|
90
97
|
}
|
|
91
98
|
hasAllNullValues(allowScalar) {
|
|
92
99
|
return this.items.every(node => {
|
|
93
|
-
if (!
|
|
100
|
+
if (!isPair(node))
|
|
94
101
|
return false;
|
|
95
102
|
const n = node.value;
|
|
96
103
|
return (n == null ||
|
|
@@ -129,82 +136,6 @@ class Collection extends NodeBase {
|
|
|
129
136
|
throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
|
|
130
137
|
}
|
|
131
138
|
}
|
|
132
|
-
_toString(ctx, { blockItem, flowChars, itemIndent }, onComment, onChompKeep) {
|
|
133
|
-
const { indent, indentStep } = ctx;
|
|
134
|
-
const inFlow = this.flow || ctx.inFlow;
|
|
135
|
-
if (inFlow)
|
|
136
|
-
itemIndent += indentStep;
|
|
137
|
-
ctx = Object.assign({}, ctx, { indent: itemIndent, inFlow, type: null });
|
|
138
|
-
let chompKeep = false;
|
|
139
|
-
let hasItemWithNewLine = false;
|
|
140
|
-
const nodes = this.items.reduce((nodes, item, i) => {
|
|
141
|
-
let comment = null;
|
|
142
|
-
if (isNode(item) || isPair(item)) {
|
|
143
|
-
if (!chompKeep && item.spaceBefore)
|
|
144
|
-
nodes.push({ type: 'comment', str: '' });
|
|
145
|
-
if (item.commentBefore) {
|
|
146
|
-
// This match will always succeed on a non-empty string
|
|
147
|
-
for (const line of item.commentBefore.match(/^.*$/gm))
|
|
148
|
-
nodes.push({ type: 'comment', str: `#${line}` });
|
|
149
|
-
}
|
|
150
|
-
if (item.comment)
|
|
151
|
-
comment = item.comment;
|
|
152
|
-
const pair = item; // Apply guards manually in the following
|
|
153
|
-
if (inFlow &&
|
|
154
|
-
((!chompKeep && item.spaceBefore) ||
|
|
155
|
-
item.commentBefore ||
|
|
156
|
-
item.comment ||
|
|
157
|
-
(pair.key && (pair.key.commentBefore || pair.key.comment)) ||
|
|
158
|
-
(pair.value && (pair.value.commentBefore || pair.value.comment))))
|
|
159
|
-
hasItemWithNewLine = true;
|
|
160
|
-
}
|
|
161
|
-
chompKeep = false;
|
|
162
|
-
let str = stringify(item, ctx, () => (comment = null), () => (chompKeep = true));
|
|
163
|
-
if (inFlow && !hasItemWithNewLine && str.includes('\n'))
|
|
164
|
-
hasItemWithNewLine = true;
|
|
165
|
-
if (inFlow && i < this.items.length - 1)
|
|
166
|
-
str += ',';
|
|
167
|
-
str = addComment(str, itemIndent, comment);
|
|
168
|
-
if (chompKeep && (comment || inFlow))
|
|
169
|
-
chompKeep = false;
|
|
170
|
-
nodes.push({ type: 'item', str });
|
|
171
|
-
return nodes;
|
|
172
|
-
}, []);
|
|
173
|
-
let str;
|
|
174
|
-
if (nodes.length === 0) {
|
|
175
|
-
str = flowChars.start + flowChars.end;
|
|
176
|
-
}
|
|
177
|
-
else if (inFlow) {
|
|
178
|
-
const { start, end } = flowChars;
|
|
179
|
-
const strings = nodes.map(n => n.str);
|
|
180
|
-
if (hasItemWithNewLine ||
|
|
181
|
-
strings.reduce((sum, str) => sum + str.length + 2, 2) >
|
|
182
|
-
Collection.maxFlowStringSingleLineLength) {
|
|
183
|
-
str = start;
|
|
184
|
-
for (const s of strings) {
|
|
185
|
-
str += s ? `\n${indentStep}${indent}${s}` : '\n';
|
|
186
|
-
}
|
|
187
|
-
str += `\n${indent}${end}`;
|
|
188
|
-
}
|
|
189
|
-
else {
|
|
190
|
-
str = `${start} ${strings.join(' ')} ${end}`;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
else {
|
|
194
|
-
const strings = nodes.map(blockItem);
|
|
195
|
-
str = strings.shift() || '';
|
|
196
|
-
for (const s of strings)
|
|
197
|
-
str += s ? `\n${indent}${s}` : '\n';
|
|
198
|
-
}
|
|
199
|
-
if (this.comment) {
|
|
200
|
-
str += '\n' + this.comment.replace(/^/gm, `${indent}#`);
|
|
201
|
-
if (onComment)
|
|
202
|
-
onComment();
|
|
203
|
-
}
|
|
204
|
-
else if (chompKeep && onChompKeep)
|
|
205
|
-
onChompKeep();
|
|
206
|
-
return str;
|
|
207
|
-
}
|
|
208
139
|
}
|
|
209
140
|
Collection.maxFlowStringSingleLineLength = 60;
|
|
210
141
|
|
|
@@ -31,10 +31,18 @@ function isNode(node) {
|
|
|
31
31
|
}
|
|
32
32
|
return false;
|
|
33
33
|
}
|
|
34
|
+
const hasAnchor = (node) => (isScalar(node) || isCollection(node)) && !!node.anchor;
|
|
34
35
|
class NodeBase {
|
|
35
36
|
constructor(type) {
|
|
36
37
|
Object.defineProperty(this, NODE_TYPE, { value: type });
|
|
37
38
|
}
|
|
39
|
+
/** Create a copy of this node. */
|
|
40
|
+
clone() {
|
|
41
|
+
const copy = Object.create(Object.getPrototypeOf(this), Object.getOwnPropertyDescriptors(this));
|
|
42
|
+
if (this.range)
|
|
43
|
+
copy.range = this.range.slice();
|
|
44
|
+
return copy;
|
|
45
|
+
}
|
|
38
46
|
}
|
|
39
47
|
|
|
40
|
-
export { ALIAS, DOC, MAP, NODE_TYPE, NodeBase, PAIR, SCALAR, SEQ, isAlias, isCollection, isDocument, isMap, isNode, isPair, isScalar, isSeq };
|
|
48
|
+
export { ALIAS, DOC, MAP, NODE_TYPE, NodeBase, PAIR, SCALAR, SEQ, hasAnchor, isAlias, isCollection, isDocument, isMap, isNode, isPair, isScalar, isSeq };
|
|
@@ -1,251 +1,36 @@
|
|
|
1
1
|
import { createNode } from '../doc/createNode.js';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { Scalar } from './Scalar.js';
|
|
6
|
-
import { toJS } from './toJS.js';
|
|
7
|
-
import { NodeBase, PAIR, isNode, isScalar, isSeq, isCollection, isAlias, isMap } from './Node.js';
|
|
2
|
+
import { stringifyPair } from '../stringify/stringifyPair.js';
|
|
3
|
+
import { addPairToJSMap } from './addPairToJSMap.js';
|
|
4
|
+
import { NODE_TYPE, PAIR, isNode } from './Node.js';
|
|
8
5
|
|
|
9
6
|
function createPair(key, value, ctx) {
|
|
10
7
|
const k = createNode(key, undefined, ctx);
|
|
11
8
|
const v = createNode(value, undefined, ctx);
|
|
12
9
|
return new Pair(k, v);
|
|
13
10
|
}
|
|
14
|
-
|
|
15
|
-
(isScalar(key) &&
|
|
16
|
-
key.value === Pair.MERGE_KEY &&
|
|
17
|
-
(!key.type || key.type === Scalar.PLAIN));
|
|
18
|
-
// If the value associated with a merge key is a single mapping node, each of
|
|
19
|
-
// its key/value pairs is inserted into the current mapping, unless the key
|
|
20
|
-
// already exists in it. If the value associated with the merge key is a
|
|
21
|
-
// sequence, then this sequence is expected to contain mapping nodes and each
|
|
22
|
-
// of these nodes is merged in turn according to its order in the sequence.
|
|
23
|
-
// Keys in mapping nodes earlier in the sequence override keys specified in
|
|
24
|
-
// later mapping nodes. -- http://yaml.org/type/merge.html
|
|
25
|
-
function mergeToJSMap(ctx, map, value) {
|
|
26
|
-
if (!isAlias(value) || !isMap(value.source))
|
|
27
|
-
throw new Error('Merge sources must be map aliases');
|
|
28
|
-
const srcMap = value.source.toJSON(null, ctx, Map);
|
|
29
|
-
for (const [key, value] of srcMap) {
|
|
30
|
-
if (map instanceof Map) {
|
|
31
|
-
if (!map.has(key))
|
|
32
|
-
map.set(key, value);
|
|
33
|
-
}
|
|
34
|
-
else if (map instanceof Set) {
|
|
35
|
-
map.add(key);
|
|
36
|
-
}
|
|
37
|
-
else if (!Object.prototype.hasOwnProperty.call(map, key)) {
|
|
38
|
-
Object.defineProperty(map, key, {
|
|
39
|
-
value,
|
|
40
|
-
writable: true,
|
|
41
|
-
enumerable: true,
|
|
42
|
-
configurable: true
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
return map;
|
|
47
|
-
}
|
|
48
|
-
class Pair extends NodeBase {
|
|
11
|
+
class Pair {
|
|
49
12
|
constructor(key, value = null) {
|
|
50
|
-
|
|
13
|
+
Object.defineProperty(this, NODE_TYPE, { value: PAIR });
|
|
51
14
|
this.key = key;
|
|
52
15
|
this.value = value;
|
|
53
16
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if (isNode(this.key))
|
|
62
|
-
this.key.commentBefore = cb;
|
|
63
|
-
else {
|
|
64
|
-
const msg = 'Pair.commentBefore is an alias for Pair.key.commentBefore. To set it, the key must be a Node.';
|
|
65
|
-
throw new Error(msg);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
// @ts-ignore This is fine.
|
|
69
|
-
get spaceBefore() {
|
|
70
|
-
return isNode(this.key) ? this.key.spaceBefore : undefined;
|
|
71
|
-
}
|
|
72
|
-
set spaceBefore(sb) {
|
|
73
|
-
if (this.key == null)
|
|
74
|
-
this.key = new Scalar(null); // FIXME
|
|
75
|
-
if (isNode(this.key))
|
|
76
|
-
this.key.spaceBefore = sb;
|
|
77
|
-
else {
|
|
78
|
-
const msg = 'Pair.spaceBefore is an alias for Pair.key.spaceBefore. To set it, the key must be a Node.';
|
|
79
|
-
throw new Error(msg);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
addToJSMap(ctx, map) {
|
|
83
|
-
if (ctx && ctx.doc.schema.merge && isMergeKey(this.key)) {
|
|
84
|
-
if (isSeq(this.value))
|
|
85
|
-
for (const it of this.value.items)
|
|
86
|
-
mergeToJSMap(ctx, map, it);
|
|
87
|
-
else if (Array.isArray(this.value))
|
|
88
|
-
for (const it of this.value)
|
|
89
|
-
mergeToJSMap(ctx, map, it);
|
|
90
|
-
else
|
|
91
|
-
mergeToJSMap(ctx, map, this.value);
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
const key = toJS(this.key, '', ctx);
|
|
95
|
-
if (map instanceof Map) {
|
|
96
|
-
const value = toJS(this.value, key, ctx);
|
|
97
|
-
map.set(key, value);
|
|
98
|
-
}
|
|
99
|
-
else if (map instanceof Set) {
|
|
100
|
-
map.add(key);
|
|
101
|
-
}
|
|
102
|
-
else {
|
|
103
|
-
const stringKey = stringifyKey(this.key, key, ctx);
|
|
104
|
-
const value = toJS(this.value, stringKey, ctx);
|
|
105
|
-
if (stringKey in map)
|
|
106
|
-
Object.defineProperty(map, stringKey, {
|
|
107
|
-
value,
|
|
108
|
-
writable: true,
|
|
109
|
-
enumerable: true,
|
|
110
|
-
configurable: true
|
|
111
|
-
});
|
|
112
|
-
else
|
|
113
|
-
map[stringKey] = value;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
return map;
|
|
17
|
+
clone(schema) {
|
|
18
|
+
let { key, value } = this;
|
|
19
|
+
if (isNode(key))
|
|
20
|
+
key = key.clone(schema);
|
|
21
|
+
if (isNode(value))
|
|
22
|
+
value = value.clone(schema);
|
|
23
|
+
return new Pair(key, value);
|
|
117
24
|
}
|
|
118
25
|
toJSON(_, ctx) {
|
|
119
26
|
const pair = ctx && ctx.mapAsMap ? new Map() : {};
|
|
120
|
-
return
|
|
27
|
+
return addPairToJSMap(ctx, pair, this);
|
|
121
28
|
}
|
|
122
29
|
toString(ctx, onComment, onChompKeep) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
let { key, value } = this;
|
|
127
|
-
let keyComment = (isNode(key) && key.comment) || null;
|
|
128
|
-
if (simpleKeys) {
|
|
129
|
-
if (keyComment) {
|
|
130
|
-
throw new Error('With simple keys, key nodes cannot have comments');
|
|
131
|
-
}
|
|
132
|
-
if (isCollection(key)) {
|
|
133
|
-
const msg = 'With simple keys, collection cannot be used as a key value';
|
|
134
|
-
throw new Error(msg);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
let explicitKey = !simpleKeys &&
|
|
138
|
-
(!key ||
|
|
139
|
-
(keyComment && value == null) ||
|
|
140
|
-
isCollection(key) ||
|
|
141
|
-
(isScalar(key)
|
|
142
|
-
? key.type === Scalar.BLOCK_FOLDED || key.type === Scalar.BLOCK_LITERAL
|
|
143
|
-
: typeof key === 'object'));
|
|
144
|
-
ctx = Object.assign({}, ctx, {
|
|
145
|
-
allNullValues: false,
|
|
146
|
-
implicitKey: !explicitKey && (simpleKeys || !allNullValues),
|
|
147
|
-
indent: indent + indentStep
|
|
148
|
-
});
|
|
149
|
-
let chompKeep = false;
|
|
150
|
-
let str = stringify(key, ctx, () => (keyComment = null), () => (chompKeep = true));
|
|
151
|
-
if (!explicitKey && !ctx.inFlow && str.length > 1024) {
|
|
152
|
-
if (simpleKeys)
|
|
153
|
-
throw new Error('With simple keys, single line scalar must not span more than 1024 characters');
|
|
154
|
-
explicitKey = true;
|
|
155
|
-
}
|
|
156
|
-
if ((allNullValues && (!simpleKeys || ctx.inFlow)) ||
|
|
157
|
-
(value == null && (explicitKey || ctx.inFlow))) {
|
|
158
|
-
str = addComment(str, ctx.indent, keyComment);
|
|
159
|
-
if (this.comment) {
|
|
160
|
-
if (keyComment && !this.comment.includes('\n'))
|
|
161
|
-
str += `\n${ctx.indent || ''}#${this.comment}`;
|
|
162
|
-
else
|
|
163
|
-
str = addComment(str, ctx.indent, this.comment);
|
|
164
|
-
if (onComment)
|
|
165
|
-
onComment();
|
|
166
|
-
}
|
|
167
|
-
else if (chompKeep && !keyComment && onChompKeep)
|
|
168
|
-
onChompKeep();
|
|
169
|
-
return ctx.inFlow && !explicitKey ? str : `? ${str}`;
|
|
170
|
-
}
|
|
171
|
-
str = explicitKey
|
|
172
|
-
? `? ${addComment(str, ctx.indent, keyComment)}\n${indent}:`
|
|
173
|
-
: addComment(`${str}:`, ctx.indent, keyComment);
|
|
174
|
-
if (this.comment) {
|
|
175
|
-
if (keyComment && !explicitKey && !this.comment.includes('\n'))
|
|
176
|
-
str += `\n${ctx.indent || ''}#${this.comment}`;
|
|
177
|
-
else
|
|
178
|
-
str = addComment(str, ctx.indent, this.comment);
|
|
179
|
-
if (onComment)
|
|
180
|
-
onComment();
|
|
181
|
-
}
|
|
182
|
-
let vcb = '';
|
|
183
|
-
let valueComment = null;
|
|
184
|
-
if (isNode(value)) {
|
|
185
|
-
if (value.spaceBefore)
|
|
186
|
-
vcb = '\n';
|
|
187
|
-
if (value.commentBefore) {
|
|
188
|
-
const cs = value.commentBefore.replace(/^/gm, `${ctx.indent}#`);
|
|
189
|
-
vcb += `\n${cs}`;
|
|
190
|
-
}
|
|
191
|
-
valueComment = value.comment;
|
|
192
|
-
}
|
|
193
|
-
else if (value && typeof value === 'object') {
|
|
194
|
-
value = doc.createNode(value);
|
|
195
|
-
}
|
|
196
|
-
ctx.implicitKey = false;
|
|
197
|
-
if (!explicitKey && !keyComment && !this.comment && isScalar(value))
|
|
198
|
-
ctx.indentAtStart = str.length + 1;
|
|
199
|
-
chompKeep = false;
|
|
200
|
-
if (!indentSeq &&
|
|
201
|
-
indentStep.length >= 2 &&
|
|
202
|
-
!ctx.inFlow &&
|
|
203
|
-
!explicitKey &&
|
|
204
|
-
isSeq(value) &&
|
|
205
|
-
!value.flow &&
|
|
206
|
-
!value.tag &&
|
|
207
|
-
!doc.anchors.getName(value)) {
|
|
208
|
-
// If indentSeq === false, consider '- ' as part of indentation where possible
|
|
209
|
-
ctx.indent = ctx.indent.substr(2);
|
|
210
|
-
}
|
|
211
|
-
const valueStr = stringify(value, ctx, () => (valueComment = null), () => (chompKeep = true));
|
|
212
|
-
let ws = ' ';
|
|
213
|
-
if (vcb || keyComment || this.comment) {
|
|
214
|
-
ws = `${vcb}\n${ctx.indent}`;
|
|
215
|
-
}
|
|
216
|
-
else if (!explicitKey && isCollection(value)) {
|
|
217
|
-
const flow = valueStr[0] === '[' || valueStr[0] === '{';
|
|
218
|
-
if (!flow || valueStr.includes('\n'))
|
|
219
|
-
ws = `\n${ctx.indent}`;
|
|
220
|
-
}
|
|
221
|
-
else if (valueStr[0] === '\n')
|
|
222
|
-
ws = '';
|
|
223
|
-
if (chompKeep && !valueComment && onChompKeep)
|
|
224
|
-
onChompKeep();
|
|
225
|
-
return addComment(str + ws + valueStr, ctx.indent, valueComment);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
Pair.MERGE_KEY = '<<';
|
|
229
|
-
function stringifyKey(key, jsKey, ctx) {
|
|
230
|
-
if (jsKey === null)
|
|
231
|
-
return '';
|
|
232
|
-
if (typeof jsKey !== 'object')
|
|
233
|
-
return String(jsKey);
|
|
234
|
-
if (isNode(key) && ctx && ctx.doc) {
|
|
235
|
-
const strCtx = createStringifyContext(ctx.doc, {});
|
|
236
|
-
strCtx.inFlow = true;
|
|
237
|
-
strCtx.inStringifyKey = true;
|
|
238
|
-
const strKey = key.toString(strCtx);
|
|
239
|
-
if (!ctx.mapKeyWarned) {
|
|
240
|
-
let jsonStr = JSON.stringify(strKey);
|
|
241
|
-
if (jsonStr.length > 40)
|
|
242
|
-
jsonStr = jsonStr.substring(0, 36) + '..."';
|
|
243
|
-
warn(ctx.doc.options.logLevel, `Keys with collection values will be stringified due to JS Object restrictions: ${jsonStr}. Set mapAsMap: true to use object keys.`);
|
|
244
|
-
ctx.mapKeyWarned = true;
|
|
245
|
-
}
|
|
246
|
-
return strKey;
|
|
30
|
+
return ctx && ctx.doc
|
|
31
|
+
? stringifyPair(this, ctx, onComment, onChompKeep)
|
|
32
|
+
: JSON.stringify(this);
|
|
247
33
|
}
|
|
248
|
-
return JSON.stringify(jsKey);
|
|
249
34
|
}
|
|
250
35
|
|
|
251
36
|
export { Pair, createPair };
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { stringifyCollection } from '../stringify/stringifyCollection.js';
|
|
2
|
+
import { addPairToJSMap } from './addPairToJSMap.js';
|
|
1
3
|
import { Collection } from './Collection.js';
|
|
2
4
|
import { isPair, isScalar, MAP } from './Node.js';
|
|
3
5
|
import { Pair } from './Pair.js';
|
|
@@ -89,7 +91,7 @@ class YAMLMap extends Collection {
|
|
|
89
91
|
if (ctx && ctx.onCreate)
|
|
90
92
|
ctx.onCreate(map);
|
|
91
93
|
for (const item of this.items)
|
|
92
|
-
|
|
94
|
+
addPairToJSMap(ctx, map, item);
|
|
93
95
|
return map;
|
|
94
96
|
}
|
|
95
97
|
toString(ctx, onComment, onChompKeep) {
|
|
@@ -101,11 +103,13 @@ class YAMLMap extends Collection {
|
|
|
101
103
|
}
|
|
102
104
|
if (!ctx.allNullValues && this.hasAllNullValues(false))
|
|
103
105
|
ctx = Object.assign({}, ctx, { allNullValues: true });
|
|
104
|
-
return
|
|
106
|
+
return stringifyCollection(this, ctx, {
|
|
105
107
|
blockItem: n => n.str,
|
|
106
108
|
flowChars: { start: '{', end: '}' },
|
|
107
|
-
itemIndent: ctx.indent || ''
|
|
108
|
-
|
|
109
|
+
itemIndent: ctx.indent || '',
|
|
110
|
+
onChompKeep,
|
|
111
|
+
onComment
|
|
112
|
+
});
|
|
109
113
|
}
|
|
110
114
|
}
|
|
111
115
|
|