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.
Files changed (210) hide show
  1. package/README.md +5 -5
  2. package/browser/dist/compose/compose-collection.js +12 -9
  3. package/browser/dist/compose/compose-doc.js +23 -6
  4. package/browser/dist/compose/compose-node.js +20 -17
  5. package/browser/dist/compose/compose-scalar.js +20 -23
  6. package/browser/dist/compose/composer.js +105 -76
  7. package/browser/dist/compose/resolve-block-map.js +38 -29
  8. package/browser/dist/compose/resolve-block-scalar.js +14 -17
  9. package/browser/dist/compose/resolve-block-seq.js +21 -17
  10. package/browser/dist/compose/resolve-end.js +6 -7
  11. package/browser/dist/compose/resolve-flow-collection.js +153 -199
  12. package/browser/dist/compose/resolve-flow-scalar.js +49 -25
  13. package/browser/dist/compose/resolve-props.js +47 -35
  14. package/browser/dist/compose/util-contains-newline.js +15 -12
  15. package/browser/dist/doc/Document.js +50 -99
  16. package/browser/dist/doc/anchors.js +72 -0
  17. package/browser/dist/doc/createNode.js +27 -17
  18. package/browser/dist/errors.js +16 -12
  19. package/browser/dist/index.js +3 -3
  20. package/browser/dist/nodes/Alias.js +51 -28
  21. package/browser/dist/nodes/Collection.js +5 -83
  22. package/browser/dist/nodes/Node.js +2 -1
  23. package/browser/dist/nodes/Pair.js +9 -232
  24. package/browser/dist/nodes/YAMLMap.js +8 -4
  25. package/browser/dist/nodes/YAMLSeq.js +7 -4
  26. package/browser/dist/nodes/addPairToJSMap.js +103 -0
  27. package/browser/dist/nodes/toJS.js +12 -10
  28. package/browser/dist/options.js +0 -2
  29. package/browser/dist/parse/cst-scalar.js +219 -0
  30. package/browser/dist/parse/cst-stringify.js +61 -0
  31. package/browser/dist/parse/cst-visit.js +97 -0
  32. package/{dist/parse/tokens.js → browser/dist/parse/cst.js} +12 -7
  33. package/browser/dist/parse/lexer.js +99 -105
  34. package/browser/dist/parse/parser.js +219 -144
  35. package/browser/dist/public-api.js +11 -14
  36. package/browser/dist/schema/Schema.js +23 -0
  37. package/browser/dist/{tags/failsafe → schema/common}/map.js +0 -0
  38. package/browser/dist/schema/common/null.js +13 -0
  39. package/browser/dist/{tags/failsafe → schema/common}/seq.js +1 -1
  40. package/browser/dist/{tags/failsafe → schema/common}/string.js +0 -0
  41. package/browser/dist/schema/core/bool.js +19 -0
  42. package/browser/dist/schema/core/float.js +40 -0
  43. package/browser/dist/schema/core/int.js +38 -0
  44. package/browser/dist/schema/core/schema.js +23 -0
  45. package/browser/dist/{tags/json.js → schema/json/schema.js} +5 -6
  46. package/browser/dist/schema/tags.js +79 -0
  47. package/browser/dist/{tags → schema}/yaml-1.1/binary.js +0 -0
  48. package/browser/dist/schema/yaml-1.1/bool.js +26 -0
  49. package/browser/dist/schema/yaml-1.1/float.js +43 -0
  50. package/browser/dist/schema/yaml-1.1/int.js +71 -0
  51. package/browser/dist/{tags → schema}/yaml-1.1/omap.js +0 -0
  52. package/browser/dist/{tags → schema}/yaml-1.1/pairs.js +9 -6
  53. package/browser/dist/schema/yaml-1.1/schema.js +37 -0
  54. package/browser/dist/{tags → schema}/yaml-1.1/set.js +0 -0
  55. package/browser/dist/{tags → schema}/yaml-1.1/timestamp.js +0 -0
  56. package/browser/dist/stringify/addComment.js +1 -7
  57. package/browser/dist/stringify/stringify.js +8 -6
  58. package/browser/dist/stringify/stringifyCollection.js +108 -0
  59. package/browser/dist/stringify/stringifyDocument.js +61 -0
  60. package/browser/dist/stringify/stringifyPair.js +113 -0
  61. package/browser/dist/stringify/stringifyString.js +53 -52
  62. package/browser/dist/visit.js +20 -1
  63. package/dist/compose/compose-collection.d.ts +4 -4
  64. package/dist/compose/compose-collection.js +12 -9
  65. package/dist/compose/compose-doc.d.ts +4 -3
  66. package/dist/compose/compose-doc.js +23 -6
  67. package/dist/compose/compose-node.d.ts +15 -7
  68. package/dist/compose/compose-node.js +20 -17
  69. package/dist/compose/compose-scalar.d.ts +4 -3
  70. package/dist/compose/compose-scalar.js +19 -22
  71. package/dist/compose/composer.d.ts +28 -23
  72. package/dist/compose/composer.js +106 -77
  73. package/dist/compose/resolve-block-map.d.ts +4 -4
  74. package/dist/compose/resolve-block-map.js +38 -29
  75. package/dist/compose/resolve-block-scalar.d.ts +5 -3
  76. package/dist/compose/resolve-block-scalar.js +14 -17
  77. package/dist/compose/resolve-block-seq.d.ts +4 -4
  78. package/dist/compose/resolve-block-seq.js +21 -17
  79. package/dist/compose/resolve-end.d.ts +3 -2
  80. package/dist/compose/resolve-end.js +6 -7
  81. package/dist/compose/resolve-flow-collection.d.ts +4 -5
  82. package/dist/compose/resolve-flow-collection.js +152 -198
  83. package/dist/compose/resolve-flow-scalar.d.ts +5 -3
  84. package/dist/compose/resolve-flow-scalar.js +49 -25
  85. package/dist/compose/resolve-props.d.ts +17 -10
  86. package/dist/compose/resolve-props.js +47 -35
  87. package/dist/compose/util-contains-newline.d.ts +1 -1
  88. package/dist/compose/util-contains-newline.js +15 -12
  89. package/dist/compose/util-empty-scalar-position.d.ts +1 -1
  90. package/dist/doc/Document.d.ts +27 -15
  91. package/dist/doc/Document.js +48 -97
  92. package/dist/doc/anchors.d.ts +24 -0
  93. package/dist/doc/anchors.js +77 -0
  94. package/dist/doc/createNode.d.ts +8 -10
  95. package/dist/doc/createNode.js +26 -16
  96. package/dist/errors.d.ts +11 -8
  97. package/dist/errors.js +16 -12
  98. package/dist/index.d.ts +5 -3
  99. package/dist/index.js +3 -3
  100. package/dist/nodes/Alias.d.ts +19 -9
  101. package/dist/nodes/Alias.js +51 -28
  102. package/dist/nodes/Collection.d.ts +3 -17
  103. package/dist/nodes/Collection.js +4 -82
  104. package/dist/nodes/Node.d.ts +6 -4
  105. package/dist/nodes/Node.js +2 -0
  106. package/dist/nodes/Pair.d.ts +6 -11
  107. package/dist/nodes/Pair.js +8 -231
  108. package/dist/nodes/Scalar.d.ts +6 -3
  109. package/dist/nodes/YAMLMap.d.ts +3 -3
  110. package/dist/nodes/YAMLMap.js +8 -4
  111. package/dist/nodes/YAMLSeq.d.ts +3 -3
  112. package/dist/nodes/YAMLSeq.js +7 -4
  113. package/dist/nodes/addPairToJSMap.d.ts +3 -0
  114. package/dist/nodes/addPairToJSMap.js +105 -0
  115. package/dist/nodes/toJS.d.ts +4 -5
  116. package/dist/nodes/toJS.js +12 -10
  117. package/dist/options.d.ts +20 -26
  118. package/dist/options.js +0 -2
  119. package/dist/parse/cst-scalar.d.ts +58 -0
  120. package/dist/parse/cst-scalar.js +223 -0
  121. package/dist/parse/cst-stringify.d.ts +8 -0
  122. package/dist/parse/cst-stringify.js +63 -0
  123. package/dist/parse/cst-visit.d.ts +39 -0
  124. package/dist/parse/cst-visit.js +99 -0
  125. package/dist/parse/{tokens.d.ts → cst.d.ts} +23 -7
  126. package/{browser/dist/parse/tokens.js → dist/parse/cst.js} +27 -1
  127. package/dist/parse/lexer.d.ts +4 -13
  128. package/dist/parse/lexer.js +100 -106
  129. package/dist/parse/parser.d.ts +30 -24
  130. package/dist/parse/parser.js +221 -146
  131. package/dist/public-api.d.ts +7 -7
  132. package/dist/public-api.js +11 -14
  133. package/dist/{doc → schema}/Schema.d.ts +5 -3
  134. package/dist/schema/Schema.js +25 -0
  135. package/dist/{tags/failsafe → schema/common}/map.d.ts +0 -0
  136. package/dist/{tags/failsafe → schema/common}/map.js +0 -0
  137. package/dist/schema/common/null.d.ts +4 -0
  138. package/dist/schema/common/null.js +15 -0
  139. package/dist/{tags/failsafe → schema/common}/seq.d.ts +0 -0
  140. package/dist/{tags/failsafe → schema/common}/seq.js +1 -1
  141. package/dist/{tags/failsafe → schema/common}/string.d.ts +0 -0
  142. package/dist/{tags/failsafe → schema/common}/string.js +0 -0
  143. package/dist/schema/core/bool.d.ts +4 -0
  144. package/dist/schema/core/bool.js +21 -0
  145. package/dist/schema/core/float.d.ts +4 -0
  146. package/dist/schema/core/float.js +44 -0
  147. package/dist/schema/core/int.d.ts +4 -0
  148. package/dist/schema/core/int.js +42 -0
  149. package/dist/schema/core/schema.d.ts +1 -0
  150. package/dist/schema/core/schema.js +25 -0
  151. package/dist/schema/json/schema.d.ts +2 -0
  152. package/dist/{tags/json.js → schema/json/schema.js} +5 -6
  153. package/dist/schema/tags.d.ts +41 -0
  154. package/dist/schema/tags.js +82 -0
  155. package/dist/{tags → schema}/types.d.ts +3 -7
  156. package/dist/{tags → schema}/yaml-1.1/binary.d.ts +0 -0
  157. package/dist/{tags → schema}/yaml-1.1/binary.js +0 -0
  158. package/dist/schema/yaml-1.1/bool.d.ts +7 -0
  159. package/dist/schema/yaml-1.1/bool.js +29 -0
  160. package/dist/schema/yaml-1.1/float.d.ts +4 -0
  161. package/dist/schema/yaml-1.1/float.js +47 -0
  162. package/dist/schema/yaml-1.1/int.d.ts +5 -0
  163. package/dist/schema/yaml-1.1/int.js +76 -0
  164. package/dist/{tags → schema}/yaml-1.1/omap.d.ts +0 -0
  165. package/dist/{tags → schema}/yaml-1.1/omap.js +0 -0
  166. package/dist/{tags → schema}/yaml-1.1/pairs.d.ts +3 -2
  167. package/dist/{tags → schema}/yaml-1.1/pairs.js +9 -6
  168. package/dist/schema/yaml-1.1/schema.d.ts +1 -0
  169. package/dist/schema/yaml-1.1/schema.js +39 -0
  170. package/dist/{tags → schema}/yaml-1.1/set.d.ts +1 -1
  171. package/dist/{tags → schema}/yaml-1.1/set.js +0 -0
  172. package/dist/{tags → schema}/yaml-1.1/timestamp.d.ts +0 -0
  173. package/dist/{tags → schema}/yaml-1.1/timestamp.js +0 -0
  174. package/dist/stringify/addComment.js +0 -7
  175. package/dist/stringify/stringify.d.ts +1 -2
  176. package/dist/stringify/stringify.js +8 -6
  177. package/dist/stringify/stringifyCollection.d.ts +21 -0
  178. package/dist/stringify/stringifyCollection.js +110 -0
  179. package/dist/stringify/stringifyDocument.d.ts +3 -0
  180. package/dist/stringify/stringifyDocument.js +63 -0
  181. package/dist/stringify/stringifyPair.d.ts +3 -0
  182. package/dist/stringify/stringifyPair.js +115 -0
  183. package/dist/stringify/stringifyString.js +53 -52
  184. package/dist/test-events.d.ts +1 -2
  185. package/dist/test-events.js +25 -12
  186. package/dist/util.d.ts +1 -1
  187. package/dist/visit.d.ts +10 -1
  188. package/dist/visit.js +20 -1
  189. package/package.json +4 -3
  190. package/browser/dist/doc/Anchors.js +0 -102
  191. package/browser/dist/doc/Schema.js +0 -27
  192. package/browser/dist/doc/getSchemaTags.js +0 -30
  193. package/browser/dist/tags/core.js +0 -109
  194. package/browser/dist/tags/failsafe/index.js +0 -7
  195. package/browser/dist/tags/index.js +0 -34
  196. package/browser/dist/tags/yaml-1.1/index.js +0 -152
  197. package/dist/doc/Anchors.d.ts +0 -36
  198. package/dist/doc/Anchors.js +0 -104
  199. package/dist/doc/Schema.js +0 -29
  200. package/dist/doc/getSchemaTags.d.ts +0 -3
  201. package/dist/doc/getSchemaTags.js +0 -32
  202. package/dist/tags/core.d.ts +0 -14
  203. package/dist/tags/core.js +0 -119
  204. package/dist/tags/failsafe/index.d.ts +0 -1
  205. package/dist/tags/failsafe/index.js +0 -9
  206. package/dist/tags/index.d.ts +0 -31
  207. package/dist/tags/index.js +0 -37
  208. package/dist/tags/json.d.ts +0 -2
  209. package/dist/tags/yaml-1.1/index.d.ts +0 -2
  210. package/dist/tags/yaml-1.1/index.js +0 -154
