securemark 0.293.1 → 0.293.3
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/README.md +7 -10
- package/dist/index.js +329 -150
- package/package.json +1 -1
- package/src/combinator/control/manipulation/indent.test.ts +6 -1
- package/src/combinator/control/manipulation/indent.ts +1 -1
- package/src/combinator/control/manipulation/scope.ts +3 -4
- package/src/combinator/control/manipulation/surround.ts +2 -1
- package/src/combinator/data/parser/context/delimiter.ts +7 -12
- package/src/combinator/data/parser/some.ts +4 -8
- package/src/parser/api/parse.test.ts +2 -2
- package/src/parser/block/olist.test.ts +8 -6
- package/src/parser/block/olist.ts +2 -2
- package/src/parser/block/sidefence.ts +2 -2
- package/src/parser/block/table.ts +2 -2
- package/src/parser/block.ts +38 -36
- package/src/parser/inline/annotation.test.ts +1 -1
- package/src/parser/inline/autolink/url.test.ts +5 -5
- package/src/parser/inline/bracket.test.ts +6 -4
- package/src/parser/inline/bracket.ts +114 -88
- package/src/parser/inline/html.ts +24 -13
- package/src/parser/inline/italic.test.ts +9 -9
- package/src/parser/inline/link.ts +1 -1
- package/src/parser/inline/mark.test.ts +5 -5
- package/src/parser/inline/math.ts +2 -2
- package/src/parser/inline/media.ts +3 -2
- package/src/parser/inline/reference.test.ts +1 -1
- package/src/parser/inline/remark.ts +2 -2
- package/src/parser/inline/template.ts +1 -1
- package/src/parser/inline.test.ts +24 -23
- package/src/parser/inline.ts +46 -47
- package/src/parser/segment.ts +12 -12
- package/src/parser/source/escapable.test.ts +1 -1
- package/src/parser/source/escapable.ts +7 -4
- package/src/parser/source/text.ts +162 -25
- package/src/parser/source/unescapable.ts +5 -3
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BracketParser } from '../inline';
|
|
2
2
|
import { State, Recursion, Backtrack } from '../context';
|
|
3
|
-
import { union, some, recursion, precedence,
|
|
3
|
+
import { union, some, recursion, precedence, surround, isBacktrack, setBacktrack, lazy } from '../../combinator';
|
|
4
4
|
import { inline } from '../inline';
|
|
5
5
|
import { textlink } from './link';
|
|
6
6
|
import { str } from '../source';
|
|
@@ -11,93 +11,119 @@ const indexA = /^[0-9A-Za-z]+(?:(?:[.-]|, )[0-9A-Za-z]+)*$/;
|
|
|
11
11
|
const indexF = new RegExp(indexA.source.replace(', ', '[,、]')
|
|
12
12
|
.replace(/[09AZaz.]|\-(?!\w)/g, c => String.fromCodePoint(c.codePointAt(0)! + 0xFEE0)));
|
|
13
13
|
|
|
14
|
-
export const bracket: BracketParser = lazy(() =>
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
str
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
14
|
+
export const bracket: BracketParser = lazy(() => union([
|
|
15
|
+
input => {
|
|
16
|
+
const { context: { source, position } } = input;
|
|
17
|
+
switch (source[position]) {
|
|
18
|
+
case '(':
|
|
19
|
+
return p1(input);
|
|
20
|
+
case '(':
|
|
21
|
+
return p2(input);
|
|
22
|
+
case '[':
|
|
23
|
+
return s1(input);
|
|
24
|
+
case '[':
|
|
25
|
+
return s2(input);
|
|
26
|
+
case '{':
|
|
27
|
+
return c1(input);
|
|
28
|
+
case '{':
|
|
29
|
+
return c2(input);
|
|
30
|
+
case '"':
|
|
31
|
+
return d1(input);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
])) as any;
|
|
35
|
+
|
|
36
|
+
const p1 = lazy(() => surround(
|
|
37
|
+
str('('),
|
|
38
|
+
precedence(1, recursion(Recursion.bracket, some(inline, ')', [[')', 1]]))),
|
|
39
|
+
str(')'),
|
|
40
|
+
true,
|
|
41
|
+
([as, bs = [], cs], { source, position, range = 0 }) => {
|
|
42
|
+
const str = source.slice(position - range + 1, position - 1);
|
|
43
|
+
return indexA.test(str)
|
|
44
|
+
? [[as[0], str, cs[0]]]
|
|
45
|
+
: [[html('span', { class: 'paren' }, defrag(push(unshift(as, bs), cs)))]];
|
|
46
|
+
},
|
|
47
|
+
([as, bs = []]) => [unshift(as, bs)],
|
|
48
|
+
[2 | Backtrack.bracket]));
|
|
49
|
+
|
|
50
|
+
const p2 = lazy(() => surround(
|
|
51
|
+
str('('),
|
|
52
|
+
precedence(1, recursion(Recursion.bracket, some(inline, ')', [[')', 1]]))),
|
|
53
|
+
str(')'),
|
|
54
|
+
true,
|
|
55
|
+
([as, bs = [], cs], { source, position, range = 0 }) => {
|
|
56
|
+
const str = source.slice(position - range + 1, position - 1);
|
|
57
|
+
return indexF.test(str)
|
|
58
|
+
? [[as[0], str, cs[0]]]
|
|
59
|
+
: [[html('span', { class: 'paren' }, defrag(push(unshift(as, bs), cs)))]];
|
|
60
|
+
},
|
|
61
|
+
([as, bs = []]) => [unshift(as, bs)],
|
|
62
|
+
[2 | Backtrack.bracket]));
|
|
63
|
+
|
|
64
|
+
const s1 = lazy(() => surround(
|
|
65
|
+
str('['),
|
|
66
|
+
precedence(1, recursion(Recursion.bracket, some(inline, ']', [[']', 1]]))),
|
|
67
|
+
str(']'),
|
|
68
|
+
true,
|
|
69
|
+
([as, bs = [], cs], context) => {
|
|
70
|
+
if (context.state! & State.link) {
|
|
71
|
+
const { source, position, range = 0 } = context;
|
|
72
|
+
const head = position - range;
|
|
73
|
+
if (context.linebreak !== 0 || source[position] !== '{') {
|
|
74
|
+
setBacktrack(context, [2 | Backtrack.link], head);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
context.state! ^= State.link;
|
|
78
|
+
const result = !isBacktrack(context, [1 | Backtrack.link])
|
|
79
|
+
? textlink({ context })
|
|
80
|
+
: undefined;
|
|
81
|
+
context.position = position;
|
|
82
|
+
if (!result) {
|
|
50
83
|
setBacktrack(context, [2 | Backtrack.link], head);
|
|
51
84
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const result = !isBacktrack(context, [1 | Backtrack.link])
|
|
55
|
-
? textlink({ context })
|
|
56
|
-
: undefined;
|
|
57
|
-
context.position = position;
|
|
58
|
-
if (!result) {
|
|
59
|
-
setBacktrack(context, [2 | Backtrack.link], head);
|
|
60
|
-
}
|
|
61
|
-
context.state! ^= State.link;
|
|
62
|
-
context.range = range;
|
|
63
|
-
}
|
|
85
|
+
context.state! ^= State.link;
|
|
86
|
+
context.range = range;
|
|
64
87
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
88
|
+
}
|
|
89
|
+
return [push(unshift(as, bs), cs)];
|
|
90
|
+
},
|
|
91
|
+
([as, bs = []]) => [unshift(as, bs)],
|
|
92
|
+
[2 | Backtrack.bracket]));
|
|
93
|
+
|
|
94
|
+
const s2 = lazy(() => surround(
|
|
95
|
+
str('['),
|
|
96
|
+
precedence(1, recursion(Recursion.bracket, some(inline, ']', [[']', 1]]))),
|
|
97
|
+
str(']'),
|
|
98
|
+
true,
|
|
99
|
+
undefined,
|
|
100
|
+
([as, bs = []]) => [unshift(as, bs)],
|
|
101
|
+
[2 | Backtrack.bracket]));
|
|
102
|
+
|
|
103
|
+
const c1 = lazy(() => surround(
|
|
104
|
+
str('{'),
|
|
105
|
+
precedence(1, recursion(Recursion.bracket, some(inline, '}', [['}', 1]]))),
|
|
106
|
+
str('}'),
|
|
107
|
+
true,
|
|
108
|
+
undefined,
|
|
109
|
+
([as, bs = []]) => [unshift(as, bs)],
|
|
110
|
+
[2 | Backtrack.bracket]));
|
|
111
|
+
|
|
112
|
+
const c2 = lazy(() => surround(
|
|
113
|
+
str('{'),
|
|
114
|
+
precedence(1, recursion(Recursion.bracket, some(inline, '}', [['}', 1]]))),
|
|
115
|
+
str('}'),
|
|
116
|
+
true,
|
|
117
|
+
undefined,
|
|
118
|
+
([as, bs = []]) => [unshift(as, bs)],
|
|
119
|
+
[2 | Backtrack.bracket]));
|
|
120
|
+
|
|
121
|
+
const d1 = lazy(() => surround(
|
|
122
|
+
str('"'),
|
|
123
|
+
// 改行の優先度を構文ごとに変える場合シグネチャの優先度対応が必要
|
|
124
|
+
precedence(2, recursion(Recursion.bracket, some(inline, /["\n]/y, [['"', 2], ['\n', 3]]))),
|
|
125
|
+
str('"'),
|
|
126
|
+
true,
|
|
127
|
+
undefined,
|
|
128
|
+
([as, bs = []]) => [unshift(as, bs)],
|
|
129
|
+
[2 | Backtrack.bracket]));
|
|
@@ -7,7 +7,7 @@ import { str } from '../source';
|
|
|
7
7
|
import { isLooseNodeStart, blankWith } from '../visibility';
|
|
8
8
|
import { invalid } from '../util';
|
|
9
9
|
import { memoize } from 'spica/memoize';
|
|
10
|
-
import { unshift, push
|
|
10
|
+
import { unshift, push } from 'spica/array';
|
|
11
11
|
import { html as h, defrag } from 'typed-dom/dom';
|
|
12
12
|
|
|
13
13
|
const tags: readonly string[] = ['wbr', 'bdo', 'bdi'];
|
|
@@ -42,10 +42,14 @@ export const html: HTMLParser = lazy(() => validate(/<[a-z]+(?=[^\S\n]|>)/yi,
|
|
|
42
42
|
true,
|
|
43
43
|
([as, bs = [], cs]) => [push(unshift(as, bs), cs)],
|
|
44
44
|
([as, bs = []]) => [unshift(as, bs)]),
|
|
45
|
-
|
|
45
|
+
// 不可視のHTML構造が可視構造を変化させるべきでない。
|
|
46
|
+
// 可視のHTMLは優先度変更を検討する。
|
|
47
|
+
// このため<>は将来的に共通構造を変化させる可能性があり
|
|
48
|
+
// 共通構造を変更させない非構造文字列としては依然としてエスケープを要する。
|
|
49
|
+
precedence(0, recursion(Recursion.inline,
|
|
46
50
|
some(union([
|
|
47
|
-
some(inline, blankWith('\n', `</${tag}>`)
|
|
48
|
-
open('\n', some(inline, `</${tag}
|
|
51
|
+
some(inline, blankWith('\n', `</${tag}>`)),
|
|
52
|
+
open('\n', some(inline, `</${tag}>`), true),
|
|
49
53
|
])))),
|
|
50
54
|
str(`</${tag}>`),
|
|
51
55
|
true,
|
|
@@ -81,7 +85,7 @@ function elem(tag: string, content: boolean, as: string[], bs: (HTMLElement | st
|
|
|
81
85
|
if (bs.length === 0) return ielem('content', `Missing the content`, context);
|
|
82
86
|
if (!isLooseNodeStart(bs)) return ielem('content', `Missing the visible content in the same line`, context);
|
|
83
87
|
}
|
|
84
|
-
const attrs = attributes('html', attrspecs[tag], as.slice(1, as.at(-1) === '>' ? -1 : as.length));
|
|
88
|
+
const [attrs] = attributes('html', attrspecs[tag], as.slice(1, as.at(-1) === '>' ? -1 : as.length));
|
|
85
89
|
if (/(?<!\S)invalid(?!\S)/.test(attrs['class'] ?? '')) return ielem('attribute', 'Invalid HTML attribute', context)
|
|
86
90
|
if (as.at(-1) !== '>') return ielem('tag', `Missing the closing symbol ">"`, context);
|
|
87
91
|
return h(tag as 'span', attrs, defrag(bs));
|
|
@@ -101,11 +105,12 @@ const requiredAttributes = memoize(
|
|
|
101
105
|
export function attributes(
|
|
102
106
|
syntax: string,
|
|
103
107
|
spec: Readonly<Record<string, readonly (string | undefined)[] | undefined>> | undefined,
|
|
104
|
-
params: string[],
|
|
105
|
-
): Record<string, string | undefined
|
|
108
|
+
params: readonly string[],
|
|
109
|
+
): [Record<string, string | undefined>, string[]] {
|
|
106
110
|
assert(spec instanceof Object === false);
|
|
107
111
|
assert(!spec?.['__proto__']);
|
|
108
112
|
assert(!spec?.toString);
|
|
113
|
+
const remains = [];
|
|
109
114
|
let invalidation = false;
|
|
110
115
|
const attrs: Record<string, string | undefined> = {};
|
|
111
116
|
for (let i = 0; i < params.length; ++i) {
|
|
@@ -116,19 +121,25 @@ export function attributes(
|
|
|
116
121
|
? param.slice(name.length + 2, -1).replace(/\\(.?)/g, '$1')
|
|
117
122
|
: undefined;
|
|
118
123
|
invalidation ||= name === '' || !spec || name in attrs;
|
|
119
|
-
if (name === ''
|
|
120
|
-
spec
|
|
121
|
-
|
|
122
|
-
|
|
124
|
+
if (name === '')continue;
|
|
125
|
+
if (spec && name in spec && !spec[name]) {
|
|
126
|
+
remains.push(params[i]);
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (spec?.[name]?.includes(value) || spec?.[name]?.length === 0 && value !== undefined) {
|
|
130
|
+
attrs[name] = value ?? ''
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
invalidation ||= !!spec;
|
|
134
|
+
}
|
|
123
135
|
assert(!(name in {} && attrs.hasOwnProperty(name)));
|
|
124
|
-
splice(params, i--, 1);
|
|
125
136
|
}
|
|
126
137
|
invalidation ||= !!spec && !requiredAttributes(spec).every(name => name in attrs);
|
|
127
138
|
if (invalidation) {
|
|
128
139
|
attrs['class'] = 'invalid';
|
|
129
140
|
Object.assign(attrs, invalid(syntax, 'argument', 'Invalid argument'));
|
|
130
141
|
}
|
|
131
|
-
return attrs;
|
|
142
|
+
return [attrs, remains];
|
|
132
143
|
}
|
|
133
144
|
|
|
134
145
|
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element
|
|
@@ -11,14 +11,14 @@ describe('Unit: parser/inline/italic', () => {
|
|
|
11
11
|
it('invalid', () => {
|
|
12
12
|
assert.deepStrictEqual(inspect(parser('///'), ctx), undefined);
|
|
13
13
|
assert.deepStrictEqual(inspect(parser('///a'), ctx), [['///', 'a'], '']);
|
|
14
|
-
assert.deepStrictEqual(inspect(parser('///a ///'), ctx), [['///', 'a', ' ', '
|
|
15
|
-
assert.deepStrictEqual(inspect(parser('///a ///'), ctx), [['///', 'a', ' ', '
|
|
16
|
-
assert.deepStrictEqual(inspect(parser('///a\n///'), ctx), [['///', 'a', '<br>', '
|
|
17
|
-
assert.deepStrictEqual(inspect(parser('///a\\ ///'), ctx), [['///', 'a', ' ', '
|
|
18
|
-
assert.deepStrictEqual(inspect(parser('///a\\\n///'), ctx), [['///', 'a', '<br>', '
|
|
14
|
+
assert.deepStrictEqual(inspect(parser('///a ///'), ctx), [['///', 'a', ' ', '///'], '']);
|
|
15
|
+
assert.deepStrictEqual(inspect(parser('///a ///'), ctx), [['///', 'a', ' ', '///'], '']);
|
|
16
|
+
assert.deepStrictEqual(inspect(parser('///a\n///'), ctx), [['///', 'a', '<br>', '///'], '']);
|
|
17
|
+
assert.deepStrictEqual(inspect(parser('///a\\ ///'), ctx), [['///', 'a', ' ', '///'], '']);
|
|
18
|
+
assert.deepStrictEqual(inspect(parser('///a\\\n///'), ctx), [['///', 'a', '<br>', '///'], '']);
|
|
19
19
|
assert.deepStrictEqual(inspect(parser('///a/b'), ctx), [['///', 'a', '/b'], '']);
|
|
20
|
-
assert.deepStrictEqual(inspect(parser('///a//b'), ctx), [['///', 'a', '
|
|
21
|
-
assert.deepStrictEqual(inspect(parser('///a*b///'), ctx), [['///', 'a', '*', 'b', '
|
|
20
|
+
assert.deepStrictEqual(inspect(parser('///a//b'), ctx), [['///', 'a', '//b'], '']);
|
|
21
|
+
assert.deepStrictEqual(inspect(parser('///a*b///'), ctx), [['///', 'a', '*', 'b', '///'], '']);
|
|
22
22
|
assert.deepStrictEqual(inspect(parser('/// ///'), ctx), undefined);
|
|
23
23
|
assert.deepStrictEqual(inspect(parser('/// a///'), ctx), undefined);
|
|
24
24
|
assert.deepStrictEqual(inspect(parser('/// a ///'), ctx), undefined);
|
|
@@ -53,8 +53,8 @@ describe('Unit: parser/inline/italic', () => {
|
|
|
53
53
|
assert.deepStrictEqual(inspect(parser('//////a///b'), ctx), [['///', '<i>a</i>', 'b'], '']);
|
|
54
54
|
assert.deepStrictEqual(inspect(parser('//////a////'), ctx), [['///', '<i>a</i>', '/'], '']);
|
|
55
55
|
assert.deepStrictEqual(inspect(parser('//////a////b'), ctx), [['///', '<i>a</i>', '/b'], '']);
|
|
56
|
-
assert.deepStrictEqual(inspect(parser('//////a/////'), ctx), [['///', '<i>a</i>', '
|
|
57
|
-
assert.deepStrictEqual(inspect(parser('//////a/////b'), ctx), [['///', '<i>a</i>', '
|
|
56
|
+
assert.deepStrictEqual(inspect(parser('//////a/////'), ctx), [['///', '<i>a</i>', '//'], '']);
|
|
57
|
+
assert.deepStrictEqual(inspect(parser('//////a/////b'), ctx), [['///', '<i>a</i>', '//b'], '']);
|
|
58
58
|
assert.deepStrictEqual(inspect(parser('//////a//////'), ctx), [['<i><i>a</i></i>'], '']);
|
|
59
59
|
assert.deepStrictEqual(inspect(parser('//////a///b///'), ctx), [['<i><i>a</i>b</i>'], '']);
|
|
60
60
|
assert.deepStrictEqual(inspect(parser('///a ///b//////'), ctx), [['<i>a <i>b</i></i>'], '']);
|
|
@@ -135,7 +135,7 @@ function parse(
|
|
|
135
135
|
context.host?.origin || location.origin);
|
|
136
136
|
return el.classList.contains('invalid')
|
|
137
137
|
? el
|
|
138
|
-
: define(el, attributes('link', optspec, params));
|
|
138
|
+
: define(el, attributes('link', optspec, params)[0]);
|
|
139
139
|
}
|
|
140
140
|
|
|
141
141
|
function elem(
|
|
@@ -14,11 +14,11 @@ describe('Unit: parser/inline/mark', () => {
|
|
|
14
14
|
assert.deepStrictEqual(inspect(parser('=='), ctx), undefined);
|
|
15
15
|
assert.deepStrictEqual(inspect(parser('==a'), ctx), [['==', 'a'], '']);
|
|
16
16
|
assert.deepStrictEqual(inspect(parser('==a='), ctx), [['==', 'a', '='], '']);
|
|
17
|
-
assert.deepStrictEqual(inspect(parser('==a =='), ctx), [['==', 'a', ' ', '
|
|
18
|
-
assert.deepStrictEqual(inspect(parser('==a =='), ctx), [['==', 'a', ' ', '
|
|
19
|
-
assert.deepStrictEqual(inspect(parser('==a\n=='), ctx), [['==', 'a', '<br>', '
|
|
20
|
-
assert.deepStrictEqual(inspect(parser('==a\\ =='), ctx), [['==', 'a', ' ', '
|
|
21
|
-
assert.deepStrictEqual(inspect(parser('==a\\\n=='), ctx), [['==', 'a', '<br>', '
|
|
17
|
+
assert.deepStrictEqual(inspect(parser('==a =='), ctx), [['==', 'a', ' ', '=='], '']);
|
|
18
|
+
assert.deepStrictEqual(inspect(parser('==a =='), ctx), [['==', 'a', ' ', '=='], '']);
|
|
19
|
+
assert.deepStrictEqual(inspect(parser('==a\n=='), ctx), [['==', 'a', '<br>', '=='], '']);
|
|
20
|
+
assert.deepStrictEqual(inspect(parser('==a\\ =='), ctx), [['==', 'a', ' ', '=='], '']);
|
|
21
|
+
assert.deepStrictEqual(inspect(parser('==a\\\n=='), ctx), [['==', 'a', '<br>', '=='], '']);
|
|
22
22
|
assert.deepStrictEqual(inspect(parser('== =='), ctx), undefined);
|
|
23
23
|
assert.deepStrictEqual(inspect(parser('== a=='), ctx), undefined);
|
|
24
24
|
assert.deepStrictEqual(inspect(parser('== a =='), ctx), undefined);
|
|
@@ -11,14 +11,14 @@ export const math: MathParser = lazy(() => rewrite(
|
|
|
11
11
|
union([
|
|
12
12
|
surround(
|
|
13
13
|
/\$(?={)/y,
|
|
14
|
-
precedence(
|
|
14
|
+
precedence(4, bracket),
|
|
15
15
|
'$',
|
|
16
16
|
false, undefined, undefined, [3 | Backtrack.bracket]),
|
|
17
17
|
surround(
|
|
18
18
|
/\$(?![\s{}])/y,
|
|
19
19
|
precedence(2, some(union([
|
|
20
20
|
some(escsource, /\s?\$|[`"{}\n]/y),
|
|
21
|
-
precedence(
|
|
21
|
+
precedence(4, bracket),
|
|
22
22
|
]))),
|
|
23
23
|
/\$(?![-0-9A-Za-z])/y,
|
|
24
24
|
false, undefined, undefined, [3 | Backtrack.bracket]),
|
|
@@ -87,7 +87,8 @@ export const media: MediaParser = lazy(() => constraint(State.media, creation(10
|
|
|
87
87
|
el.setAttribute('alt', text);
|
|
88
88
|
if (!sanitize(el, uri)) return [[el]];
|
|
89
89
|
assert(!el.matches('.invalid'));
|
|
90
|
-
|
|
90
|
+
const [attrs, linkparams] = attributes('media', optspec, params);
|
|
91
|
+
define(el, attrs);
|
|
91
92
|
assert(el.matches('img') || !el.matches('.invalid'));
|
|
92
93
|
// Awaiting the generic support for attr().
|
|
93
94
|
if (el.hasAttribute('aspect-ratio')) {
|
|
@@ -103,7 +104,7 @@ export const media: MediaParser = lazy(() => constraint(State.media, creation(10
|
|
|
103
104
|
context.position = position;
|
|
104
105
|
return [define(link, { class: null, target: '_blank' }, [el])];
|
|
105
106
|
})
|
|
106
|
-
(subinput(`{ ${INSECURE_URI}${
|
|
107
|
+
(subinput(`{ ${INSECURE_URI}${linkparams.join('')} }`, context));
|
|
107
108
|
})))));
|
|
108
109
|
|
|
109
110
|
const bracket: MediaParser.TextParser.BracketParser = lazy(() => recursion(Recursion.terminal, union([
|
|
@@ -17,7 +17,7 @@ describe('Unit: parser/inline/reference', () => {
|
|
|
17
17
|
assert.deepStrictEqual(inspect(parser('[[]]]'), ctx), undefined);
|
|
18
18
|
assert.deepStrictEqual(inspect(parser('[["]]'), ctx), undefined);
|
|
19
19
|
assert.deepStrictEqual(inspect(parser('[[(]]'), ctx), undefined);
|
|
20
|
-
assert.deepStrictEqual(inspect(parser('[[
|
|
20
|
+
assert.deepStrictEqual(inspect(parser('[[[%]]'), ctx), undefined);
|
|
21
21
|
assert.deepStrictEqual(inspect(parser('[[ ]]'), ctx), undefined);
|
|
22
22
|
assert.deepStrictEqual(inspect(parser('[[ [a'), ctx), undefined);
|
|
23
23
|
assert.deepStrictEqual(inspect(parser('[[\n]]'), ctx), undefined);
|
|
@@ -9,8 +9,8 @@ import { html, defrag } from 'typed-dom/dom';
|
|
|
9
9
|
|
|
10
10
|
export const remark: RemarkParser = lazy(() => fallback(surround(
|
|
11
11
|
str(/\[%(?=\s)/y),
|
|
12
|
-
precedence(
|
|
13
|
-
some(union([inline]), /\s%\]/y, [[/\s%\]/y,
|
|
12
|
+
precedence(3, recursion(Recursion.inline,
|
|
13
|
+
some(union([inline]), /\s%\]/y, [[/\s%\]/y, 3]]))),
|
|
14
14
|
close(text, str(`%]`)), true,
|
|
15
15
|
([as, bs = [], cs]) => [[
|
|
16
16
|
html('span', { class: 'remark' }, [
|
|
@@ -34,7 +34,7 @@ const bracket: TemplateParser.BracketParser = lazy(() => union([
|
|
|
34
34
|
undefined, () => [[]], [3 | Backtrack.escbracket]),
|
|
35
35
|
surround(
|
|
36
36
|
str('"'),
|
|
37
|
-
precedence(2, recursion(Recursion.terminal, some(escsource,
|
|
37
|
+
precedence(2, recursion(Recursion.terminal, some(escsource, /["\n]/y, [['"', 2], ['\n', 3]]))),
|
|
38
38
|
str('"'),
|
|
39
39
|
true,
|
|
40
40
|
([as, bs = [], cs], context) =>
|
|
@@ -22,7 +22,7 @@ describe('Unit: parser/inline', () => {
|
|
|
22
22
|
it('nest', () => {
|
|
23
23
|
assert.deepStrictEqual(inspect(parser('あ(A)'), ctx), [['あ', '(', 'A', ')'], '']);
|
|
24
24
|
assert.deepStrictEqual(inspect(parser('あ(い)'), ctx), [['あ', '<span class="paren">(い)</span>'], '']);
|
|
25
|
-
assert.deepStrictEqual(inspect(parser('* a*'), ctx), [['*
|
|
25
|
+
assert.deepStrictEqual(inspect(parser('* a*'), ctx), [['* a', '*'], '']);
|
|
26
26
|
assert.deepStrictEqual(inspect(parser('** a**'), ctx), [['**', ' a', '**'], '']);
|
|
27
27
|
assert.deepStrictEqual(inspect(parser('*** a***'), ctx), [['***', ' a', '***'], '']);
|
|
28
28
|
assert.deepStrictEqual(inspect(parser('**** a****'), ctx), [['****', ' a', '****'], '']);
|
|
@@ -82,19 +82,19 @@ describe('Unit: parser/inline', () => {
|
|
|
82
82
|
assert.deepStrictEqual(inspect(parser('*++ a ++*'), ctx), [['<em><ins> a </ins></em>'], '']);
|
|
83
83
|
assert.deepStrictEqual(inspect(parser('*++ a ++*'), ctx), [['<em><ins> a </ins></em>'], '']);
|
|
84
84
|
assert.deepStrictEqual(inspect(parser('*<bdi>`a`</bdi>*'), ctx), [['<em><bdi><code data-src="`a`">a</code></bdi></em>'], '']);
|
|
85
|
-
assert.deepStrictEqual(inspect(parser('*a"\nb*'), ctx), [['
|
|
85
|
+
assert.deepStrictEqual(inspect(parser('*a"\nb*'), ctx), [['<em>a"<br>b</em>'], '']);
|
|
86
86
|
assert.deepStrictEqual(inspect(parser('*a"\n"("b*'), ctx), [['<em>a"<br>"("b</em>'], '']);
|
|
87
|
-
assert.deepStrictEqual(inspect(parser('"*a\nb*'), ctx), [['"', '
|
|
88
|
-
assert.deepStrictEqual(inspect(parser('"*a\n""b*'), ctx), [['"', '
|
|
87
|
+
assert.deepStrictEqual(inspect(parser('"*a\nb*'), ctx), [['"', '*', 'a', '<br>', 'b', '*'], '']);
|
|
88
|
+
assert.deepStrictEqual(inspect(parser('"*a\n""b*'), ctx), [['"', '*', 'a', '<br>', '"', '"', 'b', '*'], '']);
|
|
89
89
|
assert.deepStrictEqual(inspect(parser('"a\n"*b"c*'), ctx), [['"', 'a', '<br>', '"', '*', 'b', '"', 'c', '*'], '']);
|
|
90
|
-
assert.deepStrictEqual(inspect(parser('"*a**b\nc**"("*'), ctx), [['"', '
|
|
91
|
-
assert.deepStrictEqual(inspect(parser('
|
|
92
|
-
assert.deepStrictEqual(inspect(parser('"<bdi>"a\n""b</bdi>"'), ctx), [['"', '<bdi>"a<br>""b</bdi>', '"'], '']);
|
|
90
|
+
assert.deepStrictEqual(inspect(parser('"*a**b\nc**"("*'), ctx), [['"', '*', 'a', '**', 'b', '<br>', 'c', '**', '"', '(', '"', '*'], '']);
|
|
91
|
+
assert.deepStrictEqual(inspect(parser('[% a"\nb %]'), ctx), [['<span class="remark"><input type="checkbox"><span>[% a"<br>b %]</span></span>'], '']);
|
|
92
|
+
assert.deepStrictEqual(inspect(parser('"<bdi>"a\n""b</bdi>"'), ctx), [['"', '<span class="invalid"><bdi></span>', '"', 'a', '<br>', '"', '"', 'b', '</bdi', '>', '"'], '']);
|
|
93
93
|
assert.deepStrictEqual(inspect(parser('<bdi>*<bdi>a</bdi>*</bdi>'), ctx), [['<bdi><em><bdi>a</bdi></em></bdi>'], '']);
|
|
94
94
|
assert.deepStrictEqual(inspect(parser('<bdi>((<bdi>((a))</bdi>))</bdi>'), ctx), [['<bdi><sup class="annotation"><span><bdi><span class="paren">((a))</span></bdi></span></sup></bdi>'], '']);
|
|
95
95
|
assert.deepStrictEqual(inspect(parser('<bdi>[[<bdi>[[a]]</bdi>]]</bdi>'), ctx), [['<bdi><sup class="reference"><span><bdi>[[a]]</bdi></span></sup></bdi>'], '']);
|
|
96
|
-
assert.deepStrictEqual(inspect(parser('<bdi>[#</bdi>]'), ctx), [['<bdi
|
|
97
|
-
assert.deepStrictEqual(inspect(parser('"<bdi>("")</bdi>'), ctx), [['"', '<
|
|
96
|
+
assert.deepStrictEqual(inspect(parser('<bdi>[#</bdi>]'), ctx), [['<span class="invalid"><bdi>[#</bdi>]</span>'], '']);
|
|
97
|
+
assert.deepStrictEqual(inspect(parser('"<bdi>("")</bdi>'), ctx), [['"', '<span class="invalid"><bdi>(</span>', '"', '"', ')', '</bdi', '>'], '']);
|
|
98
98
|
assert.deepStrictEqual(inspect(parser('++\na\n++\n~~\nb\n~~\nc'), ctx), [['<ins><br>a</ins>', '<br>', '<del><br>b</del>', '<br>', 'c'], '']);
|
|
99
99
|
assert.deepStrictEqual(inspect(parser('[@a]'), ctx), [['[', '<a class="account" href="/@a">@a</a>', ']'], '']);
|
|
100
100
|
assert.deepStrictEqual(inspect(parser('[#1][#2]'), ctx), [['<a class="index" href="#index::1">1</a>', '<a class="index" href="#index::2">2</a>'], '']);
|
|
@@ -121,11 +121,11 @@ describe('Unit: parser/inline', () => {
|
|
|
121
121
|
assert.deepStrictEqual(inspect(parser('{}'), ctx), [['{', '}'], '']);
|
|
122
122
|
assert.deepStrictEqual(inspect(parser('{a}'), ctx), [['<a class="url" href="a">a</a>'], '']);
|
|
123
123
|
assert.deepStrictEqual(inspect(parser('{{a}}'), ctx), [['<span class="template">{{a}}</span>'], '']);
|
|
124
|
-
assert.deepStrictEqual(inspect(parser('
|
|
125
|
-
assert.deepStrictEqual(inspect(parser('
|
|
126
|
-
assert.deepStrictEqual(inspect(parser('
|
|
127
|
-
assert.deepStrictEqual(inspect(parser('
|
|
128
|
-
assert.deepStrictEqual(inspect(parser('
|
|
124
|
+
assert.deepStrictEqual(inspect(parser('!{}'), ctx), [['!', '{', '}'], '']);
|
|
125
|
+
assert.deepStrictEqual(inspect(parser('!{a}'), ctx), [['!', '<a class="url" href="a">a</a>'], '']);
|
|
126
|
+
assert.deepStrictEqual(inspect(parser('!{{a}}'), ctx), [['!', '<span class="template">{{a}}</span>'], '']);
|
|
127
|
+
assert.deepStrictEqual(inspect(parser('!{{{a}}}'), ctx), [['!', '<span class="template">{{{a}}}</span>'], '']);
|
|
128
|
+
assert.deepStrictEqual(inspect(parser('!!{a}'), ctx), [['!', '!', '<a class="url" href="a">a</a>'], '']);
|
|
129
129
|
assert.deepStrictEqual(inspect(parser('${a}'), ctx), [['$', '<a class="url" href="a">a</a>'], '']);
|
|
130
130
|
assert.deepStrictEqual(inspect(parser('${{a}}'), ctx), [['$', '<span class="template">{{a}}</span>'], '']);
|
|
131
131
|
assert.deepStrictEqual(inspect(parser('${{{a}}}'), ctx), [['$', '<span class="template">{{{a}}}</span>'], '']);
|
|
@@ -165,16 +165,16 @@ describe('Unit: parser/inline', () => {
|
|
|
165
165
|
assert.deepStrictEqual(inspect(parser('"[% *"*"*'), ctx), [['"', '[%', ' ', '*', '"', '*', '"', '*'], '']);
|
|
166
166
|
assert.deepStrictEqual(inspect(parser('"[% "*"* %]'), ctx), [['"', '<span class="remark"><input type="checkbox"><span>[% "*"* %]</span></span>'], '']);
|
|
167
167
|
assert.deepStrictEqual(inspect(parser('"{{""}}'), ctx), [['"', '{', '{', '"', '"', '}', '}'], '']);
|
|
168
|
-
assert.deepStrictEqual(inspect(parser('[#http://host/(<bdi>)]</bdi>'), ctx), [['<a class="index" href="#index::http://host/(<bdi>)">http://host/(<bdi>)</a>', '
|
|
169
|
-
assert.deepStrictEqual(inspect(parser('[#@a/http://host/(<bdi>)]</bdi>'), ctx), [['<a class="index" href="#index::@a/http://host/(<bdi>)">@a/http://host/(<bdi>)</a>', '
|
|
170
|
-
assert.deepStrictEqual(inspect(parser('[#a|<bdi>]</bdi>'), ctx), [['
|
|
171
|
-
assert.deepStrictEqual(inspect(parser('[[#a|<bdi>]</bdi>'), ctx), [['[', '
|
|
168
|
+
assert.deepStrictEqual(inspect(parser('[#http://host/(<bdi>)]</bdi>'), ctx), [['<a class="index" href="#index::http://host/(<bdi>)">http://host/(<bdi>)</a>', '</bdi', '>'], '']);
|
|
169
|
+
assert.deepStrictEqual(inspect(parser('[#@a/http://host/(<bdi>)]</bdi>'), ctx), [['<a class="index" href="#index::@a/http://host/(<bdi>)">@a/http://host/(<bdi>)</a>', '</bdi', '>'], '']);
|
|
170
|
+
assert.deepStrictEqual(inspect(parser('[#a|<bdi>]</bdi>'), ctx), [['<a class="index" href="#index::a|<bdi>">a|<span class="invalid"><bdi></span></a>', '</bdi', '>'], '']);
|
|
171
|
+
assert.deepStrictEqual(inspect(parser('[[#a|<bdi>]</bdi>'), ctx), [['[', '<a class="index" href="#index::a|<bdi>">a|<span class="invalid"><bdi></span></a>', '</bdi', '>'], '']);
|
|
172
172
|
});
|
|
173
173
|
|
|
174
174
|
it('uri', () => {
|
|
175
175
|
assert.deepStrictEqual(inspect(parser('\nhttp://host'), ctx), [['<br>', '<a class="url" href="http://host" target="_blank">http://host</a>'], '']);
|
|
176
|
-
assert.deepStrictEqual(inspect(parser('0http://host'), ctx), [['0http:', '
|
|
177
|
-
assert.deepStrictEqual(inspect(parser('0aAhttp://host'), ctx), [['0aAhttp:', '
|
|
176
|
+
assert.deepStrictEqual(inspect(parser('0http://host'), ctx), [['0http:', '//host'], '']);
|
|
177
|
+
assert.deepStrictEqual(inspect(parser('0aAhttp://host'), ctx), [['0aAhttp:', '//host'], '']);
|
|
178
178
|
assert.deepStrictEqual(inspect(parser('?http://host'), ctx), [['?', '<a class="url" href="http://host" target="_blank">http://host</a>'], '']);
|
|
179
179
|
assert.deepStrictEqual(inspect(parser('0!http://host'), ctx), [['0', '!', '<a class="url" href="http://host" target="_blank">http://host</a>'], '']);
|
|
180
180
|
assert.deepStrictEqual(inspect(parser('0?http://host'), ctx), [['0', '?', '<a class="url" href="http://host" target="_blank">http://host</a>'], '']);
|
|
@@ -196,7 +196,8 @@ describe('Unit: parser/inline', () => {
|
|
|
196
196
|
assert.deepStrictEqual(inspect(parser('*a@b*'), ctx), [['<em><a class="email" href="mailto:a@b">a@b</a></em>'], '']);
|
|
197
197
|
assert.deepStrictEqual(inspect(parser('(a@b)'), ctx), [['<span class="paren">(<a class="email" href="mailto:a@b">a@b</a>)</span>'], '']);
|
|
198
198
|
assert.deepStrictEqual(inspect(parser(' a@b'), ctx), [[' ', '<a class="email" href="mailto:a@b">a@b</a>'], '']);
|
|
199
|
-
assert.deepStrictEqual(inspect(parser('++a
|
|
199
|
+
assert.deepStrictEqual(inspect(parser('++a@b++'), ctx), [['<ins><a class="email" href="mailto:a@b">a@b</a></ins>'], '']);
|
|
200
|
+
assert.deepStrictEqual(inspect(parser('++a++b@c++'), ctx), [['<ins>a</ins>', '<a class="email" href="mailto:b@c">b@c</a>', '++'], '']);
|
|
200
201
|
});
|
|
201
202
|
|
|
202
203
|
it('channel', () => {
|
|
@@ -209,7 +210,7 @@ describe('Unit: parser/inline', () => {
|
|
|
209
210
|
|
|
210
211
|
it('account', () => {
|
|
211
212
|
assert.deepStrictEqual(inspect(parser('@a'), ctx), [['<a class="account" href="/@a">@a</a>'], '']);
|
|
212
|
-
assert.deepStrictEqual(inspect(parser('@http://host'), ctx), [['@http', '
|
|
213
|
+
assert.deepStrictEqual(inspect(parser('@http://host'), ctx), [['@http', '://host'], '']);
|
|
213
214
|
assert.deepStrictEqual(inspect(parser('_@a'), ctx), [['_', '<a class="account" href="/@a">@a</a>'], '']);
|
|
214
215
|
assert.deepStrictEqual(inspect(parser('_@a_'), ctx), [['_', '<a class="account" href="/@a">@a</a>', '_'], '']);
|
|
215
216
|
assert.deepStrictEqual(inspect(parser('*@a*'), ctx), [['<em><a class="account" href="/@a">@a</a></em>'], '']);
|
|
@@ -221,7 +222,7 @@ describe('Unit: parser/inline', () => {
|
|
|
221
222
|
assert.deepStrictEqual(inspect(parser('#a#'), ctx), [['#a', '#'], '']);
|
|
222
223
|
assert.deepStrictEqual(inspect(parser('#a#b'), ctx), [['#a', '#b'], '']);
|
|
223
224
|
assert.deepStrictEqual(inspect(parser('#a'), ctx), [['<a class="hashtag" href="/hashtags/a">#a</a>'], '']);
|
|
224
|
-
assert.deepStrictEqual(inspect(parser('#http://host'), ctx), [['#http', '
|
|
225
|
+
assert.deepStrictEqual(inspect(parser('#http://host'), ctx), [['#http', '://host'], '']);
|
|
225
226
|
assert.deepStrictEqual(inspect(parser('#a\nb\n#c\n[#d]'), ctx), [['<a class="hashtag" href="/hashtags/a">#a</a>', '<br>', 'b', '<br>', '<a class="hashtag" href="/hashtags/c">#c</a>', '<br>', '<a class="index" href="#index::d">d</a>'], '']);
|
|
226
227
|
assert.deepStrictEqual(inspect(parser('##a'), ctx), [['##a'], '']);
|
|
227
228
|
assert.deepStrictEqual(inspect(parser('_#a'), ctx), [['_', '<a class="hashtag" href="/hashtags/a">#a</a>'], '']);
|