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.
- package/CHANGELOG.md +8 -0
- package/design.md +2 -3
- package/dist/index.js +128 -66
- package/markdown.d.ts +8 -4
- package/package.json +1 -1
- package/src/combinator/control/constraint/block.ts +12 -6
- package/src/combinator/control/manipulation/recovery.ts +3 -3
- package/src/combinator/control/manipulation/surround.ts +1 -1
- package/src/combinator/data/parser/context.test.ts +2 -2
- package/src/combinator/data/parser/context.ts +11 -2
- package/src/combinator/data/parser.ts +7 -0
- package/src/parser/api/bind.ts +15 -10
- package/src/parser/api/parse.ts +4 -3
- package/src/parser/block/extension/fig.ts +3 -1
- package/src/parser/block/extension/figure.ts +2 -1
- package/src/parser/block/extension/message.ts +1 -1
- package/src/parser/block/extension.test.ts +3 -3
- package/src/parser/block/extension.ts +3 -4
- package/src/parser/block/heading.ts +4 -4
- package/src/parser/block.ts +22 -12
- package/src/parser/context.ts +13 -0
- package/src/parser/inline/emstrong.ts +1 -1
- package/src/parser/segment.test.ts +73 -73
- package/src/parser/segment.ts +9 -11
- package/src/parser/source/line.ts +25 -6
- package/src/parser/source/str.ts +9 -10
- package/src/parser/source.ts +2 -1
|
@@ -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
|
});
|
package/src/parser/segment.ts
CHANGED
|
@@ -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,
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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 => {
|
package/src/parser/source/str.ts
CHANGED
|
@@ -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(
|
|
11
|
-
export function strs(
|
|
12
|
-
assert(
|
|
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
|
|
16
|
-
for (
|
|
17
|
-
|
|
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
|
|
21
|
-
? new List([new Node(
|
|
19
|
+
return cnt >= min
|
|
20
|
+
? new List([new Node(source.slice(position, context.position))])
|
|
22
21
|
: undefined;
|
|
23
22
|
};
|
|
24
23
|
}
|
package/src/parser/source.ts
CHANGED
|
@@ -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';
|