@@ -1,4 +1,5 @@
1
- import { isNode, isPair } from '../nodes/Node.js';
1
+ import { Alias } from '../nodes/Alias.js';
2
+ import { isNode, isPair, MAP, SEQ } from '../nodes/Node.js';
2
3
  import { Scalar } from '../nodes/Scalar.js';
3
4
 
4
5
  const defaultTagPrefix = 'tag:yaml.org,2002:';
@@ -17,7 +18,7 @@ function createNode(value, tagName, ctx) {
17
18
  if (isNode(value))
18
19
  return value;
19
20
  if (isPair(value)) {
20
- const map = (_b = (_a = ctx.schema.map).createNode) === null || _b === void 0 ? void 0 : _b.call(_a, ctx.schema, null, ctx);
21
+ const map = (_b = (_a = ctx.schema[MAP]).createNode) === null || _b === void 0 ? void 0 : _b.call(_a, ctx.schema, null, ctx);
21
22
  map.items.push(value);
22
23
  return map;
23
24
  }
@@ -29,39 +30,48 @@ function createNode(value, tagName, ctx) {
29
30
  // https://tc39.es/ecma262/#sec-serializejsonproperty
30
31
  value = value.valueOf();
31
32
  }
32
- const { onAlias, onTagObj, prevObjects } = ctx;
33
- const { map, seq, tags } = ctx.schema;
33
+ const { onAnchor, onTagObj, schema, sourceObjects } = ctx;
34
+ // Detect duplicate references to the same object & use Alias nodes for all
35
+ // after first. The `ref` wrapper allows for circular references to resolve.
36
+ let ref = undefined;
37
+ if (value && typeof value === 'object') {
38
+ ref = sourceObjects.get(value);
39
+ if (ref) {
40
+ if (!ref.anchor)
41
+ ref.anchor = onAnchor(value);
42
+ return new Alias(ref.anchor);
43
+ }
44
+ else {
45
+ ref = { anchor: null, node: null };
46
+ sourceObjects.set(value, ref);
47
+ }
48
+ }
34
49
  if (tagName && tagName.startsWith('!!'))
35
50
  tagName = defaultTagPrefix + tagName.slice(2);
36
- let tagObj = findTagObject(value, tagName, tags);
51
+ let tagObj = findTagObject(value, tagName, schema.tags);
37
52
  if (!tagObj) {
38
53
  if (value && typeof value.toJSON === 'function')
39
54
  value = value.toJSON();
40
55
  if (!value || typeof value !== 'object')
41
56
  return new Scalar(value);
42
57
  tagObj =
43
- value instanceof Map ? map : Symbol.iterator in Object(value) ? seq : map;
58
+ value instanceof Map
59
+ ? schema[MAP]
60
+ : Symbol.iterator in Object(value)
61
+ ? schema[SEQ]
62
+ : schema[MAP];
44
63
  }
45
64
  if (onTagObj) {
46
65
  onTagObj(tagObj);
47
66
  delete ctx.onTagObj;
48
67
  }
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
68
  const node = (tagObj === null || tagObj === void 0 ? void 0 : tagObj.createNode)
60
69
  ? tagObj.createNode(ctx.schema, value, ctx)
61
70
  : new Scalar(value);
62
71
  if (tagName)
63
72
  node.tag = tagName;
64
- ref.node = node;
73
+ if (ref)
74
+ ref.node = node;
65
75
  return node;
66
76
  }
