yaml 1.6.0 → 1.8.0

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 (112) hide show
  1. package/browser/dist/Anchors.js +24 -39
  2. package/browser/dist/Document.js +99 -111
  3. package/browser/dist/addComment.js +2 -11
  4. package/browser/dist/constants.js +3 -11
  5. package/browser/dist/cst/Alias.js +19 -36
  6. package/browser/dist/cst/BlankLine.js +25 -38
  7. package/browser/dist/cst/BlockValue.js +29 -51
  8. package/browser/dist/cst/Collection.js +42 -65
  9. package/browser/dist/cst/CollectionItem.js +57 -58
  10. package/browser/dist/cst/Comment.js +19 -35
  11. package/browser/dist/cst/Directive.js +20 -56
  12. package/browser/dist/cst/Document.js +47 -71
  13. package/browser/dist/cst/FlowCollection.js +38 -61
  14. package/browser/dist/cst/Node.js +30 -47
  15. package/browser/dist/cst/ParseContext.js +100 -140
  16. package/browser/dist/cst/PlainValue.js +22 -39
  17. package/browser/dist/cst/QuoteDouble.js +26 -42
  18. package/browser/dist/cst/QuoteSingle.js +25 -41
  19. package/browser/dist/cst/Range.js +9 -19
  20. package/browser/dist/cst/parse.js +5 -16
  21. package/browser/dist/cst/source-utils.js +168 -0
  22. package/browser/dist/errors.js +71 -74
  23. package/browser/dist/foldFlowLines.js +4 -15
  24. package/browser/dist/index.js +26 -45
  25. package/browser/dist/listTagNames.js +10 -24
  26. package/browser/dist/schema/Alias.js +33 -50
  27. package/browser/dist/schema/Collection.js +54 -65
  28. package/browser/dist/schema/Map.js +39 -49
  29. package/browser/dist/schema/Merge.js +33 -53
  30. package/browser/dist/schema/Node.js +3 -12
  31. package/browser/dist/schema/Pair.js +53 -56
  32. package/browser/dist/schema/Scalar.js +18 -33
  33. package/browser/dist/schema/Seq.js +23 -40
  34. package/browser/dist/schema/index.js +67 -81
  35. package/browser/dist/schema/parseMap.js +63 -70
  36. package/browser/dist/schema/parseSeq.js +45 -44
  37. package/browser/dist/schema/parseUtils.js +47 -11
  38. package/browser/dist/stringify.js +43 -48
  39. package/browser/dist/tags/core.js +30 -37
  40. package/browser/dist/tags/failsafe/index.js +4 -17
  41. package/browser/dist/tags/failsafe/map.js +17 -26
  42. package/browser/dist/tags/failsafe/seq.js +7 -18
  43. package/browser/dist/tags/failsafe/string.js +7 -19
  44. package/browser/dist/tags/index.js +35 -49
  45. package/browser/dist/tags/json.js +11 -38
  46. package/browser/dist/tags/options.js +8 -20
  47. package/browser/dist/tags/yaml-1.1/binary.js +16 -29
  48. package/browser/dist/tags/yaml-1.1/index.js +34 -54
  49. package/browser/dist/tags/yaml-1.1/omap.js +39 -58
  50. package/browser/dist/tags/yaml-1.1/pairs.js +15 -34
  51. package/browser/dist/tags/yaml-1.1/set.js +35 -61
  52. package/browser/dist/tags/yaml-1.1/timestamp.js +6 -16
  53. package/browser/dist/test-events.js +7 -19
  54. package/browser/dist/toJSON.js +1 -8
  55. package/browser/dist/warnings.js +28 -0
  56. package/browser/map.js +1 -1
  57. package/browser/pair.js +1 -1
  58. package/browser/scalar.js +1 -1
  59. package/browser/schema.js +1 -1
  60. package/browser/seq.js +1 -1
  61. package/browser/types/binary.js +1 -1
  62. package/browser/types/omap.js +1 -1
  63. package/browser/types/pairs.js +1 -1
  64. package/browser/types/set.js +1 -1
  65. package/browser/types/timestamp.js +1 -1
  66. package/dist/Document.js +21 -9
  67. package/dist/cst/BlankLine.js +4 -0
  68. package/dist/cst/BlockValue.js +1 -1
  69. package/dist/cst/CollectionItem.js +27 -6
  70. package/dist/cst/Directive.js +0 -16
  71. package/dist/cst/Node.js +7 -9
  72. package/dist/cst/ParseContext.js +41 -55
  73. package/dist/cst/PlainValue.js +1 -1
  74. package/dist/cst/source-utils.js +178 -0
  75. package/dist/errors.js +37 -3
  76. package/dist/index.js +5 -4
  77. package/dist/schema/Alias.js +2 -1
  78. package/dist/schema/Collection.js +22 -5
  79. package/dist/schema/Map.js +12 -5
  80. package/dist/schema/Merge.js +4 -5
  81. package/dist/schema/Pair.js +20 -2
  82. package/dist/schema/index.js +14 -8
  83. package/dist/schema/parseMap.js +20 -5
  84. package/dist/schema/parseSeq.js +19 -6
  85. package/dist/schema/parseUtils.js +54 -6
  86. package/dist/stringify.js +21 -11
  87. package/dist/tags/core.js +27 -10
  88. package/dist/tags/failsafe/map.js +5 -1
  89. package/dist/tags/failsafe/seq.js +1 -1
  90. package/dist/tags/index.js +13 -1
  91. package/dist/tags/json.js +2 -9
  92. package/dist/tags/yaml-1.1/index.js +6 -6
  93. package/dist/tags/yaml-1.1/omap.js +3 -5
  94. package/dist/tags/yaml-1.1/pairs.js +1 -1
  95. package/dist/tags/yaml-1.1/set.js +3 -1
  96. package/dist/{deprecation.js → warnings.js} +12 -7
  97. package/map.js +1 -1
  98. package/package.json +35 -17
  99. package/pair.js +1 -1
  100. package/scalar.js +1 -1
  101. package/schema.js +1 -1
  102. package/seq.js +1 -1
  103. package/types/binary.js +1 -1
  104. package/types/omap.js +1 -1
  105. package/types/pairs.js +1 -1
  106. package/types/set.js +1 -1
  107. package/types/timestamp.js +1 -1
  108. package/types.mjs +20 -0
  109. package/util.mjs +24 -0
  110. package/browser/dist/cst/getLinePos.js +0 -79
  111. package/browser/dist/deprecation.js +0 -34
  112. package/dist/cst/getLinePos.js +0 -79
