securemark 0.296.2 → 0.296.4

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.
@@ -4,108 +4,108 @@ import { Command } from './context';
4
4
  describe('Unit: parser/segment', () => {
5
5
  describe('segment', () => {
6
6
  it('huge input', () => {
7
- const result = segment(`${'\n'.repeat(1e6 + 1)}`).next().value?.split('\n', 1)[0];
7
+ const result = segment(`${'\n'.repeat(1e6 + 1)}`).next().value?.[0].split('\n', 1)[0];
8
8
  assert(result?.startsWith(`${Command.Error}Too large input`));
9
9
  });
10
10
 
11
11
  it('huge segment', () => {
12
- const result = segment(`${'\n'.repeat(1e5 + 1)}`).next().value?.split('\n', 1)[0];
12
+ const result = segment(`${'\n'.repeat(1e5 + 1)}`).next().value?.[0].split('\n', 1)[0];
13
13
  assert(result?.startsWith(`${Command.Error}Too large segment`));
14
14
  });
15
15
 
16
16
  it('basic', () => {
17
- assert.deepStrictEqual([...segment('')], []);
18
- assert.deepStrictEqual([...segment('a')], ['a']);
19
- assert.deepStrictEqual([...segment('a\n')], ['a\n']);
20
- assert.deepStrictEqual([...segment('a\n\n')], ['a\n', '\n']);
21
- assert.deepStrictEqual([...segment('a\n\n\n')], ['a\n', '\n\n']);
22
- assert.deepStrictEqual([...segment('a\nb')], ['a\nb']);
23
- assert.deepStrictEqual([...segment('a\nb\n')], ['a\nb\n']);
24
- assert.deepStrictEqual([...segment('a\nb\n\n')], ['a\nb\n', '\n']);
25
- assert.deepStrictEqual([...segment('a\nb\n\n\n')], ['a\nb\n', '\n\n']);
26
- assert.deepStrictEqual([...segment('a\nb\n\nc\n\nd')], ['a\nb\n', '\n', 'c\n', '\n', 'd']);
27
- assert.deepStrictEqual([...segment('a\n\\\nb')], ['a\n\\\nb']);
28
- assert.deepStrictEqual([...segment('a ')], ['a ']);
29
- assert.deepStrictEqual([...segment(' a')], [' a']);
30
- assert.deepStrictEqual([...segment(' a ')], [' a ']);
17
+ assert.deepStrictEqual([...segment('')].map(t => t[0]), []);
18
+ assert.deepStrictEqual([...segment('a')].map(t => t[0]), ['a']);
19
+ assert.deepStrictEqual([...segment('a\n')].map(t => t[0]), ['a\n']);
20
+ assert.deepStrictEqual([...segment('a\n\n')].map(t => t[0]), ['a\n', '\n']);
21
+ assert.deepStrictEqual([...segment('a\n\n\n')].map(t => t[0]), ['a\n', '\n\n']);
22
+ assert.deepStrictEqual([...segment('a\nb')].map(t => t[0]), ['a\nb']);
23
+ assert.deepStrictEqual([...segment('a\nb\n')].map(t => t[0]), ['a\nb\n']);
24
+ assert.deepStrictEqual([...segment('a\nb\n\n')].map(t => t[0]), ['a\nb\n', '\n']);
25
+ assert.deepStrictEqual([...segment('a\nb\n\n\n')].map(t => t[0]), ['a\nb\n', '\n\n']);
26
+ assert.deepStrictEqual([...segment('a\nb\n\nc\n\nd')].map(t => t[0]), ['a\nb\n', '\n', 'c\n', '\n', 'd']);
27
+ assert.deepStrictEqual([...segment('a\n\\\nb')].map(t => t[0]), ['a\n\\\nb']);
28
+ assert.deepStrictEqual([...segment('a ')].map(t => t[0]), ['a ']);
29
+ assert.deepStrictEqual([...segment(' a')].map(t => t[0]), [' a']);
30
+ assert.deepStrictEqual([...segment(' a ')].map(t => t[0]), [' a ']);
31
31
  });
32
32
 
33
33
  it('linebreak', () => {
34
- assert.deepStrictEqual([...segment('\n')], ['\n']);
35
- assert.deepStrictEqual([...segment('\n\n')], ['\n\n']);
36
- assert.deepStrictEqual([...segment('\n\n\n')], ['\n\n\n']);
37
- assert.deepStrictEqual([...segment('\n\n\n\n')], ['\n\n\n\n']);
38
- assert.deepStrictEqual([...segment(' ')], [' ']);
39
- assert.deepStrictEqual([...segment(' \n')], [' \n']);
40
- assert.deepStrictEqual([...segment(' \n \n \n ')], [' \n \n \n ']);
41
- assert.deepStrictEqual([...segment('a\n')], ['a\n']);
42
- assert.deepStrictEqual([...segment('a\n ')], ['a\n', ' ']);
43
- assert.deepStrictEqual([...segment('a\n\n ')], ['a\n', '\n ']);
44
- assert.deepStrictEqual([...segment('a\n\n\n ')], ['a\n', '\n\n ']);
45
- assert.deepStrictEqual([...segment('a\n\n\n\n ')], ['a\n', '\n\n\n ']);
46
- assert.deepStrictEqual([...segment('a\n\n\n\n\n ')], ['a\n', '\n\n\n\n ']);
47
- assert.deepStrictEqual([...segment('a\n\n\n\n\n\n ')], ['a\n', '\n\n\n\n\n ']);
34
+ assert.deepStrictEqual([...segment('\n')].map(t => t[0]), ['\n']);
35
+ assert.deepStrictEqual([...segment('\n\n')].map(t => t[0]), ['\n\n']);
36
+ assert.deepStrictEqual([...segment('\n\n\n')].map(t => t[0]), ['\n\n\n']);
37
+ assert.deepStrictEqual([...segment('\n\n\n\n')].map(t => t[0]), ['\n\n\n\n']);
38
+ assert.deepStrictEqual([...segment(' ')].map(t => t[0]), [' ']);
39
+ assert.deepStrictEqual([...segment(' \n')].map(t => t[0]), [' \n']);
40
+ assert.deepStrictEqual([...segment(' \n \n \n ')].map(t => t[0]), [' \n \n \n ']);
41
+ assert.deepStrictEqual([...segment('a\n')].map(t => t[0]), ['a\n']);
42
+ assert.deepStrictEqual([...segment('a\n ')].map(t => t[0]), ['a\n', ' ']);
43
+ assert.deepStrictEqual([...segment('a\n\n ')].map(t => t[0]), ['a\n', '\n ']);
44
+ assert.deepStrictEqual([...segment('a\n\n\n ')].map(t => t[0]), ['a\n', '\n\n ']);
45
+ assert.deepStrictEqual([...segment('a\n\n\n\n ')].map(t => t[0]), ['a\n', '\n\n\n ']);
46
+ assert.deepStrictEqual([...segment('a\n\n\n\n\n ')].map(t => t[0]), ['a\n', '\n\n\n\n ']);
47
+ assert.deepStrictEqual([...segment('a\n\n\n\n\n\n ')].map(t => t[0]), ['a\n', '\n\n\n\n\n ']);
48
48
  });
49
49
 
50
50
  it('codeblock', () => {
51
- assert.deepStrictEqual([...segment('```')], ['```']);
52
- assert.deepStrictEqual([...segment('```\n```')], ['```\n```']);
53
- assert.deepStrictEqual([...segment('```\n\n```')], ['```\n\n```']);
54
- assert.deepStrictEqual([...segment('```\n\n\n```')], ['```\n', '\n\n', '```']);
55
- assert.deepStrictEqual([...segment('```\n\n0\n```')], ['```\n', '\n', '0\n```']);
56
- assert.deepStrictEqual([...segment('```\n0\n\n```')], ['```\n0\n\n```']);
57
- assert.deepStrictEqual([...segment('```\n````\n```')], ['```\n````\n```']);
58
- assert.deepStrictEqual([...segment('````\n```\n````')], ['````\n```\n````']);
59
- assert.deepStrictEqual([...segment('```\n\n```\n\n')], ['```\n\n```\n', '\n']);
51
+ assert.deepStrictEqual([...segment('```')].map(t => t[0]), ['```']);
52
+ assert.deepStrictEqual([...segment('```\n```')].map(t => t[0]), ['```\n```']);
53
+ assert.deepStrictEqual([...segment('```\n\n```')].map(t => t[0]), ['```\n\n```']);
54
+ assert.deepStrictEqual([...segment('```\n\n\n```')].map(t => t[0]), ['```\n', '\n\n', '```']);
55
+ assert.deepStrictEqual([...segment('```\n\n0\n```')].map(t => t[0]), ['```\n', '\n', '0\n```']);
56
+ assert.deepStrictEqual([...segment('```\n0\n\n```')].map(t => t[0]), ['```\n0\n\n```']);
57
+ assert.deepStrictEqual([...segment('```\n````\n```')].map(t => t[0]), ['```\n````\n```']);
58
+ assert.deepStrictEqual([...segment('````\n```\n````')].map(t => t[0]), ['````\n```\n````']);
59
+ assert.deepStrictEqual([...segment('```\n\n```\n\n')].map(t => t[0]), ['```\n\n```\n', '\n']);
60
60
  });
61
61
 
62
62
  it('mathblock', () => {
63
- assert.deepStrictEqual([...segment('$$')], ['$$']);
64
- assert.deepStrictEqual([...segment('$$\n$$')], ['$$\n$$']);
65
- assert.deepStrictEqual([...segment('$$\n\n$$')], ['$$\n\n$$']);
66
- assert.deepStrictEqual([...segment('$$\n\n\n$$')], ['$$\n', '\n\n', '$$']);
67
- assert.deepStrictEqual([...segment('$$\n\n0\n$$')], ['$$\n', '\n', '0\n$$']);
68
- assert.deepStrictEqual([...segment('$$\n0\n\n$$')], ['$$\n0\n\n$$']);
69
- assert.deepStrictEqual([...segment('$$\n\n$$\n\n')], ['$$\n\n$$\n', '\n']);
63
+ assert.deepStrictEqual([...segment('$$')].map(t => t[0]), ['$$']);
64
+ assert.deepStrictEqual([...segment('$$\n$$')].map(t => t[0]), ['$$\n$$']);
65
+ assert.deepStrictEqual([...segment('$$\n\n$$')].map(t => t[0]), ['$$\n\n$$']);
66
+ assert.deepStrictEqual([...segment('$$\n\n\n$$')].map(t => t[0]), ['$$\n', '\n\n', '$$']);
67
+ assert.deepStrictEqual([...segment('$$\n\n0\n$$')].map(t => t[0]), ['$$\n', '\n', '0\n$$']);
68
+ assert.deepStrictEqual([...segment('$$\n0\n\n$$')].map(t => t[0]), ['$$\n0\n\n$$']);
69
+ assert.deepStrictEqual([...segment('$$\n\n$$\n\n')].map(t => t[0]), ['$$\n\n$$\n', '\n']);
70
70
  });
71
71
 
72
72
  it('extension', () => {
73
- assert.deepStrictEqual([...segment('~~~')], ['~~~']);
74
- assert.deepStrictEqual([...segment('~~~\n~~~')], ['~~~\n~~~']);
75
- assert.deepStrictEqual([...segment('~~~\n\n~~~')], ['~~~\n\n~~~']);
76
- assert.deepStrictEqual([...segment('~~~\n\n\n~~~')], ['~~~\n', '\n\n', '~~~']);
77
- assert.deepStrictEqual([...segment('~~~\n\n0\n~~~')], ['~~~\n', '\n', '0\n~~~']);
78
- assert.deepStrictEqual([...segment('~~~\n0\n\n~~~')], ['~~~\n0\n\n~~~']);
79
- assert.deepStrictEqual([...segment('~~~\n~~~~\n~~~')], ['~~~\n~~~~\n~~~']);
80
- assert.deepStrictEqual([...segment('~~~~\n~~~\n~~~~')], ['~~~~\n~~~\n~~~~']);
81
- assert.deepStrictEqual([...segment('~~~\n\n~~~\n\n')], ['~~~\n\n~~~\n', '\n']);
82
- assert.deepStrictEqual([...segment('~~~\n```\n~~~\n```\n~~~')], ['~~~\n```\n~~~\n```\n~~~']);
83
- assert.deepStrictEqual([...segment('~~~\ninvalid\n~~~')], ['~~~\ninvalid\n~~~']);
84
- assert.deepStrictEqual([...segment('~~~\ninvalid\n\ncaption\n~~~')], ['~~~\ninvalid\n\ncaption\n~~~']);
85
- assert.deepStrictEqual([...segment('~~~figure [$-name]\n$$\n$$\n\n```\n~~~')], ['~~~figure [$-name]\n$$\n$$\n\n```\n~~~']);
73
+ assert.deepStrictEqual([...segment('~~~')].map(t => t[0]), ['~~~']);
74
+ assert.deepStrictEqual([...segment('~~~\n~~~')].map(t => t[0]), ['~~~\n~~~']);
75
+ assert.deepStrictEqual([...segment('~~~\n\n~~~')].map(t => t[0]), ['~~~\n\n~~~']);
76
+ assert.deepStrictEqual([...segment('~~~\n\n\n~~~')].map(t => t[0]), ['~~~\n', '\n\n', '~~~']);
77
+ assert.deepStrictEqual([...segment('~~~\n\n0\n~~~')].map(t => t[0]), ['~~~\n', '\n', '0\n~~~']);
78
+ assert.deepStrictEqual([...segment('~~~\n0\n\n~~~')].map(t => t[0]), ['~~~\n0\n\n~~~']);
79
+ assert.deepStrictEqual([...segment('~~~\n~~~~\n~~~')].map(t => t[0]), ['~~~\n~~~~\n~~~']);
80
+ assert.deepStrictEqual([...segment('~~~~\n~~~\n~~~~')].map(t => t[0]), ['~~~~\n~~~\n~~~~']);
81
+ assert.deepStrictEqual([...segment('~~~\n\n~~~\n\n')].map(t => t[0]), ['~~~\n\n~~~\n', '\n']);
82
+ assert.deepStrictEqual([...segment('~~~\n```\n~~~\n```\n~~~')].map(t => t[0]), ['~~~\n```\n~~~\n```\n~~~']);
83
+ assert.deepStrictEqual([...segment('~~~\ninvalid\n~~~')].map(t => t[0]), ['~~~\ninvalid\n~~~']);
84
+ assert.deepStrictEqual([...segment('~~~\ninvalid\n\ncaption\n~~~')].map(t => t[0]), ['~~~\ninvalid\n\ncaption\n~~~']);
85
+ assert.deepStrictEqual([...segment('~~~figure [$-name]\n$$\n$$\n\n```\n~~~')].map(t => t[0]), ['~~~figure [$-name]\n$$\n$$\n\n```\n~~~']);
86
86
  });
87
87
 
88
88
  it('mixed', () => {
89
- assert.deepStrictEqual([...segment('```\n\n\n')], ['```\n', '\n\n']);
90
- assert.deepStrictEqual([...segment('~~~\n\n\n')], ['~~~\n', '\n\n']);
91
- assert.deepStrictEqual([...segment('```\n~~~\n```')], ['```\n~~~\n```']);
92
- assert.deepStrictEqual([...segment('~~~\n```\n~~~')], ['~~~\n```\n~~~']);
93
- assert.deepStrictEqual([...segment('```\n```\n\n~~~\n~~~')], ['```\n```\n', '\n', '~~~\n~~~']);
94
- assert.deepStrictEqual([...segment('~~~\n~~~\n\n```\n```')], ['~~~\n~~~\n', '\n', '```\n```']);
95
- assert.deepStrictEqual([...segment(' ```\n\n```')], [' ```\n', '\n', '```']);
96
- assert.deepStrictEqual([...segment(' ~~~\n\n~~~')], [' ~~~\n', '\n', '~~~']);
89
+ assert.deepStrictEqual([...segment('```\n\n\n')].map(t => t[0]), ['```\n', '\n\n']);
90
+ assert.deepStrictEqual([...segment('~~~\n\n\n')].map(t => t[0]), ['~~~\n', '\n\n']);
91
+ assert.deepStrictEqual([...segment('```\n~~~\n```')].map(t => t[0]), ['```\n~~~\n```']);
92
+ assert.deepStrictEqual([...segment('~~~\n```\n~~~')].map(t => t[0]), ['~~~\n```\n~~~']);
93
+ assert.deepStrictEqual([...segment('```\n```\n\n~~~\n~~~')].map(t => t[0]), ['```\n```\n', '\n', '~~~\n~~~']);
94
+ assert.deepStrictEqual([...segment('~~~\n~~~\n\n```\n```')].map(t => t[0]), ['~~~\n~~~\n', '\n', '```\n```']);
95
+ assert.deepStrictEqual([...segment(' ```\n\n```')].map(t => t[0]), [' ```\n', '\n', '```']);
96
+ assert.deepStrictEqual([...segment(' ~~~\n\n~~~')].map(t => t[0]), [' ~~~\n', '\n', '~~~']);
97
97
  });
98
98
 
99
99
  it('blockquote', () => {
100
- assert.deepStrictEqual([...segment('> ```\n\n```')], ['> ```\n', '\n', '```']);
101
- assert.deepStrictEqual([...segment('!> ```\n\n```')], ['!> ```\n', '\n', '```']);
100
+ assert.deepStrictEqual([...segment('> ```\n\n```')].map(t => t[0]), ['> ```\n', '\n', '```']);
101
+ assert.deepStrictEqual([...segment('!> ```\n\n```')].map(t => t[0]), ['!> ```\n', '\n', '```']);
102
102
  });
103
103
 
104
104
  it('heading', () => {
105
- assert.deepStrictEqual([...segment('# a\n\n# b\n')], ['# a\n', '\n', '# b\n']);
106
- assert.deepStrictEqual([...segment('# a\n# b\n')], ['# a\n', '# b\n']);
107
- assert.deepStrictEqual([...segment('# a\n# b')], ['# a\n', '# b']);
108
- assert.deepStrictEqual([...segment('# a\n # b')], ['# a\n # b']);
105
+ assert.deepStrictEqual([...segment('# a\n\n# b\n')].map(t => t[0]), ['# a\n', '\n', '# b\n']);
106
+ assert.deepStrictEqual([...segment('# a\n# b\n')].map(t => t[0]), ['# a\n', '# b\n']);
107
+ assert.deepStrictEqual([...segment('# a\n# b')].map(t => t[0]), ['# a\n', '# b']);
108
+ assert.deepStrictEqual([...segment('# a\n # b')].map(t => t[0]), ['# a\n # b']);
109
109
  });
110
110
 
111
111
  });
@@ -1,11 +1,11 @@
1
1
  import { MarkdownParser } from '../../markdown';
2
- import { Context, Command } from './context';
2
+ import { Context, Segment, Command } from './context';
3
3
  import { union, some } from '../combinator';
4
4
  import { segment as heading } from './block/heading';
5
5
  import { segment as codeblock } from './block/codeblock';
6
6
  import { segment as mathblock } from './block/mathblock';
7
7
  import { segment as extension } from './block/extension';
8
- import { contentline, emptyline } from './source';
8
+ import { contentline, emptysegment } from './source';
9
9
 
10
10
  import SegmentParser = MarkdownParser.SegmentParser;
11
11
 
@@ -13,7 +13,7 @@ export const MAX_SEGMENT_SIZE = 100_000; // 100,000 bytes (Max value size of FDB
13
13
  export const MAX_INPUT_SIZE = MAX_SEGMENT_SIZE * 10;
14
14
 
15
15
  const parser: SegmentParser = union([
16
- some(emptyline, MAX_SEGMENT_SIZE + 1),
16
+ some(emptysegment, MAX_SEGMENT_SIZE + 1),
17
17
  input => {
18
18
  const { context: { source, position } } = input;
19
19
  if (position === source.length) return;
@@ -26,21 +26,19 @@ const parser: SegmentParser = union([
26
26
  break;
27
27
  case '$':
28
28
  if (source[position + 1] === '$') return mathblock(input);
29
- break;
29
+ return extension(input);
30
30
  case '[':
31
31
  if (source[position + 1] === '$') return extension(input);
32
32
  break;
33
33
  case '#':
34
34
  return heading(input);
35
- case '$':
36
- return extension(input);
37
35
  }
38
36
  },
39
37
  some(contentline, MAX_SEGMENT_SIZE + 1),
40
38
  ]) as any;
41
39
 
42
- export function* segment(source: string): Generator<string, undefined, undefined> {
43
- if (!validate(source, MAX_INPUT_SIZE)) return yield `${Command.Error}Too large input over ${MAX_INPUT_SIZE.toLocaleString('en')} bytes.\n${source.slice(0, 1001)}`;
40
+ export function* segment(source: string): Generator<readonly [string, Segment], undefined, undefined> {
41
+ if (!validate(source, MAX_INPUT_SIZE)) return yield [`${Command.Error}Too large input over ${MAX_INPUT_SIZE.toLocaleString('en')} bytes.\n${source.slice(0, 1001)}`, Segment.unknown];
44
42
  assert(source.length < Number.MAX_SAFE_INTEGER);
45
43
  for (let position = 0; position < source.length;) {
46
44
  const context = new Context({ source, position });
@@ -51,13 +49,13 @@ export function* segment(source: string): Generator<string, undefined, undefined
51
49
  ? result.foldl<string[]>((acc, { value }) => void acc.push(value) || acc, [])
52
50
  : [source.slice(position, context.position)];
53
51
  assert(segs.join('') === source.slice(position, context.position));
52
+ position = context.position;
54
53
  for (let i = 0; i < segs.length; ++i) {
55
54
  const seg = segs[i];
56
55
  validate(seg, MAX_SEGMENT_SIZE)
57
- ? yield seg
58
- : yield `${Command.Error}Too large segment over ${MAX_SEGMENT_SIZE.toLocaleString('en')} bytes.\n${seg}`
56
+ ? yield [seg, context.segment]
57
+ : yield [`${Command.Error}Too large segment over ${MAX_SEGMENT_SIZE.toLocaleString('en')} bytes.\n${seg}`, Segment.unknown];
59
58
  }
60
- position = context.position;
61
59
  }
62
60
  }
63
61
 
@@ -1,4 +1,5 @@
1
- import { AnyLineParser, EmptyLineParser, ContentLineParser } from '../source';
1
+ import { AnyLineParser, EmptyLineParser, EmptySegmentParser, ContentLineParser } from '../source';
2
+ import { Segment } from '../context';
2
3
  import { List } from '../../combinator/data/parser';
3
4
 
4
5
  export const anyline: AnyLineParser = input => {
@@ -14,14 +15,32 @@ export const emptyline: EmptyLineParser = input => {
14
15
  const { context } = input;
15
16
  const { source, position } = context;
16
17
  if (position === source.length) return;
17
- if (source[position] === '\n') return ++context.position, new List();
18
- regEmptyline.lastIndex = position;
19
- regEmptyline.test(source);
20
- const i = regEmptyline.lastIndex;
21
- if (i === 0) return;
18
+ const i = eoel(source, position);
19
+ if (i === position) return;
20
+ context.position = i;
21
+ return new List();
22
+ };
23
+ export const emptysegment: EmptySegmentParser = input => {
24
+ const { context } = input;
25
+ const { source, position, segment } = context;
26
+ if (position === source.length) return;
27
+ if (segment & Segment.write) {
28
+ if (segment !== (Segment.empty | Segment.write)) return;
29
+ context.position = source.length;
30
+ return new List();
31
+ }
32
+ const i = eoel(source, position);
33
+ if (i === position) return;
22
34
  context.position = i;
35
+ context.segment = Segment.empty;
23
36
  return new List();
24
37
  };
38
+ function eoel(source: string, position: number): number {
39
+ if (source[position] === '\n') return position + 1;
40
+ regEmptyline.lastIndex = position;
41
+ regEmptyline.test(source);
42
+ return regEmptyline.lastIndex || position;
43
+ }
25
44
 
26
45
  const regContentline = /[^\S\n]*\S[^\n]*(?:$|\n)/y;
27
46
  export const contentline: ContentLineParser = input => {
@@ -7,18 +7,17 @@ export function str(pattern: string | RegExp, after?: string | RegExp): Parser<s
7
7
  return matcher(pattern, true, after ? tester(after, false) : undefined);
8
8
  }
9
9
 
10
- export function strs(pattern: string, limit?: number): StrParser;
11
- export function strs(pattern: string, limit: number = -1): Parser<string> {
12
- assert(pattern);
10
+ export function strs(char: string, min?: number, max?: number): StrParser;
11
+ export function strs(char: string, min: number = 1, max: number = -1): Parser<string> {
12
+ assert(char.length === 1);
13
13
  return ({ context }) => {
14
- const { source } = context;
15
- let acc = '';
16
- for (let i = 0; i !== limit && context.position < source.length && source.startsWith(pattern, context.position); ++i) {
17
- acc += pattern;
18
- context.position += pattern.length;
14
+ const { source, position } = context;
15
+ let cnt = 0;
16
+ for (; cnt !== max && context.position < source.length && source[context.position] === char; ++cnt) {
17
+ context.position += char.length;
19
18
  }
20
- return acc
21
- ? new List([new Node(acc)])
19
+ return cnt >= min
20
+ ? new List([new Node(source.slice(position, context.position))])
22
21
  : undefined;
23
22
  };
24
23
  }
@@ -8,10 +8,11 @@ export import UnescapableSourceParser = SourceParser.UnescapableSourceParser;
8
8
  export import StrParser = SourceParser.StrParser;
9
9
  export import ContentLineParser = SourceParser.ContentLineParser;
10
10
  export import EmptyLineParser = SourceParser.EmptyLineParser;
11
+ export import EmptySegmentParser = SourceParser.EmptySegmentParser;
11
12
  export import AnyLineParser = SourceParser.AnyLineParser;
12
13
 
13
14
  export { text, txt } from './source/text';
14
15
  export { escsource } from './source/escapable';
15
16
  export { unescsource } from './source/unescapable';
16
17
  export { str, strs } from './source/str';
17
- export { contentline, emptyline, anyline } from './source/line';
18
+ export { contentline, emptyline, emptysegment, anyline } from './source/line';