securemark 0.293.5 → 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 +4 -0
- package/dist/index.js +845 -534
- 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 +12 -13
- 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 +8 -8
- package/src/combinator/data/parser/context.ts +3 -3
- 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 +4 -6
- package/src/parser/api/header.ts +1 -1
- package/src/parser/api/normalize.ts +1 -1
- 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 +6 -4
- package/src/parser/block/reply.ts +6 -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.ts +18 -18
- 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 +9 -8
- package/src/parser/source/unescapable.ts +6 -5
- package/src/parser/util.ts +18 -13
- package/src/parser/visibility.ts +19 -20
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ExtensionParser } from '../../inline';
|
|
2
2
|
import { State, Backtrack } from '../../context';
|
|
3
|
+
import { List, Data } from '../../../combinator/data/parser';
|
|
3
4
|
import { union, constraint, clear, surround, fmap } from '../../../combinator';
|
|
4
5
|
import { str } from '../../source';
|
|
5
6
|
import { html } from 'typed-dom/dom';
|
|
@@ -16,9 +17,12 @@ export const label: ExtensionParser.LabelParser = constraint(State.label, fmap(
|
|
|
16
17
|
surround('[', body, ']', false, undefined, undefined, [1 | Backtrack.bracket, 1]),
|
|
17
18
|
body,
|
|
18
19
|
]),
|
|
19
|
-
([
|
|
20
|
-
html('a', {
|
|
21
|
-
|
|
20
|
+
([{ value }]) => new List([
|
|
21
|
+
new Data(html('a', {
|
|
22
|
+
class: 'label',
|
|
23
|
+
'data-label': value.slice(value[1] === '-' ? 0 : 1).toLowerCase(),
|
|
24
|
+
}, value)),
|
|
25
|
+
])));
|
|
22
26
|
|
|
23
27
|
export function number(label: string, base: string): string {
|
|
24
28
|
return isFixed(label)
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { ExtensionParser } from '../../inline';
|
|
2
2
|
import { Recursion, Backtrack } from '../../context';
|
|
3
|
+
import { List, Data } from '../../../combinator/data/parser';
|
|
3
4
|
import { union, some, recursion, precedence, surround, lazy } from '../../../combinator';
|
|
4
5
|
import { inline } from '../../inline';
|
|
5
6
|
import { str } from '../../source';
|
|
6
7
|
import { tightStart } from '../../visibility';
|
|
7
8
|
import { invalid } from '../../util';
|
|
8
|
-
import { unshift } from 'spica/array';
|
|
9
9
|
import { html } from 'typed-dom/dom';
|
|
10
10
|
|
|
11
11
|
// Don't use the symbols already used: !#$%@&*+~=|
|
|
@@ -18,13 +18,13 @@ export const placeholder: ExtensionParser.PlaceholderParser = lazy(() => surroun
|
|
|
18
18
|
precedence(1, recursion(Recursion.inline,
|
|
19
19
|
tightStart(some(union([inline]), ']', [[']', 1]])))),
|
|
20
20
|
str(']'), false,
|
|
21
|
-
(_, context) => [
|
|
22
|
-
html('span',
|
|
21
|
+
(_, context) => new List([
|
|
22
|
+
new Data(html('span',
|
|
23
23
|
{
|
|
24
24
|
class: 'invalid',
|
|
25
25
|
...invalid('extension', 'syntax', `Invalid start symbol or linebreak`),
|
|
26
26
|
},
|
|
27
|
-
context.source.slice(context.position - context.range!, context.position))
|
|
28
|
-
]
|
|
29
|
-
([as, bs]) => bs &&
|
|
27
|
+
context.source.slice(context.position - context.range!, context.position)))
|
|
28
|
+
]),
|
|
29
|
+
([as, bs]) => bs && as.import(bs as List<Data<string>>),
|
|
30
30
|
[3 | Backtrack.bracket]));
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { HTMLParser } from '../inline';
|
|
2
2
|
import { Recursion } from '../context';
|
|
3
|
-
import { Ctx } from '../../combinator/data/parser';
|
|
3
|
+
import { List, Data, Ctx } from '../../combinator/data/parser';
|
|
4
4
|
import { union, some, recursion, precedence, validate, surround, open, match, lazy } from '../../combinator';
|
|
5
5
|
import { inline } from '../inline';
|
|
6
6
|
import { str } from '../source';
|
|
7
7
|
import { isLooseNodeStart, blankWith } from '../visibility';
|
|
8
|
-
import { invalid } from '../util';
|
|
8
|
+
import { invalid, unwrap } from '../util';
|
|
9
9
|
import { memoize } from 'spica/memoize';
|
|
10
|
-
import { unshift, push } from 'spica/array';
|
|
11
10
|
import { html as h, defrag } from 'typed-dom/dom';
|
|
12
11
|
|
|
13
12
|
const tags: readonly string[] = ['wbr', 'bdo', 'bdi'];
|
|
@@ -28,10 +27,10 @@ export const html: HTMLParser = lazy(() => validate(/<[a-z]+(?=[ >])/yi,
|
|
|
28
27
|
some(union([attribute])),
|
|
29
28
|
open(str(/ ?/y), str('>'), true),
|
|
30
29
|
true,
|
|
31
|
-
([as, bs =
|
|
32
|
-
[
|
|
33
|
-
([as, bs =
|
|
34
|
-
[
|
|
30
|
+
([as, bs = new List(), cs], context) =>
|
|
31
|
+
new List([new Data(elem(as.head!.value.slice(1), false, [...unwrap(as.import(bs).import(cs))], new List(), new List(), context))]),
|
|
32
|
+
([as, bs = new List()], context) =>
|
|
33
|
+
new List([new Data(elem(as.head!.value.slice(1), false, [...unwrap(as.import(bs))], new List(), new List(), context))])),
|
|
35
34
|
match(
|
|
36
35
|
new RegExp(String.raw`<(${TAGS.join('|')})(?=[^\S\n]|>)`, 'y'),
|
|
37
36
|
memoize(
|
|
@@ -40,8 +39,8 @@ export const html: HTMLParser = lazy(() => validate(/<[a-z]+(?=[ >])/yi,
|
|
|
40
39
|
surround(
|
|
41
40
|
str(`<${tag}`), some(attribute), open(str(/ ?/y), str('>'), true),
|
|
42
41
|
true,
|
|
43
|
-
([as, bs =
|
|
44
|
-
([as, bs =
|
|
42
|
+
([as, bs = new List(), cs]) => as.import(bs).import(cs),
|
|
43
|
+
([as, bs = new List()]) => as.import(bs)),
|
|
45
44
|
// 不可視のHTML構造が可視構造を変化させるべきでない。
|
|
46
45
|
// 可視のHTMLは優先度変更を検討する。
|
|
47
46
|
// このため<>は将来的に共通構造を変化させる可能性があり
|
|
@@ -53,10 +52,10 @@ export const html: HTMLParser = lazy(() => validate(/<[a-z]+(?=[ >])/yi,
|
|
|
53
52
|
])))),
|
|
54
53
|
str(`</${tag}>`),
|
|
55
54
|
true,
|
|
56
|
-
([as, bs =
|
|
57
|
-
[
|
|
58
|
-
([as, bs =
|
|
59
|
-
[
|
|
55
|
+
([as, bs = new List(), cs], context) =>
|
|
56
|
+
new List([new Data(elem(tag, true, [...unwrap(as)], bs, cs, context))]),
|
|
57
|
+
([as, bs = new List()], context) =>
|
|
58
|
+
new List([new Data(elem(tag, true, [...unwrap(as)], bs, new List(), context))])),
|
|
60
59
|
([, tag]) => tag,
|
|
61
60
|
new Map())),
|
|
62
61
|
surround(
|
|
@@ -65,10 +64,10 @@ export const html: HTMLParser = lazy(() => validate(/<[a-z]+(?=[ >])/yi,
|
|
|
65
64
|
some(union([attribute])),
|
|
66
65
|
open(str(/ ?/y), str('>'), true),
|
|
67
66
|
true,
|
|
68
|
-
([as, bs =
|
|
69
|
-
[
|
|
70
|
-
([as, bs =
|
|
71
|
-
[
|
|
67
|
+
([as, bs = new List(), cs], context) =>
|
|
68
|
+
new List([new Data(elem(as.head!.value.slice(1), false, [...unwrap(as.import(bs).import(cs))], new List(), new List(), context))]),
|
|
69
|
+
([as, bs = new List()], context) =>
|
|
70
|
+
new List([new Data(elem(as.head!.value.slice(1), false, [...unwrap(as.import(bs))], new List(), new List(), context))])),
|
|
72
71
|
])));
|
|
73
72
|
|
|
74
73
|
export const attribute: HTMLParser.AttributeParser = union([
|
|
@@ -76,7 +75,7 @@ export const attribute: HTMLParser.AttributeParser = union([
|
|
|
76
75
|
str(/ [^\s<>]+/y),
|
|
77
76
|
]);
|
|
78
77
|
|
|
79
|
-
function elem(tag: string, content: boolean, as: string[], bs:
|
|
78
|
+
function elem(tag: string, content: boolean, as: readonly string[], bs: List<Data<HTMLElement | string>>, cs: List<Data<string>>, context: Ctx): HTMLElement {
|
|
80
79
|
assert(as.length > 0);
|
|
81
80
|
assert(as[0][0] === '<');
|
|
82
81
|
if (!tags.includes(tag)) return ielem('tag', `Invalid HTML tag name "${tag}"`, context);
|
|
@@ -88,7 +87,7 @@ function elem(tag: string, content: boolean, as: string[], bs: (HTMLElement | st
|
|
|
88
87
|
const [attrs] = attributes('html', attrspecs[tag], as.slice(1, as.at(-1) === '>' ? -1 : as.length));
|
|
89
88
|
if (/(?<!\S)invalid(?!\S)/.test(attrs['class'] ?? '')) return ielem('attribute', 'Invalid HTML attribute', context)
|
|
90
89
|
if (as.at(-1) !== '>') return ielem('tag', `Missing the closing symbol ">"`, context);
|
|
91
|
-
return h(tag as 'span', attrs, defrag(bs));
|
|
90
|
+
return h(tag as 'span', attrs, defrag(unwrap(bs)));
|
|
92
91
|
}
|
|
93
92
|
|
|
94
93
|
function ielem(type: string, message: string, context: Ctx): HTMLElement {
|
|
@@ -105,7 +104,7 @@ const requiredAttributes = memoize(
|
|
|
105
104
|
export function attributes(
|
|
106
105
|
syntax: string,
|
|
107
106
|
spec: Readonly<Record<string, readonly (string | undefined)[] | undefined>> | undefined,
|
|
108
|
-
params:
|
|
107
|
+
params: Iterable<string>,
|
|
109
108
|
): [Record<string, string | undefined>, string[]] {
|
|
110
109
|
assert(spec instanceof Object === false);
|
|
111
110
|
assert(!spec?.['__proto__']);
|
|
@@ -113,17 +112,17 @@ export function attributes(
|
|
|
113
112
|
const remains = [];
|
|
114
113
|
let invalidation = false;
|
|
115
114
|
const attrs: Record<string, string | undefined> = {};
|
|
116
|
-
for (
|
|
117
|
-
const
|
|
118
|
-
if (
|
|
119
|
-
const name =
|
|
120
|
-
const value =
|
|
121
|
-
?
|
|
115
|
+
for (const param of params) {
|
|
116
|
+
const attr = param.trimStart();
|
|
117
|
+
if (attr === '') continue;
|
|
118
|
+
const name = attr.split('=', 1)[0];
|
|
119
|
+
const value = attr !== name
|
|
120
|
+
? attr.slice(name.length + 2, -1).replace(/\\(.?)/g, '$1')
|
|
122
121
|
: undefined;
|
|
123
122
|
invalidation ||= name === '' || !spec || name in attrs;
|
|
124
|
-
if (name === '')continue;
|
|
123
|
+
if (name === '') continue;
|
|
125
124
|
if (spec && name in spec && !spec[name]) {
|
|
126
|
-
remains.push(
|
|
125
|
+
remains.push(param);
|
|
127
126
|
continue;
|
|
128
127
|
}
|
|
129
128
|
if (spec?.[name]?.includes(value) || spec?.[name]?.length === 0 && value !== undefined) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { HTMLEntityParser, UnsafeHTMLEntityParser } from '../inline';
|
|
2
|
+
import { List, Data } from '../../combinator/data/parser';
|
|
2
3
|
import { union, focus, fmap } from '../../combinator';
|
|
3
4
|
import { invalid } from '../util';
|
|
4
5
|
import { html } from 'typed-dom/dom';
|
|
@@ -10,20 +11,20 @@ export const unsafehtmlentity: UnsafeHTMLEntityParser = focus(
|
|
|
10
11
|
const { source } = context;
|
|
11
12
|
context.position += source.length;
|
|
12
13
|
return source.length > 1 && source.at(-1) === ';'
|
|
13
|
-
? [
|
|
14
|
-
: [
|
|
14
|
+
? new List([new Data(parser(source) ?? source)])
|
|
15
|
+
: new List([new Data(source)]);
|
|
15
16
|
});
|
|
16
17
|
|
|
17
18
|
export const htmlentity: HTMLEntityParser = fmap(
|
|
18
19
|
union([unsafehtmlentity]),
|
|
19
|
-
([
|
|
20
|
-
length === 1 ||
|
|
21
|
-
?
|
|
22
|
-
: html('span', {
|
|
20
|
+
([{ value }]) => new List([
|
|
21
|
+
length === 1 || value.at(-1) !== ';'
|
|
22
|
+
? new Data(value)
|
|
23
|
+
: new Data(html('span', {
|
|
23
24
|
class: 'invalid',
|
|
24
25
|
...invalid('htmlentity', 'syntax', 'Invalid HTML entity'),
|
|
25
|
-
},
|
|
26
|
-
]);
|
|
26
|
+
}, value))
|
|
27
|
+
]));
|
|
27
28
|
|
|
28
29
|
const parser = (el => (entity: string): string | undefined => {
|
|
29
30
|
if (entity === '
') return ' ';
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { InsertionParser } from '../inline';
|
|
2
2
|
import { Recursion, Command } from '../context';
|
|
3
|
+
import { List, Data } from '../../combinator/data/parser';
|
|
3
4
|
import { union, some, recursion, precedence, validate, surround, open, lazy } from '../../combinator';
|
|
4
5
|
import { inline } from '../inline';
|
|
5
6
|
import { blankWith } from '../visibility';
|
|
6
|
-
import { repeat } from '../util';
|
|
7
|
-
import { push } from 'spica/array';
|
|
7
|
+
import { unwrap, repeat } from '../util';
|
|
8
8
|
import { html, defrag } from 'typed-dom/dom';
|
|
9
9
|
|
|
10
10
|
export const insertion: InsertionParser = lazy(() => validate('++',
|
|
@@ -16,6 +16,6 @@ export const insertion: InsertionParser = lazy(() => validate('++',
|
|
|
16
16
|
open('\n', some(inline, '+'), true),
|
|
17
17
|
]))),
|
|
18
18
|
'++', false,
|
|
19
|
-
([, bs], { buffer }) =>
|
|
20
|
-
([, bs], { buffer }) => bs &&
|
|
21
|
-
nodes => [html('ins', defrag(nodes))]))));
|
|
19
|
+
([, bs], { buffer }) => buffer!.import(bs),
|
|
20
|
+
([, bs], { buffer }) => bs && buffer!.import(bs).push(new Data(Command.Cancel)) && buffer!),
|
|
21
|
+
nodes => new List([new Data(html('ins', defrag(unwrap(nodes))))])))));
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { ItalicParser } from '../inline';
|
|
2
2
|
import { Recursion, Command } from '../context';
|
|
3
|
+
import { List, Data } from '../../combinator/data/parser';
|
|
3
4
|
import { union, some, recursion, precedence, validate, surround, open, lazy } from '../../combinator';
|
|
4
5
|
import { inline } from '../inline';
|
|
5
6
|
import { tightStart, blankWith } from '../visibility';
|
|
6
|
-
import { repeat } from '../util';
|
|
7
|
-
import { push } from 'spica/array';
|
|
7
|
+
import { unwrap, repeat } from '../util';
|
|
8
8
|
import { html, defrag } from 'typed-dom/dom';
|
|
9
9
|
|
|
10
10
|
// 可読性のため実際にはオブリーク体を指定する。
|
|
@@ -19,6 +19,6 @@ export const italic: ItalicParser = lazy(() => validate('///',
|
|
|
19
19
|
open(some(inline, '/'), inline),
|
|
20
20
|
])))),
|
|
21
21
|
'///', false,
|
|
22
|
-
([, bs], { buffer }) =>
|
|
23
|
-
([, bs], { buffer }) => bs &&
|
|
24
|
-
nodes => [html('i', defrag(nodes))]))));
|
|
22
|
+
([, bs], { buffer }) => buffer!.import(bs),
|
|
23
|
+
([, bs], { buffer }) => bs && buffer!.import(bs).push(new Data(Command.Cancel)) && buffer!),
|
|
24
|
+
nodes => new List([new Data(html('i', defrag(unwrap(nodes))))])))));
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { MarkdownParser } from '../../../markdown';
|
|
2
2
|
import { LinkParser } from '../inline';
|
|
3
3
|
import { State, Backtrack, Command } from '../context';
|
|
4
|
+
import { List, Data } from '../../combinator/data/parser';
|
|
4
5
|
import { union, inits, tails, sequence, subsequence, some, creation, precedence, state, constraint, validate, surround, open, setBacktrack, dup, reverse, lazy, fmap, bind } from '../../combinator';
|
|
5
6
|
import { inline, media, shortmedia } from '../inline';
|
|
6
7
|
import { attributes } from './html';
|
|
7
8
|
import { unescsource, str } from '../source';
|
|
8
9
|
import { trimBlankStart, trimBlankNodeEnd } from '../visibility';
|
|
9
|
-
import { invalid, stringify } from '../util';
|
|
10
|
+
import { unwrap, invalid, stringify } from '../util';
|
|
10
11
|
import { ReadonlyURL } from 'spica/url';
|
|
11
|
-
import { unshift, push } from 'spica/array';
|
|
12
12
|
import { html, define, defrag } from 'typed-dom/dom';
|
|
13
13
|
|
|
14
14
|
const optspec = {
|
|
@@ -24,9 +24,9 @@ export const textlink: LinkParser.TextLinkParser = lazy(() => constraint(State.l
|
|
|
24
24
|
trimBlankStart(some(union([inline]), ']', [[']', 1]])),
|
|
25
25
|
']',
|
|
26
26
|
true,
|
|
27
|
-
([, ns =
|
|
27
|
+
([, ns = new List()], context) =>
|
|
28
28
|
context.linebreak === 0
|
|
29
|
-
?
|
|
29
|
+
? ns.push(new Data(Command.Separator)) && ns
|
|
30
30
|
: undefined,
|
|
31
31
|
undefined,
|
|
32
32
|
[3 | Backtrack.bracket, 3 | Backtrack.link, 2 | Backtrack.ruby])),
|
|
@@ -42,12 +42,12 @@ export const textlink: LinkParser.TextLinkParser = lazy(() => constraint(State.l
|
|
|
42
42
|
if (!bs) return;
|
|
43
43
|
const head = context.position - context.range!;
|
|
44
44
|
setBacktrack(context, [2 | Backtrack.link], head);
|
|
45
|
-
return
|
|
45
|
+
return as.import(bs).push(new Data(Command.Cancel)) && as;
|
|
46
46
|
},
|
|
47
47
|
[3 | Backtrack.link])),
|
|
48
48
|
]),
|
|
49
|
-
([content,
|
|
50
|
-
if (content.
|
|
49
|
+
([{ value: content }, { value: params = undefined } = {}], context) => {
|
|
50
|
+
if (content.last!.value === Command.Separator) {
|
|
51
51
|
content.pop();
|
|
52
52
|
if (params === undefined) {
|
|
53
53
|
const head = context.position - context.range!;
|
|
@@ -55,37 +55,37 @@ export const textlink: LinkParser.TextLinkParser = lazy(() => constraint(State.l
|
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
else {
|
|
58
|
-
params = content as string
|
|
59
|
-
content =
|
|
58
|
+
params = content as List<Data<string>>;
|
|
59
|
+
content = new List();
|
|
60
60
|
}
|
|
61
|
-
if (params.
|
|
61
|
+
if (params.last!.value === Command.Cancel) {
|
|
62
62
|
params.pop();
|
|
63
|
-
return [
|
|
64
|
-
html('span',
|
|
63
|
+
return new List([
|
|
64
|
+
new Data(html('span',
|
|
65
65
|
{
|
|
66
66
|
class: 'invalid',
|
|
67
67
|
...invalid('link', 'syntax', 'Missing the closing symbol "}"')
|
|
68
68
|
},
|
|
69
|
-
context.source.slice(context.position - context.range!, context.position))
|
|
70
|
-
]
|
|
69
|
+
context.source.slice(context.position - context.range!, context.position)))
|
|
70
|
+
]);
|
|
71
71
|
}
|
|
72
|
-
assert(!html('div', content).querySelector('a, .media, .annotation, .reference'));
|
|
73
|
-
assert(content
|
|
72
|
+
assert(!html('div', unwrap(content)).querySelector('a, .media, .annotation, .reference'));
|
|
73
|
+
assert(content.head?.value !== '');
|
|
74
74
|
if (content.length !== 0 && trimBlankNodeEnd(content).length === 0) return;
|
|
75
|
-
return [
|
|
75
|
+
return new List([new Data(parse(content, params as List<Data<string>>, context))]);
|
|
76
76
|
}))))));
|
|
77
77
|
|
|
78
78
|
export const medialink: LinkParser.MediaLinkParser = lazy(() => constraint(State.link | State.media, validate(/[[{]/y, creation(10,
|
|
79
79
|
state(State.linkers,
|
|
80
|
-
bind(
|
|
80
|
+
bind(sequence([
|
|
81
81
|
dup(surround(
|
|
82
82
|
'[',
|
|
83
83
|
union([media, shortmedia]),
|
|
84
84
|
']')),
|
|
85
85
|
dup(surround(/{(?![{}])/y, inits([uri, some(option)]), / ?}/y)),
|
|
86
|
-
])
|
|
87
|
-
([
|
|
88
|
-
[
|
|
86
|
+
]),
|
|
87
|
+
([{ value: content }, { value: params }], context) =>
|
|
88
|
+
new List([new Data(parse(content, params as List<Data<string>>, context))])))))));
|
|
89
89
|
|
|
90
90
|
export const unsafelink: LinkParser.UnsafeLinkParser = lazy(() =>
|
|
91
91
|
creation(10,
|
|
@@ -96,8 +96,8 @@ export const unsafelink: LinkParser.UnsafeLinkParser = lazy(() =>
|
|
|
96
96
|
']')),
|
|
97
97
|
dup(surround(/{(?![{}])/y, inits([uri, some(option)]), / ?}/y)),
|
|
98
98
|
])),
|
|
99
|
-
([params, content =
|
|
100
|
-
[
|
|
99
|
+
([{ value: params }, { value: content } = new Data(new List<Data<string>>())], context) =>
|
|
100
|
+
new List([new Data(parse(content, params, context))]))));
|
|
101
101
|
|
|
102
102
|
export const uri: LinkParser.ParameterParser.UriParser = union([
|
|
103
103
|
open(/ /y, str(/\S+/y)),
|
|
@@ -105,19 +105,18 @@ export const uri: LinkParser.ParameterParser.UriParser = union([
|
|
|
105
105
|
]);
|
|
106
106
|
|
|
107
107
|
export const option: LinkParser.ParameterParser.OptionParser = union([
|
|
108
|
-
fmap(str(/ nofollow(?=[ }])/y), () => [
|
|
108
|
+
fmap(str(/ nofollow(?=[ }])/y), () => new List([new Data(' rel="nofollow"')])),
|
|
109
109
|
str(/ [a-z]+(?:-[a-z]+)*(?:="(?:\\[^\n]|[^\\\n"])*")?(?=[ }])/yi),
|
|
110
110
|
str(/ [^\s{}]+/y),
|
|
111
111
|
]);
|
|
112
112
|
|
|
113
113
|
function parse(
|
|
114
|
-
content:
|
|
115
|
-
params: string
|
|
114
|
+
content: List<Data<string | HTMLElement>>,
|
|
115
|
+
params: List<Data<string>>,
|
|
116
116
|
context: MarkdownParser.Context,
|
|
117
117
|
): HTMLAnchorElement {
|
|
118
118
|
assert(params.length > 0);
|
|
119
|
-
|
|
120
|
-
const INSECURE_URI = params.shift()!;
|
|
119
|
+
const INSECURE_URI = params.shift()!.value;
|
|
121
120
|
assert(INSECURE_URI === INSECURE_URI.trim());
|
|
122
121
|
assert(!INSECURE_URI.match(/\s/));
|
|
123
122
|
let uri: ReadonlyURL | undefined;
|
|
@@ -135,12 +134,12 @@ function parse(
|
|
|
135
134
|
context.host?.origin || location.origin);
|
|
136
135
|
return el.classList.contains('invalid')
|
|
137
136
|
? el
|
|
138
|
-
: define(el, attributes('link', optspec, params)[0]);
|
|
137
|
+
: define(el, attributes('link', optspec, unwrap(params))[0]);
|
|
139
138
|
}
|
|
140
139
|
|
|
141
140
|
function elem(
|
|
142
141
|
INSECURE_URI: string,
|
|
143
|
-
content:
|
|
142
|
+
content: List<Data<string | HTMLElement>>,
|
|
144
143
|
uri: ReadonlyURL | undefined,
|
|
145
144
|
origin: string,
|
|
146
145
|
): HTMLAnchorElement {
|
|
@@ -155,7 +154,7 @@ function elem(
|
|
|
155
154
|
case 'https:':
|
|
156
155
|
assert(uri.host);
|
|
157
156
|
switch (true) {
|
|
158
|
-
case /[0-9a-z]:\S/i.test(stringify(content)):
|
|
157
|
+
case /[0-9a-z]:\S/i.test(stringify(unwrap(content))):
|
|
159
158
|
type = 'content';
|
|
160
159
|
message = 'URI must not be contained';
|
|
161
160
|
break;
|
|
@@ -171,20 +170,19 @@ function elem(
|
|
|
171
170
|
href: uri.source,
|
|
172
171
|
target: undefined
|
|
173
172
|
|| uri.origin !== origin
|
|
174
|
-
|| typeof content
|
|
173
|
+
|| typeof content.head?.value === 'object' && content.head!.value.classList.contains('media')
|
|
175
174
|
? '_blank'
|
|
176
175
|
: undefined,
|
|
177
176
|
},
|
|
178
177
|
content.length === 0
|
|
179
178
|
? decode(INSECURE_URI)
|
|
180
|
-
: content);
|
|
179
|
+
: defrag(unwrap(content)));
|
|
181
180
|
}
|
|
182
181
|
break;
|
|
183
182
|
case 'tel:':
|
|
184
|
-
assert(content.length <= 1);
|
|
185
183
|
const tel = content.length === 0
|
|
186
184
|
? INSECURE_URI
|
|
187
|
-
: content
|
|
185
|
+
: stringify(unwrap(content));
|
|
188
186
|
const pattern = /^(?:tel:)?(?:\+(?!0))?\d+(?:-\d+)*$/i;
|
|
189
187
|
switch (true) {
|
|
190
188
|
case content.length <= 1
|
|
@@ -198,8 +196,8 @@ function elem(
|
|
|
198
196
|
href: uri.source,
|
|
199
197
|
},
|
|
200
198
|
content.length === 0
|
|
201
|
-
?
|
|
202
|
-
: content);
|
|
199
|
+
? INSECURE_URI
|
|
200
|
+
: defrag(unwrap(content)));
|
|
203
201
|
default:
|
|
204
202
|
type = 'content';
|
|
205
203
|
message = 'Invalid content';
|
|
@@ -216,7 +214,7 @@ function elem(
|
|
|
216
214
|
},
|
|
217
215
|
content.length === 0
|
|
218
216
|
? INSECURE_URI
|
|
219
|
-
: content);
|
|
217
|
+
: defrag(unwrap(content)));
|
|
220
218
|
}
|
|
221
219
|
|
|
222
220
|
export function resolve(uri: string, host: URL | Location, source: URL | Location): string {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { MarkParser } from '../inline';
|
|
2
2
|
import { State, Recursion, Command } from '../context';
|
|
3
|
+
import { List, Data } from '../../combinator/data/parser';
|
|
3
4
|
import { union, some, recursion, precedence, state, constraint, validate, surround, open, lazy } from '../../combinator';
|
|
4
5
|
import { inline } from '../inline';
|
|
5
6
|
import { identity, signature } from './extension/indexee';
|
|
6
7
|
import { tightStart, blankWith } from '../visibility';
|
|
7
|
-
import { repeat } from '../util';
|
|
8
|
-
import { push } from 'spica/array';
|
|
8
|
+
import { unwrap, repeat } from '../util';
|
|
9
9
|
import { html, define, defrag } from 'typed-dom/dom';
|
|
10
10
|
|
|
11
11
|
export const mark: MarkParser = lazy(() => constraint(State.linkers & ~State.mark, validate('==',
|
|
@@ -17,12 +17,12 @@ export const mark: MarkParser = lazy(() => constraint(State.linkers & ~State.mar
|
|
|
17
17
|
open(some(inline, '='), inline),
|
|
18
18
|
])))),
|
|
19
19
|
'==', false,
|
|
20
|
-
([, bs], { buffer }) =>
|
|
21
|
-
([, bs], { buffer }) => bs &&
|
|
20
|
+
([, bs], { buffer }) => buffer!.import(bs),
|
|
21
|
+
([, bs], { buffer }) => bs && buffer!.import(bs).push(new Data(Command.Cancel)) && buffer!),
|
|
22
22
|
(nodes, { id }) => {
|
|
23
|
-
const el = html('mark', defrag(nodes));
|
|
23
|
+
const el = html('mark', defrag(unwrap(nodes)));
|
|
24
24
|
define(el, { id: identity('mark', id, signature(el)) });
|
|
25
25
|
return el.id
|
|
26
|
-
? [el, html('a', { href: `#${el.id}` })]
|
|
27
|
-
: [el];
|
|
26
|
+
? new List([new Data(el), new Data(html('a', { href: `#${el.id}` }))])
|
|
27
|
+
: new List([new Data(el)]);
|
|
28
28
|
}))))));
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { MathParser } from '../inline';
|
|
2
2
|
import { Backtrack, Recursion } from '../context';
|
|
3
|
+
import { List, Data } from '../../combinator/data/parser';
|
|
3
4
|
import { union, some, recursion, precedence, rewrite, surround, lazy } from '../../combinator';
|
|
4
5
|
import { escsource, str } from '../source';
|
|
5
6
|
import { invalid } from '../util';
|
|
@@ -23,8 +24,8 @@ export const math: MathParser = lazy(() => rewrite(
|
|
|
23
24
|
/\$(?![-0-9A-Za-z])/y,
|
|
24
25
|
false, undefined, undefined, [3 | Backtrack.bracket]),
|
|
25
26
|
]),
|
|
26
|
-
({ context: { source, caches: { math: cache } = {} } }) => [
|
|
27
|
-
cache?.get(source)?.cloneNode(true) ||
|
|
27
|
+
({ context: { source, caches: { math: cache } = {} } }) => new List([
|
|
28
|
+
new Data(cache?.get(source)?.cloneNode(true) ||
|
|
28
29
|
html('span',
|
|
29
30
|
!forbiddenCommand.test(source)
|
|
30
31
|
? { class: 'math', translate: 'no', 'data-src': source }
|
|
@@ -34,8 +35,8 @@ export const math: MathParser = lazy(() => rewrite(
|
|
|
34
35
|
...invalid('math', 'content',
|
|
35
36
|
`"${source.match(forbiddenCommand)![0]}" command is forbidden`),
|
|
36
37
|
},
|
|
37
|
-
source)
|
|
38
|
-
]
|
|
38
|
+
source))
|
|
39
|
+
])));
|
|
39
40
|
|
|
40
41
|
const bracket: MathParser.BracketParser = lazy(() => surround(
|
|
41
42
|
str('{'),
|