yaml 2.0.0-5 → 2.0.0-9

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 (94) hide show
  1. package/browser/dist/compose/compose-doc.js +1 -1
  2. package/browser/dist/compose/compose-node.js +10 -1
  3. package/browser/dist/compose/compose-scalar.js +2 -1
  4. package/browser/dist/compose/composer.js +3 -2
  5. package/browser/dist/compose/resolve-block-map.js +15 -5
  6. package/browser/dist/compose/resolve-block-scalar.js +2 -2
  7. package/browser/dist/compose/resolve-block-seq.js +1 -1
  8. package/browser/dist/compose/resolve-end.js +2 -2
  9. package/browser/dist/compose/resolve-flow-collection.js +14 -6
  10. package/browser/dist/compose/resolve-flow-scalar.js +19 -7
  11. package/browser/dist/compose/resolve-props.js +30 -7
  12. package/browser/dist/compose/util-map-includes.js +17 -0
  13. package/browser/dist/doc/Document.js +26 -2
  14. package/browser/dist/doc/createNode.js +11 -5
  15. package/browser/dist/doc/directives.js +5 -0
  16. package/browser/dist/node_modules/tslib/tslib.es6.js +164 -0
  17. package/browser/dist/nodes/Collection.js +28 -15
  18. package/browser/dist/nodes/Node.js +7 -0
  19. package/browser/dist/nodes/Pair.js +9 -1
  20. package/browser/dist/nodes/addPairToJSMap.js +4 -3
  21. package/browser/dist/options.js +2 -0
  22. package/browser/dist/parse/cst-scalar.js +2 -6
  23. package/browser/dist/parse/lexer.js +64 -31
  24. package/browser/dist/parse/parser.js +53 -52
  25. package/browser/dist/schema/Schema.js +5 -0
  26. package/browser/dist/schema/tags.js +9 -5
  27. package/browser/dist/stringify/stringify.js +2 -1
  28. package/browser/dist/stringify/stringifyCollection.js +23 -9
  29. package/browser/dist/stringify/stringifyComment.js +14 -0
  30. package/browser/dist/stringify/stringifyDocument.js +8 -5
  31. package/browser/dist/stringify/stringifyPair.js +5 -7
  32. package/browser/dist/stringify/stringifyString.js +35 -34
  33. package/browser/dist/util.js +3 -0
  34. package/dist/compose/compose-doc.js +1 -1
  35. package/dist/compose/compose-node.js +10 -1
  36. package/dist/compose/compose-scalar.js +2 -1
  37. package/dist/compose/composer.js +3 -2
  38. package/dist/compose/resolve-block-map.d.ts +2 -1
  39. package/dist/compose/resolve-block-map.js +15 -5
  40. package/dist/compose/resolve-block-scalar.js +2 -2
  41. package/dist/compose/resolve-block-seq.js +1 -1
  42. package/dist/compose/resolve-end.js +2 -2
  43. package/dist/compose/resolve-flow-collection.js +14 -6
  44. package/dist/compose/resolve-flow-scalar.js +19 -7
  45. package/dist/compose/resolve-props.d.ts +3 -4
  46. package/dist/compose/resolve-props.js +30 -7
  47. package/dist/compose/util-map-includes.d.ts +4 -0
  48. package/dist/compose/util-map-includes.js +19 -0
  49. package/dist/doc/Document.d.ts +10 -2
  50. package/dist/doc/Document.js +25 -1
  51. package/dist/doc/createNode.d.ts +2 -1
  52. package/dist/doc/createNode.js +10 -4
  53. package/dist/doc/directives.d.ts +1 -0
  54. package/dist/doc/directives.js +5 -0
  55. package/dist/errors.d.ts +1 -1
  56. package/dist/index.d.ts +2 -2
  57. package/dist/node_modules/tslib/tslib.es6.js +76 -0
  58. package/dist/nodes/Alias.d.ts +7 -3
  59. package/dist/nodes/Collection.d.ts +10 -4
  60. package/dist/nodes/Collection.js +27 -14
  61. package/dist/nodes/Node.d.ts +10 -3
  62. package/dist/nodes/Node.js +7 -0
  63. package/dist/nodes/Pair.d.ts +7 -2
  64. package/dist/nodes/Pair.js +8 -0
  65. package/dist/nodes/Scalar.d.ts +2 -0
  66. package/dist/nodes/YAMLMap.d.ts +2 -0
  67. package/dist/nodes/YAMLSeq.d.ts +2 -0
  68. package/dist/nodes/addPairToJSMap.js +3 -2
  69. package/dist/options.d.ts +40 -3
  70. package/dist/options.js +2 -0
  71. package/dist/parse/cst-scalar.d.ts +6 -0
  72. package/dist/parse/cst-scalar.js +2 -6
  73. package/dist/parse/lexer.d.ts +3 -1
  74. package/dist/parse/lexer.js +64 -31
  75. package/dist/parse/parser.d.ts +1 -0
  76. package/dist/parse/parser.js +53 -52
  77. package/dist/schema/Schema.d.ts +1 -0
  78. package/dist/schema/Schema.js +5 -0
  79. package/dist/schema/tags.js +9 -5
  80. package/dist/stringify/stringify.js +2 -1
  81. package/dist/stringify/stringifyCollection.d.ts +1 -1
  82. package/dist/stringify/stringifyCollection.js +24 -10
  83. package/dist/stringify/stringifyComment.d.ts +2 -0
  84. package/dist/stringify/{addComment.js → stringifyComment.js} +5 -1
  85. package/dist/stringify/stringifyDocument.js +9 -6
  86. package/dist/stringify/stringifyPair.js +9 -11
  87. package/dist/stringify/stringifyString.js +35 -34
  88. package/dist/test-events.d.ts +1 -1
  89. package/dist/util.d.ts +3 -0
  90. package/dist/util.js +6 -0
  91. package/package.json +9 -8
  92. package/util.d.ts +3 -0
  93. package/browser/dist/stringify/addComment.js +0 -11
  94. package/dist/stringify/addComment.d.ts +0 -2