@@ -50,7 +50,7 @@ class BlockValue extends _Node.default {
50
50
  end -= 1;
51
51
 
52
52
  if (end <= start) {
53
- if (this.chomping === Chomp.KEEP) break;else return '';
53
+ if (this.chomping === Chomp.KEEP) break;else return ''; // probably never happens
54
54
  }
55
55
 
56
56
  if (ch === '\n') lastNewLine = end;
@@ -49,12 +49,15 @@ class CollectionItem extends _Node.default {
49
49
  let offset = _Node.default.endOfWhiteSpace(src, start + 1);
50
50
 
51
51
  let ch = src[offset];
52
+ const inlineComment = ch === '#';
53
+ const comments = [];
54
+ let blankLine = null;
52
55
 
53
56
  while (ch === '\n' || ch === '#') {
54
57
  if (ch === '#') {
55
58
  const end = _Node.default.endOfLine(src, offset + 1);
56
59
 
57
- this.props.push(new _Range.default(offset, end));
60
+ comments.push(new _Range.default(offset, end));
58
61
  offset = end;
59
62
  } else {
60
63
  atLineStart = true;
@@ -62,13 +65,11 @@ class CollectionItem extends _Node.default {
62
65
 
63
66
  const wsEnd = _Node.default.endOfWhiteSpace(src, lineStart);
64
67
 
65
- if (src[wsEnd] === '\n') {
66
- const blankLine = new _BlankLine.default();
68
+ if (src[wsEnd] === '\n' && comments.length === 0) {
69
+ blankLine = new _BlankLine.default();
67
70
  lineStart = blankLine.parse({
68
71
  src
69
72
  }, lineStart);
70
- const items = context.parent.items || context.parent.contents;
71
- items.push(blankLine);
72
73
  }
73
74
 
74
75
  offset = _Node.default.endOfIndent(src, lineStart);
@@ -85,11 +86,31 @@ class CollectionItem extends _Node.default {
85
86
  lineStart,
86
87
  parent: this
87
88
  }, offset);
88
- if (this.node) offset = this.node.range.end;
89
89
  } else if (ch && lineStart > start + 1) {
90
90
  offset = lineStart - 1;
91
91
  }
92
92
 
93
+ if (this.node) {
94
+ if (blankLine) {
95
+ // Only blank lines preceding non-empty nodes are captured. Note that
96
+ // this means that collection item range start indices do not always
97
+ // increase monotonically. -- eemeli/yaml#126
98
+ const items = context.parent.items || context.parent.contents;
99
+ if (items) items.push(blankLine);
100
+ }
101
+
102
+ if (comments.length) Array.prototype.push.apply(this.props, comments);
103
+ offset = this.node.range.end;
104
+ } else {
105
+ if (inlineComment) {
106
+ const c = comments[0];
107
+ this.props.push(c);
108
+ offset = c.end;
109
+ } else {
110
+ offset = _Node.default.endOfLine(src, start + 1);
111
+ }
112
+ }
113
+
93
114
  const end = this.node ? this.node.valueRange.end : offset;
94
115
  this.valueRange = new _Range.default(start, end);
95
116
  return offset;
@@ -14,22 +14,6 @@ var _Range = _interopRequireDefault(require("./Range"));
14
14
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
15
 
16
16
  class Directive extends _Node.default {
17
- static endOfDirective(src, offset) {
18
- let ch = src[offset];
19
-
20
- while (ch && ch !== '\n' && ch !== '#') ch = src[offset += 1]; // last char can't be whitespace
21
-
22
-
23
- ch = src[offset - 1];
24
-
25
- while (ch === ' ' || ch === '\t') {
26
- offset -= 1;
27
- ch = src[offset - 1];
28
- }
29
-
30
- return offset;
31
- }
32
-
33
17
  constructor() {
34
18
  super(_constants.Type.DIRECTIVE);
35
19
  this.name = null;
package/dist/cst/Node.js CHANGED
@@ -7,7 +7,7 @@ exports.default = void 0;
7
7
 
8
8
  var _constants = require("../constants");
9
9
 
10
- var _getLinePos = _interopRequireDefault(require("./getLinePos"));
10
+ var _sourceUtils = require("./source-utils");
11
11
 
12
12
  var _Range = _interopRequireDefault(require("./Range"));
13
13
 
@@ -114,11 +114,6 @@ class Node {
114
114
  return ch === '\n' || ch === '\t' || ch === ' ' || endAsBlank && !ch;
115
115
  }
116
116
 
117
- static atCollectionItem(src, offset) {
118
- const ch = src[offset];
119
- return (ch === '?' || ch === ':' || ch === '-') && Node.atBlank(src, offset + 1, true);
120
- }
121
-
122
117
  static nextNodeIsIndented(ch, indentDiff, indicatorAsIndent) {
123
118
  if (!ch || indentDiff < 0) return false;
124
119
  if (indentDiff > 0) return true;
@@ -171,7 +166,10 @@ class Node {
171
166
  }
172
167
 
173
168
  constructor(type, props, context) {
174
- this.context = context || null;
169
+ Object.defineProperty(this, 'context', {
170
+ value: context || null,
171
+ writable: true
172
+ });
175
173
  this.error = null;
176
174
  this.range = null;
177
175
  this.valueRange = null;
@@ -260,9 +258,9 @@ class Node {
260
258
 
261
259
  get rangeAsLinePos() {
262
260
  if (!this.range || !this.context) return undefined;
263
- const start = (0, _getLinePos.default)(this.range.start, this.context.root);
261
+ const start = (0, _sourceUtils.getLinePos)(this.range.start, this.context.root);
264
262
  if (!start) return undefined;
265
- const end = (0, _getLinePos.default)(this.range.end, this.context.root);
263
+ const end = (0, _sourceUtils.getLinePos)(this.range.end, this.context.root);
266
264
  return {
267
265
  start,
268
266
  end
@@ -33,6 +33,41 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
33
33
 
34
34
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
35
35
 
36
+ function createNewNode(type, props) {
37
+ switch (type) {
38
+ case _constants.Type.ALIAS:
39
+ return new _Alias.default(type, props);
40
+
41
+ case _constants.Type.BLOCK_FOLDED:
42
+ case _constants.Type.BLOCK_LITERAL:
43
+ return new _BlockValue.default(type, props);
44
+
45
+ case _constants.Type.FLOW_MAP:
46
+ case _constants.Type.FLOW_SEQ:
47
+ return new _FlowCollection.default(type, props);
48
+
49
+ case _constants.Type.MAP_KEY:
50
+ case _constants.Type.MAP_VALUE:
51
+ case _constants.Type.SEQ_ITEM:
52
+ return new _CollectionItem.default(type, props);
53
+
54
+ case _constants.Type.COMMENT:
55
+ case _constants.Type.PLAIN:
56
+ return new _PlainValue.default(type, props);
57
+
58
+ case _constants.Type.QUOTE_DOUBLE:
59
+ return new _QuoteDouble.default(type, props);
60
+
61
+ case _constants.Type.QUOTE_SINGLE:
62
+ return new _QuoteSingle.default(type, props);
63
+
64
+ /* istanbul ignore next */
65
+
66
+ default:
67
+ return null;
68
+ // should never happen
69
+ }
70
+ }
36
71
  /**
37
72
  * @param {boolean} atLineStart - Node starts at beginning of line
38
73
  * @param {boolean} inFlow - true if currently in a flow context
@@ -42,6 +77,8 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
42
77
  * @param {Node} parent - The parent of the node
43
78
  * @param {string} src - Source of the YAML document
44
79
  */
80
+
81
+
45
82
  class ParseContext {
46
83
  static parseType(src, offset, inFlow) {
47
84
  switch (src[offset]) {
@@ -96,52 +133,14 @@ class ParseContext {
96
133
  type,
97
134
  valueStart
98
135
  } = context.parseProps(start);
99
- let node;
100
-
101
- switch (type) {
102
- case _constants.Type.ALIAS:
103
- node = new _Alias.default(type, props);
104
- break;
105
-
106
- case _constants.Type.BLOCK_FOLDED:
107
- case _constants.Type.BLOCK_LITERAL:
108
- node = new _BlockValue.default(type, props);
109
- break;
110
-
111
- case _constants.Type.FLOW_MAP:
112
- case _constants.Type.FLOW_SEQ:
113
- node = new _FlowCollection.default(type, props);
114
- break;
115
-
116
- case _constants.Type.MAP_KEY:
117
- case _constants.Type.MAP_VALUE:
118
- case _constants.Type.SEQ_ITEM:
119
- node = new _CollectionItem.default(type, props);
120
- break;
121
-
122
- case _constants.Type.COMMENT:
123
- case _constants.Type.PLAIN:
124
- node = new _PlainValue.default(type, props);
125
- break;
126
-
127
- case _constants.Type.QUOTE_DOUBLE:
128
- node = new _QuoteDouble.default(type, props);
129
- break;
130
-
131
- case _constants.Type.QUOTE_SINGLE:
132
- node = new _QuoteSingle.default(type, props);
133
- break;
134
-
135
- default:
136
- node.error = new _errors.YAMLSyntaxError(node, `Unknown node type: ${JSON.stringify(type)}`);
137
- node.range = new _Range.default(start, start + 1);
138
- return node;
139
- }
140
-
136
+ const node = createNewNode(type, props);
141
137
  let offset = node.parse(context, valueStart);
142
138
  node.range = new _Range.default(start, offset);
139
+ /* istanbul ignore if */
143
140
 
144
141
  if (offset <= start) {
142
+ // This should never happen, but if it does, let's make sure to at least
143
+ // step one character forward to avoid a busy loop.
145
144
  node.error = new Error(`Node#parse consumed no characters`);
146
145
  node.error.parseEnd = offset;
147
146
  node.error.source = node;
@@ -170,19 +169,6 @@ class ParseContext {
170
169
  this.parent = parent != null ? parent : orig.parent || {};
171
170
  this.root = orig.root;
172
171
  this.src = orig.src;
173
- } // for logging
174
-
175
-
176
- get pretty() {
177
- const obj = {
178
- start: `${this.lineStart} + ${this.indent}`,
179
- in: [],
180
- parent: this.parent.type
181
- };
182
- if (!this.atLineStart) obj.start += ' + N';
183
- if (this.inCollection) obj.in.push('collection');
184
- if (this.inFlow) obj.in.push('flow');
185
- return obj;
186
172
  }
187
173
 
188
174
  nodeStartsCollection(node) {
@@ -19,7 +19,7 @@ class PlainValue extends _Node.default {
19
19
  while (ch && ch !== '\n') {
20
20
  if (inFlow && (ch === '[' || ch === ']' || ch === '{' || ch === '}' || ch === ',')) break;
21
21
  const next = src[offset + 1];
22
- if (ch === ':' && (next === '\n' || next === '\t' || next === ' ' || inFlow && next === ',')) break;
22
+ if (ch === ':' && (!next || next === '\n' || next === '\t' || next === ' ' || inFlow && next === ',')) break;
23
23
  if ((ch === ' ' || ch === '\t') && next === '#') break;
24
24
  offset += 1;
25
25
  ch = next;
@@ -0,0 +1,178 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getLinePos = getLinePos;
7
+ exports.getLine = getLine;
8
+ exports.getPrettyContext = getPrettyContext;
9
+
10
+ function findLineStarts(src) {
11
+ const ls = [0];
12
+ let offset = src.indexOf('\n');
13
+
14
+ while (offset !== -1) {
15
+ offset += 1;
16
+ ls.push(offset);
17
+ offset = src.indexOf('\n', offset);
18
+ }
19
+
20
+ return ls;
21
+ }
22
+
23
+ function getSrcInfo(cst) {
24
+ let lineStarts, src;
25
+
26
+ if (typeof cst === 'string') {
27
+ lineStarts = findLineStarts(cst);
28
+ src = cst;
29
+ } else {
30
+ if (Array.isArray(cst)) cst = cst[0];
31
+
32
+ if (cst && cst.context) {
33
+ if (!cst.lineStarts) cst.lineStarts = findLineStarts(cst.context.src);
34
+ lineStarts = cst.lineStarts;
35
+ src = cst.context.src;
36
+ }
37
+ }
38
+
39
+ return {
40
+ lineStarts,
41
+ src
42
+ };
43
+ }
44
+ /**
45
+ * @typedef {Object} LinePos - One-indexed position in the source
46
+ * @property {number} line
47
+ * @property {number} col
48
+ */
49
+
50
+ /**
51
+ * Determine the line/col position matching a character offset.
52
+ *
53
+ * Accepts a source string or a CST document as the second parameter. With
54
+ * the latter, starting indices for lines are cached in the document as
55
+ * `lineStarts: number[]`.
56
+ *
57
+ * Returns a one-indexed `{ line, col }` location if found, or
58
+ * `undefined` otherwise.
59
+ *
60
+ * @param {number} offset
61
+ * @param {string|Document|Document[]} cst
62
+ * @returns {?LinePos}
63
+ */
64
+
65
+
66
+ function getLinePos(offset, cst) {
67
+ if (typeof offset !== 'number' || offset < 0) return null;
68
+ const {
69
+ lineStarts,
70
+ src
71
+ } = getSrcInfo(cst);
72
+ if (!lineStarts || !src || offset > src.length) return null;
73
+
74
+ for (let i = 0; i < lineStarts.length; ++i) {
75
+ const start = lineStarts[i];
76
+
77
+ if (offset < start) {
78
+ return {
79
+ line: i,
80
+ col: offset - lineStarts[i - 1] + 1
81
+ };
82
+ }
83
+
84
+ if (offset === start) return {
85
+ line: i + 1,
86
+ col: 1
87
+ };
88
+ }
89
+
90
+ const line = lineStarts.length;
91
+ return {
92
+ line,
93
+ col: offset - lineStarts[line - 1] + 1
94
+ };
95
+ }
96
+ /**
97
+ * Get a specified line from the source.
98
+ *
99
+ * Accepts a source string or a CST document as the second parameter. With
100
+ * the latter, starting indices for lines are cached in the document as
101
+ * `lineStarts: number[]`.
102
+ *
103
+ * Returns the line as a string if found, or `null` otherwise.
104
+ *
105
+ * @param {number} line One-indexed line number
106
+ * @param {string|Document|Document[]} cst
107
+ * @returns {?string}
108
+ */
109
+
110
+
111
+ function getLine(line, cst) {
112
+ const {
113
+ lineStarts,
114
+ src
115
+ } = getSrcInfo(cst);
116
+ if (!lineStarts || !(line >= 1) || line > lineStarts.length) return null;
117
+ const start = lineStarts[line - 1];
118
+ let end = lineStarts[line]; // undefined for last line; that's ok for slice()
119
+
120
+ while (end && end > start && src[end - 1] === '\n') --end;
121
+
122
+ return src.slice(start, end);
123
+ }
124
+ /**
125
+ * Pretty-print the starting line from the source indicated by the range `pos`
126
+ *
127
+ * Trims output to `maxWidth` chars while keeping the starting column visible,
128
+ * using `…` at either end to indicate dropped characters.
129
+ *
130
+ * Returns a two-line string (or `null`) with `\n` as separator; the second line
131
+ * will hold appropriately indented `^` marks indicating the column range.
132
+ *
133
+ * @param {Object} pos
134
+ * @param {LinePos} pos.start
135
+ * @param {LinePos} [pos.end]
136
+ * @param {string|Document|Document[]*} cst
137
+ * @param {number} [maxWidth=80]
138
+ * @returns {?string}
139
+ */
140
+
141
+
142
+ function getPrettyContext({
143
+ start,
144
+ end
145
+ }, cst, maxWidth = 80) {
146
+ let src = getLine(start.line, cst);
147
+ if (!src) return null;
148
+ let {
149
+ col
150
+ } = start;
151
+
152
+ if (src.length > maxWidth) {
153
+ if (col <= maxWidth - 10) {
154
+ src = src.substr(0, maxWidth - 1) + '…';
155
+ } else {
156
+ const halfWidth = Math.round(maxWidth / 2);
157
+ if (src.length > col + halfWidth) src = src.substr(0, col + halfWidth - 1) + '…';
158
+ col -= src.length - maxWidth;
159
+ src = '…' + src.substr(1 - maxWidth);
160
+ }
161
+ }
162
+
163
+ let errLen = 1;
164
+ let errEnd = '';
165
+
166
+ if (end) {
167
+ if (end.line === start.line && col + (end.col - start.col) <= maxWidth + 1) {
168
+ errLen = end.col - start.col;
169
+ } else {
170
+ errLen = Math.min(src.length + 1, maxWidth) - col;
171
+ errEnd = '…';
172
+ }
173
+ }
174
+
175
+ const offset = col > 1 ? ' '.repeat(col - 1) : '';
176
+ const err = '^'.repeat(errLen);
177
+ return `${src}\n${offset}${err}${errEnd}`;
178
+ }
package/dist/errors.js CHANGED
@@ -7,6 +7,10 @@ exports.YAMLWarning = exports.YAMLSyntaxError = exports.YAMLSemanticError = expo
7
7
 
8
8
  var _Node = _interopRequireDefault(require("./cst/Node"));
9
9
 
10
+ var _sourceUtils = require("./cst/source-utils");
11
+
12
+ var _Range = _interopRequireDefault(require("./cst/Range"));
13
+
10
14
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
15
 
12
16
  class YAMLError extends Error {
@@ -19,12 +23,42 @@ class YAMLError extends Error {
19
23
  }
20
24
 
21
25
  makePretty() {
22
- if (this.source) {
23
- this.nodeType = this.source.type;
26
+ if (!this.source) return;
27
+ this.nodeType = this.source.type;
28
+ const cst = this.source.context && this.source.context.root;
29
+
30
+ if (typeof this.offset === 'number') {
31
+ this.range = new _Range.default(this.offset, this.offset + 1);
32
+ const start = cst && (0, _sourceUtils.getLinePos)(this.offset, cst);
33
+
34
+ if (start) {
35
+ const end = {
36
+ line: start.line,
37
+ col: start.col + 1
38
+ };
39
+ this.linePos = {
40
+ start,
41
+ end
42
+ };
43
+ }
44
+
45
+ delete this.offset;
46
+ } else {
24
47
  this.range = this.source.range;
25
48
  this.linePos = this.source.rangeAsLinePos;
26
- delete this.source;
27
49
  }
50
+
51
+ if (this.linePos) {
52
+ const {
53
+ line,
54
+ col
55
+ } = this.linePos.start;
56
+ this.message += ` at line ${line}, column ${col}`;
57
+ const ctx = cst && (0, _sourceUtils.getPrettyContext)(this.linePos, cst);
58
+ if (ctx) this.message += `:\n\n${ctx}\n`;
59
+ }
60
+
61
+ delete this.source;
28
62
  }
29
63
 
30
64
  }
package/dist/index.js CHANGED
@@ -13,9 +13,10 @@ var _errors = require("./errors");
13
13
 
14
14
  var _schema = _interopRequireDefault(require("./schema"));
15
15
 
16
+ var _warnings = require("./warnings");
17
+
16
18
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
19
 
18
- /* global console */
19
20
  const defaultOptions = {
20
21
  anchorPrefix: 'a',
21
22
  customTags: null,
@@ -26,6 +27,7 @@ const defaultOptions = {
26
27
  maxAliasCount: 100,
27
28
  prettyErrors: false,
28
29
  // TODO Set true in v2
30
+ simpleKeys: false,
29
31
  version: '1.2'
30
32
  };
31
33
 
@@ -74,9 +76,8 @@ function parseDocument(src, options) {
74
76
  }
75
77
 
76
78
  function parse(src, options) {
77
- const doc = parseDocument(src, options); // eslint-disable-next-line no-console
78
-
79
- doc.warnings.forEach(warning => console.warn(warning));
79
+ const doc = parseDocument(src, options);
80
+ doc.warnings.forEach(warning => (0, _warnings.warn)(warning));
80
81
  if (doc.errors.length > 0) throw doc.errors[0];
81
82
  return doc.toJSON();
82
83
  }
@@ -77,8 +77,9 @@ class Alias extends _Node.default {
77
77
  maxAliasCount
78
78
  } = ctx;
79
79
  const anchor = anchors.find(a => a.node === this.source);
80
+ /* istanbul ignore if */
80
81
 
81
- if (!anchor || !anchor.res) {
82
+ if (!anchor || anchor.res === undefined) {
82
83
  const msg = 'This should not happen: Alias anchor was not resolved?';
83
84
  if (this.cstNode) throw new _errors.YAMLReferenceError(this.cstNode, msg);else throw new ReferenceError(msg);
84
85
  }
@@ -17,23 +17,38 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
17
17
 
18
18
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
19
19
 
20
- // null, undefined, or an empty non-string iterable (e.g. [])
20
+ function collectionFromPath(schema, path, value) {
21
+ let v = value;
22
+
23
+ for (let i = path.length - 1; i >= 0; --i) {
24
+ const k = path[i];
25
+ const o = Number.isInteger(k) && k >= 0 ? [] : {};
26
+ o[k] = v;
27
+ v = o;
28
+ }
29
+
30
+ return schema.createNode(v, false);
31
+ } // null, undefined, or an empty non-string iterable (e.g. [])
32
+
33
+
21
34
  const isEmptyPath = path => path == null || typeof path === 'object' && path[Symbol.iterator]().next().done;
22
35
 
23
36
  exports.isEmptyPath = isEmptyPath;
24
37
 
25
38
  class Collection extends _Node.default {
26
- constructor(...args) {
27
- super(...args);
39
+ constructor(schema) {
40
+ super();
28
41
 
29
42
  _defineProperty(this, "items", []);
43
+
44
+ this.schema = schema;
30
45
  }
31
46
 
32
47
  addIn(path, value) {
33
48
  if (isEmptyPath(path)) this.add(value);else {
34
49
  const [key, ...rest] = path;
35
50
  const node = this.get(key, true);
36
- if (node instanceof Collection) node.addIn(rest, value);else throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
51
+ if (node instanceof Collection) node.addIn(rest, value);else if (node === undefined && this.schema) this.set(key, collectionFromPath(this.schema, rest, value));else throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
37
52
  }
38
53
  }
39
54
 
@@ -67,10 +82,12 @@ class Collection extends _Node.default {
67
82
  this.set(key, value);
68
83
  } else {
69
84
  const node = this.get(key, true);
70
- if (node instanceof Collection) node.setIn(rest, value);else throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
85
+ if (node instanceof Collection) node.setIn(rest, value);else if (node === undefined && this.schema) this.set(key, collectionFromPath(this.schema, rest, value));else throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
71
86
  }
72
87
  } // overridden in implementations
73
88
 
89
+ /* istanbul ignore next */
90
+
74
91
 
75
92
  toJSON() {
76
93
  return null;
@@ -28,11 +28,19 @@ function findPair(items, key) {
28
28
  }
29
29
 
30
30
  class YAMLMap extends _Collection.default {
31
- add(pair) {
31
+ add(pair, overwrite) {
32
32
  if (!pair) pair = new _Pair.default(pair);else if (!(pair instanceof _Pair.default)) pair = new _Pair.default(pair.key || pair, pair.value);
33
33
  const prev = findPair(this.items, pair.key);
34
- if (prev) throw new Error(`Key ${pair.key} already set`);
35
- this.items.push(pair);
34
+ const sortEntries = this.schema && this.schema.sortMapEntries;
35
+
36
+ if (prev) {
37
+ if (overwrite) prev.value = pair.value;else throw new Error(`Key ${pair.key} already set`);
38
+ } else if (sortEntries) {
39
+ const i = this.items.findIndex(item => sortEntries(pair, item) < 0);
40
+ if (i === -1) this.items.push(pair);else this.items.splice(i, 0, pair);
41
+ } else {
42
+ this.items.push(pair);
43
+ }
36
44
  }
37
45
 
38
46
  delete(key) {
@@ -53,8 +61,7 @@ class YAMLMap extends _Collection.default {
53
61
  }
54
62
 
55
63
  set(key, value) {
56
- const prev = findPair(this.items, key);
57
- if (prev) prev.value = value;else this.items.push(new _Pair.default(key, value));
64
+ this.add(new _Pair.default(key, value), true);
58
65
  }
59
66
  /**
60
67
  * @param {*} arg ignored
@@ -46,10 +46,9 @@ class Merge extends _Pair.default {
46
46
 
47
47
 
48
48
  addToJSMap(ctx, map) {
49
- for (const _ref of this.value.items) {
50
- const {
51
- source
52
- } = _ref;
49
+ for (const {
50
+ source
51
+ } of this.value.items) {
53
52
  if (!(source instanceof _Map.default)) throw new Error('Merge sources must be maps');
54
53
  const srcMap = source.toJSON(null, ctx, Map);
55
54
 
@@ -59,7 +58,7 @@ class Merge extends _Pair.default {
59
58
  } else if (map instanceof Set) {
60
59
  map.add(key);
61
60
  } else {
62
- if (!map.hasOwnProperty(key)) map[key] = value;
61
+ if (!Object.prototype.hasOwnProperty.call(map, key)) map[key] = value;
63
62
  }
64
63
  }
65
64
  }