securemark 0.293.4 → 0.294.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/dist/index.js +868 -564
- package/markdown.d.ts +13 -13
- package/package.json +3 -3
- package/src/combinator/control/constraint/block.test.ts +6 -6
- package/src/combinator/control/constraint/contract.ts +3 -3
- package/src/combinator/control/constraint/line.test.ts +7 -7
- package/src/combinator/control/constraint/line.ts +1 -1
- package/src/combinator/control/manipulation/clear.ts +2 -3
- package/src/combinator/control/manipulation/convert.ts +2 -2
- package/src/combinator/control/manipulation/duplicate.ts +4 -5
- package/src/combinator/control/manipulation/fence.ts +2 -2
- package/src/combinator/control/manipulation/indent.test.ts +2 -2
- package/src/combinator/control/manipulation/indent.ts +4 -4
- package/src/combinator/control/manipulation/reverse.ts +2 -2
- package/src/combinator/control/manipulation/scope.ts +3 -4
- package/src/combinator/control/manipulation/surround.ts +14 -15
- package/src/combinator/control/monad/bind.ts +6 -6
- package/src/combinator/control/monad/fmap.ts +7 -7
- package/src/combinator/data/data.ts +135 -0
- package/src/combinator/data/parser/context.test.ts +16 -15
- package/src/combinator/data/parser/context.ts +5 -4
- package/src/combinator/data/parser/inits.ts +6 -7
- package/src/combinator/data/parser/sequence.test.ts +3 -3
- package/src/combinator/data/parser/sequence.ts +6 -7
- package/src/combinator/data/parser/some.test.ts +3 -3
- package/src/combinator/data/parser/some.ts +4 -4
- package/src/combinator/data/parser/subsequence.test.ts +4 -4
- package/src/combinator/data/parser/subsequence.ts +3 -3
- package/src/combinator/data/parser/tails.ts +3 -3
- package/src/combinator/data/parser/union.test.ts +3 -3
- package/src/combinator/data/parser.ts +16 -7
- package/src/debug.test.ts +6 -5
- package/src/parser/api/bind.ts +6 -8
- package/src/parser/api/header.ts +1 -1
- package/src/parser/api/normalize.ts +2 -4
- package/src/parser/api/parse.ts +3 -1
- package/src/parser/block/blockquote.ts +6 -4
- package/src/parser/block/codeblock.ts +8 -7
- package/src/parser/block/dlist.ts +9 -8
- package/src/parser/block/extension/aside.ts +27 -21
- package/src/parser/block/extension/example.ts +29 -26
- package/src/parser/block/extension/fig.ts +1 -1
- package/src/parser/block/extension/figbase.ts +6 -5
- package/src/parser/block/extension/figure.ts +23 -19
- package/src/parser/block/extension/message.ts +35 -24
- package/src/parser/block/extension/placeholder.ts +17 -13
- package/src/parser/block/extension/table.ts +47 -40
- package/src/parser/block/heading.test.ts +3 -12
- package/src/parser/block/heading.ts +12 -8
- package/src/parser/block/ilist.ts +13 -12
- package/src/parser/block/mathblock.ts +21 -17
- package/src/parser/block/mediablock.ts +7 -5
- package/src/parser/block/olist.ts +15 -5
- package/src/parser/block/pagebreak.ts +2 -1
- package/src/parser/block/paragraph.ts +3 -1
- package/src/parser/block/reply/cite.ts +20 -15
- package/src/parser/block/reply/quote.ts +9 -7
- package/src/parser/block/reply.ts +7 -3
- package/src/parser/block/sidefence.ts +8 -7
- package/src/parser/block/table.ts +23 -22
- package/src/parser/block/ulist.ts +16 -12
- package/src/parser/block.ts +7 -6
- package/src/parser/header.test.ts +3 -1
- package/src/parser/header.ts +20 -20
- package/src/parser/inline/annotation.ts +3 -1
- package/src/parser/inline/autolink/account.ts +3 -2
- package/src/parser/inline/autolink/anchor.ts +3 -2
- package/src/parser/inline/autolink/channel.ts +5 -4
- package/src/parser/inline/autolink/email.ts +4 -3
- package/src/parser/inline/autolink/hashnum.ts +3 -2
- package/src/parser/inline/autolink/hashtag.ts +4 -3
- package/src/parser/inline/autolink/url.ts +7 -6
- package/src/parser/inline/bracket.ts +16 -15
- package/src/parser/inline/code.ts +5 -4
- package/src/parser/inline/deletion.ts +5 -5
- package/src/parser/inline/emphasis.ts +4 -3
- package/src/parser/inline/emstrong.test.ts +18 -18
- package/src/parser/inline/emstrong.ts +39 -30
- package/src/parser/inline/extension/index.ts +22 -19
- package/src/parser/inline/extension/indexee.ts +2 -2
- package/src/parser/inline/extension/indexer.ts +2 -1
- package/src/parser/inline/extension/label.ts +7 -3
- package/src/parser/inline/extension/placeholder.ts +6 -6
- package/src/parser/inline/html.ts +27 -28
- package/src/parser/inline/htmlentity.ts +9 -8
- package/src/parser/inline/insertion.ts +5 -5
- package/src/parser/inline/italic.ts +5 -5
- package/src/parser/inline/link.ts +36 -38
- package/src/parser/inline/mark.ts +7 -7
- package/src/parser/inline/math.ts +5 -4
- package/src/parser/inline/media.ts +33 -32
- package/src/parser/inline/reference.ts +19 -20
- package/src/parser/inline/remark.ts +11 -11
- package/src/parser/inline/ruby.ts +50 -53
- package/src/parser/inline/strong.ts +4 -3
- package/src/parser/inline/template.ts +16 -15
- package/src/parser/inline.test.ts +3 -3
- package/src/parser/segment.ts +3 -1
- package/src/parser/source/escapable.ts +9 -8
- package/src/parser/source/line.ts +4 -3
- package/src/parser/source/str.ts +2 -2
- package/src/parser/source/text.ts +19 -26
- package/src/parser/source/unescapable.ts +6 -5
- package/src/parser/util.ts +16 -30
- package/src/parser/visibility.ts +19 -20
|
@@ -1,25 +1,29 @@
|
|
|
1
1
|
import { ExtensionParser } from '../../block';
|
|
2
2
|
import { Recursion } from '../../context';
|
|
3
|
+
import { List, Data } from '../../../combinator/data/parser';
|
|
3
4
|
import { recursion, block, fence, fmap } from '../../../combinator';
|
|
4
5
|
import { identity } from '../../inline/extension/indexee';
|
|
5
|
-
import { invalid } from '../../util';
|
|
6
|
+
import { unwrap, invalid } from '../../util';
|
|
6
7
|
import { parse } from '../../api/parse';
|
|
7
8
|
import { html } from 'typed-dom/dom';
|
|
8
9
|
|
|
9
10
|
export const aside: ExtensionParser.AsideParser = recursion(Recursion.block, block(fmap(
|
|
10
11
|
fence(/(~{3,})aside(?!\S)([^\n]*)(?:$|\n)/y, 300),
|
|
11
12
|
// Bug: Type mismatch between outer and inner.
|
|
12
|
-
(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
'
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
overflow ?
|
|
21
|
-
|
|
22
|
-
|
|
13
|
+
(nodes: List<Data<string>>, context) => {
|
|
14
|
+
const [body, overflow, closer, opener, delim, param] = unwrap(nodes);
|
|
15
|
+
if (!closer || overflow || param.trimStart()) return new List([
|
|
16
|
+
new Data(html('pre', {
|
|
17
|
+
class: 'invalid',
|
|
18
|
+
translate: 'no',
|
|
19
|
+
...invalid(
|
|
20
|
+
'aside',
|
|
21
|
+
!closer || overflow ? 'fence' : 'argument',
|
|
22
|
+
!closer ? `Missing the closing delimiter "${delim}"` :
|
|
23
|
+
overflow ? `Invalid trailing line after the closing delimiter "${delim}"` :
|
|
24
|
+
'Invalid argument'),
|
|
25
|
+
}, `${opener}${body}${overflow || closer}`))
|
|
26
|
+
]);
|
|
23
27
|
const references = html('ol', { class: 'references' });
|
|
24
28
|
const document = parse(body.slice(0, -1), {
|
|
25
29
|
id: '',
|
|
@@ -29,17 +33,19 @@ export const aside: ExtensionParser.AsideParser = recursion(Recursion.block, blo
|
|
|
29
33
|
}, context);
|
|
30
34
|
assert(!document.querySelector('[id]'));
|
|
31
35
|
const heading = 'H1 H2 H3 H4 H5 H6'.split(' ').includes(document.firstElementChild?.tagName!) && document.firstElementChild as HTMLHeadingElement;
|
|
32
|
-
if (!heading) return [
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
if (!heading) return new List([
|
|
37
|
+
new Data(html('pre', {
|
|
38
|
+
class: 'invalid',
|
|
39
|
+
translate: 'no',
|
|
40
|
+
...invalid('aside', 'content', 'Missing the title at the first line'),
|
|
41
|
+
}, `${opener}${body}${closer}`))
|
|
42
|
+
]);
|
|
37
43
|
assert(identity('index', context.id, heading));
|
|
38
|
-
return [
|
|
39
|
-
html('aside', { id: identity('index', context.id, heading), class: 'aside' }, [
|
|
44
|
+
return new List([
|
|
45
|
+
new Data(html('aside', { id: identity('index', context.id, heading), class: 'aside' }, [
|
|
40
46
|
document,
|
|
41
47
|
html('h2', 'References'),
|
|
42
48
|
references,
|
|
43
|
-
])
|
|
44
|
-
];
|
|
49
|
+
]))
|
|
50
|
+
]);
|
|
45
51
|
})));
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ExtensionParser } from '../../block';
|
|
2
2
|
import { Recursion } from '../../context';
|
|
3
|
-
import {
|
|
3
|
+
import { List, Data, subinput, eval } from '../../../combinator/data/parser';
|
|
4
4
|
import { recursion, block, fence, fmap } from '../../../combinator';
|
|
5
5
|
import { mathblock } from '../mathblock';
|
|
6
|
-
import { invalid } from '../../util';
|
|
6
|
+
import { unwrap, invalid } from '../../util';
|
|
7
7
|
import { parse } from '../../api/parse';
|
|
8
8
|
import { html } from 'typed-dom/dom';
|
|
9
9
|
|
|
@@ -12,17 +12,20 @@ const opener = /(~{3,})(?:example\/(\S+))?(?!\S)([^\n]*)(?:$|\n)/y;
|
|
|
12
12
|
export const example: ExtensionParser.ExampleParser = recursion(Recursion.block, block(fmap(
|
|
13
13
|
fence(opener, 300),
|
|
14
14
|
// Bug: Type mismatch between outer and inner.
|
|
15
|
-
(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
'
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
overflow ?
|
|
24
|
-
|
|
25
|
-
|
|
15
|
+
(nodes: List<Data<string>>, context) => {
|
|
16
|
+
const [body, overflow, closer, opener, delim, type = 'markdown', param] = unwrap(nodes);
|
|
17
|
+
if (!closer || overflow || param.trimStart()) return new List([
|
|
18
|
+
new Data(html('pre', {
|
|
19
|
+
class: 'invalid',
|
|
20
|
+
translate: 'no',
|
|
21
|
+
...invalid(
|
|
22
|
+
'example',
|
|
23
|
+
!closer || overflow ? 'fence' : 'argument',
|
|
24
|
+
!closer ? `Missing the closing delimiter "${delim}"` :
|
|
25
|
+
overflow ? `Invalid trailing line after the closing delimiter "${delim}"` :
|
|
26
|
+
'Invalid argument'),
|
|
27
|
+
}, `${opener}${body}${overflow || closer}`))
|
|
28
|
+
]);
|
|
26
29
|
switch (type) {
|
|
27
30
|
case 'markdown': {
|
|
28
31
|
const references = html('ol', { class: 'references' });
|
|
@@ -33,29 +36,29 @@ export const example: ExtensionParser.ExampleParser = recursion(Recursion.block,
|
|
|
33
36
|
},
|
|
34
37
|
}, context);
|
|
35
38
|
assert(!document.querySelector('[id]'));
|
|
36
|
-
return [
|
|
37
|
-
html('aside', { class: 'example', 'data-type': 'markdown' }, [
|
|
39
|
+
return new List([
|
|
40
|
+
new Data(html('aside', { class: 'example', 'data-type': 'markdown' }, [
|
|
38
41
|
html('pre', { translate: 'no' }, body.slice(0, -1)),
|
|
39
42
|
html('hr'),
|
|
40
43
|
html('section', [document, html('h2', 'References'), references]),
|
|
41
|
-
]),
|
|
42
|
-
];
|
|
44
|
+
])),
|
|
45
|
+
]);
|
|
43
46
|
}
|
|
44
47
|
case 'math':
|
|
45
|
-
return [
|
|
46
|
-
html('aside', { class: 'example', 'data-type': 'math' }, [
|
|
48
|
+
return new List([
|
|
49
|
+
new Data(html('aside', { class: 'example', 'data-type': 'math' }, [
|
|
47
50
|
html('pre', { translate: 'no' }, body.slice(0, -1)),
|
|
48
51
|
html('hr'),
|
|
49
|
-
eval(mathblock(
|
|
50
|
-
]),
|
|
51
|
-
];
|
|
52
|
+
eval(mathblock(subinput(`$$\n${body}$$`, context)))!.head!.value,
|
|
53
|
+
])),
|
|
54
|
+
]);
|
|
52
55
|
default:
|
|
53
|
-
return [
|
|
54
|
-
html('pre', {
|
|
56
|
+
return new List([
|
|
57
|
+
new Data(html('pre', {
|
|
55
58
|
class: 'invalid',
|
|
56
59
|
translate: 'no',
|
|
57
60
|
...invalid('example', 'type', 'Invalid example type'),
|
|
58
|
-
}, `${opener}${body}${closer}`),
|
|
59
|
-
];
|
|
61
|
+
}, `${opener}${body}${closer}`)),
|
|
62
|
+
]);
|
|
60
63
|
}
|
|
61
64
|
})));
|
|
@@ -36,7 +36,7 @@ export const fig: FigParser = block(rewrite(segment, verify(convert(
|
|
|
36
36
|
},
|
|
37
37
|
union([figure]),
|
|
38
38
|
false),
|
|
39
|
-
([el]) => el.tagName === 'FIGURE')));
|
|
39
|
+
([{ value: el }]) => el.tagName === 'FIGURE')));
|
|
40
40
|
|
|
41
41
|
const parser = sequence([
|
|
42
42
|
line(close(seg_label, /(?=\s).*\n/y)),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ExtensionParser } from '../../block';
|
|
2
|
+
import { List, Data } from '../../../combinator/data/parser';
|
|
2
3
|
import { union, block, line, validate, fmap } from '../../../combinator';
|
|
3
4
|
import { label } from '../../inline/extension/label';
|
|
4
5
|
import { html } from 'typed-dom/dom';
|
|
@@ -6,14 +7,14 @@ import { html } from 'typed-dom/dom';
|
|
|
6
7
|
export const figbase: ExtensionParser.FigbaseParser = block(fmap(
|
|
7
8
|
validate(/\[?\$-(?:[0-9]+\.)*0\]?[^\S\n]*(?!\S|\n[^\S\n]*\S)/y,
|
|
8
9
|
line(union([label]))),
|
|
9
|
-
([el]) => {
|
|
10
|
+
([{ value: el }]) => {
|
|
10
11
|
const label = el.getAttribute('data-label')!;
|
|
11
12
|
const group = label.split('-', 1)[0];
|
|
12
|
-
return [
|
|
13
|
-
html('figure', {
|
|
13
|
+
return new List([
|
|
14
|
+
new Data(html('figure', {
|
|
14
15
|
'data-label': label,
|
|
15
16
|
'data-group': group,
|
|
16
17
|
hidden: '',
|
|
17
|
-
}),
|
|
18
|
-
];
|
|
18
|
+
})),
|
|
19
|
+
]);
|
|
19
20
|
}));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ExtensionParser } from '../../block';
|
|
2
|
-
import {
|
|
2
|
+
import { List, Data, subinput } from '../../../combinator/data/parser';
|
|
3
3
|
import { union, inits, sequence, some, block, line, fence, rewrite, close, match, convert, fallback, fmap } from '../../../combinator';
|
|
4
4
|
import { str, contentline, emptyline } from '../../source';
|
|
5
5
|
import { label, segment as seg_label } from '../../inline/extension/label';
|
|
@@ -14,7 +14,7 @@ import { blockquote, segment as seg_blockquote } from '../blockquote';
|
|
|
14
14
|
import { placeholder, segment_ as seg_placeholder } from './placeholder';
|
|
15
15
|
import { inline, media, lineshortmedia } from '../../inline';
|
|
16
16
|
import { visualize, trimBlank } from '../../visibility';
|
|
17
|
-
import { invalid } from '../../util';
|
|
17
|
+
import { unwrap, invalid } from '../../util';
|
|
18
18
|
import { memoize } from 'spica/memoize';
|
|
19
19
|
import { html, defrag } from 'typed-dom/dom';
|
|
20
20
|
|
|
@@ -68,20 +68,24 @@ export const figure: FigureParser = block(fallback(rewrite(segment, fmap(
|
|
|
68
68
|
block(visualize(trimBlank(some(inline)))),
|
|
69
69
|
]),
|
|
70
70
|
]), false),
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
html('
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
71
|
+
nodes => {
|
|
72
|
+
const [label, param, content, ...caption] = unwrap(nodes) as [HTMLAnchorElement, string, ...HTMLElement[]];
|
|
73
|
+
return new List([
|
|
74
|
+
new Data(html('figure',
|
|
75
|
+
attributes(label.getAttribute('data-label')!, param, content, caption),
|
|
76
|
+
[
|
|
77
|
+
html('figcaption', [
|
|
78
|
+
html('span', { class: 'figindex' }),
|
|
79
|
+
html('span', { class: 'figtext' }, defrag(caption)),
|
|
80
|
+
]),
|
|
81
|
+
html('div', [content]),
|
|
82
|
+
]))
|
|
83
|
+
]);
|
|
84
|
+
})),
|
|
82
85
|
fmap(
|
|
83
86
|
fence(/(~{3,})(?:figure|\[?\$\S*)(?!\S)[^\n]*(?:$|\n)/y, 300),
|
|
84
|
-
(
|
|
87
|
+
(nodes, context) => {
|
|
88
|
+
const [body, overflow, closer, opener, delim] = unwrap<string>(nodes);
|
|
85
89
|
const violation =
|
|
86
90
|
!closer && [
|
|
87
91
|
'fence',
|
|
@@ -91,7 +95,7 @@ export const figure: FigureParser = block(fallback(rewrite(segment, fmap(
|
|
|
91
95
|
'fence',
|
|
92
96
|
`Invalid trailing line after the closing delimiter "${delim}"`,
|
|
93
97
|
] ||
|
|
94
|
-
!seg_label(
|
|
98
|
+
!seg_label(subinput(opener.match(/^~+(?:figure[^\S\n]+)?(\[?\$\S+)/)?.[1] ?? '', context)) && [
|
|
95
99
|
'label',
|
|
96
100
|
'Invalid label',
|
|
97
101
|
] ||
|
|
@@ -103,13 +107,13 @@ export const figure: FigureParser = block(fallback(rewrite(segment, fmap(
|
|
|
103
107
|
'content',
|
|
104
108
|
'Invalid content',
|
|
105
109
|
];
|
|
106
|
-
return [
|
|
107
|
-
html('pre', {
|
|
110
|
+
return new List([
|
|
111
|
+
new Data(html('pre', {
|
|
108
112
|
class: 'invalid',
|
|
109
113
|
translate: 'no',
|
|
110
114
|
...invalid('figure', violation[0], violation[1]),
|
|
111
|
-
}, `${opener}${body}${overflow || closer}`),
|
|
112
|
-
];
|
|
115
|
+
}, `${opener}${body}${overflow || closer}`)),
|
|
116
|
+
]);
|
|
113
117
|
})));
|
|
114
118
|
|
|
115
119
|
function attributes(label: string, param: string, content: HTMLElement, caption: readonly HTMLElement[]): Record<string, string | undefined> {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ExtensionParser } from '../../block';
|
|
2
|
-
import {
|
|
2
|
+
import { List, Data, subinput, eval } from '../../../combinator/data/parser';
|
|
3
3
|
import { union, block, fence, fmap } from '../../../combinator';
|
|
4
4
|
import { segment } from '../../segment';
|
|
5
5
|
import { emptyline } from '../../source';
|
|
@@ -13,8 +13,8 @@ import { sidefence } from '../sidefence';
|
|
|
13
13
|
import { blockquote } from '../blockquote';
|
|
14
14
|
import { mediablock } from '../mediablock';
|
|
15
15
|
import { paragraph } from '../paragraph';
|
|
16
|
-
import { invalid } from '../../util';
|
|
17
|
-
import {
|
|
16
|
+
import { unwrap, invalid } from '../../util';
|
|
17
|
+
import { push } from 'spica/array';
|
|
18
18
|
import { html } from 'typed-dom/dom';
|
|
19
19
|
|
|
20
20
|
import MessageParser = ExtensionParser.MessageParser;
|
|
@@ -22,34 +22,45 @@ import MessageParser = ExtensionParser.MessageParser;
|
|
|
22
22
|
export const message: MessageParser = block(fmap(
|
|
23
23
|
fence(/(~{3,})message\/(\S+)([^\n]*)(?:$|\n)/y, 300),
|
|
24
24
|
// Bug: Type mismatch between outer and inner.
|
|
25
|
-
(
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
'
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
overflow ?
|
|
34
|
-
|
|
35
|
-
|
|
25
|
+
(nodes: List<Data<string>>, context) => {
|
|
26
|
+
const [body, overflow, closer, opener, delim, type, param] = unwrap(nodes);
|
|
27
|
+
if (!closer || overflow || param.trimStart()) return new List([
|
|
28
|
+
new Data(html('pre', {
|
|
29
|
+
class: 'invalid',
|
|
30
|
+
translate: 'no',
|
|
31
|
+
...invalid(
|
|
32
|
+
'message',
|
|
33
|
+
!closer || overflow ? 'fence' : 'argument',
|
|
34
|
+
!closer ? `Missing the closing delimiter "${delim}"` :
|
|
35
|
+
overflow ? `Invalid trailing line after the closing delimiter "${delim}"` :
|
|
36
|
+
'Invalid argument'),
|
|
37
|
+
}, `${opener}${body}${overflow || closer}`))
|
|
38
|
+
]);
|
|
36
39
|
switch (type) {
|
|
37
40
|
case 'note':
|
|
38
41
|
case 'caution':
|
|
39
42
|
case 'warning':
|
|
40
43
|
break;
|
|
41
44
|
default:
|
|
42
|
-
return [
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
return new List([
|
|
46
|
+
new Data(html('pre', {
|
|
47
|
+
class: 'invalid',
|
|
48
|
+
translate: 'no',
|
|
49
|
+
...invalid('message', 'type', 'Invalid message type'),
|
|
50
|
+
}, `${opener}${body}${closer}`))
|
|
51
|
+
]);
|
|
47
52
|
}
|
|
48
|
-
return [
|
|
49
|
-
html('section',
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
+
return new List([
|
|
54
|
+
new Data(html('section',
|
|
55
|
+
{
|
|
56
|
+
class: `message`,
|
|
57
|
+
'data-type': type,
|
|
58
|
+
},
|
|
59
|
+
[...segment(body)].reduce(
|
|
60
|
+
(acc, seg) =>
|
|
61
|
+
push(acc, unwrap(eval(content(subinput(seg, context)))!)),
|
|
62
|
+
[html('h1', title(type))])))
|
|
63
|
+
]);
|
|
53
64
|
}));
|
|
54
65
|
|
|
55
66
|
function title(type: string): string {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ExtensionParser } from '../../block';
|
|
2
|
+
import { List, Data } from '../../../combinator/data/parser';
|
|
2
3
|
import { block, fence, clear, fmap } from '../../../combinator';
|
|
3
|
-
import { invalid } from '../../util';
|
|
4
|
+
import { unwrap, invalid } from '../../util';
|
|
4
5
|
import { html } from 'typed-dom/dom';
|
|
5
6
|
|
|
6
7
|
const opener = /(~{3,})(?!~)[^\n]*(?:$|\n)/y;
|
|
@@ -13,15 +14,18 @@ export const segment_: ExtensionParser.PlaceholderParser.SegmentParser = block(
|
|
|
13
14
|
|
|
14
15
|
export const placeholder: ExtensionParser.PlaceholderParser = block(fmap(
|
|
15
16
|
fence(opener, Infinity),
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
'
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
17
|
+
nodes => {
|
|
18
|
+
const [body, overflow, closer, opener, delim] = unwrap(nodes);
|
|
19
|
+
return new List([
|
|
20
|
+
new Data(html('pre', {
|
|
21
|
+
class: 'invalid',
|
|
22
|
+
translate: 'no',
|
|
23
|
+
...invalid(
|
|
24
|
+
'extension',
|
|
25
|
+
'fence',
|
|
26
|
+
!closer ? `Missing the closing delimiter "${delim}"` :
|
|
27
|
+
overflow ? `Invalid trailing line after the closing delimiter "${delim}"` :
|
|
28
|
+
'Invalid argument'),
|
|
29
|
+
}, `${opener}${body}${overflow || closer}`)),
|
|
30
|
+
]);
|
|
31
|
+
}));
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { max, min
|
|
1
|
+
import { max, min } from 'spica/alias';
|
|
2
2
|
import { ExtensionParser } from '../../block';
|
|
3
|
-
import {
|
|
3
|
+
import { List, Data, subinput, eval } from '../../../combinator/data/parser';
|
|
4
4
|
import { union, subsequence, inits, some, block, line, validate, fence, rewrite, clear, surround, open, convert, dup, lazy, fmap } from '../../../combinator';
|
|
5
5
|
import { inline, medialink, media, lineshortmedia } from '../../inline';
|
|
6
6
|
import { str, anyline, emptyline, contentline } from '../../source';
|
|
7
|
-
import { invalid } from '../../util';
|
|
7
|
+
import { unwrap, invalid } from '../../util';
|
|
8
8
|
import { visualize, trimBlank, trimBlankEnd } from '../../visibility';
|
|
9
|
-
import {
|
|
9
|
+
import { splice } from 'spica/array';
|
|
10
10
|
import { html, define, defrag } from 'typed-dom/dom';
|
|
11
11
|
|
|
12
12
|
import TableParser = ExtensionParser.TableParser;
|
|
@@ -25,40 +25,49 @@ export const segment_: TableParser.SegmentParser = block(
|
|
|
25
25
|
export const table: TableParser = block(fmap(
|
|
26
26
|
fence(opener, 10000),
|
|
27
27
|
// Bug: Type mismatch between outer and inner.
|
|
28
|
-
(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
'
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
overflow ?
|
|
37
|
-
|
|
38
|
-
|
|
28
|
+
(nodes: List<Data<string>>, context) => {
|
|
29
|
+
const [body, overflow, closer, opener, delim, type, param] = unwrap(nodes);
|
|
30
|
+
if (!closer || overflow || param.trimStart()) return new List([
|
|
31
|
+
new Data(html('pre', {
|
|
32
|
+
class: 'invalid',
|
|
33
|
+
translate: 'no',
|
|
34
|
+
...invalid(
|
|
35
|
+
'table',
|
|
36
|
+
!closer || overflow ? 'fence' : 'argument',
|
|
37
|
+
!closer ? `Missing the closing delimiter "${delim}"` :
|
|
38
|
+
overflow ? `Invalid trailing line after the closing delimiter "${delim}"` :
|
|
39
|
+
'Invalid argument'),
|
|
40
|
+
}, `${opener}${body}${overflow || closer}`))
|
|
41
|
+
]);
|
|
39
42
|
switch (type) {
|
|
40
43
|
case 'grid':
|
|
41
44
|
case undefined:
|
|
42
|
-
return (eval(parser(
|
|
43
|
-
.
|
|
45
|
+
return (eval(parser(subinput(body, context))) ?? new List([new Data(html('table'))]))
|
|
46
|
+
.foldl(
|
|
47
|
+
(acc, { value }) => acc.push(new Data(define(value, { 'data-type': type }))) && acc,
|
|
48
|
+
new List());
|
|
44
49
|
default:
|
|
45
|
-
return [
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
return new List([
|
|
51
|
+
new Data(html('pre', {
|
|
52
|
+
class: 'invalid',
|
|
53
|
+
translate: 'no',
|
|
54
|
+
...invalid('table', 'argument', 'Invalid table type'),
|
|
55
|
+
}, `${opener}${body}${closer}`))
|
|
56
|
+
]);
|
|
50
57
|
}
|
|
51
58
|
}));
|
|
52
59
|
|
|
53
60
|
const parser: TableParser = lazy(() => block(fmap(
|
|
54
61
|
some(union([row])),
|
|
55
|
-
rows =>
|
|
62
|
+
rows => new List([
|
|
63
|
+
new Data(html('table', format([...unwrap(rows)])))
|
|
64
|
+
]))));
|
|
56
65
|
|
|
57
66
|
const row: RowParser = lazy(() => dup(fmap(
|
|
58
67
|
subsequence([
|
|
59
|
-
|
|
68
|
+
union([
|
|
60
69
|
align,
|
|
61
|
-
])
|
|
70
|
+
]),
|
|
62
71
|
some(union([
|
|
63
72
|
head,
|
|
64
73
|
data,
|
|
@@ -66,13 +75,13 @@ const row: RowParser = lazy(() => dup(fmap(
|
|
|
66
75
|
emptyline,
|
|
67
76
|
])),
|
|
68
77
|
]),
|
|
69
|
-
ns =>
|
|
78
|
+
ns => Array.isArray(ns.head?.value) ? ns : ns.unshift(new Data([[]])) && ns)));
|
|
70
79
|
|
|
71
80
|
const alignment = /[-=<>]+(?:\/[-=^v]*)?(?=[^\S\n]*\n)/y;
|
|
72
81
|
|
|
73
82
|
const align: AlignParser = line(fmap(
|
|
74
83
|
union([str(alignment)]),
|
|
75
|
-
([
|
|
84
|
+
([{ value }]) => new List([new Data(value.split('/').map(s => s.split('')) as [string[], string[]?])])));
|
|
76
85
|
|
|
77
86
|
const delimiter = /[-=<>]+(?:\/[-=^v]*)?(?=[^\S\n]*\n)|[#:](?:(?!:\D|0)\d*:(?!0)\d*)?(?:!+[+]?)?(?=\s)/y;
|
|
78
87
|
|
|
@@ -91,11 +100,11 @@ const head: CellParser.HeadParser = block(fmap(open(
|
|
|
91
100
|
media,
|
|
92
101
|
lineshortmedia,
|
|
93
102
|
]),
|
|
94
|
-
|
|
103
|
+
/[^\S\n]*(?:$|\n)/y)),
|
|
95
104
|
open(/(?:[^\S\n]*\n|\s)/y, visualize(trimBlank(some(inline))), true),
|
|
96
105
|
])),
|
|
97
106
|
true),
|
|
98
|
-
ns => [html('th', attributes(ns.shift()
|
|
107
|
+
ns => new List([new Data(html('th', attributes(ns.shift()!.value as string), defrag(unwrap(ns))))])),
|
|
99
108
|
false);
|
|
100
109
|
|
|
101
110
|
const data: CellParser.DataParser = block(fmap(open(
|
|
@@ -113,11 +122,11 @@ const data: CellParser.DataParser = block(fmap(open(
|
|
|
113
122
|
media,
|
|
114
123
|
lineshortmedia,
|
|
115
124
|
]),
|
|
116
|
-
|
|
125
|
+
/[^\S\n]*(?:$|\n)/y)),
|
|
117
126
|
open(/(?:[^\S\n]*\n|\s)/y, visualize(trimBlankEnd(some(inline))), true),
|
|
118
127
|
])),
|
|
119
128
|
true),
|
|
120
|
-
ns => [html('td', attributes(ns.shift()
|
|
129
|
+
ns => new List([new Data(html('td', attributes(ns.shift()!.value as string), defrag(unwrap(ns))))])),
|
|
121
130
|
false);
|
|
122
131
|
|
|
123
132
|
const dataline: CellParser.DatalineParser = line(
|
|
@@ -157,7 +166,7 @@ function attributes(source: string): Record<string, string | undefined> {
|
|
|
157
166
|
};
|
|
158
167
|
}
|
|
159
168
|
|
|
160
|
-
function format(rows:
|
|
169
|
+
function format(rows: List<Data<[string[], string[]?] | HTMLTableCellElement>>[]): HTMLTableSectionElement[] {
|
|
161
170
|
const thead = html('thead');
|
|
162
171
|
const tbody = html('tbody');
|
|
163
172
|
const tfoot = html('tfoot');
|
|
@@ -167,13 +176,11 @@ function format(rows: Node<RowParser>[]): HTMLTableSectionElement[] {
|
|
|
167
176
|
let ranges: Record<number, Record<number, HTMLTableCellElement>> = {};
|
|
168
177
|
let verticalHighlightExtensions = 0n;
|
|
169
178
|
let verticalHighlightLevels: string[] = [];
|
|
170
|
-
|
|
171
|
-
|
|
179
|
+
|
|
180
|
+
let cnt = 0;
|
|
181
|
+
for (const list of rows) ROW: for (let i = cnt++; i < cnt; ++i) {
|
|
172
182
|
// Copy to make them retryable.
|
|
173
|
-
const [[[...as], [...vs] = []], ...cells] =
|
|
174
|
-
assert(as !== rows[i][0]?.[0]);
|
|
175
|
-
assert(vs !== rows[i][0]?.[1]);
|
|
176
|
-
assert(cells !== rows[i]);
|
|
183
|
+
const [{ value: [[...as], [...vs] = []] }, ...cells] = list as any as [Data<[string[], string[]?]>, ...Data<HTMLTableCellElement>[]];
|
|
177
184
|
let isBody = target === tfoot
|
|
178
185
|
? false
|
|
179
186
|
: undefined;
|
|
@@ -248,7 +255,7 @@ function format(rows: Node<RowParser>[]): HTMLTableSectionElement[] {
|
|
|
248
255
|
const isVirtual = !!ranges[i]?.[j];
|
|
249
256
|
const cell = isVirtual
|
|
250
257
|
? splice(cells, j, 0, undefined) && ranges[i][j]
|
|
251
|
-
: cells[j];
|
|
258
|
+
: cells[j].value;
|
|
252
259
|
const isHeadCell = cell.tagName === 'TH';
|
|
253
260
|
heads |= isHeadCell ? 1n << jn : 0n;
|
|
254
261
|
highlights |= cell.className === 'highlight' ? 1n << jn : 0n;
|
|
@@ -326,7 +333,7 @@ function format(rows: Node<RowParser>[]): HTMLTableSectionElement[] {
|
|
|
326
333
|
const lHighlight = ~lHeadCellIndex && horizontalHighlights & 1n << lHeadCellIndex;
|
|
327
334
|
const rHighlight = ~rHeadCellIndex && horizontalHighlights & 1n << rHeadCellIndex;
|
|
328
335
|
for (let i = 0, m = 1n; i < cells.length; ++i, m <<= 1n) {
|
|
329
|
-
const cell = cells[i];
|
|
336
|
+
const cell = cells[i]?.value;
|
|
330
337
|
if (!cell) continue;
|
|
331
338
|
if (heads & m) continue;
|
|
332
339
|
assert(cell.tagName === 'TD');
|
|
@@ -1,16 +1,11 @@
|
|
|
1
|
-
import { heading
|
|
2
|
-
import { input
|
|
1
|
+
import { heading } from './heading';
|
|
2
|
+
import { input } from '../../combinator/data/parser';
|
|
3
3
|
import { some } from '../../combinator';
|
|
4
4
|
import { inspect } from '../../debug.test';
|
|
5
5
|
|
|
6
6
|
describe('Unit: parser/block/heading', () => {
|
|
7
7
|
describe('heading', () => {
|
|
8
|
-
const parser = (source: string) =>
|
|
9
|
-
const result = segment(input(source, ctx));
|
|
10
|
-
return result
|
|
11
|
-
? [eval(result).flatMap(seg => eval<HTMLElement | string>(heading(input(seg, {})), [seg]))] as const
|
|
12
|
-
: some(heading)(input(source, ctx));
|
|
13
|
-
};
|
|
8
|
+
const parser = (source: string) => some(heading)(input(source, ctx));
|
|
14
9
|
const { context: ctx } = input('', {});
|
|
15
10
|
|
|
16
11
|
it('invalid', () => {
|
|
@@ -54,10 +49,6 @@ describe('Unit: parser/block/heading', () => {
|
|
|
54
49
|
assert.deepStrictEqual(inspect(parser('# a[[b]]'), ctx), [['<h1 id="index::a[[b]]">a[[b]]</h1>'], '']);
|
|
55
50
|
assert.deepStrictEqual(inspect(parser('## a[[b]]'), ctx), [['<h2 id="index::a[[b]]">a[[b]]</h2>'], '']);
|
|
56
51
|
assert.deepStrictEqual(inspect(parser('###### a'), ctx), [['<h6 id="index::a">a</h6>'], '']);
|
|
57
|
-
assert.deepStrictEqual(inspect(parser('# a\n##'), ctx), [['<h1 id="index::a">a</h1>', '##'], '']);
|
|
58
|
-
assert.deepStrictEqual(inspect(parser('# a\n## '), ctx), [['<h1 id="index::a">a</h1>', '## '], '']);
|
|
59
|
-
assert.deepStrictEqual(inspect(parser('# a\n## b'), ctx), [['<h1 id="index::a">a</h1>', '<h2 id="index::b">b</h2>'], '']);
|
|
60
|
-
assert.deepStrictEqual(inspect(parser('# a\n##\n## b'), ctx), [['<h1 id="index::a">a</h1>', '##\n', '<h2 id="index::b">b</h2>'], '']);
|
|
61
52
|
});
|
|
62
53
|
|
|
63
54
|
it('indexer', () => {
|