securemark 0.299.3 → 0.300.0
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 +0 -6
- package/dist/index.js +3479 -2750
- package/index.d.ts +2 -1
- package/index.ts +2 -2
- package/markdown.d.ts +209 -183
- package/package.json +1 -1
- package/src/{parser/api → api}/bind.test.ts +2 -24
- package/src/{parser/api → api}/bind.ts +18 -13
- package/src/{parser/api → api}/body.test.ts +1 -1
- package/src/{parser/api → api}/cache.ts +1 -1
- package/src/{parser/api → api}/header.test.ts +1 -1
- package/src/{parser/api → api}/header.ts +9 -6
- package/src/{parser/api → api}/normalize.test.ts +1 -1
- package/src/{parser/api → api}/parse.test.ts +120 -124
- package/src/api/parse.ts +30 -0
- package/src/api/run.ts +6 -0
- package/src/{parser/api.ts → api.ts} +1 -0
- package/src/combinator/control/inits.ts +26 -0
- package/src/combinator/control/sequence.test.ts +38 -0
- package/src/combinator/control/sequence.ts +17 -0
- package/src/combinator/control/some.test.ts +41 -0
- package/src/combinator/{data/parser → control}/some.ts +39 -26
- package/src/combinator/control/state.ts +42 -0
- package/src/combinator/control/subsequence.test.ts +47 -0
- package/src/combinator/control/subsequence.ts +16 -0
- package/src/combinator/control/tails.ts +8 -0
- package/src/combinator/control/union.test.ts +37 -0
- package/src/combinator/control/union.ts +18 -0
- package/src/combinator/{data/delimiter.ts → delimiter.ts} +40 -60
- package/src/combinator/effect/backtrack.ts +64 -0
- package/src/combinator/effect/clock.ts +10 -0
- package/src/combinator/effect/precedence.ts +50 -0
- package/src/combinator/effect/recursion.ts +30 -0
- package/src/combinator/effect/scope.ts +100 -0
- package/src/combinator/effect/state.ts +72 -0
- package/src/combinator/{data/node.ts → parser/list.ts} +38 -13
- package/src/combinator/parser.ts +293 -0
- package/src/combinator/process/bind.ts +34 -0
- package/src/combinator/process/block.test.ts +20 -0
- package/src/combinator/process/block.ts +33 -0
- package/src/combinator/process/clear.ts +16 -0
- package/src/combinator/process/contract.ts +35 -0
- package/src/combinator/process/duplicate.ts +7 -0
- package/src/combinator/process/error.ts +13 -0
- package/src/combinator/{control/manipulation → process}/fallback.ts +3 -3
- package/src/combinator/process/fence.ts +59 -0
- package/src/combinator/process/fmap.ts +10 -0
- package/src/combinator/process/indent.test.ts +31 -0
- package/src/combinator/process/indent.ts +51 -0
- package/src/combinator/process/lazy.ts +8 -0
- package/src/combinator/process/line.test.ts +21 -0
- package/src/combinator/process/line.ts +55 -0
- package/src/combinator/process/match.ts +37 -0
- package/src/combinator/process/reverse.ts +7 -0
- package/src/combinator/process/scope.ts +102 -0
- package/src/combinator/process/surround.ts +271 -0
- package/src/combinator.ts +28 -24
- package/src/debug.test.ts +11 -8
- package/src/parser/autolink.test.ts +17 -18
- package/src/parser/block/blockquote.test.ts +78 -79
- package/src/parser/block/blockquote.ts +32 -25
- package/src/parser/block/codeblock.test.ts +56 -57
- package/src/parser/block/codeblock.ts +44 -26
- package/src/parser/block/dlist.test.ts +56 -57
- package/src/parser/block/dlist.ts +5 -5
- package/src/parser/block/extension/aside.test.ts +8 -9
- package/src/parser/block/extension/aside.ts +76 -47
- package/src/parser/block/extension/example.test.ts +18 -19
- package/src/parser/block/extension/example.ts +88 -48
- package/src/parser/block/extension/fig.test.ts +37 -36
- package/src/parser/block/extension/fig.ts +20 -25
- package/src/parser/block/extension/figbase.test.ts +18 -19
- package/src/parser/block/extension/figbase.ts +3 -3
- package/src/parser/block/extension/figure.test.ts +62 -63
- package/src/parser/block/extension/figure.ts +23 -21
- package/src/parser/block/extension/message.test.ts +13 -14
- package/src/parser/block/extension/message.ts +52 -39
- package/src/parser/block/extension/placeholder.test.ts +13 -13
- package/src/parser/block/extension/placeholder.ts +23 -21
- package/src/parser/block/extension/table.test.ts +70 -71
- package/src/parser/block/extension/table.ts +43 -31
- package/src/parser/block/extension.test.ts +24 -24
- package/src/parser/block/extension.ts +3 -3
- package/src/parser/block/heading.test.ts +58 -59
- package/src/parser/block/heading.ts +19 -18
- package/src/parser/block/ilist.test.ts +8 -8
- package/src/parser/block/ilist.ts +9 -7
- package/src/parser/block/mathblock.test.ts +31 -32
- package/src/parser/block/mathblock.ts +24 -23
- package/src/parser/block/mediablock.ts +7 -7
- package/src/parser/block/olist.test.ts +102 -103
- package/src/parser/block/olist.ts +11 -12
- package/src/parser/block/pagebreak.test.ts +15 -16
- package/src/parser/block/pagebreak.ts +5 -5
- package/src/parser/block/paragraph.test.ts +57 -58
- package/src/parser/block/paragraph.ts +1 -1
- package/src/parser/block/reply/cite.test.ts +39 -40
- package/src/parser/block/reply/cite.ts +5 -5
- package/src/parser/block/reply/quote.test.ts +50 -51
- package/src/parser/block/reply/quote.ts +8 -7
- package/src/parser/block/reply.test.ts +19 -20
- package/src/parser/block/reply.ts +2 -2
- package/src/parser/block/sidefence.test.ts +41 -48
- package/src/parser/block/sidefence.ts +17 -11
- package/src/parser/block/table.test.ts +48 -49
- package/src/parser/block/table.ts +10 -9
- package/src/parser/block/ulist.test.ts +52 -53
- package/src/parser/block/ulist.ts +9 -8
- package/src/parser/block.ts +63 -51
- package/src/parser/context.ts +35 -32
- package/src/parser/document.ts +48 -0
- package/src/parser/header.test.ts +19 -20
- package/src/parser/header.ts +31 -25
- package/src/parser/inline/annotation.test.ts +49 -50
- package/src/parser/inline/annotation.ts +14 -16
- package/src/parser/inline/autolink/account.test.ts +32 -33
- package/src/parser/inline/autolink/account.ts +18 -19
- package/src/parser/inline/autolink/anchor.test.ts +21 -22
- package/src/parser/inline/autolink/anchor.ts +7 -8
- package/src/parser/inline/autolink/channel.test.ts +14 -15
- package/src/parser/inline/autolink/email.test.ts +36 -37
- package/src/parser/inline/autolink/email.ts +6 -6
- package/src/parser/inline/autolink/hashnum.test.ts +32 -33
- package/src/parser/inline/autolink/hashnum.ts +7 -8
- package/src/parser/inline/autolink/hashtag.test.ts +59 -60
- package/src/parser/inline/autolink/hashtag.ts +8 -9
- package/src/parser/inline/autolink/url.test.ts +75 -76
- package/src/parser/inline/autolink/url.ts +13 -14
- package/src/parser/inline/autolink.ts +24 -11
- package/src/parser/inline/bracket.test.ts +73 -74
- package/src/parser/inline/bracket.ts +88 -63
- package/src/parser/inline/code.test.ts +30 -31
- package/src/parser/inline/code.ts +6 -6
- package/src/parser/inline/deletion.test.ts +27 -28
- package/src/parser/inline/deletion.ts +5 -5
- package/src/parser/inline/emphasis.test.ts +39 -40
- package/src/parser/inline/emphasis.ts +5 -5
- package/src/parser/inline/emstrong.test.ts +101 -102
- package/src/parser/inline/emstrong.ts +103 -85
- package/src/parser/inline/extension/index.test.ts +91 -92
- package/src/parser/inline/extension/index.ts +17 -13
- package/src/parser/inline/extension/indexee.ts +4 -4
- package/src/parser/inline/extension/indexer.test.ts +23 -24
- package/src/parser/inline/extension/indexer.ts +6 -5
- package/src/parser/inline/extension/label.test.ts +32 -33
- package/src/parser/inline/extension/label.ts +14 -5
- package/src/parser/inline/extension/placeholder.test.ts +42 -43
- package/src/parser/inline/extension/placeholder.ts +8 -9
- package/src/parser/inline/html.test.ts +109 -109
- package/src/parser/inline/html.ts +27 -27
- package/src/parser/inline/htmlentity.test.ts +37 -38
- package/src/parser/inline/htmlentity.ts +6 -7
- package/src/parser/inline/insertion.test.ts +27 -28
- package/src/parser/inline/insertion.ts +5 -5
- package/src/parser/inline/italic.test.ts +55 -56
- package/src/parser/inline/italic.ts +5 -5
- package/src/parser/inline/link.test.ts +186 -187
- package/src/parser/inline/link.ts +31 -32
- package/src/parser/inline/mark.test.ts +31 -32
- package/src/parser/inline/mark.ts +6 -6
- package/src/parser/inline/math.test.ts +140 -141
- package/src/parser/inline/math.ts +6 -7
- package/src/parser/inline/media.test.ts +92 -93
- package/src/parser/inline/media.ts +32 -38
- package/src/parser/inline/reference.test.ts +111 -112
- package/src/parser/inline/reference.ts +61 -32
- package/src/parser/inline/remark.test.ts +49 -50
- package/src/parser/inline/remark.ts +13 -13
- package/src/parser/inline/ruby.test.ts +49 -50
- package/src/parser/inline/ruby.ts +60 -49
- package/src/parser/inline/shortmedia.test.ts +9 -10
- package/src/parser/inline/shortmedia.ts +11 -9
- package/src/parser/inline/strong.test.ts +36 -37
- package/src/parser/inline/strong.ts +5 -5
- package/src/parser/inline/template.test.ts +22 -23
- package/src/parser/inline/template.ts +13 -16
- package/src/parser/inline.test.ts +225 -226
- package/src/parser/inline.ts +68 -34
- package/src/parser/node.ts +1 -1
- package/src/parser/parser.ts +51 -0
- package/src/parser/repeat.ts +118 -91
- package/src/parser/segment.test.ts +0 -11
- package/src/parser/segment.ts +25 -28
- package/src/parser/source/escapable.test.ts +23 -24
- package/src/parser/source/escapable.ts +20 -20
- package/src/parser/source/line.test.ts +17 -18
- package/src/parser/source/line.ts +19 -24
- package/src/parser/source/str.ts +17 -10
- package/src/parser/source/text.test.ts +88 -89
- package/src/parser/source/text.ts +19 -20
- package/src/parser/source/unescapable.test.ts +23 -24
- package/src/parser/source/unescapable.ts +16 -16
- package/src/parser/util.ts +1 -1
- package/src/parser/visibility.ts +36 -15
- package/src/{parser/processor → processor}/figure.test.ts +23 -23
- package/src/{parser/processor → processor}/figure.ts +20 -12
- package/src/{parser/processor → processor}/note.test.ts +15 -15
- package/src/{parser/processor → processor}/note.ts +6 -4
- package/src/renderer/render/media/pdf.ts +2 -2
- package/src/renderer/render/media/twitter.ts +2 -2
- package/src/renderer/render/media.test.ts +12 -13
- package/src/renderer/render.test.ts +11 -11
- package/src/util/info.test.ts +2 -2
- package/src/util/quote.test.ts +3 -3
- package/src/util/quote.ts +6 -5
- package/src/util/toc.test.ts +12 -12
- package/src/combinator/control/constraint/block.test.ts +0 -20
- package/src/combinator/control/constraint/block.ts +0 -28
- package/src/combinator/control/constraint/contract.ts +0 -27
- package/src/combinator/control/constraint/line.test.ts +0 -21
- package/src/combinator/control/constraint/line.ts +0 -42
- package/src/combinator/control/manipulation/clear.ts +0 -5
- package/src/combinator/control/manipulation/convert.ts +0 -22
- package/src/combinator/control/manipulation/duplicate.ts +0 -7
- package/src/combinator/control/manipulation/fence.ts +0 -54
- package/src/combinator/control/manipulation/indent.test.ts +0 -31
- package/src/combinator/control/manipulation/indent.ts +0 -39
- package/src/combinator/control/manipulation/lazy.ts +0 -8
- package/src/combinator/control/manipulation/match.ts +0 -27
- package/src/combinator/control/manipulation/recovery.ts +0 -18
- package/src/combinator/control/manipulation/reverse.ts +0 -8
- package/src/combinator/control/manipulation/scope.ts +0 -61
- package/src/combinator/control/manipulation/surround.ts +0 -223
- package/src/combinator/control/monad/bind.ts +0 -26
- package/src/combinator/control/monad/fmap.ts +0 -10
- package/src/combinator/data/parser/context.ts +0 -96
- package/src/combinator/data/parser/inits.ts +0 -20
- package/src/combinator/data/parser/sequence.test.ts +0 -33
- package/src/combinator/data/parser/sequence.ts +0 -20
- package/src/combinator/data/parser/some.test.ts +0 -37
- package/src/combinator/data/parser/subsequence.test.ts +0 -41
- package/src/combinator/data/parser/subsequence.ts +0 -13
- package/src/combinator/data/parser/tails.ts +0 -8
- package/src/combinator/data/parser/union.test.ts +0 -33
- package/src/combinator/data/parser/union.ts +0 -18
- package/src/combinator/data/parser.ts +0 -144
- package/src/parser/api/parse.ts +0 -48
- package/src/parser.ts +0 -1
- /package/src/{parser/api → api}/body.ts +0 -0
- /package/src/{parser/api → api}/normalize.ts +0 -0
package/src/parser/inline.ts
CHANGED
|
@@ -50,76 +50,110 @@ export import AutolinkParser = InlineParser.AutolinkParser;
|
|
|
50
50
|
|
|
51
51
|
const stars = strs('*');
|
|
52
52
|
|
|
53
|
+
const p1 = lazy(() => union([
|
|
54
|
+
annotation,
|
|
55
|
+
bracket,
|
|
56
|
+
]));
|
|
57
|
+
const p2 = lazy(() => union([
|
|
58
|
+
reference,
|
|
59
|
+
textlink,
|
|
60
|
+
bracket,
|
|
61
|
+
]));
|
|
62
|
+
const p3 = lazy(() => union([
|
|
63
|
+
remark,
|
|
64
|
+
textlink,
|
|
65
|
+
ruby,
|
|
66
|
+
bracket,
|
|
67
|
+
]));
|
|
68
|
+
const p4 = lazy(() => union([
|
|
69
|
+
extension,
|
|
70
|
+
textlink,
|
|
71
|
+
ruby,
|
|
72
|
+
bracket,
|
|
73
|
+
]));
|
|
74
|
+
const p5 = lazy(() => union([
|
|
75
|
+
textlink,
|
|
76
|
+
ruby,
|
|
77
|
+
bracket,
|
|
78
|
+
]));
|
|
79
|
+
const p6 = lazy(() => union([
|
|
80
|
+
template,
|
|
81
|
+
bracket,
|
|
82
|
+
]));
|
|
83
|
+
const p7 = lazy(() => union([
|
|
84
|
+
textlink,
|
|
85
|
+
bracket,
|
|
86
|
+
]));
|
|
87
|
+
const p8 = lazy(() => union([
|
|
88
|
+
label,
|
|
89
|
+
math,
|
|
90
|
+
]));
|
|
91
|
+
const p9 = lazy(() => union([
|
|
92
|
+
emstrong,
|
|
93
|
+
stars,
|
|
94
|
+
]));
|
|
95
|
+
const p10 = lazy(() => union([
|
|
96
|
+
strong,
|
|
97
|
+
stars,
|
|
98
|
+
]));
|
|
53
99
|
export const inline: InlineParser = lazy(() => union([
|
|
54
|
-
input => {
|
|
100
|
+
(input, output) => {
|
|
55
101
|
const { source, position } = input;
|
|
56
102
|
if (position === source.length) return;
|
|
57
103
|
switch (source[position]) {
|
|
58
104
|
case '(':
|
|
59
|
-
if (source[position + 1] === '(') return
|
|
60
|
-
return bracket(input);
|
|
105
|
+
if (source[position + 1] === '(') return p1(input, output);
|
|
106
|
+
return bracket(input, output);
|
|
61
107
|
case '[':
|
|
62
108
|
switch (source[position + 1]) {
|
|
63
109
|
case '[':
|
|
64
|
-
return
|
|
65
|
-
|| textlink(input)
|
|
66
|
-
|| bracket(input);
|
|
110
|
+
return p2(input, output);
|
|
67
111
|
case '%':
|
|
68
|
-
return
|
|
69
|
-
|| textlink(input)
|
|
70
|
-
|| ruby(input)
|
|
71
|
-
|| bracket(input);
|
|
112
|
+
return p3(input, output);
|
|
72
113
|
case '#':
|
|
73
114
|
case '$':
|
|
74
115
|
case ':':
|
|
75
116
|
case '^':
|
|
76
117
|
case '|':
|
|
77
|
-
return
|
|
78
|
-
|| textlink(input)
|
|
79
|
-
|| ruby(input)
|
|
80
|
-
|| bracket(input);
|
|
118
|
+
return p4(input, output);
|
|
81
119
|
}
|
|
82
|
-
return
|
|
83
|
-
|| ruby(input)
|
|
84
|
-
|| bracket(input);
|
|
120
|
+
return p5(input, output);
|
|
85
121
|
case '{':
|
|
86
|
-
if (source[position + 1] === '{') return
|
|
87
|
-
return
|
|
88
|
-
|| bracket(input);
|
|
122
|
+
if (source[position + 1] === '{') return p6(input, output);
|
|
123
|
+
return p7(input, output);
|
|
89
124
|
case '"':
|
|
90
125
|
case '(':
|
|
91
126
|
case '[':
|
|
92
127
|
case '{':
|
|
93
|
-
return bracket(input);
|
|
128
|
+
return bracket(input, output);
|
|
94
129
|
case '<':
|
|
95
|
-
if (isAlphabet(source[position + 1])) return html(input);
|
|
130
|
+
if (isAlphabet(source[position + 1])) return html(input, output);
|
|
96
131
|
break;
|
|
97
132
|
case '$':
|
|
98
|
-
if (source[position + 1] === '{') return math(input);
|
|
99
|
-
return
|
|
100
|
-
|| math(input);
|
|
133
|
+
if (source[position + 1] === '{') return math(input, output);
|
|
134
|
+
return p8(input, output);
|
|
101
135
|
case '+':
|
|
102
|
-
if (source[position + 1] === '+') return insertion(input);
|
|
136
|
+
if (source[position + 1] === '+') return insertion(input, output);
|
|
103
137
|
break;
|
|
104
138
|
case '~':
|
|
105
|
-
if (source[position + 1] === '~') return deletion(input);
|
|
139
|
+
if (source[position + 1] === '~') return deletion(input, output);
|
|
106
140
|
break;
|
|
107
141
|
case '=':
|
|
108
|
-
if (source[position + 1] === '=') return mark(input);
|
|
142
|
+
if (source[position + 1] === '=') return mark(input, output);
|
|
109
143
|
break;
|
|
110
144
|
case '/':
|
|
111
|
-
if (source[position + 1] === '/' && source[position + 2] === '/') return italic(input);
|
|
145
|
+
if (source[position + 1] === '/' && source[position + 2] === '/') return italic(input, output);
|
|
112
146
|
break;
|
|
113
147
|
case '*':
|
|
114
148
|
return source[position + 1] === '*'
|
|
115
149
|
? source[position + 2] === '*'
|
|
116
|
-
?
|
|
117
|
-
:
|
|
118
|
-
: emphasis(input);
|
|
150
|
+
? p9(input, output)
|
|
151
|
+
: p10(input, output)
|
|
152
|
+
: emphasis(input, output);
|
|
119
153
|
case '`':
|
|
120
|
-
return code(input);
|
|
154
|
+
return code(input, output);
|
|
121
155
|
case '&':
|
|
122
|
-
return htmlentity(input);
|
|
156
|
+
return htmlentity(input, output);
|
|
123
157
|
}
|
|
124
158
|
},
|
|
125
159
|
autolink,
|
package/src/parser/node.ts
CHANGED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Input, Segment } from './context';
|
|
2
|
+
import { Parser, Result, List, Node } from '../combinator/parser';
|
|
3
|
+
|
|
4
|
+
export function build(segment: Parser<string, Input>, block: Parser<HTMLElement, Input>): Result<HTMLElement> {
|
|
5
|
+
interface Memory {
|
|
6
|
+
readonly position: number;
|
|
7
|
+
}
|
|
8
|
+
const loop: Result<string | HTMLElement, Input<Memory | List<Node<string>>>> = [
|
|
9
|
+
(input, output) => {
|
|
10
|
+
input.segment = Segment.unknown;
|
|
11
|
+
input.memory = {
|
|
12
|
+
position: input.position,
|
|
13
|
+
};
|
|
14
|
+
output.push();
|
|
15
|
+
return output.context;
|
|
16
|
+
},
|
|
17
|
+
segment,
|
|
18
|
+
(input, output) => {
|
|
19
|
+
input.segment |= Segment.write;
|
|
20
|
+
const segs = output.pop() as List<Node<string>>;
|
|
21
|
+
assert(input.memory = input.memory as Memory);
|
|
22
|
+
if (segs.length === 0) {
|
|
23
|
+
segs.push(new Node(input.source.slice(input.memory.position, input.position)));
|
|
24
|
+
}
|
|
25
|
+
input.memory = segs;
|
|
26
|
+
return input.memory.length === 0
|
|
27
|
+
? output.context
|
|
28
|
+
: subloop;
|
|
29
|
+
},
|
|
30
|
+
(input, output) => {
|
|
31
|
+
input.header &&= false;
|
|
32
|
+
return input.position === input.source.length
|
|
33
|
+
? output.context
|
|
34
|
+
: loop;
|
|
35
|
+
},
|
|
36
|
+
];
|
|
37
|
+
const subloop: Result<HTMLElement, Input<List<Node<string>>>> = [
|
|
38
|
+
(input, output) => {
|
|
39
|
+
input.scope.focus(input.memory.shift()!.value);
|
|
40
|
+
return output.context;
|
|
41
|
+
},
|
|
42
|
+
block,
|
|
43
|
+
(input, output) => {
|
|
44
|
+
input.scope.unfocus();
|
|
45
|
+
return input.memory.length === 0
|
|
46
|
+
? output.context
|
|
47
|
+
: subloop;
|
|
48
|
+
},
|
|
49
|
+
];
|
|
50
|
+
return loop;
|
|
51
|
+
}
|
package/src/parser/repeat.ts
CHANGED
|
@@ -1,117 +1,144 @@
|
|
|
1
|
-
import { Parser, Result, List, Node } from '../combinator/
|
|
2
|
-
import { tester } from '../combinator/
|
|
1
|
+
import { Parser, Result, Output, List, Node } from '../combinator/parser';
|
|
2
|
+
import { tester } from '../combinator/delimiter';
|
|
3
3
|
import { recur } from '../combinator';
|
|
4
|
-
import {
|
|
4
|
+
import { Input, Recursion, Command } from './context';
|
|
5
5
|
import { min } from 'spica/alias';
|
|
6
6
|
|
|
7
|
-
export function repeat<P extends Parser<HTMLElement | string,
|
|
7
|
+
export function repeat<P extends Parser<HTMLElement | string, Input>>(
|
|
8
8
|
opener: string, after: string | RegExp, closer: string, recursion: Recursion, parser: P,
|
|
9
|
-
cons: (nodes: List<Node<Parser.Node<P>>>,
|
|
9
|
+
cons: (nodes: List<Node<Parser.Node<P>>>, input: Parser.Input<P>, output: Output<Parser.Node<P>>, lead: number, follow: number) =>
|
|
10
10
|
List<Node<Parser.Node<P>>>,
|
|
11
|
-
termination?: (
|
|
11
|
+
termination?: (nodes: List<Node<Parser.Node<P>>>, input: Input, output: Output<Parser.Node<P>>, prefix: number, postfix: number, state: boolean) =>
|
|
12
12
|
Result<string | Parser.Node<P>>,
|
|
13
13
|
): P;
|
|
14
|
-
export function repeat<
|
|
15
|
-
opener: string, after: string | RegExp, closer: string, recursion: Recursion, parser: Parser<
|
|
16
|
-
cons: (nodes: List<Node<
|
|
17
|
-
List<Node<
|
|
18
|
-
termination: (
|
|
19
|
-
Result<string |
|
|
20
|
-
(nodes,
|
|
21
|
-
const acc = new List<Node<string | N>>();
|
|
14
|
+
export function repeat<T extends HTMLElement | string>(
|
|
15
|
+
opener: string, after: string | RegExp, closer: string, recursion: Recursion, parser: Parser<string | T>,
|
|
16
|
+
cons: (nodes: List<Node<string | T>>, input: Input, output: Output<string | T>, lead: number, follow: number) =>
|
|
17
|
+
List<Node<T>>,
|
|
18
|
+
termination: (nodes: List<Node<string | T>>, input: Input, output: Output<string | T>, prefix: number, postfix: number, state: boolean) =>
|
|
19
|
+
Result<string | T, Input> =
|
|
20
|
+
(nodes, input, output, prefix, postfix) => {
|
|
22
21
|
if (prefix > 0) {
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
nodes.unshift(new Node(opener[0].repeat(prefix)));
|
|
23
|
+
input.range += prefix;
|
|
25
24
|
}
|
|
26
|
-
acc.import(nodes);
|
|
27
25
|
if (postfix > 0) {
|
|
28
|
-
const { source, position } =
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
26
|
+
const { source, position } = input;
|
|
27
|
+
nodes.push(new Node(source.slice(position, position + postfix)));
|
|
28
|
+
input.position += postfix;
|
|
29
|
+
input.range += postfix;
|
|
32
30
|
}
|
|
33
|
-
return
|
|
31
|
+
return output.import(nodes);
|
|
34
32
|
},
|
|
35
|
-
): Parser<string |
|
|
33
|
+
): Parser<string | T, Input> {
|
|
36
34
|
const test = tester(after, false);
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
35
|
+
interface Memory {
|
|
36
|
+
readonly position: number;
|
|
37
|
+
i: number;
|
|
38
|
+
lead: number;
|
|
39
|
+
follow: number;
|
|
40
|
+
state: boolean;
|
|
41
|
+
depth: number;
|
|
42
|
+
}
|
|
43
|
+
const cont: Result<T, Input<Memory>> = [
|
|
44
|
+
(input, output) => {
|
|
45
|
+
const { source, position, resources: { recursions } } = input;
|
|
46
|
+
if (!source.startsWith(opener, input.position)) return Result.skip;
|
|
47
|
+
let i = opener.length;
|
|
48
|
+
for (; source[input.position + i] === source[input.position];) ++i;
|
|
49
|
+
input.position += i;
|
|
50
|
+
if (!test(input, output)) {
|
|
51
|
+
input.position = position;
|
|
52
|
+
return Result.skip;
|
|
53
|
+
}
|
|
54
|
+
let depth = i / opener.length + 1 | 0;
|
|
55
|
+
recur(output, recursions, recursion, depth, true);
|
|
56
|
+
input.memory = {
|
|
57
|
+
position,
|
|
58
|
+
i,
|
|
59
|
+
lead: 0,
|
|
60
|
+
follow: 0,
|
|
61
|
+
state: false,
|
|
62
|
+
depth,
|
|
63
|
+
};
|
|
64
|
+
output.push();
|
|
65
|
+
return loop;
|
|
66
|
+
},
|
|
67
|
+
(input, output) => {
|
|
68
|
+
const { source, memory: m, resources: { recursions } } = input;
|
|
69
|
+
recur(output, recursions, recursion, -m.depth);
|
|
70
|
+
m.depth = 0;
|
|
71
|
+
const prefix = m.i;
|
|
72
|
+
m.i = 0;
|
|
73
|
+
for (let len = min(prefix, source.length - input.position); m.i < len && source[input.position + m.i] === closer[0];) {
|
|
74
|
+
++m.i;
|
|
75
|
+
}
|
|
76
|
+
const postfix = m.i;
|
|
77
|
+
input.range = input.position - m.position - prefix;
|
|
78
|
+
return termination(output.pop(), input, output, prefix, postfix, m.state);
|
|
79
|
+
},
|
|
80
|
+
];
|
|
81
|
+
const loop: Result<T, Input<Memory>> = [
|
|
82
|
+
(input, output) => {
|
|
83
|
+
const { source, memory: m, resources: { recursions } } = input;
|
|
84
|
+
for (; m.i >= opener.length; m.i -= opener.length, m.follow -= closer.length) {
|
|
85
|
+
recur(output, recursions, recursion, -1);
|
|
86
|
+
m.depth -= 1;
|
|
87
|
+
const lead = m.lead = m.i - opener.length;
|
|
88
|
+
if (source.startsWith(closer, input.position)) {
|
|
89
|
+
input.position += closer.length;
|
|
90
|
+
const pos = input.position;
|
|
91
|
+
m.follow = m.follow > 0 ? m.follow : countFollows(source, pos, closer, lead / opener.length | 0);
|
|
92
|
+
output.push(cons(output.pop(), input, output, lead, m.follow));
|
|
93
|
+
if (input.position > pos) {
|
|
94
|
+
const advance = input.position - pos;
|
|
95
|
+
m.i -= advance;
|
|
96
|
+
m.follow -= advance;
|
|
97
|
+
m.depth -= advance / closer.length | 0;
|
|
98
|
+
}
|
|
99
|
+
continue;
|
|
67
100
|
}
|
|
68
|
-
|
|
101
|
+
return output.context;
|
|
69
102
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
103
|
+
return Result.skip;
|
|
104
|
+
},
|
|
105
|
+
parser,
|
|
106
|
+
(input, output) => {
|
|
107
|
+
const { source, memory: m } = input;
|
|
108
|
+
const { lead } = m;
|
|
109
|
+
input.range = input.position - m.position - m.i + opener.length;
|
|
110
|
+
if (!output.state) return;
|
|
111
|
+
const pos = input.position;
|
|
112
|
+
const nodes = output.peek();
|
|
78
113
|
switch (nodes.last?.value) {
|
|
79
114
|
case Command.Cancel:
|
|
80
|
-
assert(!source.startsWith(closer,
|
|
115
|
+
assert(!source.startsWith(closer, input.position));
|
|
81
116
|
nodes.pop();
|
|
82
|
-
state = false;
|
|
83
|
-
|
|
117
|
+
m.state = false;
|
|
118
|
+
return;
|
|
84
119
|
case Command.Separator:
|
|
85
|
-
assert(!source.startsWith(closer,
|
|
86
|
-
follow = follow > 0 ? follow : countFollows(source, pos, closer, lead / opener.length | 0);
|
|
120
|
+
assert(!source.startsWith(closer, input.position));
|
|
121
|
+
m.follow = m.follow > 0 ? m.follow : countFollows(source, pos, closer, lead / opener.length | 0);
|
|
87
122
|
nodes.pop();
|
|
88
|
-
state = true;
|
|
89
|
-
|
|
123
|
+
m.state = true;
|
|
124
|
+
m.i -= opener.length, m.follow -= closer.length;
|
|
125
|
+
return loop;
|
|
90
126
|
default:
|
|
91
|
-
follow = follow > 0 ? follow : countFollows(source, pos, closer, lead / opener.length | 0);
|
|
92
|
-
|
|
93
|
-
state = true;
|
|
94
|
-
if (
|
|
95
|
-
const advance =
|
|
96
|
-
i -= advance;
|
|
97
|
-
follow -= advance;
|
|
98
|
-
depth -= advance / closer.length | 0;
|
|
127
|
+
m.follow = m.follow > 0 ? m.follow : countFollows(source, pos, closer, lead / opener.length | 0);
|
|
128
|
+
output.push(cons(output.pop(), input, output, lead, m.follow));
|
|
129
|
+
m.state = true;
|
|
130
|
+
if (input.position > pos) {
|
|
131
|
+
const advance = input.position - pos;
|
|
132
|
+
m.i -= advance;
|
|
133
|
+
m.follow -= advance;
|
|
134
|
+
m.depth -= advance / closer.length | 0;
|
|
99
135
|
}
|
|
100
|
-
|
|
136
|
+
m.i -= opener.length, m.follow -= closer.length;
|
|
137
|
+
return loop;
|
|
101
138
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
depth = 0;
|
|
106
|
-
const prefix = i;
|
|
107
|
-
i = 0;
|
|
108
|
-
for (let len = min(prefix, source.length - context.position); i < len && source[context.position + i] === closer[0];) {
|
|
109
|
-
++i;
|
|
110
|
-
}
|
|
111
|
-
const postfix = i;
|
|
112
|
-
context.range = context.position - position - prefix;
|
|
113
|
-
return termination(nodes, context, prefix, postfix, state);
|
|
114
|
-
};
|
|
139
|
+
},
|
|
140
|
+
];
|
|
141
|
+
return () => cont;
|
|
115
142
|
}
|
|
116
143
|
|
|
117
144
|
function countFollows(source: string, position: number, closer: string, limit: number): number {
|
|
@@ -1,18 +1,7 @@
|
|
|
1
1
|
import { segment } from './segment';
|
|
2
|
-
import { Command } from './context';
|
|
3
2
|
|
|
4
3
|
describe('Unit: parser/segment', () => {
|
|
5
4
|
describe('segment', () => {
|
|
6
|
-
it('huge input', () => {
|
|
7
|
-
const result = segment(`${'\n'.repeat(1e6 + 1)}`).next().value?.[0].split('\n', 1)[0];
|
|
8
|
-
assert(result?.startsWith(`${Command.Error}Too large input`));
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
it('huge segment', () => {
|
|
12
|
-
const result = segment(`${'\n'.repeat(1e5 + 1)}`).next().value?.[0].split('\n', 1)[0];
|
|
13
|
-
assert(result?.startsWith(`${Command.Error}Too large segment`));
|
|
14
|
-
});
|
|
15
|
-
|
|
16
5
|
it('basic', () => {
|
|
17
6
|
assert.deepStrictEqual([...segment('')].map(t => t[0]), []);
|
|
18
7
|
assert.deepStrictEqual([...segment('a')].map(t => t[0]), ['a']);
|
package/src/parser/segment.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { MarkdownParser } from '../../markdown';
|
|
2
|
-
import {
|
|
2
|
+
import { Input, Segment } from './context';
|
|
3
|
+
import { Output, List, Node, run } from '../combinator/parser';
|
|
3
4
|
import { union, some } from '../combinator';
|
|
4
5
|
import { segment as heading } from './block/heading';
|
|
5
6
|
import { segment as codeblock } from './block/codeblock';
|
|
@@ -9,54 +10,50 @@ import { contentline, emptysegment } from './source';
|
|
|
9
10
|
|
|
10
11
|
import SegmentParser = MarkdownParser.SegmentParser;
|
|
11
12
|
|
|
12
|
-
const parser: SegmentParser = union([
|
|
13
|
-
some(emptysegment
|
|
14
|
-
input => {
|
|
13
|
+
export const parser: SegmentParser = union([
|
|
14
|
+
some(emptysegment),
|
|
15
|
+
(input, output) => {
|
|
15
16
|
const { source, position } = input;
|
|
16
17
|
if (position === source.length) return;
|
|
17
18
|
switch (source[position]) {
|
|
18
19
|
case '`':
|
|
19
|
-
if (source.startsWith('```', position)) return codeblock(input);
|
|
20
|
+
if (source.startsWith('```', position)) return codeblock(input, output);
|
|
20
21
|
break;
|
|
21
22
|
case '~':
|
|
22
|
-
if (source.startsWith('~~~', position)) return extension(input);
|
|
23
|
+
if (source.startsWith('~~~', position)) return extension(input, output);
|
|
23
24
|
break;
|
|
24
25
|
case '$':
|
|
25
|
-
if (source[position + 1] === '$') return mathblock(input);
|
|
26
|
-
return extension(input);
|
|
26
|
+
if (source[position + 1] === '$') return mathblock(input, output);
|
|
27
|
+
return extension(input, output);
|
|
27
28
|
case '[':
|
|
28
|
-
if (source[position + 1] === '$') return extension(input);
|
|
29
|
+
if (source[position + 1] === '$') return extension(input, output);
|
|
29
30
|
break;
|
|
30
31
|
case '#':
|
|
31
|
-
return heading(input);
|
|
32
|
+
return heading(input, output);
|
|
32
33
|
}
|
|
33
34
|
},
|
|
34
|
-
some(contentline
|
|
35
|
+
some(contentline),
|
|
35
36
|
]);
|
|
36
37
|
|
|
37
|
-
export function* segment(source: string
|
|
38
|
-
if (initial && !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];
|
|
38
|
+
export function* segment(source: string): Generator<readonly [string, Segment], undefined, undefined> {
|
|
39
39
|
assert(source.length < Number.MAX_SAFE_INTEGER);
|
|
40
|
+
const input = new Input({ source, segment: Segment.unknown });
|
|
41
|
+
const output = new Output<string>();
|
|
40
42
|
for (let position = 0, len = source.length; position < len;) {
|
|
41
|
-
|
|
42
|
-
const
|
|
43
|
-
assert(
|
|
44
|
-
assert(
|
|
43
|
+
input.segment = Segment.unknown;
|
|
44
|
+
for (const _ of run(parser, input, output));
|
|
45
|
+
assert(~input.segment & Segment.write);
|
|
46
|
+
assert(input.position > position);
|
|
47
|
+
assert(output.data.length === 1);
|
|
48
|
+
const result = new List<Node<string>>().import(output.peek());
|
|
45
49
|
const segs = result.length === 0
|
|
46
|
-
? [source.slice(position,
|
|
50
|
+
? [source.slice(position, input.position)]
|
|
47
51
|
: result.foldl<string[]>((acc, { value }) => (acc.push(value), acc), []);
|
|
48
|
-
assert(segs.join('') === source.slice(position,
|
|
49
|
-
position =
|
|
52
|
+
assert(segs.join('') === source.slice(position, input.position));
|
|
53
|
+
position = input.position;
|
|
50
54
|
for (let i = 0; i < segs.length; ++i) {
|
|
51
55
|
const seg = segs[i];
|
|
52
|
-
|
|
53
|
-
? yield [`${Command.Error}Too large segment over ${MAX_SEGMENT_SIZE.toLocaleString('en')} bytes.\n${seg}`, Segment.unknown]
|
|
54
|
-
: yield [seg, context.segment];
|
|
56
|
+
yield [seg, input.segment];
|
|
55
57
|
}
|
|
56
58
|
}
|
|
57
59
|
}
|
|
58
|
-
|
|
59
|
-
function validate(source: string, size: number): boolean {
|
|
60
|
-
return source.length <= size / 2
|
|
61
|
-
|| source.length <= size && new Blob([source]).size <= size;
|
|
62
|
-
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { escsource } from './escapable';
|
|
2
2
|
import { some } from '../../combinator';
|
|
3
|
-
import { input } from '
|
|
4
|
-
import { Context } from '../context';
|
|
3
|
+
import { input } from '../context';
|
|
5
4
|
import { inspect } from '../../debug.test';
|
|
6
5
|
|
|
7
6
|
describe('Unit: parser/source/escsource', () => {
|
|
@@ -9,40 +8,40 @@ describe('Unit: parser/source/escsource', () => {
|
|
|
9
8
|
const parser = some(escsource);
|
|
10
9
|
|
|
11
10
|
it('invalid', () => {
|
|
12
|
-
assert.deepStrictEqual(inspect(parser, input(''
|
|
11
|
+
assert.deepStrictEqual(inspect(parser, input('')), undefined);
|
|
13
12
|
});
|
|
14
13
|
|
|
15
14
|
it('basic', () => {
|
|
16
|
-
assert.deepStrictEqual(inspect(parser, input('a'
|
|
17
|
-
assert.deepStrictEqual(inspect(parser, input('ab'
|
|
18
|
-
assert.deepStrictEqual(inspect(parser, input('a b c'
|
|
19
|
-
assert.deepStrictEqual(inspect(parser, input('09あいAZaz'
|
|
15
|
+
assert.deepStrictEqual(inspect(parser, input('a')), [['a'], '']);
|
|
16
|
+
assert.deepStrictEqual(inspect(parser, input('ab')), [['ab'], '']);
|
|
17
|
+
assert.deepStrictEqual(inspect(parser, input('a b c')), [['a b c'], '']);
|
|
18
|
+
assert.deepStrictEqual(inspect(parser, input('09あいAZaz')), [['09あいAZaz'], '']);
|
|
20
19
|
});
|
|
21
20
|
|
|
22
21
|
it('space', () => {
|
|
23
|
-
assert.deepStrictEqual(inspect(parser, input(' '
|
|
24
|
-
assert.deepStrictEqual(inspect(parser, input(' '
|
|
25
|
-
assert.deepStrictEqual(inspect(parser, input(' '
|
|
26
|
-
assert.deepStrictEqual(inspect(parser, input(' \n'
|
|
27
|
-
assert.deepStrictEqual(inspect(parser, input(' \n'
|
|
28
|
-
assert.deepStrictEqual(inspect(parser, input(' \n'
|
|
22
|
+
assert.deepStrictEqual(inspect(parser, input(' ')), [[' '], '']);
|
|
23
|
+
assert.deepStrictEqual(inspect(parser, input(' ')), [[' '], '']);
|
|
24
|
+
assert.deepStrictEqual(inspect(parser, input(' ')), [[' '], '']);
|
|
25
|
+
assert.deepStrictEqual(inspect(parser, input(' \n')), [[' ', '<br>'], '']);
|
|
26
|
+
assert.deepStrictEqual(inspect(parser, input(' \n')), [[' ', '<br>'], '']);
|
|
27
|
+
assert.deepStrictEqual(inspect(parser, input(' \n')), [[' ', '<br>'], '']);
|
|
29
28
|
});
|
|
30
29
|
|
|
31
30
|
it('linebreak', () => {
|
|
32
|
-
assert.deepStrictEqual(inspect(parser, input('\n\n'
|
|
31
|
+
assert.deepStrictEqual(inspect(parser, input('\n\n')), [['<br>', '<br>'], '']);
|
|
33
32
|
});
|
|
34
33
|
|
|
35
34
|
it('\\', () => {
|
|
36
|
-
assert.deepStrictEqual(inspect(parser, input('\\'
|
|
37
|
-
assert.deepStrictEqual(inspect(parser, input('\\\\'
|
|
38
|
-
assert.deepStrictEqual(inspect(parser, input('\\\\\\'
|
|
39
|
-
assert.deepStrictEqual(inspect(parser, input('\\ '
|
|
40
|
-
assert.deepStrictEqual(inspect(parser, input('\\_'
|
|
41
|
-
assert.deepStrictEqual(inspect(parser, input('\\0'
|
|
42
|
-
assert.deepStrictEqual(inspect(parser, input('\\a'
|
|
43
|
-
assert.deepStrictEqual(inspect(parser, input('\\$'
|
|
44
|
-
assert.deepStrictEqual(inspect(parser, input('\\ '
|
|
45
|
-
assert.deepStrictEqual(inspect(parser, input('\\\n'
|
|
35
|
+
assert.deepStrictEqual(inspect(parser, input('\\')), [['\\'], '']);
|
|
36
|
+
assert.deepStrictEqual(inspect(parser, input('\\\\')), [['\\\\'], '']);
|
|
37
|
+
assert.deepStrictEqual(inspect(parser, input('\\\\\\')), [['\\\\', '\\'], '']);
|
|
38
|
+
assert.deepStrictEqual(inspect(parser, input('\\ ')), [['\\ '], '']);
|
|
39
|
+
assert.deepStrictEqual(inspect(parser, input('\\_')), [['\\_'], '']);
|
|
40
|
+
assert.deepStrictEqual(inspect(parser, input('\\0')), [['\\0'], '']);
|
|
41
|
+
assert.deepStrictEqual(inspect(parser, input('\\a')), [['\\a'], '']);
|
|
42
|
+
assert.deepStrictEqual(inspect(parser, input('\\$')), [['\\$'], '']);
|
|
43
|
+
assert.deepStrictEqual(inspect(parser, input('\\ ')), [['\\ '], '']);
|
|
44
|
+
assert.deepStrictEqual(inspect(parser, input('\\\n')), [['\\', '<br>'], '']);
|
|
46
45
|
});
|
|
47
46
|
|
|
48
47
|
});
|