yaml 2.4.4 → 2.4.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.
@@ -17,6 +17,7 @@ function composeDoc(options, directives, { offset, start, value, end }, onError)
17
17
  next: value ?? end?.[0],
18
18
  offset,
19
19
  onError,
20
+ parentIndent: 0,
20
21
  startOnNewline: true
21
22
  });
22
23
  if (props.found) {
@@ -5,7 +5,7 @@ import { resolveFlowScalar } from './resolve-flow-scalar.js';
5
5
 
6
6
  function composeScalar(ctx, token, tagToken, onError) {
7
7
  const { value, type, comment, range } = token.type === 'block-scalar'
8
- ? resolveBlockScalar(token, ctx.options.strict, onError)
8
+ ? resolveBlockScalar(ctx, token, onError)
9
9
  : resolveFlowScalar(token, ctx.options.strict, onError);
10
10
  const tagName = tagToken
11
11
  ? ctx.directives.tagName(tagToken.source, msg => onError(tagToken, 'TAG_RESOLVE_FAILED', msg))
@@ -21,6 +21,7 @@ function resolveBlockMap({ composeNode, composeEmptyNode }, ctx, bm, onError, ta
21
21
  next: key ?? sep?.[0],
22
22
  offset,
23
23
  onError,
24
+ parentIndent: bm.indent,
24
25
  startOnNewline: true
25
26
  });
26
27
  const implicitKey = !keyProps.found;
@@ -63,6 +64,7 @@ function resolveBlockMap({ composeNode, composeEmptyNode }, ctx, bm, onError, ta
63
64
  next: value,
64
65
  offset: keyNode.range[2],
65
66
  onError,
67
+ parentIndent: bm.indent,
66
68
  startOnNewline: !key || key.type === 'block-scalar'
67
69
  });
68
70
  offset = valueProps.end;
@@ -1,8 +1,8 @@
1
1
  import { Scalar } from '../nodes/Scalar.js';
2
2
 
3
- function resolveBlockScalar(scalar, strict, onError) {
3
+ function resolveBlockScalar(ctx, scalar, onError) {
4
4
  const start = scalar.offset;
5
- const header = parseBlockScalarHeader(scalar, strict, onError);
5
+ const header = parseBlockScalarHeader(scalar, ctx.options.strict, onError);
6
6
  if (!header)
7
7
  return { value: '', type: null, comment: '', range: [start, start, start] };
8
8
  const type = header.mode === '>' ? Scalar.BLOCK_FOLDED : Scalar.BLOCK_LITERAL;
@@ -44,6 +44,10 @@ function resolveBlockScalar(scalar, strict, onError) {
44
44
  if (header.indent === 0)
45
45
  trimIndent = indent.length;
46
46
  contentStart = i;
47
+ if (trimIndent === 0 && !ctx.atRoot) {
48
+ const message = 'Block scalar values in collections must be indented';
49
+ onError(offset, 'BAD_INDENT', message);
50
+ }
47
51
  break;
48
52
  }
49
53
  offset += indent.length + content.length + 1;
@@ -15,6 +15,7 @@ function resolveBlockSeq({ composeNode, composeEmptyNode }, ctx, bs, onError, ta
15
15
  next: value,
16
16
  offset,
17
17
  onError,
18
+ parentIndent: bs.indent,
18
19
  startOnNewline: true
19
20
  });
20
21
  if (!props.found) {
@@ -28,6 +28,7 @@ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onErr
28
28
  next: key ?? sep?.[0],
29
29
  offset,
30
30
  onError,
31
+ parentIndent: fc.indent,
31
32
  startOnNewline: false
32
33
  });
33
34
  if (!props.found) {
@@ -109,6 +110,7 @@ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onErr
109
110
  next: value,
110
111
  offset: keyNode.range[2],
111
112
  onError,
113
+ parentIndent: fc.indent,
112
114
  startOnNewline: false
113
115
  });
