securemark 0.283.2 → 0.283.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 +4 -0
- package/dist/index.js +86 -48
- package/package.json +1 -1
- package/src/combinator/control/manipulation/indent.ts +1 -1
- package/src/combinator/data/parser/context/delimiter.ts +28 -3
- package/src/combinator/data/parser/context.ts +5 -2
- package/src/parser/block/dlist.ts +1 -1
- package/src/parser/context.ts +2 -2
- package/src/parser/inline/annotation.ts +2 -2
- package/src/parser/inline/autolink/url.ts +2 -2
- package/src/parser/inline/autolink.ts +1 -1
- package/src/parser/inline/bracket.ts +17 -14
- package/src/parser/inline/code.ts +1 -1
- package/src/parser/inline/deletion.ts +1 -1
- package/src/parser/inline/emphasis.test.ts +2 -2
- package/src/parser/inline/emphasis.ts +3 -3
- package/src/parser/inline/emstrong.ts +7 -7
- package/src/parser/inline/extension/index.ts +3 -3
- package/src/parser/inline/extension/indexee.ts +4 -2
- package/src/parser/inline/extension/placeholder.ts +2 -2
- package/src/parser/inline/html.ts +4 -4
- package/src/parser/inline/htmlentity.ts +5 -5
- package/src/parser/inline/insertion.ts +1 -1
- package/src/parser/inline/link.ts +4 -4
- package/src/parser/inline/mark.test.ts +2 -2
- package/src/parser/inline/mark.ts +3 -3
- package/src/parser/inline/math.ts +2 -2
- package/src/parser/inline/media.ts +2 -2
- package/src/parser/inline/reference.ts +2 -2
- package/src/parser/inline/remark.ts +2 -2
- package/src/parser/inline/ruby.ts +2 -2
- package/src/parser/inline/strong.test.ts +2 -2
- package/src/parser/inline/strong.ts +3 -3
- package/src/parser/inline/template.ts +2 -2
- package/src/parser/inline.test.ts +4 -2
- package/src/parser/visibility.ts +4 -4
|
@@ -33,7 +33,7 @@ const desc: DListParser.DescriptionParser = block(fmap(open(
|
|
|
33
33
|
false);
|
|
34
34
|
|
|
35
35
|
function fillTrailingDescription(es: HTMLElement[]): HTMLElement[] {
|
|
36
|
-
return es.length > 0 && es
|
|
36
|
+
return es.length > 0 && es.at(-1)!.tagName === 'DT'
|
|
37
37
|
? push(es, [html('dd')])
|
|
38
38
|
: es;
|
|
39
39
|
}
|
package/src/parser/context.ts
CHANGED
|
@@ -8,8 +8,8 @@ import { html, defrag } from 'typed-dom/dom';
|
|
|
8
8
|
export const annotation: AnnotationParser = lazy(() => creation(1, Recursion.ignore, surround(
|
|
9
9
|
'((',
|
|
10
10
|
constraint(State.annotation, false,
|
|
11
|
-
syntax(
|
|
12
|
-
trimBlankStart(some(union([inline]), ')', [[/^\\?\n/, 9], [')',
|
|
11
|
+
syntax(1, State.annotation | State.media,
|
|
12
|
+
trimBlankStart(some(union([inline]), ')', [[/^\\?\n/, 9], [')', 1]])))),
|
|
13
13
|
'))',
|
|
14
14
|
false,
|
|
15
15
|
([, ns], rest) => [[html('sup', { class: 'annotation' }, [html('span', trimNodeEnd(defrag(ns)))])], rest],
|
|
@@ -25,9 +25,9 @@ export const lineurl: AutolinkParser.UrlParser.LineUrlParser = lazy(() => open(
|
|
|
25
25
|
unsafelink)),
|
|
26
26
|
])));
|
|
27
27
|
|
|
28
|
-
const bracket: AutolinkParser.UrlParser.BracketParser = lazy(() => creation(0, Recursion.terminal, precedence(
|
|
28
|
+
const bracket: AutolinkParser.UrlParser.BracketParser = lazy(() => creation(0, Recursion.terminal, precedence(1, union([
|
|
29
29
|
surround(str('('), some(union([bracket, unescsource]), ')'), str(')'), true, undefined, undefined, 3 | Backtrack.url),
|
|
30
30
|
surround(str('['), some(union([bracket, unescsource]), ']'), str(']'), true, undefined, undefined, 3 | Backtrack.url),
|
|
31
31
|
surround(str('{'), some(union([bracket, unescsource]), '}'), str('}'), true, undefined, undefined, 3 | Backtrack.url),
|
|
32
|
-
surround(str('"'), precedence(
|
|
32
|
+
surround(str('"'), precedence(2, some(unescsource, '"')), str('"'), true, undefined, undefined, 3 | Backtrack.url),
|
|
33
33
|
]))));
|
|
@@ -14,7 +14,7 @@ import { stringify } from '../util';
|
|
|
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(0, ~State.shortcut,
|
|
18
18
|
union([
|
|
19
19
|
some(union([lineurl])),
|
|
20
20
|
fmap(some(union([
|
|
@@ -6,42 +6,45 @@ import { State, Recursion, Backtrack } from '../context';
|
|
|
6
6
|
import { unshift, push } from 'spica/array';
|
|
7
7
|
import { html, defrag } from 'typed-dom/dom';
|
|
8
8
|
|
|
9
|
-
const
|
|
9
|
+
const indexA = /^[0-9A-Za-z]+(?:(?:[.-]|, )[0-9A-Za-z]+)*/;
|
|
10
|
+
const indexF = new RegExp(indexA.source.replace(', ', '[,、]')
|
|
11
|
+
.replace(/[09AZaz.]|\-(?!\w)/g, c => String.fromCodePoint(c.codePointAt(0)! + 0xFEE0)));
|
|
10
12
|
|
|
11
13
|
export const bracket: BracketParser = lazy(() => union([
|
|
12
|
-
surround(str('('), creation(0, Recursion.bracket, syntax(
|
|
13
|
-
surround(str('('), creation(0, Recursion.bracket, syntax(
|
|
14
|
+
surround(str('('), creation(0, Recursion.bracket, syntax(1, State.none, str(indexA))), str(')')),
|
|
15
|
+
surround(str('('), creation(0, Recursion.bracket, syntax(1, State.none, some(inline, ')', [[')', 1]]))), str(')'), true,
|
|
14
16
|
([as, bs = [], cs], rest) => [[html('span', { class: 'paren' }, defrag(push(unshift(as, bs), cs)))], rest],
|
|
15
17
|
([as, bs = []], rest) => [unshift(as, bs), rest], 3 | Backtrack.bracket),
|
|
16
|
-
surround(str('('), creation(0, Recursion.bracket, syntax(
|
|
17
|
-
surround(str('('), creation(0, Recursion.bracket, syntax(
|
|
18
|
+
surround(str('('), creation(0, Recursion.bracket, syntax(1, State.none, str(indexF))), str(')')),
|
|
19
|
+
surround(str('('), creation(0, Recursion.bracket, syntax(1, State.none, some(inline, ')', [[')', 1]]))), str(')'), true,
|
|
18
20
|
([as, bs = [], cs], rest) => [[html('span', { class: 'paren' }, defrag(push(unshift(as, bs), cs)))], rest],
|
|
19
21
|
([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
20
|
-
surround(str('['), creation(0, Recursion.bracket, syntax(
|
|
22
|
+
surround(str('['), creation(0, Recursion.bracket, syntax(1, State.none, some(inline, ']', [[']', 1]]))), str(']'), true,
|
|
21
23
|
undefined,
|
|
22
24
|
([as, bs = []], rest) => [unshift(as, bs), rest], 3 | Backtrack.bracket),
|
|
23
|
-
surround(str('['), creation(0, Recursion.bracket, syntax(
|
|
25
|
+
surround(str('['), creation(0, Recursion.bracket, syntax(1, State.none, some(inline, ']', [[']', 1]]))), str(']'), true,
|
|
24
26
|
undefined,
|
|
25
27
|
([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
26
|
-
surround(str('{'), creation(0, Recursion.bracket, syntax(
|
|
28
|
+
surround(str('{'), creation(0, Recursion.bracket, syntax(1, State.none, some(inline, '}', [['}', 1]]))), str('}'), true,
|
|
27
29
|
undefined,
|
|
28
30
|
([as, bs = []], rest) => [unshift(as, bs), rest], 3 | Backtrack.bracket),
|
|
29
|
-
surround(str('{'), creation(0, Recursion.bracket, syntax(
|
|
31
|
+
surround(str('{'), creation(0, Recursion.bracket, syntax(1, State.none, some(inline, '}', [['}', 1]]))), str('}'), true,
|
|
30
32
|
undefined,
|
|
31
33
|
([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
32
|
-
|
|
34
|
+
// 改行禁止はバックトラックなしでは内側の構文を破壊するため安易に行えない。
|
|
35
|
+
surround(str('"'), creation(0, Recursion.bracket, syntax(2, State.none, some(inline, '"', [[/^\\?\n/, 9], ['"', 2]]))), str('"'), true,
|
|
33
36
|
undefined,
|
|
34
37
|
([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
35
|
-
surround(str('“'), creation(0, Recursion.bracket, syntax(
|
|
38
|
+
surround(str('“'), creation(0, Recursion.bracket, syntax(2, State.none, some(inline, '”', [[/^\\?\n/, 9], ['”', 2]]))), str('”'), true,
|
|
36
39
|
undefined,
|
|
37
40
|
([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
38
|
-
surround(str('‘'), creation(0, Recursion.bracket, syntax(
|
|
41
|
+
surround(str('‘'), creation(0, Recursion.bracket, syntax(2, State.none, some(inline, '’', [[/^\\?\n/, 9], ['’', 2]]))), str('’'), true,
|
|
39
42
|
undefined,
|
|
40
43
|
([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
41
|
-
surround(str('「'), creation(0, Recursion.bracket, syntax(
|
|
44
|
+
surround(str('「'), creation(0, Recursion.bracket, syntax(2, State.none, some(inline, '」', [[/^\\?\n/, 9], ['」', 2]]))), str('」'), true,
|
|
42
45
|
undefined,
|
|
43
46
|
([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
44
|
-
surround(str('『'), creation(0, Recursion.bracket, syntax(
|
|
47
|
+
surround(str('『'), creation(0, Recursion.bracket, syntax(2, State.none, some(inline, '』', [[/^\\?\n/, 9], ['』', 2]]))), str('』'), true,
|
|
45
48
|
undefined,
|
|
46
49
|
([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
47
50
|
]));
|
|
@@ -10,7 +10,7 @@ export const code: CodeParser = creation(1, Recursion.ignore, validate('`', matc
|
|
|
10
10
|
|
|
11
11
|
function format(text: string): string {
|
|
12
12
|
assert(text.length > 0);
|
|
13
|
-
return `${text[0]}${text
|
|
13
|
+
return `${text[0]}${text.at(-1)}` === ' '
|
|
14
14
|
&& text.trimStart()
|
|
15
15
|
? text.slice(1, -1)
|
|
16
16
|
: text;
|
|
@@ -9,7 +9,7 @@ import { html, defrag } from 'typed-dom/dom';
|
|
|
9
9
|
|
|
10
10
|
export const deletion: DeletionParser = lazy(() => creation(1, Recursion.inline, surround(
|
|
11
11
|
str('~~', '~'),
|
|
12
|
-
syntax(
|
|
12
|
+
syntax(0, State.none,
|
|
13
13
|
some(union([
|
|
14
14
|
some(inline, blankWith('\n', '~~')),
|
|
15
15
|
open('\n', some(inline, '~'), true),
|
|
@@ -12,10 +12,8 @@ describe('Unit: parser/inline/emphasis', () => {
|
|
|
12
12
|
assert.deepStrictEqual(inspect(parser('*a *')), [['*', 'a'], ' *']);
|
|
13
13
|
assert.deepStrictEqual(inspect(parser('*a *')), [['*', 'a', ' '], ' *']);
|
|
14
14
|
assert.deepStrictEqual(inspect(parser('*a\n*')), [['*', 'a'], '\n*']);
|
|
15
|
-
assert.deepStrictEqual(inspect(parser('*a\nb*')), [['*', 'a'], '\nb*']);
|
|
16
15
|
assert.deepStrictEqual(inspect(parser('*a\\ *')), [['*', 'a'], '\\ *']);
|
|
17
16
|
assert.deepStrictEqual(inspect(parser('*a\\\n*')), [['*', 'a'], '\\\n*']);
|
|
18
|
-
assert.deepStrictEqual(inspect(parser('*a\\\nb*')), [['*', 'a'], '\\\nb*']);
|
|
19
17
|
assert.deepStrictEqual(inspect(parser('*a**b')), [['*', 'a', '**', 'b'], '']);
|
|
20
18
|
assert.deepStrictEqual(inspect(parser('*a**b*')), [['*', 'a', '**', 'b', '*'], '']);
|
|
21
19
|
assert.deepStrictEqual(inspect(parser('* *')), undefined);
|
|
@@ -35,6 +33,8 @@ describe('Unit: parser/inline/emphasis', () => {
|
|
|
35
33
|
assert.deepStrictEqual(inspect(parser('*a*')), [['<em>a</em>'], '']);
|
|
36
34
|
assert.deepStrictEqual(inspect(parser('*ab*')), [['<em>ab</em>'], '']);
|
|
37
35
|
assert.deepStrictEqual(inspect(parser('*a**')), [['<em>a</em>'], '*']);
|
|
36
|
+
assert.deepStrictEqual(inspect(parser('*a\nb*')), [['<em>a<br>b</em>'], '']);
|
|
37
|
+
assert.deepStrictEqual(inspect(parser('*a\\\nb*')), [['<em>a<br>b</em>'], '']);
|
|
38
38
|
});
|
|
39
39
|
|
|
40
40
|
it('nest', () => {
|
|
@@ -11,11 +11,11 @@ import { html, defrag } from 'typed-dom/dom';
|
|
|
11
11
|
|
|
12
12
|
export const emphasis: EmphasisParser = lazy(() => creation(1, Recursion.inline, surround(
|
|
13
13
|
str('*', '*'),
|
|
14
|
-
syntax(
|
|
14
|
+
syntax(0, State.none,
|
|
15
15
|
startTight(some(union([
|
|
16
16
|
strong,
|
|
17
|
-
some(inline, blankWith('*')
|
|
18
|
-
open(some(inline, '*'
|
|
17
|
+
some(inline, blankWith('*')),
|
|
18
|
+
open(some(inline, '*'), union([
|
|
19
19
|
emstrong,
|
|
20
20
|
strong,
|
|
21
21
|
emphasis,
|
|
@@ -11,16 +11,16 @@ import { html, defrag } from 'typed-dom/dom';
|
|
|
11
11
|
import { unshift } from 'spica/array';
|
|
12
12
|
|
|
13
13
|
const substrong: IntermediateParser<StrongParser> = lazy(() => some(union([
|
|
14
|
-
some(inline, blankWith('**')
|
|
15
|
-
open(some(inline, '*'
|
|
14
|
+
some(inline, blankWith('**')),
|
|
15
|
+
open(some(inline, '*'), union([
|
|
16
16
|
emstrong,
|
|
17
17
|
strong,
|
|
18
18
|
])),
|
|
19
19
|
])));
|
|
20
20
|
const subemphasis: IntermediateParser<EmphasisParser> = lazy(() => some(union([
|
|
21
21
|
strong,
|
|
22
|
-
some(inline, blankWith('*')
|
|
23
|
-
open(some(inline, '*'
|
|
22
|
+
some(inline, blankWith('*')),
|
|
23
|
+
open(some(inline, '*'), union([
|
|
24
24
|
emstrong,
|
|
25
25
|
strong,
|
|
26
26
|
emphasis,
|
|
@@ -29,10 +29,10 @@ const subemphasis: IntermediateParser<EmphasisParser> = lazy(() => some(union([
|
|
|
29
29
|
|
|
30
30
|
export const emstrong: EmStrongParser = lazy(() => creation(1, Recursion.inline, surround(
|
|
31
31
|
str('***'),
|
|
32
|
-
syntax(
|
|
32
|
+
syntax(0, State.none,
|
|
33
33
|
startTight(some(union([
|
|
34
|
-
some(inline, blankWith('*')
|
|
35
|
-
open(some(inline, '*'
|
|
34
|
+
some(inline, blankWith('*')),
|
|
35
|
+
open(some(inline, '*'), inline),
|
|
36
36
|
])))),
|
|
37
37
|
str(/^\*{1,3}/), false,
|
|
38
38
|
([, bs, cs], rest, context): Result<HTMLElement | string, typeof context> => {
|
|
@@ -12,12 +12,12 @@ import IndexParser = ExtensionParser.IndexParser;
|
|
|
12
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(1, State.linkers | State.media,
|
|
16
16
|
startTight(
|
|
17
17
|
some(inits([
|
|
18
18
|
inline,
|
|
19
19
|
signature,
|
|
20
|
-
]), ']', [[/^\\?\n/, 9], [']',
|
|
20
|
+
]), ']', [[/^\\?\n/, 9], [']', 1]])))),
|
|
21
21
|
']',
|
|
22
22
|
false,
|
|
23
23
|
([, ns], rest) => [[html('a', { 'data-index': dataindex(ns) }, trimNodeEnd(defrag(ns)))], rest],
|
|
@@ -42,7 +42,7 @@ const bracket: IndexParser.SignatureParser.BracketParser = lazy(() => creation(0
|
|
|
42
42
|
surround(str('('), some(union([bracket, txt]), ')'), str(')'), true, undefined, undefined, 3 | Backtrack.index),
|
|
43
43
|
surround(str('['), some(union([bracket, txt]), ']'), str(']'), true, undefined, undefined, 3 | Backtrack.index),
|
|
44
44
|
surround(str('{'), some(union([bracket, txt]), '}'), str('}'), true, undefined, undefined, 3 | Backtrack.index),
|
|
45
|
-
surround(str('"'), precedence(
|
|
45
|
+
surround(str('"'), precedence(2, some(txt, '"')), str('"'), true, undefined, undefined, 3 | Backtrack.index),
|
|
46
46
|
])));
|
|
47
47
|
|
|
48
48
|
export function dataindex(ns: readonly (string | HTMLElement)[]): string | undefined {
|
|
@@ -105,7 +105,7 @@ assert(baseR(61, 62) === 'Z');
|
|
|
105
105
|
assert(baseR(62, 62) === '10');
|
|
106
106
|
|
|
107
107
|
export function signature(source: Element | DocumentFragment): string {
|
|
108
|
-
assert(!navigator.userAgent.includes('Chrome') || !source.querySelector('br:not(:has(+ :is(ul, ol)))'));
|
|
108
|
+
assert(!navigator.userAgent.includes('Chrome') || !source.querySelector('br:not(:has(+ :is(ul, ol)))') || source.nodeName === 'MARK');
|
|
109
109
|
const target = source.cloneNode(true) as typeof source;
|
|
110
110
|
for (let es = target.querySelectorAll('code[data-src], .math[data-src], .label[data-label], .remark, rt, rp, br, .annotation, .reference, .checkbox, ul, ol'),
|
|
111
111
|
len = es.length, i = 0; i < len; ++i) {
|
|
@@ -116,11 +116,13 @@ export function signature(source: Element | DocumentFragment): string {
|
|
|
116
116
|
continue;
|
|
117
117
|
case 'RT':
|
|
118
118
|
case 'RP':
|
|
119
|
-
case 'BR':
|
|
120
119
|
case 'UL':
|
|
121
120
|
case 'OL':
|
|
122
121
|
el.remove();
|
|
123
122
|
continue;
|
|
123
|
+
case 'BR':
|
|
124
|
+
el.replaceWith('\n');
|
|
125
|
+
continue;
|
|
124
126
|
}
|
|
125
127
|
switch (el.className) {
|
|
126
128
|
case 'math':
|
|
@@ -13,8 +13,8 @@ import { html, defrag } from 'typed-dom/dom';
|
|
|
13
13
|
|
|
14
14
|
export const placeholder: ExtensionParser.PlaceholderParser = lazy(() => validate('[', creation(1, Recursion.inline, surround(
|
|
15
15
|
str(/^\[[:^|]/),
|
|
16
|
-
syntax(
|
|
17
|
-
startTight(some(union([inline]), ']', [[']',
|
|
16
|
+
syntax(1, State.none,
|
|
17
|
+
startTight(some(union([inline]), ']', [[']', 1]]))),
|
|
18
18
|
str(']'), false,
|
|
19
19
|
([, bs], rest) => [[
|
|
20
20
|
html('span', {
|
|
@@ -18,7 +18,7 @@ const attrspecs = {
|
|
|
18
18
|
Object.setPrototypeOf(attrspecs, null);
|
|
19
19
|
Object.values(attrspecs).forEach(o => Object.setPrototypeOf(o, null));
|
|
20
20
|
|
|
21
|
-
export const html: HTMLParser = lazy(() => validate('<', validate(/^<[a-z]+(?=[^\S\n]|>)/i, creation(1, Recursion.inline, syntax(
|
|
21
|
+
export const html: HTMLParser = lazy(() => validate('<', validate(/^<[a-z]+(?=[^\S\n]|>)/i, creation(1, Recursion.inline, syntax(3, State.none, union([
|
|
22
22
|
focus(
|
|
23
23
|
/^<wbr[^\S\n]*>/i,
|
|
24
24
|
() => [[h('wbr')], '']),
|
|
@@ -35,7 +35,7 @@ export const html: HTMLParser = lazy(() => validate('<', validate(/^<[a-z]+(?=[^
|
|
|
35
35
|
str(`<${tag}`), some(attribute), str(/^[^\S\n]*>/), true),
|
|
36
36
|
subsequence([
|
|
37
37
|
focus(/^[^\S\n]*\n/, some(inline)),
|
|
38
|
-
some(open(/^\n?/, some(inline, blankWith('\n', `</${tag}>`), [[blankWith('\n', `</${tag}>`),
|
|
38
|
+
some(open(/^\n?/, some(inline, blankWith('\n', `</${tag}>`), [[blankWith('\n', `</${tag}>`), 3]]), true)),
|
|
39
39
|
]),
|
|
40
40
|
str(`</${tag}>`), true,
|
|
41
41
|
([as, bs = [], cs], rest) =>
|
|
@@ -50,7 +50,7 @@ export const html: HTMLParser = lazy(() => validate('<', validate(/^<[a-z]+(?=[^
|
|
|
50
50
|
str(`<${tag}`), some(attribute), str(/^[^\S\n]*>/), true),
|
|
51
51
|
subsequence([
|
|
52
52
|
focus(/^[^\S\n]*\n/, some(inline)),
|
|
53
|
-
some(inline, `</${tag}>`, [[`</${tag}>`,
|
|
53
|
+
some(inline, `</${tag}>`, [[`</${tag}>`, 3]]),
|
|
54
54
|
]),
|
|
55
55
|
str(`</${tag}>`), true,
|
|
56
56
|
([as, bs = [], cs], rest) =>
|
|
@@ -208,7 +208,7 @@ const TAGS = Object.freeze([
|
|
|
208
208
|
|
|
209
209
|
function elem(tag: string, as: string[], bs: (HTMLElement | string)[], cs: string[]): HTMLElement {
|
|
210
210
|
assert(as.length > 0);
|
|
211
|
-
assert(as[0][0] === '<' && as
|
|
211
|
+
assert(as[0][0] === '<' && as.at(-1)!.slice(-1) === '>');
|
|
212
212
|
if (!tags.includes(tag)) return invalid('tag', `Invalid HTML tag name "${tag}"`, as, bs, cs);
|
|
213
213
|
if (cs.length === 0) return invalid('tag', `Missing the closing HTML tag "</${tag}>"`, as, bs, cs);
|
|
214
214
|
if (bs.length === 0) return invalid('content', `Missing the content`, as, bs, cs);
|
|
@@ -5,20 +5,20 @@ import { html } from 'typed-dom/dom';
|
|
|
5
5
|
import { reduce } from 'spica/memoize';
|
|
6
6
|
|
|
7
7
|
export const unsafehtmlentity: UnsafeHTMLEntityParser = creation(1, Recursion.ignore, validate('&', focus(
|
|
8
|
-
/^&[0-9A-Za-z]
|
|
8
|
+
/^&[0-9A-Za-z]{1,99};/,
|
|
9
9
|
({ source }) => [[parse(source) ?? `\x1B${source}`], ''])));
|
|
10
10
|
|
|
11
11
|
export const htmlentity: HTMLEntityParser = fmap(
|
|
12
12
|
union([unsafehtmlentity]),
|
|
13
|
-
([
|
|
14
|
-
|
|
13
|
+
([text]) => [
|
|
14
|
+
text[0] === '\x1B'
|
|
15
15
|
? html('span', {
|
|
16
16
|
class: 'invalid',
|
|
17
17
|
'data-invalid-syntax': 'htmlentity',
|
|
18
18
|
'data-invalid-type': 'syntax',
|
|
19
19
|
'data-invalid-message': 'Invalid HTML entity',
|
|
20
|
-
},
|
|
21
|
-
:
|
|
20
|
+
}, text.slice(1))
|
|
21
|
+
: text,
|
|
22
22
|
]);
|
|
23
23
|
|
|
24
24
|
const parse = reduce((el => (entity: string): string | undefined => {
|
|
@@ -9,7 +9,7 @@ import { html, defrag } from 'typed-dom/dom';
|
|
|
9
9
|
|
|
10
10
|
export const insertion: InsertionParser = lazy(() => creation(1, Recursion.inline, surround(
|
|
11
11
|
str('++', '+'),
|
|
12
|
-
syntax(
|
|
12
|
+
syntax(0, State.none,
|
|
13
13
|
some(union([
|
|
14
14
|
some(inline, blankWith('\n', '++')),
|
|
15
15
|
open('\n', some(inline, '+'), true),
|
|
@@ -22,11 +22,11 @@ export const link: LinkParser = lazy(() => validate(['[', '{'], union([
|
|
|
22
22
|
|
|
23
23
|
export const textlink: LinkParser.TextLinkParser = lazy(() => creation(1, Recursion.ignore,
|
|
24
24
|
constraint(State.link, false,
|
|
25
|
-
syntax(
|
|
25
|
+
syntax(1, State.linkers | State.media,
|
|
26
26
|
bind(reverse(tails([
|
|
27
27
|
dup(surround(
|
|
28
28
|
'[',
|
|
29
|
-
trimBlankStart(some(union([inline]), ']', [[/^\\?\n/, 9], [']',
|
|
29
|
+
trimBlankStart(some(union([inline]), ']', [[/^\\?\n/, 9], [']', 1]])),
|
|
30
30
|
']',
|
|
31
31
|
true, undefined, undefined, 1 | Backtrack.bracket)),
|
|
32
32
|
dup(surround(
|
|
@@ -44,7 +44,7 @@ export const textlink: LinkParser.TextLinkParser = lazy(() => creation(1, Recurs
|
|
|
44
44
|
|
|
45
45
|
export const medialink: LinkParser.MediaLinkParser = lazy(() => creation(1, Recursion.ignore,
|
|
46
46
|
constraint(State.link | State.media, false,
|
|
47
|
-
syntax(
|
|
47
|
+
syntax(1, State.linkers,
|
|
48
48
|
bind(reverse(sequence([
|
|
49
49
|
dup(surround(
|
|
50
50
|
'[',
|
|
@@ -61,7 +61,7 @@ export const linemedialink: LinkParser.LineMediaLinkParser = surround(
|
|
|
61
61
|
/^(?=[^\S\n]*(?:$|\n))/);
|
|
62
62
|
|
|
63
63
|
export const unsafelink: LinkParser.UnsafeLinkParser = lazy(() =>
|
|
64
|
-
creation(1, Recursion.ignore, precedence(
|
|
64
|
+
creation(1, Recursion.ignore, precedence(1,
|
|
65
65
|
bind(reverse(tails([
|
|
66
66
|
dup(surround(
|
|
67
67
|
'[',
|
|
@@ -15,10 +15,8 @@ describe('Unit: parser/inline/mark', () => {
|
|
|
15
15
|
assert.deepStrictEqual(inspect(parser('==a ==')), [['==', 'a'], ' ==']);
|
|
16
16
|
assert.deepStrictEqual(inspect(parser('==a ==')), [['==', 'a', ' '], ' ==']);
|
|
17
17
|
assert.deepStrictEqual(inspect(parser('==a\n==')), [['==', 'a'], '\n==']);
|
|
18
|
-
assert.deepStrictEqual(inspect(parser('==a\nb==')), [['==', 'a'], '\nb==']);
|
|
19
18
|
assert.deepStrictEqual(inspect(parser('==a\\ ==')), [['==', 'a'], '\\ ==']);
|
|
20
19
|
assert.deepStrictEqual(inspect(parser('==a\\\n==')), [['==', 'a'], '\\\n==']);
|
|
21
|
-
assert.deepStrictEqual(inspect(parser('==a\\\nb==')), [['==', 'a'], '\\\nb==']);
|
|
22
20
|
assert.deepStrictEqual(inspect(parser('== ==')), undefined);
|
|
23
21
|
assert.deepStrictEqual(inspect(parser('== a==')), undefined);
|
|
24
22
|
assert.deepStrictEqual(inspect(parser('== a ==')), undefined);
|
|
@@ -33,6 +31,8 @@ describe('Unit: parser/inline/mark', () => {
|
|
|
33
31
|
assert.deepStrictEqual(inspect(parser('==a=b==')), [['<mark id="mark::a=b=3lYfIw">a=b</mark>', '<a href="#mark::a=b=3lYfIw"></a>'], '']);
|
|
34
32
|
assert.deepStrictEqual(inspect(parser('==\\===')), [['<mark id="mark::=">=</mark>', '<a href="#mark::="></a>'], '']);
|
|
35
33
|
assert.deepStrictEqual(inspect(parser('==a===')), [['<mark id="mark::a">a</mark>', '<a href="#mark::a"></a>'], '=']);
|
|
34
|
+
assert.deepStrictEqual(inspect(parser('==a\nb==')), [['<mark id="mark::a_b=12Ta86">a<br>b</mark>', '<a href="#mark::a_b=12Ta86"></a>'], '']);
|
|
35
|
+
assert.deepStrictEqual(inspect(parser('==a\\\nb==')), [['<mark id="mark::a_b=12Ta86">a<br>b</mark>', '<a href="#mark::a_b=12Ta86"></a>'], '']);
|
|
36
36
|
});
|
|
37
37
|
|
|
38
38
|
it('nest', () => {
|
|
@@ -11,10 +11,10 @@ import { html, define, defrag } from 'typed-dom/dom';
|
|
|
11
11
|
export const mark: MarkParser = lazy(() => creation(1, Recursion.inline, surround(
|
|
12
12
|
str('==', '='),
|
|
13
13
|
constraint(State.mark, false,
|
|
14
|
-
syntax(
|
|
14
|
+
syntax(0, State.none,
|
|
15
15
|
startTight(some(union([
|
|
16
|
-
some(inline, blankWith('==')
|
|
17
|
-
open(some(inline, '='
|
|
16
|
+
some(inline, blankWith('==')),
|
|
17
|
+
open(some(inline, '='), mark),
|
|
18
18
|
]))))),
|
|
19
19
|
str('=='), false,
|
|
20
20
|
([, bs], rest, { id }) => {
|
|
@@ -8,10 +8,10 @@ const forbiddenCommand = /\\(?:begin|tiny|huge|large)(?![a-z])/i;
|
|
|
8
8
|
|
|
9
9
|
export const math: MathParser = lazy(() => validate('$', creation(1, Recursion.ignore, rewrite(
|
|
10
10
|
union([
|
|
11
|
-
surround('$', precedence(
|
|
11
|
+
surround('$', precedence(5, bracket), '$'),
|
|
12
12
|
surround(
|
|
13
13
|
/^\$(?![\s{}])/,
|
|
14
|
-
precedence(
|
|
14
|
+
precedence(2, some(union([
|
|
15
15
|
bracket,
|
|
16
16
|
focus(/^(?:[ ([](?!\$)|\\[\\{}$]?|[!#%&')\x2A-\x5A\]^_\x61-\x7A|~])+/, some(unescsource)),
|
|
17
17
|
]))),
|
|
@@ -21,7 +21,7 @@ Object.setPrototypeOf(optspec, null);
|
|
|
21
21
|
export const media: MediaParser = lazy(() => validate(['![', '!{'], creation(1, Recursion.ignore, open(
|
|
22
22
|
'!',
|
|
23
23
|
constraint(State.media, false,
|
|
24
|
-
syntax(
|
|
24
|
+
syntax(1, ~State.link,
|
|
25
25
|
bind(verify(fmap(tails([
|
|
26
26
|
dup(surround(
|
|
27
27
|
'[',
|
|
@@ -78,7 +78,7 @@ const bracket: MediaParser.TextParser.BracketParser = lazy(() => creation(0, Rec
|
|
|
78
78
|
undefined, ([as, bs = []], rest) => [unshift(as, bs), rest], 3 | Backtrack.media),
|
|
79
79
|
surround(str('{'), some(union([unsafehtmlentity, bracket, txt]), '}'), str('}'), true,
|
|
80
80
|
undefined, ([as, bs = []], rest) => [unshift(as, bs), rest], 3 | Backtrack.media),
|
|
81
|
-
surround(str('"'), precedence(
|
|
81
|
+
surround(str('"'), precedence(2, some(union([unsafehtmlentity, txt]), '"')), str('"'), true,
|
|
82
82
|
undefined, undefined, 3 | Backtrack.media),
|
|
83
83
|
])));
|
|
84
84
|
|
|
@@ -9,10 +9,10 @@ import { html, defrag } from 'typed-dom/dom';
|
|
|
9
9
|
export const reference: ReferenceParser = lazy(() => creation(1, Recursion.ignore, surround(
|
|
10
10
|
'[[',
|
|
11
11
|
constraint(State.reference, false,
|
|
12
|
-
syntax(
|
|
12
|
+
syntax(1, State.annotation | State.reference | State.media,
|
|
13
13
|
subsequence([
|
|
14
14
|
abbr,
|
|
15
|
-
trimBlankStart(some(inline, ']', [[/^\\?\n/, 9], [']',
|
|
15
|
+
trimBlankStart(some(inline, ']', [[/^\\?\n/, 9], [']', 1]])),
|
|
16
16
|
]))),
|
|
17
17
|
']]',
|
|
18
18
|
false,
|
|
@@ -7,13 +7,13 @@ import { memoize } from 'spica/memoize';
|
|
|
7
7
|
import { unshift, push } from 'spica/array';
|
|
8
8
|
import { html, defrag } from 'typed-dom/dom';
|
|
9
9
|
|
|
10
|
-
export const remark: RemarkParser = lazy(() => validate('[%', creation(1, Recursion.inline, syntax(
|
|
10
|
+
export const remark: RemarkParser = lazy(() => validate('[%', creation(1, Recursion.inline, syntax(4, State.none, match(
|
|
11
11
|
/^\[(%+)\s/,
|
|
12
12
|
memoize(
|
|
13
13
|
([, fence]) =>
|
|
14
14
|
surround(
|
|
15
15
|
open(str(`[${fence}`), some(text, new RegExp(String.raw`^\s+${fence}\]|^\S`)), true),
|
|
16
|
-
some(union([inline]), new RegExp(String.raw`^\s+${fence}\]`), [[new RegExp(String.raw`^\s+${fence}\]`),
|
|
16
|
+
some(union([inline]), new RegExp(String.raw`^\s+${fence}\]`), [[new RegExp(String.raw`^\s+${fence}\]`), 4]]),
|
|
17
17
|
close(some(text, /^\S/), str(`${fence}]`)), true,
|
|
18
18
|
([as, bs = [], cs], rest) => [[
|
|
19
19
|
html('span', { class: 'remark' }, [
|
|
@@ -8,11 +8,11 @@ import { isStartTightNodes } from '../visibility';
|
|
|
8
8
|
import { unshift, push } from 'spica/array';
|
|
9
9
|
import { html, defrag } from 'typed-dom/dom';
|
|
10
10
|
|
|
11
|
-
export const ruby: RubyParser = lazy(() => validate('[', creation(1, Recursion.ignore, syntax(
|
|
11
|
+
export const ruby: RubyParser = lazy(() => validate('[', creation(1, Recursion.ignore, syntax(1, State.all, fmap(
|
|
12
12
|
sequence([
|
|
13
13
|
bind(surround('[', str(/^(?:\\[^\n]|[^\\[\](){}"\n])+/), ']', false, undefined, undefined, 3 | Backtrack.ruby), ([source], rest, context) => {
|
|
14
14
|
const ns = eval(text({ source, context }), [undefined])[0];
|
|
15
|
-
ns && ns
|
|
15
|
+
ns && ns.at(-1) === '' && ns.pop();
|
|
16
16
|
return ns && isStartTightNodes(ns) ? [[ns], rest] : undefined;
|
|
17
17
|
}),
|
|
18
18
|
bind(surround('(', str(/^(?:\\[^\n]|[^\\[\](){}"\n])+/), ')', false, undefined, undefined, 3 | Backtrack.ruby), ([source], rest, context) => {
|
|
@@ -12,10 +12,8 @@ describe('Unit: parser/inline/strong', () => {
|
|
|
12
12
|
assert.deepStrictEqual(inspect(parser('**a **')), [['**', 'a'], ' **']);
|
|
13
13
|
assert.deepStrictEqual(inspect(parser('**a **')), [['**', 'a', ' '], ' **']);
|
|
14
14
|
assert.deepStrictEqual(inspect(parser('**a\n**')), [['**', 'a'], '\n**']);
|
|
15
|
-
assert.deepStrictEqual(inspect(parser('**a\nb**')), [['**', 'a'], '\nb**']);
|
|
16
15
|
assert.deepStrictEqual(inspect(parser('**a\\ **')), [['**', 'a'], '\\ **']);
|
|
17
16
|
assert.deepStrictEqual(inspect(parser('**a\\\n**')), [['**', 'a'], '\\\n**']);
|
|
18
|
-
assert.deepStrictEqual(inspect(parser('**a\\\nb**')), [['**', 'a'], '\\\nb**']);
|
|
19
17
|
assert.deepStrictEqual(inspect(parser('**a*')), [['**', 'a', '*'], '']);
|
|
20
18
|
assert.deepStrictEqual(inspect(parser('**a*b**')), [['**', 'a', '<em>b</em>', '*'], '']);
|
|
21
19
|
assert.deepStrictEqual(inspect(parser('** **')), undefined);
|
|
@@ -33,6 +31,8 @@ describe('Unit: parser/inline/strong', () => {
|
|
|
33
31
|
it('basic', () => {
|
|
34
32
|
assert.deepStrictEqual(inspect(parser('**a**')), [['<strong>a</strong>'], '']);
|
|
35
33
|
assert.deepStrictEqual(inspect(parser('**ab**')), [['<strong>ab</strong>'], '']);
|
|
34
|
+
assert.deepStrictEqual(inspect(parser('**a\nb**')), [['<strong>a<br>b</strong>'], '']);
|
|
35
|
+
assert.deepStrictEqual(inspect(parser('**a\\\nb**')), [['<strong>a<br>b</strong>'], '']);
|
|
36
36
|
});
|
|
37
37
|
|
|
38
38
|
it('nest', () => {
|
|
@@ -10,10 +10,10 @@ import { html, defrag } from 'typed-dom/dom';
|
|
|
10
10
|
|
|
11
11
|
export const strong: StrongParser = lazy(() => creation(1, Recursion.inline, surround(
|
|
12
12
|
str('**', '*'),
|
|
13
|
-
syntax(
|
|
13
|
+
syntax(0, State.none,
|
|
14
14
|
startTight(some(union([
|
|
15
|
-
some(inline, blankWith('**')
|
|
16
|
-
open(some(inline, '*'
|
|
15
|
+
some(inline, blankWith('**')),
|
|
16
|
+
open(some(inline, '*'), union([
|
|
17
17
|
emstrong,
|
|
18
18
|
strong,
|
|
19
19
|
])),
|
|
@@ -7,7 +7,7 @@ import { html } from 'typed-dom/dom';
|
|
|
7
7
|
|
|
8
8
|
export const template: TemplateParser = lazy(() => creation(1, Recursion.ignore, surround(
|
|
9
9
|
'{{',
|
|
10
|
-
syntax(
|
|
10
|
+
syntax(1, State.all, some(union([bracket, escsource]), '}')),
|
|
11
11
|
'}}',
|
|
12
12
|
true,
|
|
13
13
|
([, ns = []], rest) => [[html('span', { class: 'template' }, `{{${ns.join('').replace(/\x1B/g, '')}}}`)], rest],
|
|
@@ -20,6 +20,6 @@ const bracket: TemplateParser.BracketParser = lazy(() => creation(0, Recursion.t
|
|
|
20
20
|
undefined, ([as, bs = []], rest) => [unshift(as, bs), rest], 3 | Backtrack.template),
|
|
21
21
|
surround(str('{'), some(union([bracket, escsource]), '}'), str('}'), true,
|
|
22
22
|
undefined, ([as, bs = []], rest) => [unshift(as, bs), rest], 3 | Backtrack.template),
|
|
23
|
-
surround(str('"'), precedence(
|
|
23
|
+
surround(str('"'), precedence(2, some(escsource, /^"|^\\?\n/)), str('"'), true,
|
|
24
24
|
undefined, undefined, 3 | Backtrack.template),
|
|
25
25
|
])));
|
|
@@ -105,6 +105,7 @@ describe('Unit: parser/inline', () => {
|
|
|
105
105
|
assert.deepStrictEqual(inspect(parser('<bdi>*<bdi>a</bdi>*</bdi>')), [['<bdi><em><bdi>a</bdi></em></bdi>'], '']);
|
|
106
106
|
assert.deepStrictEqual(inspect(parser('<bdi>((<bdi>((a))</bdi>))</bdi>')), [['<bdi><sup class="annotation"><span><bdi><span class="paren">((a))</span></bdi></span></sup></bdi>'], '']);
|
|
107
107
|
assert.deepStrictEqual(inspect(parser('<bdi>[[<bdi>[[a]]</bdi>]]</bdi>')), [['<bdi><sup class="reference"><span><bdi>[[a]]</bdi></span></sup></bdi>'], '']);
|
|
108
|
+
assert.deepStrictEqual(inspect(parser('"<bdi>("")</bdi>')), [['"', '<bdi><span class="paren">("")</span></bdi>'], '']);
|
|
108
109
|
assert.deepStrictEqual(inspect(parser('*[*]')), [['*', '[', '*', ']'], '']);
|
|
109
110
|
assert.deepStrictEqual(inspect(parser('*<*>')), [['<em><</em>', '>'], '']);
|
|
110
111
|
assert.deepStrictEqual(inspect(parser('*a((b))*')), [['<em>a<sup class="annotation"><span>b</span></sup></em>'], '']);
|
|
@@ -150,7 +151,7 @@ describe('Unit: parser/inline', () => {
|
|
|
150
151
|
assert.deepStrictEqual(inspect(parser('((((a))))')), [['<sup class="annotation"><span><span class="paren">((a))</span></span></sup>'], '']);
|
|
151
152
|
assert.deepStrictEqual(inspect(parser('((${))}$')), [['(', '(', '<span class="math" translate="no" data-src="${))}$">${))}$</span>'], '']);
|
|
152
153
|
assert.deepStrictEqual(inspect(parser('((a\nb))')), [['<span class="paren">(<span class="paren">(a<br>b)</span>)</span>'], '']);
|
|
153
|
-
assert.deepStrictEqual(inspect(parser('"((""))')), [['"', '
|
|
154
|
+
assert.deepStrictEqual(inspect(parser('"((""))')), [['"', '(', '(', '"', '"', ')', ')'], '']);
|
|
154
155
|
assert.deepStrictEqual(inspect(parser('[[[a]]')), [['[', '<sup class="reference"><span>a</span></sup>'], '']);
|
|
155
156
|
assert.deepStrictEqual(inspect(parser('[[[[a]]')), [['[', '[', '<sup class="reference"><span>a</span></sup>'], '']);
|
|
156
157
|
assert.deepStrictEqual(inspect(parser('[[[[a]]]]')), [['<sup class="reference"><span>[[a]]</span></sup>'], '']);
|
|
@@ -159,7 +160,7 @@ describe('Unit: parser/inline', () => {
|
|
|
159
160
|
assert.deepStrictEqual(inspect(parser('[[[a]{b}]]')), [['<sup class="reference"><span><a class="link" href="b">a</a></span></sup>'], '']);
|
|
160
161
|
assert.deepStrictEqual(inspect(parser('[(([a]{#}))]{#}')), [['<a class="link" href="#"><span class="paren">(<span class="paren">([a]{#})</span>)</span></a>'], '']);
|
|
161
162
|
assert.deepStrictEqual(inspect(parser('[[${]]}$')), [['[', '[', '<span class="math" translate="no" data-src="${]]}$">${]]}$</span>'], '']);
|
|
162
|
-
assert.deepStrictEqual(inspect(parser('"[[""]]')), [['"', '
|
|
163
|
+
assert.deepStrictEqual(inspect(parser('"[[""]]')), [['"', '[', '[', '"', '"', ']', ']'], '']);
|
|
163
164
|
assert.deepStrictEqual(inspect(parser('[==a==]{b}')), [['<a class="link" href="b">==a==</a>'], '']);
|
|
164
165
|
assert.deepStrictEqual(inspect(parser('[[a](b)]{c}')), [['<a class="link" href="c"><ruby>a<rp>(</rp><rt>b</rt><rp>)</rp></ruby></a>'], '']);
|
|
165
166
|
assert.deepStrictEqual(inspect(parser('[[[[[[[{a}')), [['[', '[', '[', '[', '[', '[', '[', '<a class="url" href="a">a</a>'], '']);
|
|
@@ -171,6 +172,7 @@ describe('Unit: parser/inline', () => {
|
|
|
171
172
|
assert.deepStrictEqual(inspect(parser('[^a@b')), [['[^', '<a class="email" href="mailto:a@b">a@b</a>'], '']);
|
|
172
173
|
assert.deepStrictEqual(inspect(parser('"[% *"*"*')), [['"', '[%', ' ', '*', '"', '*', '"', '*'], '']);
|
|
173
174
|
assert.deepStrictEqual(inspect(parser('"[% "*"* %]')), [['"', '<span class="remark"><input type="checkbox"><span>[% "*"* %]</span></span>'], '']);
|
|
175
|
+
assert.deepStrictEqual(inspect(parser('"{{""}}')), [['"', '{', '{', '"', '"', '}', '}'], '']);
|
|
174
176
|
});
|
|
175
177
|
|
|
176
178
|
it('uri', () => {
|