@@ -13,19 +13,14 @@ function collectionFromPath(schema, path, value) {
13
13
  v = a;
14
14
  }
15
15
  else {
16
- const o = {};
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;
16
+ v = new Map([[k, v]]);
24
17
  }
25
18
  }
26
19
  return createNode.createNode(v, undefined, {
27
- onAnchor() {
28
- throw new Error('Repeated objects are not supported here');
20
+ aliasDuplicateObjects: false,
21
+ keepUndefined: false,
22
+ onAnchor: () => {
23
+ throw new Error('This should not happen, please report a bug.');
29
24
  },
30
25
  schema,
31
26
  sourceObjects: new Map()
@@ -44,6 +39,20 @@ class Collection extends Node.NodeBase {
44
39
  writable: true
45
40
  });
46
41
  }
42
+ /**
43
+ * Create a copy of this collection.
44
+ *
45
+ * @param schema - If defined, overwrites the original's schema
46
+ */
47
+ clone(schema) {
48
+ const copy = Object.create(Object.getPrototypeOf(this), Object.getOwnPropertyDescriptors(this));
49
+ if (schema)
50
+ copy.schema = schema;
51
+ copy.items = copy.items.map(it => Node.isNode(it) || Node.isPair(it) ? it.clone(schema) : it);
52
+ if (this.range)
53
+ copy.range = this.range.slice();
54
+ return copy;
55
+ }
47
56
  /**
48
57
  * Adds a value to the collection. For `!!map` and `!!omap` the value must
49
58
  * be a Pair instance or a `{ key, value }` object, which may not have a key
@@ -67,7 +76,8 @@ class Collection extends Node.NodeBase {
67
76
  * Removes a value from the collection.
68
77
  * @returns `true` if the item was found and removed.
69
78
  */
70
- deleteIn([key, ...rest]) {
79
+ deleteIn(path) {
80
+ const [key, ...rest] = path;
71
81
  if (rest.length === 0)
72
82
  return this.delete(key);
73
83
  const node = this.get(key, true);
@@ -81,7 +91,8 @@ class Collection extends Node.NodeBase {
81
91
  * scalar values from their surrounding node; to disable set `keepScalar` to
82
92
  * `true` (collections are always returned intact).
83
93
  */
84
- getIn([key, ...rest], keepScalar) {
94
+ getIn(path, keepScalar) {
95
+ const [key, ...rest] = path;
85
96
  const node = this.get(key, true);
86
97
  if (rest.length === 0)
87
98
  return !keepScalar && Node.isScalar(node) ? node.value : node;
@@ -105,7 +116,8 @@ class Collection extends Node.NodeBase {
105
116
  /**
106
117
  * Checks if the collection includes a value with the key `key`.
107
118
  */
108
- hasIn([key, ...rest]) {
119
+ hasIn(path) {
120
+ const [key, ...rest] = path;
109
121
  if (rest.length === 0)
110
122
  return this.has(key);
111
123
  const node = this.get(key, true);
@@ -115,7 +127,8 @@ class Collection extends Node.NodeBase {
115
127
  * Sets a value in this collection. For `!!set`, `value` needs to be a
116
128
  * boolean to add/remove the item from the set.
117
129
  */
118
- setIn([key, ...rest], value) {
130
+ setIn(path, value) {
131
+ const [key, ...rest] = path;
119
132
  if (rest.length === 0) {
120
133
  this.set(key, value);
121
134
  }
@@ -1,4 +1,5 @@
1
1
  import type { Document } from '../doc/Document.js';
2
+ import { Token } from '../parse/cst.js';
2
3
  import type { StringifyContext } from '../stringify/stringify.js';
3
4
  import type { Alias } from './Alias.js';
4
5
  import type { Pair } from './Pair.js';
@@ -23,7 +24,7 @@ export declare const isScalar: (node: any) => node is Scalar<unknown>;
23
24
  export declare const isSeq: (node: any) => node is YAMLSeq<unknown>;
24
25
  export declare function isCollection(node: any): node is YAMLMap | YAMLSeq;
25
26
  export declare function isNode(node: any): node is Node;
26
- export declare const hasAnchor: (node: unknown) => node is YAMLMap<unknown, unknown> | YAMLSeq<unknown> | Scalar<unknown>;
27
+ export declare const hasAnchor: (node: unknown) => node is Scalar<unknown> | YAMLMap<unknown, unknown> | YAMLSeq<unknown>;
27
28
  export declare abstract class NodeBase {
28
29
  readonly [NODE_TYPE]: symbol;
29
30
  /** A comment on or immediately after this */
@@ -31,16 +32,22 @@ export declare abstract class NodeBase {
31
32
  /** A comment before this */
32
33
  commentBefore?: string | null;
33
34
  /**
34
- * The [start, value-end, node-end] character offsets for the part of the
35
- * source parsed into this node (undefined if not parsed).
35
+ * The `[start, value-end, node-end]` character offsets for the part of the
36
+ * source parsed into this node (undefined if not parsed). The `value-end`
37
+ * and `node-end` positions are themselves not included in their respective
38
+ * ranges.
36
39
  */
37
40
  range?: Range | null;
38
41
  /** A blank line before this node and its commentBefore */
39
42
  spaceBefore?: boolean;
43
+ /** The CST token that was composed into this node. */
44
+ srcToken?: Token;
40
45
  /** A fully qualified tag, if required */
41
46
  tag?: string;
42
47
  /** A plain JS representation of this node */
43
48
  abstract toJSON(): any;
44
49
  abstract toString(ctx?: StringifyContext, onComment?: () => void, onChompKeep?: () => void): string;
45
50
  constructor(type: symbol);
51
+ /** Create a copy of this node. */
52
+ clone(): NodeBase;
46
53
  }
@@ -38,6 +38,13 @@ class NodeBase {
38
38
  constructor(type) {
39
39
  Object.defineProperty(this, NODE_TYPE, { value: type });
40
40
  }
41
+ /** Create a copy of this node. */
42
+ clone() {
43
+ const copy = Object.create(Object.getPrototypeOf(this), Object.getOwnPropertyDescriptors(this));
44
+ if (this.range)
45
+ copy.range = this.range.slice();
46
+ return copy;
47
+ }
41
48
  }
42
49
 
43
50
  exports.ALIAS = ALIAS;
@@ -1,8 +1,10 @@
1
1
  import { CreateNodeContext } from '../doc/createNode.js';
2
- import { StringifyContext } from '../stringify/stringify.js';
2
+ import type { CollectionItem } from '../parse/cst.js';
3
+ import type { Schema } from '../schema/Schema.js';
4
+ import type { StringifyContext } from '../stringify/stringify.js';
3
5
  import { addPairToJSMap } from './addPairToJSMap.js';
4
6
  import { NODE_TYPE } from './Node.js';
5
- import { ToJSContext } from './toJS.js';
7
+ import type { ToJSContext } from './toJS.js';
6
8
  export declare function createPair(key: unknown, value: unknown, ctx: CreateNodeContext): Pair<import("./Node.js").Node, import("./Alias.js").Alias | import("./Scalar.js").Scalar<unknown> | import("./YAMLMap.js").YAMLMap<unknown, unknown> | import("./YAMLSeq.js").YAMLSeq<unknown>>;
7
9
  export declare class Pair<K = unknown, V = unknown> {
8
10
  readonly [NODE_TYPE]: symbol;
@@ -10,7 +12,10 @@ export declare class Pair<K = unknown, V = unknown> {
10
12
  key: K;
11
13
  /** Always Node or null when parsed, but can be set to anything. */
12
14
  value: V | null;
15
+ /** The CST token that was composed into this pair. */
16
+ srcToken?: CollectionItem;
13
17
  constructor(key: K, value?: V | null);
18
+ clone(schema?: Schema): Pair<K, V>;
14
19
  toJSON(_?: unknown, ctx?: ToJSContext): ReturnType<typeof addPairToJSMap>;
15
20
  toString(ctx?: StringifyContext, onComment?: () => void, onChompKeep?: () => void): string;
16
21
  }
@@ -16,6 +16,14 @@ class Pair {
16
16
  this.key = key;
17
17
  this.value = value;
18
18
  }
19
+ clone(schema) {
20
+ let { key, value } = this;
21
+ if (Node.isNode(key))
22
+ key = key.clone(schema);
23
+ if (Node.isNode(value))
24
+ value = value.clone(schema);
25
+ return new Pair(key, value);
26
+ }
19
27
  toJSON(_, ctx) {
20
28
  const pair = ctx && ctx.mapAsMap ? new Map() : {};
21
29
  return addPairToJSMap.addPairToJSMap(ctx, pair, this);
@@ -1,3 +1,4 @@
1
+ import type { BlockScalar, FlowScalar } from '../parse/cst.js';
1
2
  import { NodeBase, Range } from './Node.js';
2
3
  import { ToJSContext } from './toJS.js';
3
4
  export declare const isScalarValue: (value: unknown) => boolean;
@@ -5,6 +6,7 @@ export declare namespace Scalar {
5
6
  interface Parsed extends Scalar {
6
7
  range: Range;
7
8
  source: string;
9
+ srcToken?: FlowScalar | BlockScalar;
8
10
  }
9
11
  type BLOCK_FOLDED = 'BLOCK_FOLDED';
10
12
  type BLOCK_LITERAL = 'BLOCK_LITERAL';
@@ -1,3 +1,4 @@
1
+ import type { BlockMap, FlowCollection } from '../parse/cst.js';
1
2
  import type { Schema } from '../schema/Schema.js';
2
3
  import type { StringifyContext } from '../stringify/stringify.js';
3
4
  import { Collection } from './Collection.js';
@@ -9,6 +10,7 @@ export declare namespace YAMLMap {
9
10
  interface Parsed<K extends ParsedNode = ParsedNode, V extends ParsedNode | null = ParsedNode | null> extends YAMLMap<K, V> {
10
11
  items: Pair<K, V>[];
11
12
  range: Range;
13
+ srcToken?: BlockMap | FlowCollection;
12
14
  }
13
15
  }
14
16
  export declare class YAMLMap<K = unknown, V = unknown> extends Collection {
@@ -1,3 +1,4 @@
1
+ import type { BlockSequence, FlowCollection } from '../parse/cst.js';
1
2
  import type { Schema } from '../schema/Schema.js';
2
3
  import type { StringifyContext } from '../stringify/stringify.js';
3
4
  import { Collection } from './Collection.js';
@@ -8,6 +9,7 @@ export declare namespace YAMLSeq {
8
9
  interface Parsed<T extends ParsedNode | Pair<ParsedNode, ParsedNode | null> = ParsedNode> extends YAMLSeq<T> {
9
10
  items: T[];
10
11
  range: Range;
12
+ srcToken?: BlockSequence | FlowCollection;
11
13
  }
12
14
  }
13
15
  export declare class YAMLSeq<T = unknown> extends Collection {
@@ -9,6 +9,7 @@ var toJS = require('./toJS.js');
9
9
  const MERGE_KEY = '<<';
10
10
  function addPairToJSMap(ctx, map, { key, value }) {
11
11
  if (ctx && ctx.doc.schema.merge && isMergeKey(key)) {
12
+ value = Node.isAlias(value) ? value.resolve(ctx.doc) : value;
12
13
  if (Node.isSeq(value))
13
14
  for (const it of value.items)
14
15
  mergeToJSMap(ctx, map, it);
@@ -54,9 +55,9 @@ const isMergeKey = (key) => key === MERGE_KEY ||
54
55
  // Keys in mapping nodes earlier in the sequence override keys specified in
55
56
  // later mapping nodes. -- http://yaml.org/type/merge.html
56
57
  function mergeToJSMap(ctx, map, value) {
57
- const source = ctx && Node.isAlias(value) ? value.resolve(ctx.doc) : null;
58
+ const source = ctx && Node.isAlias(value) ? value.resolve(ctx.doc) : value;
58
59
  if (!Node.isMap(source))
59
- throw new Error('Merge sources must be map aliases');
60
+ throw new Error('Merge sources must be maps or map aliases');
60
61
  const srcMap = source.toJSON(null, ctx, Map);
61
62
  for (const [key, value] of srcMap) {
62
63
  if (map instanceof Map) {
package/dist/options.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import type { Reviver } from './doc/applyReviver.js';
2
2
  import type { Directives } from './doc/directives.js';
3
3
  import type { LogLevelId } from './log.js';
4
+ import type { ParsedNode } from './nodes/Node.js';
4
5
  import type { Pair } from './nodes/Pair.js';
5
6
  import type { Scalar } from './nodes/Scalar.js';
6
7
  import type { LineCounter } from './parse/line-counter.js';
@@ -16,6 +17,13 @@ export declare type ParseOptions = {
16
17
  * https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/BigInt
17
18
  */
18
19
  intAsBigInt?: boolean;
20
+ /**
21
+ * Include a `srcToken` value on each parsed `Node`, containing the CST token
22
+ * that was composed into this node.
23
+ *
24
+ * Default: `false`
25
+ */
26
+ keepSourceTokens?: boolean;
19
27
  /**
20
28
  * If set, newlines will be tracked, to allow for `lineCounter.linePos(offset)`
21
29
  * to provide the `{ line, col }` positions within the input.
@@ -34,6 +42,19 @@ export declare type ParseOptions = {
34
42
  * Default: `true`
35
43
  */
36
44
  strict?: boolean;
45
+ /**
46
+ * YAML requires map keys to be unique. By default, this is checked by
47
+ * comparing scalar values with `===`; deep equality is not checked for
48
+ * aliases or collections. If merge keys are enabled by the schema,
49
+ * multiple `<<` keys are allowed.
50
+ *
51
+ * Set `false` to disable, or provide your own comparator function to
52
+ * customise. The comparator will be passed two `ParsedNode` values, and
53
+ * is expected to return a `boolean` indicating their equality.
54
+ *
55
+ * Default: `true`
56
+ */
57
+ uniqueKeys?: boolean | ((a: ParsedNode, b: ParsedNode) => boolean);
37
58
  };
38
59
  export declare type DocumentOptions = {
39
60
  /**
@@ -84,12 +105,20 @@ export declare type SchemaOptions = {
84
105
  /**
85
106
  * When adding to or stringifying a map, sort the entries.
86
107
  * If `true`, sort by comparing key values with `<`.
108
+ * Does not affect item order when parsing.
87
109
  *
88
110
  * Default: `false`
89
111
  */
90
112
  sortMapEntries?: boolean | ((a: Pair, b: Pair) => number);
91
113
  };
92
114
  export declare type CreateNodeOptions = {
115
+ /**
116
+ * During node construction, use anchors and aliases to keep strictly equal
117
+ * non-null objects as equivalent in YAML.
118
+ *
119
+ * Default: `true`
120
+ */
121
+ aliasDuplicateObjects?: boolean;
93
122
  /**
94
123
  * Default prefix for anchors.
95
124
  *
@@ -139,6 +168,13 @@ export declare type ToJSOptions = {
139
168
  reviver?: Reviver;
140
169
  };
141
170
  export declare type ToStringOptions = {
171
+ /**
172
+ * Use block quote styles for scalar values where applicable.
173
+ * Set to `false` to disable block quotes completely.
174
+ *
175
+ * Default: `true`
176
+ */
177
+ blockQuote?: boolean | 'folded' | 'literal';
142
178
  /**
143
179
  * The default type of string literal used to stringify implicit key values.
144
180
  * Output may use other types if required to fully represent the value.
@@ -232,11 +268,12 @@ export declare type ToStringOptions = {
232
268
  */
233
269
  simpleKeys?: boolean;
234
270
  /**
235
- * Prefer 'single quote' rather than "double quote" where applicable.
271
+ * Use 'single quote' rather than "double quote" where applicable.
272
+ * Set to `false` to disable single quotes completely.
236
273
  *
237
- * Default: `false`
274
+ * Default: `null`
238
275
  */
239
- singleQuote?: boolean;
276
+ singleQuote?: boolean | null;
240
277
  /**
241
278
  * String representation for `true`.
242
279
  * With the core schema, use `'true'`, `'True'`, or `'TRUE'`.
package/dist/options.js CHANGED
@@ -9,9 +9,11 @@
9
9
  */
10
10
  const defaultOptions = {
11
11
  intAsBigInt: false,
12
+ keepSourceTokens: false,
12
13
  logLevel: 'warn',
13
14
  prettyErrors: true,
14
15
  strict: true,
16
+ uniqueKeys: true,
15
17
  version: '1.2'
16
18
  };
17
19
 
@@ -6,6 +6,12 @@ import type { BlockScalar, FlowScalar, SourceToken, Token } from './cst.js';
6
6
  * If `token` is a CST flow or block scalar, determine its string value and a few other attributes.
7
7
  * Otherwise, return `null`.
8
8
  */
9
+ export declare function resolveAsScalar(token: FlowScalar | BlockScalar, strict?: boolean, onError?: (offset: number, code: ErrorCode, message: string) => void): {
10
+ value: string;
11
+ type: Scalar.Type | null;
12
+ comment: string;
13
+ range: Range;
14
+ };
9
15
  export declare function resolveAsScalar(token: Token | null | undefined, strict?: boolean, onError?: (offset: number, code: ErrorCode, message: string) => void): {
10
16
  value: string;
11
17
  type: Scalar.Type | null;
@@ -5,10 +5,6 @@ var resolveFlowScalar = require('../compose/resolve-flow-scalar.js');
5
5
  var errors = require('../errors.js');
6
6
  var stringifyString = require('../stringify/stringifyString.js');
7
7
 
8
- /**
9
- * If `token` is a CST flow or block scalar, determine its string value and a few other attributes.
10
- * Otherwise, return `null`.
11
- */
12
8
  function resolveAsScalar(token, strict = true, onError) {
13
9
  if (token) {
14
10
  const _onError = (pos, code, message) => {
@@ -50,7 +46,7 @@ function createScalarToken(value, context) {
50
46
  implicitKey,
51
47
  indent: indent > 0 ? ' '.repeat(indent) : '',
52
48
  inFlow,
53
- options: { lineWidth: -1 }
49
+ options: { blockQuote: true, lineWidth: -1 }
54
50
  });
55
51
  const end = (_a = context.end) !== null && _a !== void 0 ? _a : [
56
52
  { type: 'newline', offset: -1, indent, source: '\n' }
@@ -119,7 +115,7 @@ function setScalarValue(token, value, context = {}) {
119
115
  implicitKey: implicitKey || indent === null,
120
116
  indent: indent !== null && indent > 0 ? ' '.repeat(indent) : '',
121
117
  inFlow,
122
- options: { lineWidth: -1 }
118
+ options: { blockQuote: true, lineWidth: -1 }
123
119
  });
124
120
  switch (source[0]) {
125
121
  case '|':
@@ -47,6 +47,8 @@ export declare class Lexer {
47
47
  private indentNext;
48
48
  /** Indentation level of the current line. */
49
49
  private indentValue;
50
+ /** Position of the next \n character. */
51
+ private lineEndPos;
50
52
  /** Stores the state of the lexer if reaching the end of incpomplete input */
51
53
  private next;
52
54
  /** A pointer to `buffer`; the current position of the lexer. */
@@ -78,7 +80,7 @@ export declare class Lexer {
78
80
  private pushCount;
79
81
  private pushToIndex;
80
82
  private pushIndicators;
81
- private pushVerbatimTag;
83
+ private pushTag;
82
84
  private pushNewline;
83
85
  private pushSpaces;
84
86
  private pushUntil;
@@ -81,9 +81,11 @@ function isEmpty(ch) {
81
81
  return false;
82
82
  }
83
83
  }
84
- const invalidFlowScalarChars = [',', '[', ']', '{', '}'];
85
- const invalidIdentifierChars = [' ', ',', '[', ']', '{', '}', '\n', '\r', '\t'];
86
- const isNotIdentifierChar = (ch) => !ch || invalidIdentifierChars.includes(ch);
84
+ const hexDigits = '0123456789ABCDEFabcdef'.split('');
85
+ const tagChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-#;/?:@&=+$_.!~*'()".split('');
86
+ const invalidFlowScalarChars = ',[]{}'.split('');
87
+ const invalidAnchorChars = ' ,[]{}\n\r\t'.split('');
88
+ const isNotAnchorChar = (ch) => !ch || invalidAnchorChars.includes(ch);
87
89
  /**
88
90
  * Splits an input string into lexical tokens, i.e. smaller strings that are
89
91
  * easily identifiable by `tokens.tokenType()`.
@@ -134,6 +136,8 @@ class Lexer {
134
136
  this.indentNext = 0;
135
137
  /** Indentation level of the current line. */
136
138
  this.indentValue = 0;
139
+ /** Position of the next \n character. */
140
+ this.lineEndPos = null;
137
141
  /** Stores the state of the lexer if reaching the end of incpomplete input */
138
142
  this.next = null;
139
143
  /** A pointer to `buffer`; the current position of the lexer. */
@@ -146,8 +150,10 @@ class Lexer {
146
150
  * @returns A generator of lexical tokens
147
151
  */
148
152
  *lex(source, incomplete = false) {
149
- if (source)
153
+ if (source) {
150
154
  this.buffer = this.buffer ? this.buffer + source : source;
155
+ this.lineEndPos = null;
156
+ }
151
157
  this.atEnd = !incomplete;
152
158
  let next = this.next || 'stream';
153
159
  while (next && (incomplete || this.hasChars(1)))
@@ -190,7 +196,11 @@ class Lexer {
190
196
  return offset;
191
197
  }
192
198
  getLine() {
193
- let end = this.buffer.indexOf('\n', this.pos);
199
+ let end = this.lineEndPos;
200
+ if (typeof end !== 'number' || (end !== -1 && end < this.pos)) {
201
+ end = this.buffer.indexOf('\n', this.pos);
202
+ this.lineEndPos = end;
203
+ }
194
204
  if (end === -1)
195
205
  return this.atEnd ? this.buffer.substring(this.pos) : null;
196
206
  if (this.buffer[end - 1] === '\r')
@@ -203,6 +213,7 @@ class Lexer {
203
213
  setNext(state) {
204
214
  this.buffer = this.buffer.substring(this.pos);
205
215
  this.pos = 0;
216
+ this.lineEndPos = null;
206
217
  this.next = state;
207
218
  return null;
208
219
  }
@@ -327,7 +338,7 @@ class Lexer {
327
338
  yield* this.pushCount(1);
328
339
  return 'doc';
329
340
  case '*':
330
- yield* this.pushUntil(isNotIdentifierChar);
341
+ yield* this.pushUntil(isNotAnchorChar);
331
342
  return 'doc';
332
343
  case '"':
333
344
  case "'":
@@ -355,7 +366,7 @@ class Lexer {
355
366
  const line = this.getLine();
356
367
  if (line === null)
357
368
  return this.setNext('flow');
358
- if ((indent !== -1 && indent < this.indentNext) ||
369
+ if ((indent !== -1 && indent < this.indentNext && line[0] !== '#') ||
359
370
  (indent === 0 &&
360
371
  (line.startsWith('---') || line.startsWith('...')) &&
361
372
  isEmpty(line[3]))) {
@@ -373,8 +384,11 @@ class Lexer {
373
384
  }
374
385
  }
375
386
  let n = 0;
376
- while (line[n] === ',')
377
- n += (yield* this.pushCount(1)) + (yield* this.pushSpaces(true));
387
+ while (line[n] === ',') {
388
+ n += yield* this.pushCount(1);
389
+ n += yield* this.pushSpaces(true);
390
+ this.flowKey = false;
391
+ }
378
392
  n += yield* this.pushIndicators();
379
393
  switch (line[n]) {
380
394
  case undefined:
@@ -395,7 +409,7 @@ class Lexer {
395
409
  this.flowLevel -= 1;
396
410
  return this.flowLevel ? 'flow' : 'doc';
397
411
  case '*':
398
- yield* this.pushUntil(isNotIdentifierChar);
412
+ yield* this.pushUntil(isNotAnchorChar);
399
413
  return 'flow';
400
414
  case '"':
401
415
  case "'":
@@ -433,17 +447,19 @@ class Lexer {
433
447
  end = this.buffer.indexOf('"', end + 1);
434
448
  }
435
449
  }
436
- let nl = this.buffer.indexOf('\n', this.pos);
437
- if (nl !== -1 && nl < end) {
438
- while (nl !== -1 && nl < end) {
450
+ // Only looking for newlines within the quotes
451
+ const qb = this.buffer.substring(0, end);
452
+ let nl = qb.indexOf('\n', this.pos);
453
+ if (nl !== -1) {
454
+ while (nl !== -1) {
439
455
  const cs = this.continueScalar(nl + 1);
440
456
  if (cs === -1)
441
457
  break;
442
- nl = this.buffer.indexOf('\n', cs);
458
+ nl = qb.indexOf('\n', cs);
443
459
  }
444
- if (nl !== -1 && nl < end) {
460
+ if (nl !== -1) {
445
461
  // this is an error caused by an unexpected unindent
446
- end = nl - 1;
462
+ end = nl - (qb[nl - 1] === '\r' ? 2 : 1);
447
463
  }
448
464
  }
449
465
  if (end === -1) {
@@ -543,17 +559,18 @@ class Lexer {
543
559
  end = i;
544
560
  }
545
561
  else if (isEmpty(ch)) {
546
- const next = this.buffer[i + 1];
547
- if (next === '#' || (inFlow && invalidFlowScalarChars.includes(next)))
548
- break;
562
+ let next = this.buffer[i + 1];
549
563
  if (ch === '\r') {
550
564
  if (next === '\n') {
551
565
  i += 1;
552
566
  ch = '\n';
567
+ next = this.buffer[i + 1];
553
568
  }
554
569
  else
555
570
  end = i;
556
571
  }
572
+ if (next === '#' || (inFlow && invalidFlowScalarChars.includes(next)))
573
+ break;
557
574
  if (ch === '\n') {
558
575
  const cs = this.continueScalar(i + 1);
559
576
  if (cs === -1)
@@ -595,13 +612,11 @@ class Lexer {
595
612
  *pushIndicators() {
596
613
  switch (this.charAt(0)) {
597
614
  case '!':
598
- if (this.charAt(1) === '<')
599
- return ((yield* this.pushVerbatimTag()) +
600
- (yield* this.pushSpaces(true)) +
601
- (yield* this.pushIndicators()));
602
- // fallthrough
615
+ return ((yield* this.pushTag()) +
616
+ (yield* this.pushSpaces(true)) +
617
+ (yield* this.pushIndicators()));
603
618
  case '&':
604
- return ((yield* this.pushUntil(isNotIdentifierChar)) +
619
+ return ((yield* this.pushUntil(isNotAnchorChar)) +
605
620
  (yield* this.pushSpaces(true)) +
606
621
  (yield* this.pushIndicators()));
607
622
  case ':':
@@ -617,12 +632,30 @@ class Lexer {
617
632
  }
618
633
  return 0;
619
634
  }
620
- *pushVerbatimTag() {
621
- let i = this.pos + 2;
622
- let ch = this.buffer[i];
623
- while (!isEmpty(ch) && ch !== '>')
624
- ch = this.buffer[++i];
625
- return yield* this.pushToIndex(ch === '>' ? i + 1 : i, false);
635
+ *pushTag() {
636
+ if (this.charAt(1) === '<') {
637
+ let i = this.pos + 2;
638
+ let ch = this.buffer[i];
639
+ while (!isEmpty(ch) && ch !== '>')
640
+ ch = this.buffer[++i];
641
+ return yield* this.pushToIndex(ch === '>' ? i + 1 : i, false);
642
+ }
643
+ else {
644
+ let i = this.pos + 1;
645
+ let ch = this.buffer[i];
646
+ while (ch) {
647
+ if (tagChars.includes(ch))
648
+ ch = this.buffer[++i];
649
+ else if (ch === '%' &&
650
+ hexDigits.includes(this.buffer[i + 1]) &&
651
+ hexDigits.includes(this.buffer[i + 2])) {
652
+ ch = this.buffer[(i += 3)];
653
+ }
654
+ else
655
+ break;
656
+ }
657
+ return yield* this.pushToIndex(i, false);
658
+ }
626
659
  }
627
660
  *pushNewline() {
628
661
  const ch = this.buffer[this.pos];
@@ -78,6 +78,7 @@ export declare class Parser {
78
78
  private flowCollection;
79
79
  private flowScalar;
80
80
  private startBlockValue;
81
+ private atIndentedComment;
81
82
  private documentEnd;
82
83
  private lineEnd;
83
84
  }