securemark 0.299.4 → 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 +4 -0
- package/design.md +0 -6
- package/dist/index.js +2749 -1979
- package/index.d.ts +2 -1
- package/markdown.d.ts +209 -183
- package/package.json +1 -1
- package/src/api/bind.test.ts +0 -22
- package/src/api/bind.ts +15 -10
- package/src/api/header.ts +8 -5
- package/src/api/parse.test.ts +118 -122
- package/src/api/parse.ts +13 -31
- package/src/api/run.ts +6 -0
- package/src/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/list → parser}/list.ts +35 -10
- 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 +29 -30
- 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 +31 -37
- 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/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 +35 -14
- package/src/processor/figure.test.ts +20 -20
- package/src/processor/figure.ts +18 -10
- package/src/processor/note.test.ts +13 -13
- package/src/processor/note.ts +4 -2
- 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 -12
- 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/block.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { MarkdownParser } from '../../markdown';
|
|
2
|
-
import { Segment
|
|
3
|
-
import { List, Node } from '../combinator/
|
|
4
|
-
import { union,
|
|
2
|
+
import { Segment } from './context';
|
|
3
|
+
import { List, Node } from '../combinator/parser';
|
|
4
|
+
import { union, lazy, always } from '../combinator';
|
|
5
5
|
import { header } from './header';
|
|
6
6
|
import { emptysegment } from './source';
|
|
7
7
|
import { pagebreak } from './block/pagebreak';
|
|
@@ -42,90 +42,102 @@ export import MediaBlockParser = BlockParser.MediaBlockParser;
|
|
|
42
42
|
export import ReplyParser = BlockParser.ReplyParser;
|
|
43
43
|
export import ParagraphParser = BlockParser.ParagraphParser;
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
const p1 = lazy(() => union([
|
|
46
|
+
ulist,
|
|
47
|
+
ilist,
|
|
48
|
+
]));
|
|
49
|
+
const p2 = lazy(() => union([
|
|
50
|
+
blockquote,
|
|
51
|
+
reply,
|
|
52
|
+
]));
|
|
53
|
+
const p3 = lazy(() => union([
|
|
54
|
+
table,
|
|
55
|
+
sidefence,
|
|
56
|
+
]));
|
|
57
|
+
export const block: BlockParser = lazy(() => error(union([
|
|
46
58
|
emptysegment,
|
|
47
|
-
input => {
|
|
59
|
+
(input, output) => {
|
|
48
60
|
const { source, position, segment } = input;
|
|
49
61
|
if (position === source.length) return;
|
|
50
|
-
switch (segment
|
|
62
|
+
switch (segment & ~Segment.write) {
|
|
51
63
|
case Segment.heading:
|
|
52
|
-
return heading(input);
|
|
64
|
+
return heading(input, output);
|
|
53
65
|
case Segment.fig:
|
|
54
|
-
return fig(input);
|
|
66
|
+
return fig(input, output);
|
|
55
67
|
case Segment.figure:
|
|
56
|
-
return figure(input);
|
|
68
|
+
return figure(input, output);
|
|
57
69
|
}
|
|
58
70
|
const char = source[position];
|
|
59
71
|
switch (char) {
|
|
60
|
-
case Command.Error:
|
|
61
|
-
throw new Error(firstline(source, position + 1).trimEnd());
|
|
62
72
|
case '=':
|
|
63
|
-
if (source.startsWith('===', position)) return pagebreak(input);
|
|
73
|
+
if (source.startsWith('===', position)) return pagebreak(input, output);
|
|
64
74
|
break;
|
|
65
75
|
case '`':
|
|
66
|
-
if (source.startsWith('```', position)) return codeblock(input);
|
|
76
|
+
if (source.startsWith('```', position)) return codeblock(input, output);
|
|
67
77
|
break;
|
|
68
78
|
case '~':
|
|
69
|
-
if (source.startsWith('~~~', position)) return extension(input);
|
|
70
|
-
if (source[position + 1] === ' ') return dlist(input);
|
|
79
|
+
if (source.startsWith('~~~', position)) return extension(input, output);
|
|
80
|
+
if (source[position + 1] === ' ') return dlist(input, output);
|
|
71
81
|
break;
|
|
72
82
|
case '-':
|
|
73
|
-
if (source.startsWith('---', position)) return header(input);
|
|
74
|
-
if (source[position + 1] === ' ') return
|
|
83
|
+
if (source.startsWith('---', position)) return header(input, output);
|
|
84
|
+
if (source[position + 1] === ' ') return p1(input, output);
|
|
75
85
|
break;
|
|
76
86
|
case '+':
|
|
77
87
|
case '*':
|
|
78
|
-
if (source[position + 1] === ' ') return ilist(input);
|
|
88
|
+
if (source[position + 1] === ' ') return ilist(input, output);
|
|
79
89
|
break;
|
|
80
90
|
case '[':
|
|
81
91
|
switch (source[position + 1]) {
|
|
82
92
|
case '$':
|
|
83
|
-
return figbase(input);
|
|
93
|
+
return figbase(input, output);
|
|
84
94
|
case '!':
|
|
85
|
-
return mediablock(input);
|
|
95
|
+
return mediablock(input, output);
|
|
86
96
|
}
|
|
87
97
|
break;
|
|
88
98
|
case '!':
|
|
89
|
-
if (source[position + 1] === '>') return blockquote(input);
|
|
90
|
-
return mediablock(input);
|
|
99
|
+
if (source[position + 1] === '>') return blockquote(input, output);
|
|
100
|
+
return mediablock(input, output);
|
|
91
101
|
case '>':
|
|
92
|
-
if (source[position + 1] === '>') return
|
|
93
|
-
return blockquote(input);
|
|
102
|
+
if (source[position + 1] === '>') return p2(input, output);
|
|
103
|
+
return blockquote(input, output);
|
|
94
104
|
case '$':
|
|
95
|
-
if (source[position + 1] === '$') return mathblock(input);
|
|
96
|
-
return figbase(input);
|
|
105
|
+
if (source[position + 1] === '$') return mathblock(input, output);
|
|
106
|
+
return figbase(input, output);
|
|
97
107
|
case '|':
|
|
98
|
-
return
|
|
108
|
+
return p3(input, output);
|
|
99
109
|
case '(':
|
|
100
|
-
return olist(input);
|
|
110
|
+
return olist(input, output);
|
|
101
111
|
default:
|
|
102
|
-
if (char <= '9' && '0' <= char) return olist(input);
|
|
112
|
+
if (char <= '9' && '0' <= char) return olist(input, output);
|
|
103
113
|
}
|
|
104
114
|
},
|
|
105
115
|
paragraph
|
|
106
|
-
]));
|
|
116
|
+
])));
|
|
107
117
|
|
|
108
118
|
function error(parser: BlockParser): BlockParser {
|
|
109
|
-
|
|
110
|
-
return recover<BlockParser>(
|
|
119
|
+
return always([
|
|
111
120
|
parser,
|
|
112
|
-
({ source, position, id },
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
.slice(
|
|
129
|
-
|
|
130
|
-
|
|
121
|
+
({ source, position, id }, output) => {
|
|
122
|
+
const { error } = output;
|
|
123
|
+
if (!error) return output.context;
|
|
124
|
+
output.error = undefined;
|
|
125
|
+
return output.import(new List([
|
|
126
|
+
new Node(html('h1',
|
|
127
|
+
{
|
|
128
|
+
id: id !== '' ? `error:${rnd0Z(8)}` : undefined,
|
|
129
|
+
class: 'error',
|
|
130
|
+
},
|
|
131
|
+
`${error.name}: ${error.message}`)),
|
|
132
|
+
new Node(html('pre',
|
|
133
|
+
{
|
|
134
|
+
class: 'error',
|
|
135
|
+
translate: 'no',
|
|
136
|
+
},
|
|
137
|
+
source.slice(position)
|
|
138
|
+
.slice(0, 1001)
|
|
139
|
+
.replace(/^(.{997}).{4}$/s, '$1...') || undefined)),
|
|
140
|
+
]));
|
|
141
|
+
},
|
|
142
|
+
]);
|
|
131
143
|
}
|
package/src/parser/context.ts
CHANGED
|
@@ -1,67 +1,72 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Input as Ipt, input as ipt } from '../combinator/parser';
|
|
2
2
|
import { Dict } from 'spica/dict';
|
|
3
3
|
|
|
4
|
-
export
|
|
5
|
-
|
|
4
|
+
export function input(source: string, input: Input = new Input()): Input {
|
|
5
|
+
return ipt(source, input);
|
|
6
|
+
}
|
|
6
7
|
|
|
7
|
-
export class
|
|
8
|
+
export class Input<M extends object = object> extends Ipt<M> {
|
|
8
9
|
constructor(
|
|
9
|
-
options: Partial<
|
|
10
|
+
options: Partial<Input> = {},
|
|
10
11
|
) {
|
|
11
12
|
super(options);
|
|
12
13
|
const {
|
|
13
14
|
segment,
|
|
15
|
+
header,
|
|
14
16
|
local,
|
|
15
17
|
sequential,
|
|
16
|
-
buffer,
|
|
17
|
-
header,
|
|
18
18
|
host,
|
|
19
19
|
url,
|
|
20
20
|
id,
|
|
21
|
+
notes,
|
|
21
22
|
caches,
|
|
23
|
+
test,
|
|
22
24
|
} = options;
|
|
23
|
-
this.resources
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
this.resources ??= {
|
|
26
|
+
clock: -1,
|
|
27
|
+
interval: 200,
|
|
26
28
|
recursions: [
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
20 || Recursion.bracket,
|
|
32
|
-
20 || Recursion.terminal,
|
|
29
|
+
10 || Recursion.scope,
|
|
30
|
+
100 || Recursion.block,
|
|
31
|
+
100 || Recursion.inline,
|
|
32
|
+
100 || Recursion.terminal,
|
|
33
33
|
],
|
|
34
34
|
};
|
|
35
35
|
this.segment = segment ?? Segment.unknown;
|
|
36
|
+
this.header = header ?? true;
|
|
36
37
|
this.local = local ?? false;
|
|
37
38
|
this.sequential = sequential ?? false;
|
|
38
|
-
this.buffer = buffer ?? new List();
|
|
39
|
-
this.header = header ?? true;
|
|
40
39
|
this.host = host;
|
|
41
40
|
this.url = url;
|
|
42
41
|
this.id = id;
|
|
42
|
+
this.notes = notes;
|
|
43
43
|
this.caches = caches;
|
|
44
|
+
this.test = test ?? false;
|
|
44
45
|
}
|
|
45
46
|
public override readonly resources: {
|
|
46
47
|
clock: number;
|
|
47
48
|
recursions: number[];
|
|
49
|
+
interval?: number;
|
|
48
50
|
};
|
|
49
51
|
public override segment: Segment;
|
|
52
|
+
public header: boolean;
|
|
50
53
|
public local: boolean;
|
|
51
54
|
public sequential: boolean;
|
|
52
|
-
public buffer: List<Node<(string | HTMLElement)>>;
|
|
53
55
|
public recursion = new RecursionCounter(2);
|
|
54
|
-
public readonly header: boolean;
|
|
55
56
|
public readonly host?: URL;
|
|
56
57
|
public readonly url?: URL;
|
|
57
|
-
public
|
|
58
|
+
public id?: string;
|
|
59
|
+
public notes?: {
|
|
60
|
+
readonly references: HTMLOListElement;
|
|
61
|
+
};
|
|
58
62
|
public readonly caches?: {
|
|
59
63
|
readonly code?: Dict<string, HTMLElement>;
|
|
60
64
|
readonly math?: Dict<string, HTMLElement>;
|
|
61
65
|
readonly media?: Dict<string, HTMLElement>;
|
|
62
66
|
};
|
|
67
|
+
public test: boolean;
|
|
63
68
|
}
|
|
64
|
-
export type Options = Partial<
|
|
69
|
+
export type Options = Partial<Input>;
|
|
65
70
|
|
|
66
71
|
class RecursionCounter {
|
|
67
72
|
constructor(
|
|
@@ -70,11 +75,11 @@ class RecursionCounter {
|
|
|
70
75
|
}
|
|
71
76
|
private readonly stack: number[] = [];
|
|
72
77
|
private index = 0;
|
|
73
|
-
public add(depth: number):
|
|
78
|
+
public add(depth: number): Error | undefined {
|
|
74
79
|
const { stack } = this
|
|
75
|
-
for (; this.index > 0 && stack[this.index - 1]
|
|
80
|
+
for (; this.index > 0 && stack[this.index - 1] >= depth; --this.index);
|
|
76
81
|
// 内側から数えるので無効化処理できずエラーを投げるしかない。
|
|
77
|
-
if (this.index === this.limit)
|
|
82
|
+
if (this.index === this.limit) return new Error(`Too much recursion`);
|
|
78
83
|
stack[this.index] = depth;
|
|
79
84
|
++this.index;
|
|
80
85
|
}
|
|
@@ -82,12 +87,12 @@ class RecursionCounter {
|
|
|
82
87
|
|
|
83
88
|
export const enum Segment {
|
|
84
89
|
unknown = 0,
|
|
90
|
+
read = 0,
|
|
85
91
|
write = 1,
|
|
86
|
-
nonempty = 0,
|
|
87
92
|
empty = 1 << 1,
|
|
88
|
-
heading =
|
|
89
|
-
fig =
|
|
90
|
-
figure =
|
|
93
|
+
heading = 2 << 1,
|
|
94
|
+
fig = 3 << 1,
|
|
95
|
+
figure = 4 << 1,
|
|
91
96
|
}
|
|
92
97
|
|
|
93
98
|
export const enum State {
|
|
@@ -110,11 +115,9 @@ export const enum State {
|
|
|
110
115
|
}
|
|
111
116
|
|
|
112
117
|
export const enum Recursion {
|
|
118
|
+
scope,
|
|
113
119
|
block,
|
|
114
|
-
blockquote,
|
|
115
|
-
listitem,
|
|
116
120
|
inline,
|
|
117
|
-
bracket,
|
|
118
121
|
terminal,
|
|
119
122
|
}
|
|
120
123
|
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { MarkdownParser } from '../../markdown';
|
|
2
|
+
import { Input, Recursion } from './context';
|
|
3
|
+
import { Parser, Node } from '../combinator/parser';
|
|
4
|
+
import { always, force, recursion } from '../combinator';
|
|
5
|
+
import { build } from './parser';
|
|
6
|
+
import { parser as segment } from './segment';
|
|
7
|
+
import { block } from './block';
|
|
8
|
+
import { unwrap, randomID } from './util';
|
|
9
|
+
import { figure } from '../processor/figure';
|
|
10
|
+
import { note } from '../processor/note';
|
|
11
|
+
import { frag, html } from 'typed-dom/dom';
|
|
12
|
+
|
|
13
|
+
export const document: MarkdownParser = (() => {
|
|
14
|
+
interface Memory {
|
|
15
|
+
readonly interpolation?: boolean;
|
|
16
|
+
readonly references: HTMLOListElement;
|
|
17
|
+
}
|
|
18
|
+
const loop = build(segment, block);
|
|
19
|
+
return always<Parser<DocumentFragment | HTMLElement, Input<Memory>>>([
|
|
20
|
+
(input, output) => {
|
|
21
|
+
input.id =
|
|
22
|
+
input.id === '' ? '' :
|
|
23
|
+
input.local ? randomID() :
|
|
24
|
+
input.id;
|
|
25
|
+
input.memory = input.notes ?? {
|
|
26
|
+
interpolation: true,
|
|
27
|
+
references: html('ol', { class: 'references' }),
|
|
28
|
+
};
|
|
29
|
+
output.push();
|
|
30
|
+
return output.context;
|
|
31
|
+
},
|
|
32
|
+
recursion(Recursion.scope, force(() => loop)),
|
|
33
|
+
(input, output) => {
|
|
34
|
+
assert(input.position === input.source.length);
|
|
35
|
+
const doc = frag(unwrap(output.pop()));
|
|
36
|
+
output.append(new Node(doc));
|
|
37
|
+
assert(input.id !== '' || !doc.querySelector('[id], .index[href], .label[href], .annotation > a[href], .reference > a[href]'));
|
|
38
|
+
if (input.test && !input.local) return output.context;
|
|
39
|
+
const { memory } = input;
|
|
40
|
+
const orphan = !memory.references.parentNode;
|
|
41
|
+
orphan && doc.appendChild(memory.references);
|
|
42
|
+
for (const _ of figure(doc, memory, input));
|
|
43
|
+
for (const _ of note(doc, memory, input));
|
|
44
|
+
orphan && !memory.interpolation && memory.references.remove();
|
|
45
|
+
return output.context;
|
|
46
|
+
},
|
|
47
|
+
]);
|
|
48
|
+
})();
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { header } from './header';
|
|
2
|
-
import { input } from '
|
|
3
|
-
import { Context } from './context';
|
|
2
|
+
import { input } from './context';
|
|
4
3
|
import { inspect } from '../debug.test';
|
|
5
4
|
|
|
6
5
|
describe('Unit: parser/header', () => {
|
|
@@ -8,27 +7,27 @@ describe('Unit: parser/header', () => {
|
|
|
8
7
|
const parser = header;
|
|
9
8
|
|
|
10
9
|
it('invalid', () => {
|
|
11
|
-
assert.deepStrictEqual(inspect(parser, input(''
|
|
12
|
-
assert.deepStrictEqual(inspect(parser, input('---'
|
|
13
|
-
assert.deepStrictEqual(inspect(parser, input('---\n'
|
|
14
|
-
assert.deepStrictEqual(inspect(parser, input('---\n---'
|
|
15
|
-
assert.deepStrictEqual(inspect(parser, input('---\na: b\n'
|
|
16
|
-
assert.deepStrictEqual(inspect(parser, input('---\na: b\n---c'
|
|
17
|
-
assert.deepStrictEqual(inspect(parser, input('---\na: b\n---\nc'
|
|
18
|
-
assert.deepStrictEqual(inspect(parser, input('---\n\n---'
|
|
19
|
-
assert.deepStrictEqual(inspect(parser, input('---\n \n---'
|
|
20
|
-
assert.deepStrictEqual(inspect(parser, input('---\n-\n---'
|
|
21
|
-
assert.deepStrictEqual(inspect(parser, input('---\na: b\n----'
|
|
22
|
-
assert.deepStrictEqual(inspect(parser, input('----\na: b\n---'
|
|
23
|
-
assert.deepStrictEqual(inspect(parser, input(`---\n${'a: b\n'.repeat(101)}
|
|
10
|
+
assert.deepStrictEqual(inspect(parser, input('')), undefined);
|
|
11
|
+
assert.deepStrictEqual(inspect(parser, input('---')), undefined);
|
|
12
|
+
assert.deepStrictEqual(inspect(parser, input('---\n')), undefined);
|
|
13
|
+
assert.deepStrictEqual(inspect(parser, input('---\n---')), [['<pre class="invalid" translate="no">---\n---</pre>'], '']);
|
|
14
|
+
assert.deepStrictEqual(inspect(parser, input('---\na: b\n')), [['<pre class="invalid" translate="no">---\na: b\n</pre>'], '']);
|
|
15
|
+
assert.deepStrictEqual(inspect(parser, input('---\na: b\n---c')), [['<pre class="invalid" translate="no">---\na: b\n---c</pre>'], '']);
|
|
16
|
+
assert.deepStrictEqual(inspect(parser, input('---\na: b\n---\nc')), undefined);
|
|
17
|
+
assert.deepStrictEqual(inspect(parser, input('---\n\n---')), undefined);
|
|
18
|
+
assert.deepStrictEqual(inspect(parser, input('---\n \n---')), undefined);
|
|
19
|
+
assert.deepStrictEqual(inspect(parser, input('---\n-\n---')), [['<pre class="invalid" translate="no">---\n-\n---</pre>'], '']);
|
|
20
|
+
assert.deepStrictEqual(inspect(parser, input('---\na: b\n----')), [['<pre class="invalid" translate="no">---\na: b\n----</pre>'], '']);
|
|
21
|
+
assert.deepStrictEqual(inspect(parser, input('----\na: b\n---')), [['<pre class="invalid" translate="no">----\na: b\n---</pre>'], '']);
|
|
22
|
+
assert.deepStrictEqual(inspect(parser, input(`---\n${'a: b\n'.repeat(101)}---`)), [[`<pre class="invalid" translate="no">---\n${'a: b\n'.repeat(101)}---</pre>`], '']);
|
|
24
23
|
});
|
|
25
24
|
|
|
26
25
|
it('basic', () => {
|
|
27
|
-
assert.deepStrictEqual(inspect(parser, input('---\na: b\n---'
|
|
28
|
-
assert.deepStrictEqual(inspect(parser, input('---\na: b\n---\n'
|
|
29
|
-
assert.deepStrictEqual(inspect(parser, input('---\na: b\nC: D e\n---\n'
|
|
30
|
-
assert.deepStrictEqual(inspect(parser, input('---\r\na: b\r\nC: D e\r\n---\r\n'
|
|
31
|
-
assert.deepStrictEqual(inspect(parser, input('----\na: b\n----'
|
|
26
|
+
assert.deepStrictEqual(inspect(parser, input('---\na: b\n---')), [['<aside class="header"><details open=""><summary>Header</summary><div class="field" data-name="a" data-value="b"><span class="field-name">a</span>: <span class="field-value">b</span></div></details></aside>'], '']);
|
|
27
|
+
assert.deepStrictEqual(inspect(parser, input('---\na: b\n---\n')), [['<aside class="header"><details open=""><summary>Header</summary><div class="field" data-name="a" data-value="b"><span class="field-name">a</span>: <span class="field-value">b</span></div></details></aside>'], '']);
|
|
28
|
+
assert.deepStrictEqual(inspect(parser, input('---\na: b\nC: D e\n---\n')), [['<aside class="header"><details open=""><summary>Header</summary><div class="field" data-name="a" data-value="b"><span class="field-name">a</span>: <span class="field-value">b</span></div><div class="field" data-name="c" data-value="D e"><span class="field-name">C</span>: <span class="field-value">D e</span></div></details></aside>'], '']);
|
|
29
|
+
assert.deepStrictEqual(inspect(parser, input('---\r\na: b\r\nC: D e\r\n---\r\n')), [['<aside class="header"><details open=""><summary>Header</summary><div class="field" data-name="a" data-value="b"><span class="field-name">a</span>: <span class="field-value">b</span></div><div class="field" data-name="c" data-value="D e"><span class="field-name">C</span>: <span class="field-value">D e</span></div></details></aside>'], '']);
|
|
30
|
+
assert.deepStrictEqual(inspect(parser, input('----\na: b\n----')), [['<aside class="header"><details open=""><summary>Header</summary><div class="field" data-name="a" data-value="b"><span class="field-name">a</span>: <span class="field-value">b</span></div></details></aside>'], '']);
|
|
32
31
|
});
|
|
33
32
|
|
|
34
33
|
});
|
package/src/parser/header.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { MarkdownParser } from '../../markdown';
|
|
2
|
-
import { List, Node } from '../combinator/
|
|
3
|
-
import { union, inits, some, block, line, validate, focus, clear,
|
|
2
|
+
import { List, Node } from '../combinator/parser';
|
|
3
|
+
import { union, inits, some, scope, block, line, validate, focus, clear, lazy, fmap } from '../combinator';
|
|
4
4
|
import { str } from './source';
|
|
5
5
|
import { unwrap, invalid } from './util';
|
|
6
|
+
import { ReadonlyURL } from 'spica/url';
|
|
6
7
|
import { html, defrag } from 'typed-dom/dom';
|
|
7
8
|
|
|
8
9
|
export const header: MarkdownParser.HeaderParser = lazy(() => validate(
|
|
@@ -10,42 +11,47 @@ export const header: MarkdownParser.HeaderParser = lazy(() => validate(
|
|
|
10
11
|
inits([
|
|
11
12
|
block(
|
|
12
13
|
union([
|
|
13
|
-
validate(
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
14
|
+
validate(
|
|
15
|
+
input => input.header,
|
|
16
|
+
focus(/(---+)[^\S\r\n]*\r?\n(?:[a-z][0-9a-z]*(?:-[0-9a-z]+)*:[ \t]+\S[^\r\n]*\r?\n){1,32}\1[^\S\r\n]*(?:$|\r?\n)/yi,
|
|
17
|
+
scope(
|
|
18
|
+
({ source }) => source.slice(source.indexOf('\n') + 1, source.trimEnd().lastIndexOf('\n')),
|
|
19
|
+
fmap(
|
|
20
|
+
some(union([field])),
|
|
21
|
+
ns => new List([
|
|
22
|
+
new Node(html('aside', { class: 'header' }, [
|
|
23
|
+
html('details',
|
|
24
|
+
{ open: '' },
|
|
25
|
+
defrag(unwrap(ns.unshift(new Node(html('summary', 'Header')))))),
|
|
26
|
+
])),
|
|
27
|
+
])),
|
|
28
|
+
false))),
|
|
29
|
+
(input, output) => {
|
|
30
|
+
const { source, position } = input;
|
|
31
|
+
input.position += source.length;
|
|
32
|
+
return output.append(
|
|
30
33
|
new Node(html('pre', {
|
|
31
34
|
class: 'invalid',
|
|
32
35
|
translate: 'no',
|
|
33
36
|
...invalid('header', 'syntax', 'Invalid syntax'),
|
|
34
|
-
}, source.slice(position)))
|
|
35
|
-
]);
|
|
37
|
+
}, source.slice(position))));
|
|
36
38
|
},
|
|
37
39
|
])),
|
|
38
40
|
clear(str(/[^\S\r\n]*\r?\n/y)),
|
|
39
41
|
])));
|
|
40
42
|
|
|
41
|
-
const field: MarkdownParser.HeaderParser.FieldParser = line((
|
|
43
|
+
const field: MarkdownParser.HeaderParser.FieldParser = line((input, output) => {
|
|
44
|
+
const { source, position } = input;
|
|
42
45
|
const name = source.slice(position, source.indexOf(':', position));
|
|
43
46
|
const value = source.slice(position + name.length + 1).trim();
|
|
44
|
-
|
|
47
|
+
if (name.toLowerCase() === 'url') {
|
|
48
|
+
// @ts-expect-error
|
|
49
|
+
input.url = new ReadonlyURL(value as ':');
|
|
50
|
+
}
|
|
51
|
+
return output.append(
|
|
45
52
|
new Node(html('div', { class: 'field', 'data-name': name.toLowerCase(), 'data-value': value }, [
|
|
46
53
|
html('span', { class: 'field-name' }, name),
|
|
47
54
|
': ',
|
|
48
55
|
html('span', { class: 'field-value' }, value),
|
|
49
|
-
]))
|
|
50
|
-
]);
|
|
56
|
+
])));
|
|
51
57
|
});
|