114
116
  if (valueProps.found) {
@@ -1,4 +1,4 @@
1
- function resolveProps(tokens, { flow, indicator, next, offset, onError, startOnNewline }) {
1
+ function resolveProps(tokens, { flow, indicator, next, offset, onError, parentIndent, startOnNewline }) {
2
2
  let spaceBefore = false;
3
3
  let atNewline = startOnNewline;
4
4
  let hasSpace = startOnNewline;
@@ -22,7 +22,7 @@ function resolveProps(tokens, { flow, indicator, next, offset, onError, startOnN
22
22
  reqSpace = false;
23
23
  }
24
24
  if (tab) {
25
- if (token.type !== 'comment') {
25
+ if (atNewline && token.type !== 'comment' && token.type !== 'newline') {
26
26
  onError(tab, 'TAB_AS_INDENT', 'Tabs are not allowed as indentation');
27
27
  }
28
28
  tab = null;
@@ -33,9 +33,8 @@ function resolveProps(tokens, { flow, indicator, next, offset, onError, startOnN
33
33
  // as leading white space rather than indentation.
34
34
  // In a flow collection, only the parser handles indent.
35
35
  if (!flow &&
36
- atNewline &&
37
36
  (indicator !== 'doc-start' || next?.type !== 'flow-collection') &&
38
- token.source[0] === '\t') {
37
+ token.source.includes('\t')) {
39
38
  tab = token;
40
39
  }
41
40
  hasSpace = true;
@@ -97,7 +96,8 @@ function resolveProps(tokens, { flow, indicator, next, offset, onError, startOnN
97
96
  if (found)
98
97
  onError(token, 'UNEXPECTED_TOKEN', `Unexpected ${token.source} in ${flow ?? 'collection'}`);
99
98
  found = token;
100
- atNewline = false;
99
+ atNewline =
100
+ indicator === 'seq-item-ind' || indicator === 'explicit-key-ind';
101
101
  hasSpace = false;
102
102
  break;
103
103
  case 'comma':
@@ -126,7 +126,10 @@ function resolveProps(tokens, { flow, indicator, next, offset, onError, startOnN
126
126
  (next.type !== 'scalar' || next.source !== '')) {
127
127
  onError(next.offset, 'MISSING_CHAR', 'Tags and anchors must be separated from the next token by white space');
128
128
  }
129
- if (tab)
129
+ if (tab &&
130
+ ((atNewline && tab.indent <= parentIndent) ||
131
+ next?.type === 'block-map' ||
132
+ next?.type === 'block-seq'))
130
133
  onError(tab, 'TAB_AS_INDENT', 'Tabs are not allowed as indentation');
131
134
  return {
132
135
  comma,
@@ -18,7 +18,7 @@ function resolveAsScalar(token, strict = true, onError) {
18
18
  case 'double-quoted-scalar':
19
19
  return resolveFlowScalar(token, strict, _onError);
20
20
  case 'block-scalar':
21
- return resolveBlockScalar(token, strict, _onError);
21
+ return resolveBlockScalar({ options: { strict } }, token, _onError);
22
22
  }
23
23
  }
24
24
  return null;
@@ -541,14 +541,25 @@ class Lexer {
541
541
  nl = this.buffer.length;
542
542
  }
543
543
  }
544
- if (!this.blockScalarKeep) {
544
+ // Trailing insufficiently indented tabs are invalid.
545
+ // To catch that during parsing, we include them in the block scalar value.
546
+ let i = nl + 1;
547
+ ch = this.buffer[i];
548
+ while (ch === ' ')
549
+ ch = this.buffer[++i];
550
+ if (ch === '\t') {
551
+ while (ch === '\t' || ch === ' ' || ch === '\r' || ch === '\n')
552
+ ch = this.buffer[++i];
553
+ nl = i - 1;
554
+ }
555
+ else if (!this.blockScalarKeep) {
545
556
  do {
546
557
  let i = nl - 1;
547
558
  let ch = this.buffer[i];
548
559
  if (ch === '\r')
549
560
  ch = this.buffer[--i];
550
561
  const lastChar = i; // Drop the line if last char not more indented
551
- while (ch === ' ' || ch === '\t')
562
+ while (ch === ' ')
552
563
  ch = this.buffer[--i];
553
564
  if (ch === '\n' && i >= this.pos && i + 1 + indent > lastChar)
554
565
  nl = i;
@@ -19,6 +19,7 @@ function composeDoc(options, directives, { offset, start, value, end }, onError)
19
19
  next: value ?? end?.[0],
20
20
  offset,
21
21
  onError,
22
+ parentIndent: 0,
22
23
  startOnNewline: true
23
24
  });
24
25
  if (props.found) {
@@ -7,7 +7,7 @@ var resolveFlowScalar = require('./resolve-flow-scalar.js');
7
7
 
8
8
  function composeScalar(ctx, token, tagToken, onError) {
9
9
  const { value, type, comment, range } = token.type === 'block-scalar'
10
- ? resolveBlockScalar.resolveBlockScalar(token, ctx.options.strict, onError)
10
+ ? resolveBlockScalar.resolveBlockScalar(ctx, token, onError)
11
11
  : resolveFlowScalar.resolveFlowScalar(token, ctx.options.strict, onError);
12
12
  const tagName = tagToken
13
13
  ? ctx.directives.tagName(tagToken.source, msg => onError(tagToken, 'TAG_RESOLVE_FAILED', msg))
@@ -23,6 +23,7 @@ function resolveBlockMap({ composeNode, composeEmptyNode }, ctx, bm, onError, ta
23
23
  next: key ?? sep?.[0],
24
24
  offset,
25
25
  onError,
26
+ parentIndent: bm.indent,
26
27
  startOnNewline: true
27
28
  });
28
29
  const implicitKey = !keyProps.found;
@@ -65,6 +66,7 @@ function resolveBlockMap({ composeNode, composeEmptyNode }, ctx, bm, onError, ta
65
66
  next: value,
66
67
  offset: keyNode.range[2],
67
68
  onError,
69
+ parentIndent: bm.indent,
68
70
  startOnNewline: !key || key.type === 'block-scalar'
69
71
  });
70
72
  offset = valueProps.end;
@@ -1,8 +1,9 @@
1
1
  import { Range } from '../nodes/Node.js';
2
2
  import { Scalar } from '../nodes/Scalar.js';
3
3
  import type { BlockScalar } from '../parse/cst.js';
4
+ import type { ComposeContext } from './compose-node.js';
4
5
  import type { ComposeErrorHandler } from './composer.js';
5
- export declare function resolveBlockScalar(scalar: BlockScalar, strict: boolean, onError: ComposeErrorHandler): {
6
+ export declare function resolveBlockScalar(ctx: ComposeContext, scalar: BlockScalar, onError: ComposeErrorHandler): {
6
7
  value: string;
7
8
  type: Scalar.BLOCK_FOLDED | Scalar.BLOCK_LITERAL | null;
8
9
  comment: string;
@@ -2,9 +2,9 @@
2
2
 
3
3
  var Scalar = require('../nodes/Scalar.js');
4
4
 
5
- function resolveBlockScalar(scalar, strict, onError) {
5
+ function resolveBlockScalar(ctx, scalar, onError) {
6
6
  const start = scalar.offset;
7
- const header = parseBlockScalarHeader(scalar, strict, onError);
7
+ const header = parseBlockScalarHeader(scalar, ctx.options.strict, onError);
8
8
  if (!header)
9
9
  return { value: '', type: null, comment: '', range: [start, start, start] };
10
10
  const type = header.mode === '>' ? Scalar.Scalar.BLOCK_FOLDED : Scalar.Scalar.BLOCK_LITERAL;
@@ -46,6 +46,10 @@ function resolveBlockScalar(scalar, strict, onError) {
46
46
  if (header.indent === 0)
47
47
  trimIndent = indent.length;
48
48
  contentStart = i;
49
+ if (trimIndent === 0 && !ctx.atRoot) {
50
+ const message = 'Block scalar values in collections must be indented';
51
+ onError(offset, 'BAD_INDENT', message);
52
+ }
49
53
  break;
50
54
  }
51
55
  offset += indent.length + content.length + 1;
@@ -17,6 +17,7 @@ function resolveBlockSeq({ composeNode, composeEmptyNode }, ctx, bs, onError, ta
17
17
  next: value,
18
18
  offset,
19
19
  onError,
20
+ parentIndent: bs.indent,
20
21
  startOnNewline: true
21
22
  });
22
23
  if (!props.found) {
@@ -30,6 +30,7 @@ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onErr
30
30
  next: key ?? sep?.[0],
31
31
  offset,
32
32
  onError,
33
+ parentIndent: fc.indent,
33
34
  startOnNewline: false
34
35
  });
35
36
  if (!props.found) {
@@ -111,6 +112,7 @@ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onErr
111
112
  next: value,
112
113
  offset: keyNode.range[2],
113
114
  onError,
115
+ parentIndent: fc.indent,
114
116
  startOnNewline: false
115
117
  });
116
118
  if (valueProps.found) {
@@ -6,9 +6,10 @@ export interface ResolvePropsArg {
6
6
  next: Token | null | undefined;
7
7
  offset: number;
8
8
  onError: ComposeErrorHandler;
9
+ parentIndent: number;
9
10
  startOnNewline: boolean;
10
11
  }
11
- export declare function resolveProps(tokens: SourceToken[], { flow, indicator, next, offset, onError, startOnNewline }: ResolvePropsArg): {
12
+ export declare function resolveProps(tokens: SourceToken[], { flow, indicator, next, offset, onError, parentIndent, startOnNewline }: ResolvePropsArg): {
12
13
  comma: SourceToken | null;
13
14
  found: SourceToken | null;
14
15
  spaceBefore: boolean;
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- function resolveProps(tokens, { flow, indicator, next, offset, onError, startOnNewline }) {
3
+ function resolveProps(tokens, { flow, indicator, next, offset, onError, parentIndent, startOnNewline }) {
4
4
  let spaceBefore = false;
5
5
  let atNewline = startOnNewline;
6
6
  let hasSpace = startOnNewline;
@@ -24,7 +24,7 @@ function resolveProps(tokens, { flow, indicator, next, offset, onError, startOnN
24
24
  reqSpace = false;
25
25
  }
26
26
  if (tab) {
27
- if (token.type !== 'comment') {
27
+ if (atNewline && token.type !== 'comment' && token.type !== 'newline') {
28
28
  onError(tab, 'TAB_AS_INDENT', 'Tabs are not allowed as indentation');
29
29
  }
30
30
  tab = null;
@@ -35,9 +35,8 @@ function resolveProps(tokens, { flow, indicator, next, offset, onError, startOnN
35
35
  // as leading white space rather than indentation.
36
36
  // In a flow collection, only the parser handles indent.
37
37
  if (!flow &&
38
- atNewline &&
39
38
  (indicator !== 'doc-start' || next?.type !== 'flow-collection') &&
40
- token.source[0] === '\t') {
39
+ token.source.includes('\t')) {
41
40
  tab = token;
42
41
  }
43
42
  hasSpace = true;
@@ -99,7 +98,8 @@ function resolveProps(tokens, { flow, indicator, next, offset, onError, startOnN
99
98
  if (found)
100
99
  onError(token, 'UNEXPECTED_TOKEN', `Unexpected ${token.source} in ${flow ?? 'collection'}`);
101
100
  found = token;
102
- atNewline = false;
101
+ atNewline =
102
+ indicator === 'seq-item-ind' || indicator === 'explicit-key-ind';
103
103
  hasSpace = false;
104
104
  break;
105
105
  case 'comma':
@@ -128,7 +128,10 @@ function resolveProps(tokens, { flow, indicator, next, offset, onError, startOnN
128
128
  (next.type !== 'scalar' || next.source !== '')) {
129
129
  onError(next.offset, 'MISSING_CHAR', 'Tags and anchors must be separated from the next token by white space');
130
130
  }
131
- if (tab)
131
+ if (tab &&
132
+ ((atNewline && tab.indent <= parentIndent) ||
133
+ next?.type === 'block-map' ||
134
+ next?.type === 'block-seq'))
132
135
  onError(tab, 'TAB_AS_INDENT', 'Tabs are not allowed as indentation');
133
136
  return {
134
137
  comma,
@@ -20,7 +20,7 @@ function resolveAsScalar(token, strict = true, onError) {
20
20
  case 'double-quoted-scalar':
21
21
  return resolveFlowScalar.resolveFlowScalar(token, strict, _onError);
22
22
  case 'block-scalar':
23
- return resolveBlockScalar.resolveBlockScalar(token, strict, _onError);
23
+ return resolveBlockScalar.resolveBlockScalar({ options: { strict } }, token, _onError);
24
24
  }
25
25
  }
26
26
  return null;
@@ -543,14 +543,25 @@ class Lexer {
543
543
  nl = this.buffer.length;
544
544
  }
545
545
  }
546
- if (!this.blockScalarKeep) {
546
+ // Trailing insufficiently indented tabs are invalid.
547
+ // To catch that during parsing, we include them in the block scalar value.
548
+ let i = nl + 1;
549
+ ch = this.buffer[i];
550
+ while (ch === ' ')
551
+ ch = this.buffer[++i];
552
+ if (ch === '\t') {
553
+ while (ch === '\t' || ch === ' ' || ch === '\r' || ch === '\n')
554
+ ch = this.buffer[++i];
555
+ nl = i - 1;
556
+ }
557
+ else if (!this.blockScalarKeep) {
547
558
  do {
548
559
  let i = nl - 1;
549
560
  let ch = this.buffer[i];
550
561
  if (ch === '\r')
551
562
  ch = this.buffer[--i];
552
563
  const lastChar = i; // Drop the line if last char not more indented
553
- while (ch === ' ' || ch === '\t')
564
+ while (ch === ' ')
554
565
  ch = this.buffer[--i];
555
566
  if (ch === '\n' && i >= this.pos && i + 1 + indent > lastChar)
556
567
  nl = i;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yaml",
3
- "version": "2.4.4",
3
+ "version": "2.4.5",
4
4
  "license": "ISC",
5
5
  "author": "Eemeli Aro <eemeli@gmail.com>",
6
6
  "repository": "github:eemeli/yaml",