yaml 2.0.0-6 → 2.0.0-7

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.
@@ -33,6 +33,8 @@ function composeNode(ctx, token, props, onError) {
33
33
  console.log(token);
34
34
  throw new Error(`Unsupporten token type: ${token.type}`);
35
35
  }
36
+ if (anchor && node.anchor === '')
37
+ onError(anchor, 'BAD_ALIAS', 'Anchor cannot be an empty string');
36
38
  if (spaceBefore)
37
39
  node.spaceBefore = true;
38
40
  if (comment) {
@@ -51,8 +53,11 @@ function composeEmptyNode(ctx, offset, before, pos, { spaceBefore, comment, anch
51
53
  source: ''
52
54
  };
53
55
  const node = composeScalar(ctx, token, tag, onError);
54
- if (anchor)
56
+ if (anchor) {
55
57
  node.anchor = anchor.source.substring(1);
58
+ if (node.anchor === '')
59
+ onError(anchor, 'BAD_ALIAS', 'Anchor cannot be an empty string');
60
+ }
56
61
  if (spaceBefore)
57
62
  node.spaceBefore = true;
58
63
  if (comment)
@@ -61,6 +66,8 @@ function composeEmptyNode(ctx, offset, before, pos, { spaceBefore, comment, anch
61
66
  }
62
67
  function composeAlias({ options }, { offset, source, end }, onError) {
63
68
  const alias = new Alias(source.substring(1));
69
+ if (alias.source === '')
70
+ onError(offset, 'BAD_ALIAS', 'Alias cannot be an empty string');
64
71
  const valueEnd = offset + source.length;
65
72
  const re = resolveEnd(end, valueEnd, options.strict, onError);
66
73
  alias.range = [offset, valueEnd, re.offset];
@@ -15,6 +15,7 @@ function getErrorPos(src) {
15
15
  return [offset, offset + (typeof source === 'string' ? source.length : 1)];
16
16
  }
17
17
  function parsePrelude(prelude) {
18
+ var _a;
18
19
  let comment = '';
19
20
  let atComment = false;
20
21
  let afterEmptyLine = false;
@@ -29,7 +30,7 @@ function parsePrelude(prelude) {
29
30
  afterEmptyLine = false;
30
31
  break;
31
32
  case '%':
32
- if (prelude[i + 1][0] !== '#')
33
+ if (((_a = prelude[i + 1]) === null || _a === void 0 ? void 0 : _a[0]) !== '#')
33
34
  i += 1;
34
35
  atComment = false;
35
36
  break;
@@ -39,25 +39,31 @@ function resolveFlowScalar(scalar, strict, onError) {
39
39
  };
40
40
  }
41
41
  function plainValue(source, onError) {
42
- let message = '';
42
+ let badChar = '';
43
43
  switch (source[0]) {
44
44
  /* istanbul ignore next should not happen */
45
45
  case '\t':
46
- message = 'Plain value cannot start with a tab character';
46
+ badChar = 'a tab character';
47
+ break;
48
+ case ',':
49
+ badChar = 'flow indicator character ,';
50
+ break;
51
+ case '%':
52
+ badChar = 'directive indicator character %';
47
53
  break;
48
54
  case '|':
49
55
  case '>': {
50
- message = `Plain value cannot start with block scalar indicator ${source[0]}`;
56
+ badChar = `block scalar indicator ${source[0]}`;
51
57
  break;
52
58
  }
53
59
  case '@':
54
60
  case '`': {
55
- message = `Plain value cannot start with reserved character ${source[0]}`;
61
+ badChar = `reserved character ${source[0]}`;
56
62
  break;
57
63
  }
58
64
  }
59
- if (message)
60
- onError(0, 'BAD_SCALAR_START', message);
65
+ if (badChar)
66
+ onError(0, 'BAD_SCALAR_START', `Plain value cannot start with ${badChar}`);
61
67
  return foldLines(source);
62
68
  }
63
69
  function singleQuotedValue(source, onError) {
@@ -52,8 +52,12 @@ function createNode(value, tagName, ctx) {
52
52
  if (!tagObj) {
53
53
  if (value && typeof value.toJSON === 'function')
54
54
  value = value.toJSON();
55
- if (!value || typeof value !== 'object')
56
- return new Scalar(value);
55
+ if (!value || typeof value !== 'object') {
56
+ const node = new Scalar(value);
57
+ if (ref)
58
+ ref.node = node;
59
+ return node;
60
+ }
57
61
  tagObj =
58
62
  value instanceof Map
59
63
  ? schema[MAP]
@@ -52,9 +52,9 @@ const isMergeKey = (key) => key === MERGE_KEY ||
52
52
  // Keys in mapping nodes earlier in the sequence override keys specified in
53
53
  // later mapping nodes. -- http://yaml.org/type/merge.html
54
54
  function mergeToJSMap(ctx, map, value) {
55
- const source = ctx && isAlias(value) ? value.resolve(ctx.doc) : null;
55
+ const source = ctx && isAlias(value) ? value.resolve(ctx.doc) : value;
56
56
  if (!isMap(source))
57
- throw new Error('Merge sources must be map aliases');
57
+ throw new Error('Merge sources must be maps or map aliases');
58
58
  const srcMap = source.toJSON(null, ctx, Map);
59
59
  for (const [key, value] of srcMap) {
60
60
  if (map instanceof Map) {
@@ -79,9 +79,11 @@ function isEmpty(ch) {
79
79
  return false;
80
80
  }
81
81
  }
82
- const invalidFlowScalarChars = [',', '[', ']', '{', '}'];
83
- const invalidIdentifierChars = [' ', ',', '[', ']', '{', '}', '\n', '\r', '\t'];
84
- const isNotIdentifierChar = (ch) => !ch || invalidIdentifierChars.includes(ch);
82
+ const hexDigits = '0123456789ABCDEFabcdef'.split('');
83
+ const tagChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-#;/?:@&=+$_.!~*'()".split('');
84
+ const invalidFlowScalarChars = ',[]{}'.split('');
85
+ const invalidAnchorChars = ' ,[]{}\n\r\t'.split('');
86
+ const isNotAnchorChar = (ch) => !ch || invalidAnchorChars.includes(ch);
85
87
  /**
86
88
  * Splits an input string into lexical tokens, i.e. smaller strings that are
87
89
  * easily identifiable by `tokens.tokenType()`.
@@ -325,7 +327,7 @@ class Lexer {
325
327
  yield* this.pushCount(1);
326
328
  return 'doc';
327
329
  case '*':
328
- yield* this.pushUntil(isNotIdentifierChar);
330
+ yield* this.pushUntil(isNotAnchorChar);
329
331
  return 'doc';
330
332
  case '"':
331
333
  case "'":
@@ -393,7 +395,7 @@ class Lexer {
393
395
  this.flowLevel -= 1;
394
396
  return this.flowLevel ? 'flow' : 'doc';
395
397
  case '*':
396
- yield* this.pushUntil(isNotIdentifierChar);
398
+ yield* this.pushUntil(isNotAnchorChar);
397
399
  return 'flow';
398
400
  case '"':
399
401
  case "'":
@@ -593,13 +595,11 @@ class Lexer {
593
595
  *pushIndicators() {
594
596
  switch (this.charAt(0)) {
595
597
  case '!':
596
- if (this.charAt(1) === '<')
597
- return ((yield* this.pushVerbatimTag()) +
598
- (yield* this.pushSpaces(true)) +
599
- (yield* this.pushIndicators()));
600
- // fallthrough
598
+ return ((yield* this.pushTag()) +
599
+ (yield* this.pushSpaces(true)) +
600
+ (yield* this.pushIndicators()));
601
601
  case '&':
602
- return ((yield* this.pushUntil(isNotIdentifierChar)) +
602
+ return ((yield* this.pushUntil(isNotAnchorChar)) +
603
603
  (yield* this.pushSpaces(true)) +
604
604
  (yield* this.pushIndicators()));
605
605
  case ':':
@@ -615,12 +615,30 @@ class Lexer {
615
615
  }
616
616
  return 0;
617
617
  }
618
- *pushVerbatimTag() {
619
- let i = this.pos + 2;
620
- let ch = this.buffer[i];
621
- while (!isEmpty(ch) && ch !== '>')
622
- ch = this.buffer[++i];
623
- return yield* this.pushToIndex(ch === '>' ? i + 1 : i, false);
618
+ *pushTag() {
619
+ if (this.charAt(1) === '<') {
620
+ let i = this.pos + 2;
621
+ let ch = this.buffer[i];
622
+ while (!isEmpty(ch) && ch !== '>')
623
+ ch = this.buffer[++i];
624
+ return yield* this.pushToIndex(ch === '>' ? i + 1 : i, false);
625
+ }
626
+ else {
627
+ let i = this.pos + 1;
628
+ let ch = this.buffer[i];
629
+ while (ch) {
630
+ if (tagChars.includes(ch))
631
+ ch = this.buffer[++i];
632
+ else if (ch === '%' &&
633
+ hexDigits.includes(this.buffer[i + 1]) &&
634
+ hexDigits.includes(this.buffer[i + 2])) {
635
+ ch = this.buffer[(i += 3)];
636
+ }
637
+ else
638
+ break;
639
+ }
640
+ return yield* this.pushToIndex(i, false);
641
+ }
624
642
  }
625
643
  *pushNewline() {
626
644
  const ch = this.buffer[this.pos];
@@ -35,6 +35,8 @@ function composeNode(ctx, token, props, onError) {
35
35
  console.log(token);
36
36
  throw new Error(`Unsupporten token type: ${token.type}`);
37
37
  }
38
+ if (anchor && node.anchor === '')
39
+ onError(anchor, 'BAD_ALIAS', 'Anchor cannot be an empty string');
38
40
  if (spaceBefore)
39
41
  node.spaceBefore = true;
40
42
  if (comment) {
@@ -53,8 +55,11 @@ function composeEmptyNode(ctx, offset, before, pos, { spaceBefore, comment, anch
53
55
  source: ''
54
56
  };
55
57
  const node = composeScalar.composeScalar(ctx, token, tag, onError);
56
- if (anchor)
58
+ if (anchor) {
57
59
  node.anchor = anchor.source.substring(1);
60
+ if (node.anchor === '')
61
+ onError(anchor, 'BAD_ALIAS', 'Anchor cannot be an empty string');
62
+ }
58
63
  if (spaceBefore)
59
64
  node.spaceBefore = true;
60
65
  if (comment)
@@ -63,6 +68,8 @@ function composeEmptyNode(ctx, offset, before, pos, { spaceBefore, comment, anch
63
68
  }
64
69
  function composeAlias({ options }, { offset, source, end }, onError) {
65
70
  const alias = new Alias.Alias(source.substring(1));
71
+ if (alias.source === '')
72
+ onError(offset, 'BAD_ALIAS', 'Alias cannot be an empty string');
66
73
  const valueEnd = offset + source.length;
67
74
  const re = resolveEnd.resolveEnd(end, valueEnd, options.strict, onError);
68
75
  alias.range = [offset, valueEnd, re.offset];
@@ -17,6 +17,7 @@ function getErrorPos(src) {
17
17
  return [offset, offset + (typeof source === 'string' ? source.length : 1)];
18
18
  }
19
19
  function parsePrelude(prelude) {
20
+ var _a;
20
21
  let comment = '';
21
22
  let atComment = false;
22
23
  let afterEmptyLine = false;
@@ -31,7 +32,7 @@ function parsePrelude(prelude) {
31
32
  afterEmptyLine = false;
32
33
  break;
33
34
  case '%':
34
- if (prelude[i + 1][0] !== '#')
35
+ if (((_a = prelude[i + 1]) === null || _a === void 0 ? void 0 : _a[0]) !== '#')
35
36
  i += 1;
36
37
  atComment = false;
37
38
  break;
@@ -41,25 +41,31 @@ function resolveFlowScalar(scalar, strict, onError) {
41
41
  };
42
42
  }
43
43
  function plainValue(source, onError) {
44
- let message = '';
44
+ let badChar = '';
45
45
  switch (source[0]) {
46
46
  /* istanbul ignore next should not happen */
47
47
  case '\t':
48
- message = 'Plain value cannot start with a tab character';
48
+ badChar = 'a tab character';
49
+ break;
50
+ case ',':
51
+ badChar = 'flow indicator character ,';
52
+ break;
53
+ case '%':
54
+ badChar = 'directive indicator character %';
49
55
  break;
50
56
  case '|':
51
57
  case '>': {
52
- message = `Plain value cannot start with block scalar indicator ${source[0]}`;
58
+ badChar = `block scalar indicator ${source[0]}`;
53
59
  break;
54
60
  }
55
61
  case '@':
56
62
  case '`': {
57
- message = `Plain value cannot start with reserved character ${source[0]}`;
63
+ badChar = `reserved character ${source[0]}`;
58
64
  break;
59
65
  }
60
66
  }
61
- if (message)
62
- onError(0, 'BAD_SCALAR_START', message);
67
+ if (badChar)
68
+ onError(0, 'BAD_SCALAR_START', `Plain value cannot start with ${badChar}`);
63
69
  return foldLines(source);
64
70
  }
65
71
  function singleQuotedValue(source, onError) {
@@ -54,8 +54,12 @@ function createNode(value, tagName, ctx) {
54
54
  if (!tagObj) {
55
55
  if (value && typeof value.toJSON === 'function')
56
56
  value = value.toJSON();
57
- if (!value || typeof value !== 'object')
58
- return new Scalar.Scalar(value);
57
+ if (!value || typeof value !== 'object') {
58
+ const node = new Scalar.Scalar(value);
59
+ if (ref)
60
+ ref.node = node;
61
+ return node;
62
+ }
59
63
  tagObj =
60
64
  value instanceof Map
61
65
  ? schema[Node.MAP]
package/dist/errors.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { LineCounter } from './parse/line-counter';
2
- export declare type ErrorCode = 'ALIAS_PROPS' | 'BAD_DIRECTIVE' | 'BAD_DQ_ESCAPE' | 'BAD_INDENT' | 'BAD_PROP_ORDER' | 'BAD_SCALAR_START' | 'BLOCK_AS_IMPLICIT_KEY' | 'BLOCK_IN_FLOW' | 'DUPLICATE_KEY' | 'IMPOSSIBLE' | 'KEY_OVER_1024_CHARS' | 'MISSING_ANCHOR' | 'MISSING_CHAR' | 'MULTILINE_IMPLICIT_KEY' | 'MULTIPLE_ANCHORS' | 'MULTIPLE_DOCS' | 'MULTIPLE_TAGS' | 'TAB_AS_INDENT' | 'TAG_RESOLVE_FAILED' | 'UNEXPECTED_TOKEN';
2
+ export declare type ErrorCode = 'ALIAS_PROPS' | 'BAD_ALIAS' | 'BAD_DIRECTIVE' | 'BAD_DQ_ESCAPE' | 'BAD_INDENT' | 'BAD_PROP_ORDER' | 'BAD_SCALAR_START' | 'BLOCK_AS_IMPLICIT_KEY' | 'BLOCK_IN_FLOW' | 'DUPLICATE_KEY' | 'IMPOSSIBLE' | 'KEY_OVER_1024_CHARS' | 'MISSING_CHAR' | 'MULTILINE_IMPLICIT_KEY' | 'MULTIPLE_ANCHORS' | 'MULTIPLE_DOCS' | 'MULTIPLE_TAGS' | 'TAB_AS_INDENT' | 'TAG_RESOLVE_FAILED' | 'UNEXPECTED_TOKEN';
3
3
  export declare type LinePos = {
4
4
  line: number;
5
5
  col: number;
@@ -54,9 +54,9 @@ const isMergeKey = (key) => key === MERGE_KEY ||
54
54
  // Keys in mapping nodes earlier in the sequence override keys specified in
55
55
  // later mapping nodes. -- http://yaml.org/type/merge.html
56
56
  function mergeToJSMap(ctx, map, value) {
57
- const source = ctx && Node.isAlias(value) ? value.resolve(ctx.doc) : null;
57
+ const source = ctx && Node.isAlias(value) ? value.resolve(ctx.doc) : value;
58
58
  if (!Node.isMap(source))
59
- throw new Error('Merge sources must be map aliases');
59
+ throw new Error('Merge sources must be maps or map aliases');
60
60
  const srcMap = source.toJSON(null, ctx, Map);
61
61
  for (const [key, value] of srcMap) {
62
62
  if (map instanceof Map) {
@@ -78,7 +78,7 @@ export declare class Lexer {
78
78
  private pushCount;
79
79
  private pushToIndex;
80
80
  private pushIndicators;
81
- private pushVerbatimTag;
81
+ private pushTag;
82
82
  private pushNewline;
83
83
  private pushSpaces;
84
84
  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()`.
@@ -327,7 +329,7 @@ class Lexer {
327
329
  yield* this.pushCount(1);
328
330
  return 'doc';
329
331
  case '*':
330
- yield* this.pushUntil(isNotIdentifierChar);
332
+ yield* this.pushUntil(isNotAnchorChar);
331
333
  return 'doc';
332
334
  case '"':
333
335
  case "'":
@@ -395,7 +397,7 @@ class Lexer {
395
397
  this.flowLevel -= 1;
396
398
  return this.flowLevel ? 'flow' : 'doc';
397
399
  case '*':
398
- yield* this.pushUntil(isNotIdentifierChar);
400
+ yield* this.pushUntil(isNotAnchorChar);
399
401
  return 'flow';
400
402
  case '"':
401
403
  case "'":
@@ -595,13 +597,11 @@ class Lexer {
595
597
  *pushIndicators() {
596
598
  switch (this.charAt(0)) {
597
599
  case '!':
598
- if (this.charAt(1) === '<')
599
- return ((yield* this.pushVerbatimTag()) +
600
- (yield* this.pushSpaces(true)) +
601
- (yield* this.pushIndicators()));
602
- // fallthrough
600
+ return ((yield* this.pushTag()) +
601
+ (yield* this.pushSpaces(true)) +
602
+ (yield* this.pushIndicators()));
603
603
  case '&':
604
- return ((yield* this.pushUntil(isNotIdentifierChar)) +
604
+ return ((yield* this.pushUntil(isNotAnchorChar)) +
605
605
  (yield* this.pushSpaces(true)) +
606
606
  (yield* this.pushIndicators()));
607
607
  case ':':
@@ -617,12 +617,30 @@ class Lexer {
617
617
  }
618
618
  return 0;
619
619
  }
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);
620
+ *pushTag() {
621
+ if (this.charAt(1) === '<') {
622
+ let i = this.pos + 2;
623
+ let ch = this.buffer[i];
624
+ while (!isEmpty(ch) && ch !== '>')
625
+ ch = this.buffer[++i];
626
+ return yield* this.pushToIndex(ch === '>' ? i + 1 : i, false);
627
+ }
628
+ else {
629
+ let i = this.pos + 1;
630
+ let ch = this.buffer[i];
631
+ while (ch) {
632
+ if (tagChars.includes(ch))
633
+ ch = this.buffer[++i];
634
+ else if (ch === '%' &&
635
+ hexDigits.includes(this.buffer[i + 1]) &&
636
+ hexDigits.includes(this.buffer[i + 2])) {
637
+ ch = this.buffer[(i += 3)];
638
+ }
639
+ else
640
+ break;
641
+ }
642
+ return yield* this.pushToIndex(i, false);
643
+ }
626
644
  }
627
645
  *pushNewline() {
628
646
  const ch = this.buffer[this.pos];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yaml",
3
- "version": "2.0.0-6",
3
+ "version": "2.0.0-7",
4
4
  "license": "ISC",
5
5
  "author": "Eemeli Aro <eemeli@gmail.com>",
6
6
  "repository": "github:eemeli/yaml",