67
77
 
@@ -1,28 +1,27 @@
1
1
  class YAMLError extends Error {
2
- constructor(name, offset, message) {
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.offset = offset;
7
+ this.pos = pos;
9
8
  }
10
9
  }
11
10
  class YAMLParseError extends YAMLError {
12
- constructor(offset, message) {
13
- super('YAMLParseError', offset, message);
11
+ constructor(pos, code, message) {
12
+ super('YAMLParseError', pos, code, message);
14
13
  }
15
14
  }
16
15
  class YAMLWarning extends YAMLError {
17
- constructor(offset, message) {
18
- super('YAMLWarning', offset, message);
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.offset === -1)
21
+ if (error.pos[0] === -1)
23
22
  return;
24
- error.linePos = lc.linePos(error.offset);
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
- const pointer = ' '.repeat(ci) + '^';
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
  };
@@ -1,6 +1,6 @@
1
1
  export { Composer } from './compose/composer.js';
2
2
  export { Document } from './doc/Document.js';
3
- export { Schema } from './doc/Schema.js';
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
- toJSON(arg, ctx) {
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 toJS(this.source, typeof arg === 'string' ? arg : null, ctx);
17
- const { anchors, maxAliasCount } = ctx;
18
- const anchor = anchors && anchors.get(this.source);
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 (!anchor || anchor.res === undefined) {
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
- anchor.count += 1;
26
- if (anchor.aliasCount === 0)
27
- anchor.aliasCount = getAliasCount(this.source, anchors);
28
- if (anchor.count * anchor.aliasCount > maxAliasCount) {
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 anchor.res;
55
+ return data.res;
34
56
  }
35
- // Only called when stringifying an alias mapping key while constructing
36
- // Object output.
37
- toString({ anchors, doc, implicitKey, inStringifyKey }, _onComment, _onChompKeep) {
38
- let anchor = Object.keys(anchors).find(a => anchors[a] === this.source);
39
- if (!anchor && inStringifyKey)
40
- anchor = doc.anchors.getName(this.source) || doc.anchors.newName();
41
- if (anchor)
42
- return `*${anchor}${implicitKey ? ' ' : ''}`;
43
- const msg = doc.anchors.getName(this.source)
44
- ? 'Alias node must be after source node'
45
- : 'Source node not found for alias node';
46
- throw new Error(`${msg} [${this.range}]`);
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 anchor = anchors && anchors.get(node.source);
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 { addComment } from '../stringify/addComment.js';
3
- import { stringify } from '../stringify/stringify.js';
4
- import { NodeBase, isCollection, isScalar, isNode, isPair } from './Node.js';
2
+ import { NodeBase, isCollection, isScalar, isPair } from './Node.js';
5
3
 
6
4
  function collectionFromPath(schema, path, value) {
7
5
  let v = value;
@@ -24,11 +22,11 @@ function collectionFromPath(schema, path, value) {
24
22
  }
25
23
  }
26
24
  return createNode(v, undefined, {
27
- onAlias() {
25
+ onAnchor() {
28
26
  throw new Error('Repeated objects are not supported here');
29
27
  },
30
- prevObjects: new Map(),
31
- schema
28
+ schema,
29
+ sourceObjects: new Map()
32
30
  });
33
31
  }
34
32
  // null, undefined, or an empty non-string iterable (e.g. [])
@@ -90,7 +88,7 @@ class Collection extends NodeBase {
90
88
  }
91
89
  hasAllNullValues(allowScalar) {
92
90
  return this.items.every(node => {
93
- if (!node || isNode(node))
91
+ if (!isPair(node))
94
92
  return false;
95
93
  const n = node.value;
96
94
  return (n == null ||
@@ -129,82 +127,6 @@ class Collection extends NodeBase {
129
127
  throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
130
128
  }
131
129
  }
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
130
  }
209
131
  Collection.maxFlowStringSingleLineLength = 60;
210
132
 
@@ -31,10 +31,11 @@ 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
  }
38
39
  }
39
40
 
40
- export { ALIAS, DOC, MAP, NODE_TYPE, NodeBase, PAIR, SCALAR, SEQ, isAlias, isCollection, isDocument, isMap, isNode, isPair, isScalar, isSeq };
41
+ export { ALIAS, DOC, MAP, NODE_TYPE, NodeBase, PAIR, SCALAR, SEQ, hasAnchor, isAlias, isCollection, isDocument, isMap, isNode, isPair, isScalar, isSeq };
@@ -1,251 +1,28 @@
1
1
  import { createNode } from '../doc/createNode.js';
2
- import { warn } from '../log.js';
3
- import { addComment } from '../stringify/addComment.js';
4
- import { stringify, createStringifyContext } from '../stringify/stringify.js';
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 } 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
- const isMergeKey = (key) => key === Pair.MERGE_KEY ||
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
- super(PAIR);
13
+ Object.defineProperty(this, NODE_TYPE, { value: PAIR });
51
14
  this.key = key;
52
15
  this.value = value;
53
16
  }
54
- // @ts-ignore This is fine.
55
- get commentBefore() {
56
- return isNode(this.key) ? this.key.commentBefore : undefined;
57
- }
58
- set commentBefore(cb) {
59
- if (this.key == null)
60
- this.key = new Scalar(null); // FIXME
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;
117
- }
118
17
  toJSON(_, ctx) {
119
18
  const pair = ctx && ctx.mapAsMap ? new Map() : {};
120
- return this.addToJSMap(ctx, pair);
19
+ return addPairToJSMap(ctx, pair, this);
121
20
  }
122
21
  toString(ctx, onComment, onChompKeep) {
123
- if (!ctx || !ctx.doc)
124
- return JSON.stringify(this);
125
- const { allNullValues, doc, indent, indentStep, options: { indentSeq, simpleKeys } } = ctx;
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;
22
+ return ctx && ctx.doc
23
+ ? stringifyPair(this, ctx, onComment, onChompKeep)
24
+ : JSON.stringify(this);
247
25
  }
248
- return JSON.stringify(jsKey);
249
26
  }
250
27
 
251
28
  export { Pair, createPair };