securemark 0.282.0 → 0.283.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 +5 -0
- package/design.md +5 -9
- package/dist/index.js +7363 -7188
- package/package.json +2 -2
- package/src/combinator/control/manipulation/convert.ts +4 -8
- package/src/combinator/control/manipulation/indent.ts +3 -5
- package/src/combinator/control/manipulation/scope.ts +6 -3
- package/src/combinator/control/manipulation/surround.ts +17 -2
- package/src/combinator/data/parser/context.test.ts +6 -6
- package/src/combinator/data/parser/context.ts +25 -39
- package/src/combinator/data/parser.ts +2 -3
- package/src/parser/api/bind.ts +6 -6
- package/src/parser/api/parse.test.ts +17 -16
- package/src/parser/api/parse.ts +0 -3
- package/src/parser/block/blockquote.ts +4 -3
- package/src/parser/block/dlist.test.ts +1 -1
- package/src/parser/block/dlist.ts +6 -6
- package/src/parser/block/extension/aside.ts +4 -3
- package/src/parser/block/extension/example.ts +4 -3
- package/src/parser/block/extension/table.ts +7 -7
- package/src/parser/block/heading.ts +3 -2
- package/src/parser/block/ilist.ts +2 -1
- package/src/parser/block/olist.ts +4 -3
- package/src/parser/block/reply/cite.ts +3 -3
- package/src/parser/block/reply/quote.ts +3 -3
- package/src/parser/block/sidefence.ts +2 -1
- package/src/parser/block/table.ts +9 -9
- package/src/parser/block/ulist.ts +6 -5
- package/src/parser/block.ts +16 -5
- package/src/parser/context.ts +9 -21
- package/src/parser/inline/annotation.ts +5 -4
- package/src/parser/inline/autolink/email.ts +2 -1
- package/src/parser/inline/autolink/url.ts +6 -5
- package/src/parser/inline/autolink.ts +2 -2
- package/src/parser/inline/bracket.ts +17 -17
- package/src/parser/inline/code.test.ts +1 -1
- package/src/parser/inline/code.ts +2 -1
- package/src/parser/inline/deletion.ts +3 -3
- package/src/parser/inline/emphasis.ts +3 -3
- package/src/parser/inline/emstrong.ts +3 -3
- package/src/parser/inline/extension/index.ts +18 -6
- 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 +2 -2
- package/src/parser/inline/extension/placeholder.ts +4 -4
- package/src/parser/inline/html.ts +2 -2
- package/src/parser/inline/htmlentity.ts +2 -1
- package/src/parser/inline/insertion.ts +3 -3
- package/src/parser/inline/link.test.ts +2 -2
- package/src/parser/inline/link.ts +7 -7
- package/src/parser/inline/mark.ts +3 -3
- package/src/parser/inline/math.test.ts +3 -3
- package/src/parser/inline/math.ts +6 -5
- package/src/parser/inline/media.test.ts +1 -1
- package/src/parser/inline/media.ts +5 -5
- package/src/parser/inline/reference.ts +6 -5
- package/src/parser/inline/remark.ts +2 -2
- package/src/parser/inline/ruby.ts +3 -3
- package/src/parser/inline/strong.ts +3 -3
- package/src/parser/inline/template.ts +4 -4
- package/src/parser/inline.ts +1 -0
- package/src/parser/source/escapable.ts +2 -1
- package/src/parser/source/str.ts +3 -2
- package/src/parser/source/text.ts +2 -1
- package/src/parser/source/unescapable.ts +2 -1
- package/src/combinator/data/parser/context/memo.ts +0 -57
|
@@ -3,6 +3,7 @@ import { union, inits, some, creation, block, line, validate, indent, open, trim
|
|
|
3
3
|
import { ulist_, invalid, fillFirstLine } from './ulist';
|
|
4
4
|
import { olist_ } from './olist';
|
|
5
5
|
import { inline } from '../inline';
|
|
6
|
+
import { Recursion } from '../context';
|
|
6
7
|
import { lineable } from '../util';
|
|
7
8
|
import { visualize, trimBlank } from '../visibility';
|
|
8
9
|
import { html, defrag } from 'typed-dom/dom';
|
|
@@ -13,7 +14,7 @@ export const ilist: IListParser = lazy(() => block(validate(
|
|
|
13
14
|
|
|
14
15
|
export const ilist_: IListParser = lazy(() => block(fmap(validate(
|
|
15
16
|
/^[-+*](?:$|\s)/,
|
|
16
|
-
some(creation(
|
|
17
|
+
some(creation(0, Recursion.listitem, union([
|
|
17
18
|
fmap(fallback(
|
|
18
19
|
inits([
|
|
19
20
|
line(open(/^[-+*](?:$|\s)/, trim(visualize(trimBlank(lineable(some(inline))))), true)),
|
|
@@ -2,9 +2,10 @@ import { OListParser } from '../block';
|
|
|
2
2
|
import { union, inits, subsequence, some, creation, block, line, validate, indent, focus, open, match, trim, fallback, lazy, fmap } from '../../combinator';
|
|
3
3
|
import { ulist_, checkbox, invalid, fillFirstLine } from './ulist';
|
|
4
4
|
import { ilist_ } from './ilist';
|
|
5
|
-
import { inline, indexee, indexer } from '../inline';
|
|
5
|
+
import { inline, indexee, indexer, dataindex } from '../inline';
|
|
6
6
|
import { lineable } from '../util';
|
|
7
7
|
import { visualize, trimBlank } from '../visibility';
|
|
8
|
+
import { Recursion } from '../context';
|
|
8
9
|
import { memoize } from 'spica/memoize';
|
|
9
10
|
import { html, define, defrag } from 'typed-dom/dom';
|
|
10
11
|
|
|
@@ -30,7 +31,7 @@ export const olist_: OListParser = lazy(() => block(union([
|
|
|
30
31
|
])));
|
|
31
32
|
|
|
32
33
|
const list = (type: string, form: string): OListParser.ListParser => fmap(
|
|
33
|
-
some(creation(
|
|
34
|
+
some(creation(0, Recursion.listitem, union([
|
|
34
35
|
indexee(fmap(fallback(
|
|
35
36
|
inits([
|
|
36
37
|
line(open(heads[form], subsequence([
|
|
@@ -39,7 +40,7 @@ const list = (type: string, form: string): OListParser.ListParser => fmap(
|
|
|
39
40
|
indent(union([ulist_, olist_, ilist_])),
|
|
40
41
|
]),
|
|
41
42
|
invalid),
|
|
42
|
-
ns => [html('li', { 'data-marker': ns.shift() as string || undefined }, defrag(fillFirstLine(ns)))])),
|
|
43
|
+
ns => [html('li', { 'data-index': dataindex(ns), 'data-marker': ns.shift() as string || undefined }, defrag(fillFirstLine(ns)))])),
|
|
43
44
|
]))),
|
|
44
45
|
es => [format(html('ol', es), type, form)]);
|
|
45
46
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { ReplyParser } from '../../block';
|
|
2
|
-
import { union, tails,
|
|
2
|
+
import { union, tails, line, validate, focus, reverse, fmap } from '../../../combinator';
|
|
3
3
|
import { anchor } from '../../inline/autolink/anchor';
|
|
4
4
|
import { str } from '../../source';
|
|
5
5
|
import { html, define, defrag } from 'typed-dom/dom';
|
|
6
6
|
|
|
7
|
-
export const cite: ReplyParser.CiteParser =
|
|
7
|
+
export const cite: ReplyParser.CiteParser = line(fmap(validate(
|
|
8
8
|
'>>',
|
|
9
9
|
reverse(tails([
|
|
10
10
|
str(/^>*(?=>>[^>\s]+\s*$)/),
|
|
@@ -23,4 +23,4 @@ export const cite: ReplyParser.CiteParser = creation(1, false, line(fmap(validat
|
|
|
23
23
|
define(el, { 'data-depth': `${quotes.length + 1}` }, el.innerText.slice(1)),
|
|
24
24
|
])),
|
|
25
25
|
html('br'),
|
|
26
|
-
]))
|
|
26
|
+
]));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ReplyParser } from '../../block';
|
|
2
|
-
import { union, some,
|
|
2
|
+
import { union, some, block, line, validate, rewrite, convert, lazy, fmap } from '../../../combinator';
|
|
3
3
|
import { math } from '../../inline/math';
|
|
4
4
|
import { autolink } from '../../inline/autolink';
|
|
5
5
|
import { linebreak, unescsource, str, anyline } from '../../source';
|
|
@@ -7,7 +7,7 @@ import { html, defrag } from 'typed-dom/dom';
|
|
|
7
7
|
|
|
8
8
|
export const syntax = /^>+(?=[^\S\n])|^>(?=[^\s>])|^>+(?=[^\s>])(?![0-9a-z]+(?:-[0-9a-z]+)*(?![0-9A-Za-z@#:]))/;
|
|
9
9
|
|
|
10
|
-
export const quote: ReplyParser.QuoteParser = lazy(() =>
|
|
10
|
+
export const quote: ReplyParser.QuoteParser = lazy(() => block(fmap(validate(
|
|
11
11
|
'>',
|
|
12
12
|
union([
|
|
13
13
|
rewrite(
|
|
@@ -30,7 +30,7 @@ export const quote: ReplyParser.QuoteParser = lazy(() => creation(1, false, bloc
|
|
|
30
30
|
defrag(ns)),
|
|
31
31
|
html('br'),
|
|
32
32
|
]),
|
|
33
|
-
false))
|
|
33
|
+
false));
|
|
34
34
|
|
|
35
35
|
const qblock: ReplyParser.QuoteParser.BlockParser = convert(
|
|
36
36
|
source => source.replace(/\n$/, '').replace(/(?<=^>+[^\S\n])/mg, '\r'),
|
|
@@ -2,6 +2,7 @@ import { SidefenceParser } from '../block';
|
|
|
2
2
|
import { union, some, creation, block, focus, rewrite, convert, lazy, fmap } from '../../combinator';
|
|
3
3
|
import { autolink } from '../autolink';
|
|
4
4
|
import { contentline } from '../source';
|
|
5
|
+
import { Recursion } from '../context';
|
|
5
6
|
import { html, define, defrag } from 'typed-dom/dom';
|
|
6
7
|
|
|
7
8
|
export const sidefence: SidefenceParser = lazy(() => block(fmap(focus(
|
|
@@ -20,7 +21,7 @@ const opener = /^(?=\|\|+(?:$|\s))/;
|
|
|
20
21
|
const unindent = (source: string) => source.replace(/(?<=^|\n)\|(?:[^\S\n]|(?=\|*(?:$|\s)))|\n$/g, '');
|
|
21
22
|
|
|
22
23
|
const source: SidefenceParser.SourceParser = lazy(() => fmap(
|
|
23
|
-
some(creation(
|
|
24
|
+
some(creation(0, Recursion.block, union([
|
|
24
25
|
focus(
|
|
25
26
|
/^(?:\|\|+(?:[^\S\n][^\n]*)?(?:$|\n))+/,
|
|
26
27
|
convert(unindent, source, true)),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TableParser } from '../block';
|
|
2
|
-
import { union, sequence, some,
|
|
2
|
+
import { union, sequence, some, block, line, validate, focus, rewrite, surround, open, close, trimStart, fallback, lazy, fmap } from '../../combinator';
|
|
3
3
|
import { inline, media, medialink, shortmedia } from '../inline';
|
|
4
4
|
import { contentline } from '../source';
|
|
5
5
|
import { trimBlankStart, trimNodeEnd } from '../visibility';
|
|
@@ -25,7 +25,7 @@ export const table: TableParser = lazy(() => block(fmap(validate(
|
|
|
25
25
|
]),
|
|
26
26
|
])));
|
|
27
27
|
|
|
28
|
-
const row = <P extends CellParser | AlignParser>(parser: P, optional: boolean): RowParser<P> =>
|
|
28
|
+
const row = <P extends CellParser | AlignParser>(parser: P, optional: boolean): RowParser<P> => fallback(fmap(
|
|
29
29
|
line(surround(/^(?=\|)/, some(union([parser])), /^[|\\]?\s*$/, optional)),
|
|
30
30
|
es => [html('tr', es)]),
|
|
31
31
|
rewrite(contentline, ({ source }) => [[
|
|
@@ -35,9 +35,9 @@ const row = <P extends CellParser | AlignParser>(parser: P, optional: boolean):
|
|
|
35
35
|
'data-invalid-type': 'syntax',
|
|
36
36
|
'data-invalid-message': 'Missing the start symbol of the table row',
|
|
37
37
|
}, [html('td', source.replace('\n', ''))])
|
|
38
|
-
], '']))
|
|
38
|
+
], '']));
|
|
39
39
|
|
|
40
|
-
const align: AlignParser =
|
|
40
|
+
const align: AlignParser = fmap(open(
|
|
41
41
|
'|',
|
|
42
42
|
union([
|
|
43
43
|
focus(/^:-+:/, () => [['center'], '']),
|
|
@@ -45,7 +45,7 @@ const align: AlignParser = creation(1, false, fmap(open(
|
|
|
45
45
|
focus(/^-+:/, () => [['end'], '']),
|
|
46
46
|
focus(/^-+/, () => [[''], '']),
|
|
47
47
|
])),
|
|
48
|
-
ns => [html('td', defrag(ns))])
|
|
48
|
+
ns => [html('td', defrag(ns))]);
|
|
49
49
|
|
|
50
50
|
const cell: CellParser = surround(
|
|
51
51
|
/^\|\s*(?=\S)/,
|
|
@@ -57,13 +57,13 @@ const cell: CellParser = surround(
|
|
|
57
57
|
])),
|
|
58
58
|
/^[^|]*/, true);
|
|
59
59
|
|
|
60
|
-
const head: CellParser.HeadParser =
|
|
60
|
+
const head: CellParser.HeadParser = fmap(
|
|
61
61
|
cell,
|
|
62
|
-
ns => [html('th', trimNodeEnd(defrag(ns)))])
|
|
62
|
+
ns => [html('th', trimNodeEnd(defrag(ns)))]);
|
|
63
63
|
|
|
64
|
-
const data: CellParser.DataParser =
|
|
64
|
+
const data: CellParser.DataParser = fmap(
|
|
65
65
|
cell,
|
|
66
|
-
ns => [html('td', trimNodeEnd(defrag(ns)))])
|
|
66
|
+
ns => [html('td', trimNodeEnd(defrag(ns)))]);
|
|
67
67
|
|
|
68
68
|
function format(rows: HTMLTableRowElement[]): HTMLTableRowElement[] {
|
|
69
69
|
const aligns = rows[0].className === 'invalid'
|
|
@@ -3,8 +3,9 @@ import { Parser } from '../../combinator/data/parser';
|
|
|
3
3
|
import { union, inits, subsequence, some, creation, block, line, validate, indent, focus, rewrite, open, trim, fallback, lazy, fmap } from '../../combinator';
|
|
4
4
|
import { olist_ } from './olist';
|
|
5
5
|
import { ilist_ } from './ilist';
|
|
6
|
-
import { inline, indexer, indexee } from '../inline';
|
|
6
|
+
import { inline, indexer, indexee, dataindex } from '../inline';
|
|
7
7
|
import { contentline } from '../source';
|
|
8
|
+
import { Recursion } from '../context';
|
|
8
9
|
import { lineable } from '../util';
|
|
9
10
|
import { visualize, trimBlank } from '../visibility';
|
|
10
11
|
import { unshift } from 'spica/array';
|
|
@@ -16,7 +17,7 @@ export const ulist: UListParser = lazy(() => block(validate(
|
|
|
16
17
|
|
|
17
18
|
export const ulist_: UListParser = lazy(() => block(fmap(validate(
|
|
18
19
|
/^-(?=$|\s)/,
|
|
19
|
-
some(creation(
|
|
20
|
+
some(creation(0, Recursion.listitem, union([
|
|
20
21
|
indexee(fmap(fallback(
|
|
21
22
|
inits([
|
|
22
23
|
line(open(/^-(?:$|\s)/, subsequence([
|
|
@@ -26,15 +27,15 @@ export const ulist_: UListParser = lazy(() => block(fmap(validate(
|
|
|
26
27
|
indent(union([ulist_, olist_, ilist_])),
|
|
27
28
|
]),
|
|
28
29
|
invalid),
|
|
29
|
-
ns => [html('li', defrag(fillFirstLine(ns)))])),
|
|
30
|
+
ns => [html('li', { 'data-index': dataindex(ns) }, defrag(fillFirstLine(ns)))])),
|
|
30
31
|
])))),
|
|
31
32
|
es => [format(html('ul', es))])));
|
|
32
33
|
|
|
33
|
-
export const checkbox =
|
|
34
|
+
export const checkbox = focus(
|
|
34
35
|
/^\[[xX ]\](?=$|\s)/,
|
|
35
36
|
({ source }) => [[
|
|
36
37
|
html('span', { class: 'checkbox' }, source[1].trimStart() ? '☑' : '☐'),
|
|
37
|
-
], ''])
|
|
38
|
+
], '']);
|
|
38
39
|
|
|
39
40
|
export const invalid = rewrite(
|
|
40
41
|
inits([contentline, indent<Parser<string>>(({ source }) => [[source], ''])]),
|
package/src/parser/block.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MarkdownParser } from '../../markdown';
|
|
2
|
-
import { union, reset,
|
|
2
|
+
import { union, reset, open, fallback, recover } from '../combinator';
|
|
3
3
|
import { emptyline } from './source';
|
|
4
4
|
import { pagebreak } from './block/pagebreak';
|
|
5
5
|
import { heading } from './block/heading';
|
|
@@ -16,6 +16,7 @@ import { blockquote } from './block/blockquote';
|
|
|
16
16
|
import { mediablock } from './block/mediablock';
|
|
17
17
|
import { reply } from './block/reply';
|
|
18
18
|
import { paragraph } from './block/paragraph';
|
|
19
|
+
import { Recursion } from './context';
|
|
19
20
|
import { rnd0Z } from 'spica/random';
|
|
20
21
|
import { html } from 'typed-dom/dom';
|
|
21
22
|
|
|
@@ -36,9 +37,19 @@ export import MediaBlockParser = BlockParser.MediaBlockParser;
|
|
|
36
37
|
export import ReplyParser = BlockParser.ReplyParser;
|
|
37
38
|
export import ParagraphParser = BlockParser.ParagraphParser;
|
|
38
39
|
|
|
39
|
-
export const block: BlockParser =
|
|
40
|
-
|
|
41
|
-
resources: {
|
|
40
|
+
export const block: BlockParser = reset(
|
|
41
|
+
{
|
|
42
|
+
resources: {
|
|
43
|
+
clock: 20000,
|
|
44
|
+
recursions: [
|
|
45
|
+
10 || Recursion.block,
|
|
46
|
+
20 || Recursion.blockquote,
|
|
47
|
+
40 || Recursion.listitem,
|
|
48
|
+
20 || Recursion.inline,
|
|
49
|
+
20 || Recursion.bracket,
|
|
50
|
+
20 || Recursion.terminal,
|
|
51
|
+
],
|
|
52
|
+
},
|
|
42
53
|
},
|
|
43
54
|
error(union([
|
|
44
55
|
emptyline,
|
|
@@ -57,7 +68,7 @@ export const block: BlockParser = creation(0, false,
|
|
|
57
68
|
mediablock,
|
|
58
69
|
reply,
|
|
59
70
|
paragraph
|
|
60
|
-
])))
|
|
71
|
+
])));
|
|
61
72
|
|
|
62
73
|
function error(parser: BlockParser): BlockParser {
|
|
63
74
|
return recover<BlockParser>(fallback(
|
package/src/parser/context.ts
CHANGED
|
@@ -1,23 +1,3 @@
|
|
|
1
|
-
export const enum Syntax {
|
|
2
|
-
annotation = 1 << 8,
|
|
3
|
-
reference = 1 << 7,
|
|
4
|
-
index = 1 << 6,
|
|
5
|
-
placeholder = 1 << 5,
|
|
6
|
-
ruby = 1 << 4,
|
|
7
|
-
link = 1 << 3,
|
|
8
|
-
bracket = 1 << 2,
|
|
9
|
-
autolink = 1 << 1,
|
|
10
|
-
none = 0,
|
|
11
|
-
targets = 0
|
|
12
|
-
| Syntax.annotation
|
|
13
|
-
| Syntax.reference
|
|
14
|
-
| Syntax.index
|
|
15
|
-
| Syntax.placeholder
|
|
16
|
-
| Syntax.ruby
|
|
17
|
-
| Syntax.link
|
|
18
|
-
| Syntax.bracket,
|
|
19
|
-
}
|
|
20
|
-
|
|
21
1
|
export const enum State {
|
|
22
2
|
annotation = 1 << 8,
|
|
23
3
|
reference = 1 << 7,
|
|
@@ -40,4 +20,12 @@ export const enum State {
|
|
|
40
20
|
| State.autolink,
|
|
41
21
|
}
|
|
42
22
|
|
|
43
|
-
export const
|
|
23
|
+
export const enum Recursion {
|
|
24
|
+
ignore,
|
|
25
|
+
block,
|
|
26
|
+
blockquote,
|
|
27
|
+
listitem,
|
|
28
|
+
inline,
|
|
29
|
+
bracket,
|
|
30
|
+
terminal,
|
|
31
|
+
}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { AnnotationParser } from '../inline';
|
|
2
2
|
import { union, some, syntax, creation, constraint, surround, lazy } from '../../combinator';
|
|
3
3
|
import { inline } from '../inline';
|
|
4
|
-
import {
|
|
4
|
+
import { State, Recursion } from '../context';
|
|
5
5
|
import { trimBlankStart, trimNodeEnd } from '../visibility';
|
|
6
6
|
import { html, defrag } from 'typed-dom/dom';
|
|
7
7
|
|
|
8
|
-
export const annotation: AnnotationParser = lazy(() => creation(surround(
|
|
8
|
+
export const annotation: AnnotationParser = lazy(() => creation(1, Recursion.ignore, surround(
|
|
9
9
|
'((',
|
|
10
10
|
constraint(State.annotation, false,
|
|
11
|
-
syntax(
|
|
11
|
+
syntax(6, State.annotation | State.media,
|
|
12
12
|
trimBlankStart(some(union([inline]), ')', [[/^\\?\n/, 9], [')', 2], ['))', 6]])))),
|
|
13
13
|
'))',
|
|
14
14
|
false,
|
|
15
|
-
([, ns], rest) => [[html('sup', { class: 'annotation' }, [html('span', trimNodeEnd(defrag(ns)))])], rest]
|
|
15
|
+
([, ns], rest) => [[html('sup', { class: 'annotation' }, [html('span', trimNodeEnd(defrag(ns)))])], rest],
|
|
16
|
+
undefined, 1)));
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { AutolinkParser } from '../../inline';
|
|
2
2
|
import { creation, verify, rewrite } from '../../../combinator';
|
|
3
3
|
import { str } from '../../source';
|
|
4
|
+
import { Recursion } from '../../context';
|
|
4
5
|
import { html } from 'typed-dom/dom';
|
|
5
6
|
|
|
6
7
|
// https://html.spec.whatwg.org/multipage/input.html
|
|
7
8
|
|
|
8
|
-
export const email: AutolinkParser.EmailParser = creation(rewrite(verify(
|
|
9
|
+
export const email: AutolinkParser.EmailParser = creation(1, Recursion.ignore, rewrite(verify(
|
|
9
10
|
str(/^[0-9a-z](?:[_.+-](?=[0-9a-z])|[0-9a-z]){0,255}@[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?(?:\.[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?)*(?![0-9a-z])/i),
|
|
10
11
|
([source]) => source.length <= 255),
|
|
11
12
|
({ source }) => [[html('a', { class: 'email', href: `mailto:${source}` }, source)], '']));
|
|
@@ -2,6 +2,7 @@ import { AutolinkParser } from '../../inline';
|
|
|
2
2
|
import { union, tails, some, creation, precedence, validate, focus, rewrite, convert, surround, open, lazy } from '../../../combinator';
|
|
3
3
|
import { unsafelink } from '../link';
|
|
4
4
|
import { linebreak, unescsource, str } from '../../source';
|
|
5
|
+
import { Recursion } from '../../context';
|
|
5
6
|
|
|
6
7
|
const closer = /^[-+*=~^_,.;:!?]*(?=[\\"`|\[\](){}<>]|$)/;
|
|
7
8
|
|
|
@@ -24,9 +25,9 @@ export const lineurl: AutolinkParser.UrlParser.LineUrlParser = lazy(() => open(
|
|
|
24
25
|
unsafelink)),
|
|
25
26
|
])));
|
|
26
27
|
|
|
27
|
-
const bracket: AutolinkParser.UrlParser.BracketParser = lazy(() => creation(precedence(2, union([
|
|
28
|
-
surround('(', some(union([bracket, unescsource]), ')'), ')', true),
|
|
29
|
-
surround('[', some(union([bracket, unescsource]), ']'), ']', true),
|
|
30
|
-
surround('{', some(union([bracket, unescsource]), '}'), '}', true),
|
|
31
|
-
surround('"', precedence(3, some(unescsource, '"')), '"', true),
|
|
28
|
+
const bracket: AutolinkParser.UrlParser.BracketParser = lazy(() => creation(0, Recursion.terminal, precedence(2, union([
|
|
29
|
+
surround(str('('), some(union([bracket, unescsource]), ')'), str(')'), true),
|
|
30
|
+
surround(str('['), some(union([bracket, unescsource]), ']'), str(']'), true),
|
|
31
|
+
surround(str('{'), some(union([bracket, unescsource]), '}'), str('}'), true),
|
|
32
|
+
surround(str('"'), precedence(3, some(unescsource, '"')), str('"'), true),
|
|
32
33
|
]))));
|
|
@@ -8,13 +8,13 @@ import { hashtag, emoji } from './autolink/hashtag';
|
|
|
8
8
|
import { hashnum } from './autolink/hashnum';
|
|
9
9
|
import { anchor } from './autolink/anchor';
|
|
10
10
|
import { str } from '../source';
|
|
11
|
-
import {
|
|
11
|
+
import { State } from '../context';
|
|
12
12
|
import { stringify } from '../util';
|
|
13
13
|
|
|
14
14
|
export const autolink: AutolinkParser = lazy(() =>
|
|
15
15
|
validate(/^(?:[@#>0-9a-z]|\S[#>]|[\r\n]!?https?:\/\/)/iu,
|
|
16
16
|
constraint(State.autolink, false,
|
|
17
|
-
syntax(
|
|
17
|
+
syntax(1, ~State.shortcut,
|
|
18
18
|
union([
|
|
19
19
|
some(union([lineurl])),
|
|
20
20
|
fmap(some(union([
|
|
@@ -2,46 +2,46 @@ import { BracketParser } from '../inline';
|
|
|
2
2
|
import { union, some, syntax, creation, surround, lazy } from '../../combinator';
|
|
3
3
|
import { inline } from '../inline';
|
|
4
4
|
import { str } from '../source';
|
|
5
|
-
import {
|
|
5
|
+
import { State, Recursion } from '../context';
|
|
6
6
|
import { unshift, push } from 'spica/array';
|
|
7
7
|
import { html, defrag } from 'typed-dom/dom';
|
|
8
8
|
|
|
9
9
|
const index = /^[0-9A-Za-z]+(?:(?:[.-]|, )[0-9A-Za-z]+)*/;
|
|
10
10
|
|
|
11
11
|
export const bracket: BracketParser = lazy(() => union([
|
|
12
|
-
surround(str('('), creation(
|
|
13
|
-
surround(str('('), creation(
|
|
12
|
+
surround(str('('), creation(0, Recursion.bracket, syntax(2, State.none, str(index))), str(')')),
|
|
13
|
+
surround(str('('), creation(0, Recursion.bracket, syntax(2, State.none, some(inline, ')', [[/^\\?\n/, 3], [')', 2]]))), str(')'), true,
|
|
14
14
|
([as, bs = [], cs], rest) => [[html('span', { class: 'paren' }, defrag(push(unshift(as, bs), cs)))], rest],
|
|
15
|
-
([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
16
|
-
surround(str('('), creation(
|
|
17
|
-
surround(str('('), creation(
|
|
15
|
+
([as, bs = []], rest) => [unshift(as, bs), rest], 3),
|
|
16
|
+
surround(str('('), creation(0, Recursion.bracket, syntax(2, State.none, str(new RegExp(index.source.replace(', ', '[,、]').replace(/[09AZaz.]|\-(?!\w)/g, c => c.trimStart() && String.fromCharCode(c.charCodeAt(0) + 0xFEE0)))))), str(')')),
|
|
17
|
+
surround(str('('), creation(0, Recursion.bracket, syntax(2, State.none, some(inline, ')', [[/^\\?\n/, 3], [')', 2]]))), str(')'), true,
|
|
18
18
|
([as, bs = [], cs], rest) => [[html('span', { class: 'paren' }, defrag(push(unshift(as, bs), cs)))], rest],
|
|
19
19
|
([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
20
|
-
surround(str('['), creation(
|
|
20
|
+
surround(str('['), creation(0, Recursion.bracket, syntax(2, State.none, some(inline, ']', [[/^\\?\n/, 3], [']', 2]]))), str(']'), true,
|
|
21
21
|
undefined,
|
|
22
|
-
([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
23
|
-
surround(str('['), creation(
|
|
22
|
+
([as, bs = []], rest) => [unshift(as, bs), rest], 3),
|
|
23
|
+
surround(str('['), creation(0, Recursion.bracket, syntax(2, State.none, some(inline, ']', [[/^\\?\n/, 3], [']', 2]]))), str(']'), true,
|
|
24
24
|
undefined,
|
|
25
25
|
([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
26
|
-
surround(str('{'), creation(
|
|
26
|
+
surround(str('{'), creation(0, Recursion.bracket, syntax(2, State.none, some(inline, '}', [[/^\\?\n/, 3], ['}', 2]]))), str('}'), true,
|
|
27
27
|
undefined,
|
|
28
|
-
([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
29
|
-
surround(str('{'), creation(
|
|
28
|
+
([as, bs = []], rest) => [unshift(as, bs), rest], 3),
|
|
29
|
+
surround(str('{'), creation(0, Recursion.bracket, syntax(2, State.none, some(inline, '}', [[/^\\?\n/, 3], ['}', 2]]))), str('}'), true,
|
|
30
30
|
undefined,
|
|
31
31
|
([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
32
|
-
surround(str('"'), creation(
|
|
32
|
+
surround(str('"'), creation(0, Recursion.bracket, syntax(3, State.none, some(inline, '"', [[/^\\?\n/, 4], ['"', 3]]))), str('"'), true,
|
|
33
33
|
undefined,
|
|
34
34
|
([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
35
|
-
surround(str('“'), creation(
|
|
35
|
+
surround(str('“'), creation(0, Recursion.bracket, syntax(3, State.none, some(inline, '”', [[/^\\?\n/, 4], ['”', 3]]))), str('”'), true,
|
|
36
36
|
undefined,
|
|
37
37
|
([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
38
|
-
surround(str('‘'), creation(
|
|
38
|
+
surround(str('‘'), creation(0, Recursion.bracket, syntax(3, State.none, some(inline, '’', [[/^\\?\n/, 4], ['’', 3]]))), str('’'), true,
|
|
39
39
|
undefined,
|
|
40
40
|
([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
41
|
-
surround(str('「'), creation(
|
|
41
|
+
surround(str('「'), creation(0, Recursion.bracket, syntax(3, State.none, some(inline, '」', [[/^\\?\n/, 4], ['」', 3]]))), str('」'), true,
|
|
42
42
|
undefined,
|
|
43
43
|
([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
44
|
-
surround(str('『'), creation(
|
|
44
|
+
surround(str('『'), creation(0, Recursion.bracket, syntax(3, State.none, some(inline, '』', [[/^\\?\n/, 4], ['』', 3]]))), str('』'), true,
|
|
45
45
|
undefined,
|
|
46
46
|
([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
47
47
|
]));
|
|
@@ -37,7 +37,7 @@ describe('Unit: parser/inline/code', () => {
|
|
|
37
37
|
});
|
|
38
38
|
|
|
39
39
|
it('nest', () => {
|
|
40
|
-
assert.deepStrictEqual(inspect(parser('`<wbr>`')), [['<code data-src="
|
|
40
|
+
assert.deepStrictEqual(inspect(parser('`<wbr>`')), [['<code data-src="`<wbr>`"><wbr></code>'], '']);
|
|
41
41
|
assert.deepStrictEqual(inspect(parser('`*u*`')), [['<code data-src="`*u*`">*u*</code>'], '']);
|
|
42
42
|
});
|
|
43
43
|
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { CodeParser } from '../inline';
|
|
2
2
|
import { creation, validate, match } from '../../combinator';
|
|
3
|
+
import { Recursion } from '../context';
|
|
3
4
|
import { html } from 'typed-dom/dom';
|
|
4
5
|
|
|
5
|
-
export const code: CodeParser = creation(validate('`', match(
|
|
6
|
+
export const code: CodeParser = creation(1, Recursion.ignore, validate('`', match(
|
|
6
7
|
/^(`+)(?!`)([^\n]*?[^`\n])\1(?!`)/,
|
|
7
8
|
([whole, , body]) => ({ source }) =>
|
|
8
9
|
[[html('code', { 'data-src': whole }, format(body))], source.slice(whole.length)])));
|
|
@@ -2,14 +2,14 @@ import { DeletionParser } from '../inline';
|
|
|
2
2
|
import { union, some, syntax, creation, surround, open, lazy } from '../../combinator';
|
|
3
3
|
import { inline } from '../inline';
|
|
4
4
|
import { str } from '../source';
|
|
5
|
-
import {
|
|
5
|
+
import { State, Recursion } from '../context';
|
|
6
6
|
import { blankWith } from '../visibility';
|
|
7
7
|
import { unshift } from 'spica/array';
|
|
8
8
|
import { html, defrag } from 'typed-dom/dom';
|
|
9
9
|
|
|
10
|
-
export const deletion: DeletionParser = lazy(() => creation(surround(
|
|
10
|
+
export const deletion: DeletionParser = lazy(() => creation(1, Recursion.inline, surround(
|
|
11
11
|
str('~~', '~'),
|
|
12
|
-
syntax(
|
|
12
|
+
syntax(1, State.none,
|
|
13
13
|
some(union([
|
|
14
14
|
some(inline, blankWith('\n', '~~')),
|
|
15
15
|
open('\n', some(inline, '~'), true),
|
|
@@ -4,14 +4,14 @@ import { inline } from '../inline';
|
|
|
4
4
|
import { emstrong } from './emstrong';
|
|
5
5
|
import { strong } from './strong';
|
|
6
6
|
import { str } from '../source';
|
|
7
|
-
import {
|
|
7
|
+
import { State, Recursion } from '../context';
|
|
8
8
|
import { startTight, blankWith } from '../visibility';
|
|
9
9
|
import { unshift } from 'spica/array';
|
|
10
10
|
import { html, defrag } from 'typed-dom/dom';
|
|
11
11
|
|
|
12
|
-
export const emphasis: EmphasisParser = lazy(() => creation(surround(
|
|
12
|
+
export const emphasis: EmphasisParser = lazy(() => creation(1, Recursion.inline, surround(
|
|
13
13
|
str('*', '*'),
|
|
14
|
-
syntax(
|
|
14
|
+
syntax(1, State.none,
|
|
15
15
|
startTight(some(union([
|
|
16
16
|
strong,
|
|
17
17
|
some(inline, blankWith('*'), [[/^\\?\n/, 9]]),
|
|
@@ -5,7 +5,7 @@ import { inline } from '../inline';
|
|
|
5
5
|
import { strong } from './strong';
|
|
6
6
|
import { emphasis } from './emphasis';
|
|
7
7
|
import { str } from '../source';
|
|
8
|
-
import {
|
|
8
|
+
import { State, Recursion } from '../context';
|
|
9
9
|
import { startTight, blankWith } from '../visibility';
|
|
10
10
|
import { html, defrag } from 'typed-dom/dom';
|
|
11
11
|
import { unshift } from 'spica/array';
|
|
@@ -27,9 +27,9 @@ const subemphasis: IntermediateParser<EmphasisParser> = lazy(() => some(union([
|
|
|
27
27
|
])),
|
|
28
28
|
])));
|
|
29
29
|
|
|
30
|
-
export const emstrong: EmStrongParser = lazy(() => creation(surround(
|
|
30
|
+
export const emstrong: EmStrongParser = lazy(() => creation(1, Recursion.inline, surround(
|
|
31
31
|
str('***'),
|
|
32
|
-
syntax(
|
|
32
|
+
syntax(1, State.none,
|
|
33
33
|
startTight(some(union([
|
|
34
34
|
some(inline, blankWith('*'), [[/^\\?\n/, 9]]),
|
|
35
35
|
open(some(inline, '*', [[/^\\?\n/, 9]]), inline),
|
|
@@ -3,16 +3,16 @@ import { union, inits, some, syntax, creation, precedence, constraint, validate,
|
|
|
3
3
|
import { inline } from '../../inline';
|
|
4
4
|
import { indexee, identity } from './indexee';
|
|
5
5
|
import { txt, str } from '../../source';
|
|
6
|
-
import {
|
|
6
|
+
import { State, Recursion } from '../../context';
|
|
7
7
|
import { startTight, trimNodeEnd } from '../../visibility';
|
|
8
8
|
import { html, define, defrag } from 'typed-dom/dom';
|
|
9
9
|
|
|
10
10
|
import IndexParser = ExtensionParser.IndexParser;
|
|
11
11
|
|
|
12
|
-
export const index: IndexParser = lazy(() => validate('[#', creation(fmap(indexee(surround(
|
|
12
|
+
export const index: IndexParser = lazy(() => validate('[#', creation(1, Recursion.ignore, fmap(indexee(surround(
|
|
13
13
|
'[#',
|
|
14
14
|
constraint(State.index, false,
|
|
15
|
-
syntax(
|
|
15
|
+
syntax(2, State.linkers | State.media,
|
|
16
16
|
startTight(
|
|
17
17
|
some(inits([
|
|
18
18
|
inline,
|
|
@@ -20,7 +20,8 @@ export const index: IndexParser = lazy(() => validate('[#', creation(fmap(indexe
|
|
|
20
20
|
]), ']', [[/^\\?\n/, 9], [']', 2]])))),
|
|
21
21
|
']',
|
|
22
22
|
false,
|
|
23
|
-
([, ns], rest) => [[html('a', trimNodeEnd(defrag(ns)))], rest]
|
|
23
|
+
([, ns], rest) => [[html('a', { 'data-index': dataindex(ns) }, trimNodeEnd(defrag(ns)))], rest],
|
|
24
|
+
undefined, 1)),
|
|
24
25
|
([el]: [HTMLAnchorElement]) => [
|
|
25
26
|
define(el,
|
|
26
27
|
{
|
|
@@ -30,16 +31,27 @@ export const index: IndexParser = lazy(() => validate('[#', creation(fmap(indexe
|
|
|
30
31
|
}),
|
|
31
32
|
]))));
|
|
32
33
|
|
|
33
|
-
export const signature: IndexParser.SignatureParser = lazy(() => validate('|', creation(fmap(open(
|
|
34
|
+
export const signature: IndexParser.SignatureParser = lazy(() => validate('|', creation(1, Recursion.ignore, fmap(open(
|
|
34
35
|
'|',
|
|
35
36
|
startTight(some(union([bracket, txt]), ']'))),
|
|
36
37
|
ns => [
|
|
37
38
|
html('span', { class: 'indexer', 'data-index': identity('index', undefined, ns.join(''))!.slice(7) }),
|
|
38
39
|
]))));
|
|
39
40
|
|
|
40
|
-
const bracket: IndexParser.SignatureParser.BracketParser = lazy(() => creation(union([
|
|
41
|
+
const bracket: IndexParser.SignatureParser.BracketParser = lazy(() => creation(0, Recursion.terminal, union([
|
|
41
42
|
surround(str('('), some(union([bracket, txt]), ')'), str(')'), true),
|
|
42
43
|
surround(str('['), some(union([bracket, txt]), ']'), str(']'), true),
|
|
43
44
|
surround(str('{'), some(union([bracket, txt]), '}'), str('}'), true),
|
|
44
45
|
surround(str('"'), precedence(3, some(txt, '"')), str('"'), true),
|
|
45
46
|
])));
|
|
47
|
+
|
|
48
|
+
export function dataindex(ns: readonly (string | HTMLElement)[]): string | undefined {
|
|
49
|
+
if (ns.length === 0) return;
|
|
50
|
+
for (let i = ns.length - 1; i >= 0; --i) {
|
|
51
|
+
const node = ns[i];
|
|
52
|
+
if (typeof node === 'string') return;
|
|
53
|
+
if (i === ns.length - 1 && ['UL', 'OL'].includes(node.tagName)) continue;
|
|
54
|
+
if (!node.classList.contains('indexer')) return;
|
|
55
|
+
return node.getAttribute('data-index') ?? undefined;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -6,7 +6,7 @@ import { define } from 'typed-dom/dom';
|
|
|
6
6
|
|
|
7
7
|
export function indexee<P extends Parser<unknown, MarkdownParser.Context>>(parser: P): P;
|
|
8
8
|
export function indexee(parser: Parser<HTMLElement, MarkdownParser.Context>): Parser<HTMLElement> {
|
|
9
|
-
return fmap(parser, ([el], _, { id }) => [define(el, { id: identity('index', id, el) })]);
|
|
9
|
+
return fmap(parser, ([el], _, { id }) => [define(el, { id: identity('index', id, el), 'data-index': null })]);
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
const MAX = 60;
|
|
@@ -27,7 +27,7 @@ export function identity(
|
|
|
27
27
|
assert(id?.match(/^[0-9a-z/-]*$/i) ?? true);
|
|
28
28
|
if (id === '') return undefined;
|
|
29
29
|
if (typeof text !== 'string') {
|
|
30
|
-
const index = text.
|
|
30
|
+
const index = text.getAttribute('data-index') ?? undefined;
|
|
31
31
|
if (index === '' && text.tagName === 'LI') return undefined;
|
|
32
32
|
return index
|
|
33
33
|
? `${type}:${id ?? ''}:${index}`
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { ExtensionParser } from '../../inline';
|
|
2
2
|
import { union, creation, focus, surround } from '../../../combinator';
|
|
3
3
|
import { signature } from './index';
|
|
4
|
+
import { Recursion } from '../../context';
|
|
4
5
|
import { html } from 'typed-dom/dom';
|
|
5
6
|
|
|
6
7
|
export const indexer: ExtensionParser.IndexerParser = surround(
|
|
7
8
|
/^\s+\[(?=\|\S)/,
|
|
8
9
|
union([
|
|
9
10
|
signature,
|
|
10
|
-
creation(focus(/^\|(?=\])/, () => [[html('span', { class: 'indexer', 'data-index': '' })], ''])),
|
|
11
|
+
creation(1, Recursion.ignore, focus(/^\|(?=\])/, () => [[html('span', { class: 'indexer', 'data-index': '' })], ''])),
|
|
11
12
|
]),
|
|
12
13
|
/^\]\s*$/);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ExtensionParser } from '../../inline';
|
|
2
2
|
import { union, constraint, creation, validate, surround, clear, fmap } from '../../../combinator';
|
|
3
3
|
import { str } from '../../source';
|
|
4
|
-
import { State } from '../../context';
|
|
4
|
+
import { State, Recursion } from '../../context';
|
|
5
5
|
import { html } from 'typed-dom/dom';
|
|
6
6
|
|
|
7
7
|
const body = str(/^\$[A-Za-z]*(?:(?:-[A-Za-z][0-9A-Za-z]*)+|-(?:(?:0|[1-9][0-9]*)\.)*(?:0|[1-9][0-9]*)(?![0-9A-Za-z]))/);
|
|
@@ -11,7 +11,7 @@ export const segment: ExtensionParser.LabelParser.SegmentParser = clear(validate
|
|
|
11
11
|
body,
|
|
12
12
|
])));
|
|
13
13
|
|
|
14
|
-
export const label: ExtensionParser.LabelParser = validate(['[$', '$'], creation(fmap(
|
|
14
|
+
export const label: ExtensionParser.LabelParser = validate(['[$', '$'], creation(1, Recursion.ignore, fmap(
|
|
15
15
|
constraint(State.label, false,
|
|
16
16
|
union([
|
|
17
17
|
surround('[', body, ']'),
|