securemark 0.293.2 → 0.293.4
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 +349 -167
- 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/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/combinator/data/parser.ts +0 -3
- package/src/parser/api/bind.ts +1 -1
- package/src/parser/api/parse.ts +1 -1
- package/src/parser/block/dlist.test.ts +1 -1
- package/src/parser/block/heading.test.ts +1 -0
- package/src/parser/block/olist.test.ts +9 -6
- package/src/parser/block/olist.ts +2 -2
- package/src/parser/block/ulist.test.ts +1 -0
- package/src/parser/block.ts +38 -36
- package/src/parser/inline/annotation.test.ts +1 -1
- package/src/parser/inline/bracket.test.ts +4 -2
- package/src/parser/inline/bracket.ts +114 -88
- package/src/parser/inline/emphasis.test.ts +1 -0
- package/src/parser/inline/html.test.ts +3 -3
- package/src/parser/inline/html.ts +32 -21
- package/src/parser/inline/italic.test.ts +1 -0
- package/src/parser/inline/link.test.ts +10 -8
- package/src/parser/inline/link.ts +18 -18
- package/src/parser/inline/mark.test.ts +1 -0
- package/src/parser/inline/math.ts +2 -2
- package/src/parser/inline/media.test.ts +6 -7
- package/src/parser/inline/media.ts +6 -5
- package/src/parser/inline/reference.test.ts +1 -1
- package/src/parser/inline/remark.test.ts +3 -1
- package/src/parser/inline/remark.ts +2 -2
- package/src/parser/inline/strong.test.ts +1 -0
- package/src/parser/inline/template.ts +1 -1
- package/src/parser/inline.test.ts +16 -16
- package/src/parser/inline.ts +46 -47
- package/src/parser/segment.ts +12 -12
- package/src/parser/source/escapable.test.ts +1 -0
- package/src/parser/source/escapable.ts +3 -9
- package/src/parser/source/text.test.ts +5 -4
- package/src/parser/source/text.ts +175 -24
- package/src/parser/source/unescapable.test.ts +1 -0
- package/src/parser/source/unescapable.ts +2 -3
package/package.json
CHANGED
|
@@ -12,12 +12,17 @@ describe('Unit: combinator/indent', () => {
|
|
|
12
12
|
assert.deepStrictEqual(inspect(parser(input(' ', ctx)), ctx), undefined);
|
|
13
13
|
assert.deepStrictEqual(inspect(parser(input(' ', ctx)), ctx), undefined);
|
|
14
14
|
assert.deepStrictEqual(inspect(parser(input('a ', ctx)), ctx), undefined);
|
|
15
|
-
assert.deepStrictEqual(inspect(parser(input(' a
|
|
15
|
+
assert.deepStrictEqual(inspect(parser(input(' a', ctx)), ctx), [['a'], '']);
|
|
16
16
|
assert.deepStrictEqual(inspect(parser(input(' a ', ctx)), ctx), [['a '], '']);
|
|
17
|
+
assert.deepStrictEqual(inspect(parser(input(' a\n', ctx)), ctx), [['a'], '']);
|
|
17
18
|
assert.deepStrictEqual(inspect(parser(input(' a \n', ctx)), ctx), [['a '], '']);
|
|
18
19
|
assert.deepStrictEqual(inspect(parser(input(' a', ctx)), ctx), [['a'], '']);
|
|
20
|
+
assert.deepStrictEqual(inspect(parser(input(' a', ctx)), ctx), [['a'], '']);
|
|
21
|
+
assert.deepStrictEqual(inspect(parser(input(' a', ctx)), ctx), [['a'], '']);
|
|
22
|
+
assert.deepStrictEqual(inspect(parser(input(' a', ctx)), ctx), [[' a'], '']);
|
|
19
23
|
assert.deepStrictEqual(inspect(parser(input(' a\n a', ctx)), ctx), [['a\na'], '']);
|
|
20
24
|
assert.deepStrictEqual(inspect(parser(input(' a\n a', ctx)), ctx), [['a\n a'], '']);
|
|
25
|
+
assert.deepStrictEqual(inspect(parser(input(' a\n a', ctx)), ctx), [['a\n a'], '']);
|
|
21
26
|
assert.deepStrictEqual(inspect(parser(input(' a\n a', ctx)), ctx), [['a'], ' a']);
|
|
22
27
|
assert.deepStrictEqual(inspect(parser(input(' \ta', ctx)), ctx), [['\ta'], '']);
|
|
23
28
|
assert.deepStrictEqual(inspect(parser(input('\ta', ctx)), ctx), [['a'], '']);
|
|
@@ -13,7 +13,7 @@ export function indent<N>(opener: RegExp | Parser<N>, parser: Parser<N> | boolea
|
|
|
13
13
|
if (typeof opener === 'function') {
|
|
14
14
|
separation = parser as boolean;
|
|
15
15
|
parser = opener;
|
|
16
|
-
opener = /
|
|
16
|
+
opener = / {1,4}|\t{1,2}/y;
|
|
17
17
|
}
|
|
18
18
|
assert(!opener.flags.match(/[gm]/) && opener.sticky && !opener.source.startsWith('^'));
|
|
19
19
|
assert(parser);
|
|
@@ -157,7 +157,8 @@ export function setBacktrack(
|
|
|
157
157
|
position: number,
|
|
158
158
|
length: number = 1,
|
|
159
159
|
): void {
|
|
160
|
-
const { source } = context;
|
|
160
|
+
const { source, state = 0 } = context;
|
|
161
|
+
if (state === 0) return;
|
|
161
162
|
if (position === source.length) return;
|
|
162
163
|
if (length === 0) return;
|
|
163
164
|
for (const backtrack of backtracks) {
|
|
@@ -7,26 +7,24 @@ interface Delimiter {
|
|
|
7
7
|
readonly signature: number | string;
|
|
8
8
|
readonly matcher: (input: Input) => boolean | undefined;
|
|
9
9
|
readonly precedence: number;
|
|
10
|
-
readonly linebreakable: boolean;
|
|
11
10
|
state: boolean;
|
|
12
11
|
}
|
|
13
12
|
|
|
14
13
|
export class Delimiters {
|
|
15
14
|
// 手間を惜しまなければ規定のパターンはすべて配列のインデクスに変換可能。
|
|
16
|
-
public static signature(pattern: string | RegExp | undefined
|
|
15
|
+
public static signature(pattern: string | RegExp | undefined): number | string {
|
|
17
16
|
switch (typeof pattern) {
|
|
18
17
|
case 'undefined':
|
|
19
|
-
return
|
|
18
|
+
return 1 << 7;
|
|
20
19
|
case 'string':
|
|
21
20
|
assert(pattern !== '\x00');
|
|
22
21
|
if (pattern.length === 1) {
|
|
23
22
|
const code = pattern.charCodeAt(0);
|
|
24
|
-
|
|
25
|
-
if ((code & 1 << 7) === 0) return code | +linebreakable << 7;
|
|
23
|
+
return code;
|
|
26
24
|
}
|
|
27
|
-
return `s:${pattern}
|
|
25
|
+
return `s:${pattern}`;
|
|
28
26
|
case 'object':
|
|
29
|
-
return `r/${pattern.source}
|
|
27
|
+
return `r/${pattern.source}`;
|
|
30
28
|
}
|
|
31
29
|
}
|
|
32
30
|
public static matcher(pattern: string | RegExp | undefined): (input: Input<Ctx>) => true | undefined {
|
|
@@ -61,14 +59,13 @@ export class Delimiters {
|
|
|
61
59
|
readonly signature: number | string;
|
|
62
60
|
readonly matcher: (input: Input) => boolean | undefined;
|
|
63
61
|
readonly precedence: number;
|
|
64
|
-
readonly linebreakable: boolean;
|
|
65
62
|
}[]
|
|
66
63
|
): void {
|
|
67
64
|
const { delimiters, stack } = this;
|
|
68
65
|
// シグネチャ数以下
|
|
69
66
|
assert(delimiters.length < 100);
|
|
70
67
|
for (let i = 0; i < delims.length; ++i) {
|
|
71
|
-
const { signature, matcher, precedence
|
|
68
|
+
const { signature, matcher, precedence } = delims[i];
|
|
72
69
|
const memory = this.registry(signature);
|
|
73
70
|
const index = memory[0]?.index ?? delimiters.length;
|
|
74
71
|
assert(memory.length === 0 || precedence === delimiters[index].precedence);
|
|
@@ -79,7 +76,6 @@ export class Delimiters {
|
|
|
79
76
|
signature,
|
|
80
77
|
matcher,
|
|
81
78
|
precedence,
|
|
82
|
-
linebreakable,
|
|
83
79
|
state: true,
|
|
84
80
|
};
|
|
85
81
|
delimiters[index] = delimiter;
|
|
@@ -134,14 +130,13 @@ export class Delimiters {
|
|
|
134
130
|
}
|
|
135
131
|
}
|
|
136
132
|
public match(input: Input): boolean {
|
|
137
|
-
const { precedence = 0
|
|
133
|
+
const { precedence = 0 } = input.context;
|
|
138
134
|
const { delimiters } = this;
|
|
139
135
|
for (let i = delimiters.length; i--;) {
|
|
140
136
|
const delimiter = delimiters[i];
|
|
141
137
|
if (delimiter.precedence <= precedence || !delimiter.state) continue;
|
|
142
138
|
switch (delimiter.matcher(input)) {
|
|
143
139
|
case true:
|
|
144
|
-
if (!delimiter.linebreakable && linebreak > 0) return false;
|
|
145
140
|
return true;
|
|
146
141
|
case false:
|
|
147
142
|
return false;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { Parser, eval } from '../parser';
|
|
2
2
|
import { Delimiters } from './context/delimiter';
|
|
3
|
-
import { unshift, push } from 'spica/array';
|
|
4
3
|
|
|
5
|
-
type DelimiterOption = readonly [delimiter: string | RegExp, precedence: number
|
|
4
|
+
type DelimiterOption = readonly [delimiter: string | RegExp, precedence: number];
|
|
6
5
|
|
|
7
6
|
export function some<P extends Parser<unknown>>(parser: P, limit?: number): P;
|
|
8
7
|
export function some<P extends Parser<unknown>>(parser: P, end?: string | RegExp, delimiters?: readonly DelimiterOption[], limit?: number): P;
|
|
@@ -10,11 +9,10 @@ export function some<N>(parser: Parser<N>, end?: string | RegExp | number, delim
|
|
|
10
9
|
if (typeof end === 'number') return some(parser, undefined, delimiters, end);
|
|
11
10
|
assert(parser);
|
|
12
11
|
const match = Delimiters.matcher(end);
|
|
13
|
-
const delims = delimiters.map(([delimiter, precedence
|
|
14
|
-
signature: Delimiters.signature(delimiter
|
|
12
|
+
const delims = delimiters.map(([delimiter, precedence]) => ({
|
|
13
|
+
signature: Delimiters.signature(delimiter),
|
|
15
14
|
matcher: Delimiters.matcher(delimiter),
|
|
16
15
|
precedence,
|
|
17
|
-
linebreakable,
|
|
18
16
|
}));
|
|
19
17
|
return input => {
|
|
20
18
|
const { context } = input;
|
|
@@ -32,9 +30,7 @@ export function some<N>(parser: Parser<N>, end?: string | RegExp | number, delim
|
|
|
32
30
|
const result = parser(input);
|
|
33
31
|
if (result === undefined) break;
|
|
34
32
|
nodes = nodes
|
|
35
|
-
? nodes.
|
|
36
|
-
? unshift(nodes, eval(result))
|
|
37
|
-
: push(nodes, eval(result))
|
|
33
|
+
? (nodes.push(...eval(result)), nodes)
|
|
38
34
|
: eval(result);
|
|
39
35
|
if (limit >= 0 && context.position - position > limit) break;
|
|
40
36
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Delimiters } from './parser/context/delimiter';
|
|
2
|
-
import { MarkdownParser } from '../../../markdown';
|
|
3
2
|
|
|
4
3
|
export type Parser<N, C extends CtxOptions = CtxOptions, D extends Parser<unknown, C>[] = any>
|
|
5
4
|
= (input: Input<C & Ctx>) => Result<N, C, D>;
|
|
@@ -38,8 +37,6 @@ export type IntermediateParser<P extends Parser<unknown>> = Parser<SubNode<P>, C
|
|
|
38
37
|
type ExtractSubNode<D extends Parser<unknown>[]> = ExtractSubParser<D> extends infer N ? N extends Parser<infer U> ? U : never : never;
|
|
39
38
|
type ExtractSubParser<D extends Parser<unknown>[]> = D extends (infer P)[] ? P extends Parser<unknown> ? P : never : never;
|
|
40
39
|
|
|
41
|
-
export function input(source: string, context: CtxOptions): Input<Ctx>;
|
|
42
|
-
export function input(source: string, context: MarkdownParser.Options): Input<MarkdownParser.Context>;
|
|
43
40
|
export function input(source: string, context: CtxOptions): Input<Ctx> {
|
|
44
41
|
// @ts-expect-error
|
|
45
42
|
context.source = source;
|
package/src/parser/api/bind.ts
CHANGED
|
@@ -78,7 +78,7 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
|
|
|
78
78
|
for (; index < sourceSegments.length - last; ++index) {
|
|
79
79
|
assert(rev === revision);
|
|
80
80
|
const seg = sourceSegments[index];
|
|
81
|
-
const es = eval(header(input(seg, { header: index === 0 })) || block(input(seg, context)), []);
|
|
81
|
+
const es = eval(header(input(seg, { header: index === 0 } as MarkdownParser.Context)) || block(input(seg, context)), []);
|
|
82
82
|
blocks.splice(index, 0, [seg, es, url]);
|
|
83
83
|
if (es.length === 0) continue;
|
|
84
84
|
// All deletion processes always run after all addition processes have done.
|
package/src/parser/api/parse.ts
CHANGED
|
@@ -34,7 +34,7 @@ export function parse(source: string, opts: Options = {}, context?: MarkdownPars
|
|
|
34
34
|
const node = frag();
|
|
35
35
|
let index = 0;
|
|
36
36
|
for (const seg of segment(source)) {
|
|
37
|
-
node.append(...eval(header(input(seg, { header: index++ === 0 })) || block(input(seg, context)), []));
|
|
37
|
+
node.append(...eval(header(input(seg, { header: index++ === 0 } as MarkdownParser.Context)) || block(input(seg, context)), []));
|
|
38
38
|
}
|
|
39
39
|
assert(opts.id !== '' || !node.querySelector('[id], .index[href], .label[href], .annotation > a[href], .reference > a[href]'));
|
|
40
40
|
if (opts.test) return node;
|
|
@@ -69,7 +69,7 @@ describe('Unit: parser/block/dlist', () => {
|
|
|
69
69
|
it('indexer', () => {
|
|
70
70
|
assert.deepStrictEqual(inspect(parser('~ a [|b]'), ctx), [['<dl><dt id="index::b">a<span class="indexer" data-index="b"></span></dt><dd></dd></dl>'], '']);
|
|
71
71
|
assert.deepStrictEqual(inspect(parser('~ a [|b]\\'), ctx), [['<dl><dt id="index::a_[|b]">a <span class="invalid">[|b]</span></dt><dd></dd></dl>'], '']);
|
|
72
|
-
assert.deepStrictEqual(inspect(parser('~
|
|
72
|
+
assert.deepStrictEqual(inspect(parser('~ - [|b]'), ctx), [['<dl><dt id="index::b">-<span class="indexer" data-index="b"></span></dt><dd></dd></dl>'], '']);
|
|
73
73
|
assert.deepStrictEqual(inspect(parser('~ *A*'), ctx), [['<dl><dt id="index::A"><em>A</em></dt><dd></dd></dl>'], '']);
|
|
74
74
|
assert.deepStrictEqual(inspect(parser('~ `A`'), ctx), [['<dl><dt id="index::`A`"><code data-src="`A`">A</code></dt><dd></dd></dl>'], '']);
|
|
75
75
|
assert.deepStrictEqual(inspect(parser('~ ${A}$'), ctx), [['<dl><dt id="index::${A}$"><span class="math" translate="no" data-src="${A}$">${A}$</span></dt><dd></dd></dl>'], '']);
|
|
@@ -79,6 +79,7 @@ describe('Unit: parser/block/heading', () => {
|
|
|
79
79
|
assert.deepStrictEqual(inspect(parser('# a [|b] [|c]'), ctx), [['<h1 id="index::c">a <span class="invalid">[|b]</span><span class="indexer" data-index="c"></span></h1>'], '']);
|
|
80
80
|
assert.deepStrictEqual(inspect(parser('# a [|b] \n'), ctx), [['<h1 id="index::b">a<span class="indexer" data-index="b"></span></h1>'], '']);
|
|
81
81
|
assert.deepStrictEqual(inspect(parser('# a \\[|b]'), ctx), [['<h1 id="index::a_[|b]">a [|b]</h1>'], '']);
|
|
82
|
+
assert.deepStrictEqual(inspect(parser('# - [|b]'), ctx), [['<h1 id="index::b">-<span class="indexer" data-index="b"></span></h1>'], '']);
|
|
82
83
|
assert.deepStrictEqual(inspect(parser('## a [|b] [|c]'), ctx), [['<h2 id="index::c">a <span class="invalid">[|b]</span><span class="indexer" data-index="c"></span></h2>'], '']);
|
|
83
84
|
});
|
|
84
85
|
|
|
@@ -32,6 +32,8 @@ describe('Unit: parser/block/olist', () => {
|
|
|
32
32
|
assert.deepStrictEqual(inspect(parser('(1)'), ctx), undefined);
|
|
33
33
|
assert.deepStrictEqual(inspect(parser('(1)\n'), ctx), undefined);
|
|
34
34
|
assert.deepStrictEqual(inspect(parser('(1)\n(1) a'), ctx), undefined);
|
|
35
|
+
assert.deepStrictEqual(inspect(parser('I. '), ctx), undefined);
|
|
36
|
+
assert.deepStrictEqual(inspect(parser('A. '), ctx), undefined);
|
|
35
37
|
assert.deepStrictEqual(inspect(parser('(I) '), ctx), undefined);
|
|
36
38
|
assert.deepStrictEqual(inspect(parser('(A) '), ctx), undefined);
|
|
37
39
|
assert.deepStrictEqual(inspect(parser(' 1. '), ctx), undefined);
|
|
@@ -117,12 +119,12 @@ describe('Unit: parser/block/olist', () => {
|
|
|
117
119
|
});
|
|
118
120
|
|
|
119
121
|
it('type', () => {
|
|
120
|
-
assert.deepStrictEqual(inspect(parser('i. '), ctx), [['<ol type="i" data-type="lower-roman"><li></li></ol>'], '']);
|
|
121
|
-
assert.deepStrictEqual(inspect(parser('a. '), ctx), [['<ol type="a" data-type="lower-alpha"><li></li></ol>'], '']);
|
|
122
|
-
assert.deepStrictEqual(inspect(parser('I. '), ctx), [['<ol type="I" data-type="upper-roman"><li></li></ol>'], '']);
|
|
123
|
-
assert.deepStrictEqual(inspect(parser('A. '), ctx), [['<ol type="A" data-type="upper-alpha"><li></li></ol>'], '']);
|
|
124
|
-
assert.deepStrictEqual(inspect(parser('a. \
|
|
125
|
-
assert.deepStrictEqual(inspect(parser('i. 1'), ctx), [['<ol type="i" data-type="lower-roman"><li id="index::1">1</li></ol>'], '']);
|
|
122
|
+
assert.deepStrictEqual(inspect(parser('1. \n i. '), ctx), [['<ol><li><br><ol type="i" data-type="lower-roman"><li></li></ol></li></ol>'], '']);
|
|
123
|
+
assert.deepStrictEqual(inspect(parser('1. \n a. '), ctx), [['<ol><li><br><ol type="a" data-type="lower-alpha"><li></li></ol></li></ol>'], '']);
|
|
124
|
+
assert.deepStrictEqual(inspect(parser('1. \n I. '), ctx), [['<ol><li><br><ol type="I" data-type="upper-roman"><li></li></ol></li></ol>'], '']);
|
|
125
|
+
assert.deepStrictEqual(inspect(parser('1. \n A. '), ctx), [['<ol><li><br><ol type="A" data-type="upper-alpha"><li></li></ol></li></ol>'], '']);
|
|
126
|
+
assert.deepStrictEqual(inspect(parser('1. \n a. \n 1.\n c'), ctx), [['<ol><li><br><ol type="a" data-type="lower-alpha"><li></li><li data-marker="1."></li><li data-marker="c."></li></ol></li></ol>'], '']);
|
|
127
|
+
assert.deepStrictEqual(inspect(parser('1. \n i. 1'), ctx), [['<ol><li><br><ol type="i" data-type="lower-roman"><li id="index::1">1</li></ol></li></ol>'], '']);
|
|
126
128
|
});
|
|
127
129
|
|
|
128
130
|
it('checkbox', () => {
|
|
@@ -136,6 +138,7 @@ describe('Unit: parser/block/olist', () => {
|
|
|
136
138
|
assert.deepStrictEqual(inspect(parser('1. [|a]'), ctx), [['<ol><li id="index::[|a]"><span class="invalid">[|a]</span></li></ol>'], '']);
|
|
137
139
|
assert.deepStrictEqual(inspect(parser('1. a [|]'), ctx), [['<ol><li>a<span class="indexer" data-index=""></span></li></ol>'], '']);
|
|
138
140
|
assert.deepStrictEqual(inspect(parser('1. a [|b]'), ctx), [['<ol><li id="index::b">a<span class="indexer" data-index="b"></span></li></ol>'], '']);
|
|
141
|
+
assert.deepStrictEqual(inspect(parser('1. - [|]'), ctx), [['<ol><li>-<span class="indexer" data-index=""></span></li></ol>'], '']);
|
|
139
142
|
assert.deepStrictEqual(inspect(parser('1. [ ] [|a]'), ctx), [['<ol class="checklist"><li id="index::[|a]"><span class="checkbox">☐</span><span class="invalid">[|a]</span></li></ol>'], '']);
|
|
140
143
|
assert.deepStrictEqual(inspect(parser('1. [ ] a [|b]'), ctx), [['<ol class="checklist"><li id="index::b"><span class="checkbox">☐</span>a<span class="indexer" data-index="b"></span></li></ol>'], '']);
|
|
141
144
|
assert.deepStrictEqual(inspect(parser('1. a [|]\n 1. c [|d]'), ctx), [['<ol><li>a<span class="indexer" data-index=""></span><ol><li id="index::d">c<span class="indexer" data-index="d"></span></li></ol></li></ol>'], '']);
|
|
@@ -16,8 +16,8 @@ const openers = {
|
|
|
16
16
|
|
|
17
17
|
export const olist: OListParser = lazy(() => block(validate(
|
|
18
18
|
new RegExp([
|
|
19
|
-
/([0-9]
|
|
20
|
-
/\(([0-9]
|
|
19
|
+
/(?:[0-9]+)(?:-[0-9]+)*\. /y.source,
|
|
20
|
+
/\((?:[0-9]+)\)(?:-[0-9]+)* /y.source,
|
|
21
21
|
].join('|'), 'y'),
|
|
22
22
|
olist_)));
|
|
23
23
|
|
|
@@ -75,6 +75,7 @@ describe('Unit: parser/block/ulist', () => {
|
|
|
75
75
|
assert.deepStrictEqual(inspect(parser('- [|a]'), ctx), [['<ul><li id="index::[|a]"><span class="invalid">[|a]</span></li></ul>'], '']);
|
|
76
76
|
assert.deepStrictEqual(inspect(parser('- a [|]'), ctx), [['<ul><li>a<span class="indexer" data-index=""></span></li></ul>'], '']);
|
|
77
77
|
assert.deepStrictEqual(inspect(parser('- a [|b]'), ctx), [['<ul><li id="index::b">a<span class="indexer" data-index="b"></span></li></ul>'], '']);
|
|
78
|
+
assert.deepStrictEqual(inspect(parser('- - [|b]'), ctx), [['<ul><li id="index::b">-<span class="indexer" data-index="b"></span></li></ul>'], '']);
|
|
78
79
|
assert.deepStrictEqual(inspect(parser('- [ ] [|a]'), ctx), [['<ul class="checklist"><li id="index::[|a]"><span class="checkbox">☐</span><span class="invalid">[|a]</span></li></ul>'], '']);
|
|
79
80
|
assert.deepStrictEqual(inspect(parser('- [ ] a [|b]'), ctx), [['<ul class="checklist"><li id="index::b"><span class="checkbox">☐</span>a<span class="indexer" data-index="b"></span></li></ul>'], '']);
|
|
80
81
|
assert.deepStrictEqual(inspect(parser('- a [|]\n - c [|d]'), ctx), [['<ul><li>a<span class="indexer" data-index=""></span><ul><li id="index::d">c<span class="indexer" data-index="d"></span></li></ul></li></ul>'], '']);
|
package/src/parser/block.ts
CHANGED
|
@@ -58,51 +58,53 @@ export const block: BlockParser = reset(
|
|
|
58
58
|
input => {
|
|
59
59
|
const { context: { source, position } } = input;
|
|
60
60
|
if (position === source.length) return;
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
case '
|
|
67
|
-
return codeblock(input);
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
return
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
61
|
+
const fst = source[position];
|
|
62
|
+
switch (fst) {
|
|
63
|
+
case '=':
|
|
64
|
+
if (source.startsWith('===', position)) return pagebreak(input);
|
|
65
|
+
break;
|
|
66
|
+
case '`':
|
|
67
|
+
if (source.startsWith('```', position)) return codeblock(input);
|
|
68
|
+
break;
|
|
69
|
+
case '~':
|
|
70
|
+
if (source.startsWith('~~~', position)) return extension(input);
|
|
71
|
+
if (source[position + 1] === ' ') return dlist(input);
|
|
72
|
+
break;
|
|
73
|
+
case '-':
|
|
74
|
+
if (source[position + 1] === ' ') return ulist(input) || ilist(input);
|
|
75
|
+
break;
|
|
76
|
+
case '+':
|
|
77
|
+
case '*':
|
|
78
|
+
if (source[position + 1] === ' ') return ilist(input);
|
|
79
|
+
break;
|
|
80
|
+
case '[':
|
|
81
|
+
switch (source[position + 1]) {
|
|
82
|
+
case '$':
|
|
83
|
+
return extension(input);
|
|
84
|
+
case '!':
|
|
85
|
+
return mediablock(input);
|
|
86
|
+
}
|
|
87
|
+
break;
|
|
88
|
+
case '!':
|
|
89
|
+
if (source[position + 1] === '>') return blockquote(input);
|
|
75
90
|
return mediablock(input);
|
|
76
|
-
case '
|
|
91
|
+
case '>':
|
|
92
|
+
if (source[position + 1] === '>') return blockquote(input) || reply(input);
|
|
77
93
|
return blockquote(input);
|
|
78
|
-
case '>>':
|
|
79
|
-
return blockquote(input)
|
|
80
|
-
|| reply(input);
|
|
81
|
-
case '- ':
|
|
82
|
-
return ulist(input)
|
|
83
|
-
|| ilist(input);
|
|
84
|
-
case '+ ':
|
|
85
|
-
case '* ':
|
|
86
|
-
return ilist(input);
|
|
87
|
-
case '~ ':
|
|
88
|
-
return dlist(input);
|
|
89
|
-
}
|
|
90
|
-
switch (source[position]) {
|
|
91
94
|
case '#':
|
|
92
95
|
return heading(input);
|
|
93
|
-
case '|':
|
|
94
|
-
return table(input)
|
|
95
|
-
|| sidefence(input);
|
|
96
96
|
case '$':
|
|
97
|
+
if (source[position + 1] === '$') return mathblock(input);
|
|
97
98
|
return extension(input);
|
|
98
|
-
case '
|
|
99
|
-
return
|
|
100
|
-
case '
|
|
101
|
-
return
|
|
99
|
+
case '|':
|
|
100
|
+
return table(input) || sidefence(input);
|
|
101
|
+
case '(':
|
|
102
|
+
return olist(input);
|
|
103
|
+
default:
|
|
104
|
+
if ('0' <= fst && fst <= '9') return olist(input);
|
|
102
105
|
}
|
|
103
106
|
},
|
|
104
107
|
emptyline,
|
|
105
|
-
olist,
|
|
106
108
|
paragraph
|
|
107
109
|
]) as any));
|
|
108
110
|
|
|
@@ -17,7 +17,7 @@ describe('Unit: parser/inline/annotation', () => {
|
|
|
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);
|
|
@@ -41,6 +41,7 @@ describe('Unit: parser/inline/bracket', () => {
|
|
|
41
41
|
assert.deepStrictEqual(inspect(parser('(ABBR, ABBR)'), ctx), [['(', 'ABBR, ABBR', ')'], '']);
|
|
42
42
|
assert.deepStrictEqual(inspect(parser('(\\a)'), ctx), [['<span class="paren">(a)</span>'], '']);
|
|
43
43
|
assert.deepStrictEqual(inspect(parser('(==)'), ctx), [['<span class="paren">(==)</span>'], '']);
|
|
44
|
+
assert.deepStrictEqual(inspect(parser('("(\n))"(")'), ctx), [['<span class="paren">("(<br>)</span>'], ')"(")']);
|
|
44
45
|
assert.deepStrictEqual(inspect(parser('($)$'), ctx), [['(', '<span class="math" translate="no" data-src="$)$">$)$</span>'], '']);
|
|
45
46
|
assert.deepStrictEqual(inspect(parser(')'), ctx), undefined);
|
|
46
47
|
assert.deepStrictEqual(inspect(parser('(1,2)'), ctx), [['(', '1,2', ')'], '']);
|
|
@@ -82,8 +83,9 @@ describe('Unit: parser/inline/bracket', () => {
|
|
|
82
83
|
assert.deepStrictEqual(inspect(parser('"(")"'), ctx), [['"', '(', '"'], ')"']);
|
|
83
84
|
assert.deepStrictEqual(inspect(parser('"(("'), ctx), [['"', '(', '(', '"'], '']);
|
|
84
85
|
assert.deepStrictEqual(inspect(parser('"(\\")"'), ctx), [['"', '<span class="paren">(")</span>', '"'], '']);
|
|
85
|
-
assert.deepStrictEqual(inspect(parser('"\n"'), ctx), [['"', '
|
|
86
|
-
assert.deepStrictEqual(inspect(parser('"\n"
|
|
86
|
+
assert.deepStrictEqual(inspect(parser('"(\n)"(")'), ctx), [['"', '('], '\n)"(")']);
|
|
87
|
+
assert.deepStrictEqual(inspect(parser('"\n"'), ctx), [['"'], '\n"']);
|
|
88
|
+
assert.deepStrictEqual(inspect(parser('"\n"(")'), ctx), [['"'], '\n"(")']);
|
|
87
89
|
});
|
|
88
90
|
|
|
89
91
|
});
|
|
@@ -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]));
|
|
@@ -40,6 +40,7 @@ describe('Unit: parser/inline/emphasis', () => {
|
|
|
40
40
|
|
|
41
41
|
it('nest', () => {
|
|
42
42
|
assert.deepStrictEqual(inspect(parser('*a *b**'), ctx), [['<em>a <em>b</em></em>'], '']);
|
|
43
|
+
assert.deepStrictEqual(inspect(parser('*- *b**'), ctx), [['<em>- <em>b</em></em>'], '']);
|
|
43
44
|
assert.deepStrictEqual(inspect(parser('*a **b***'), ctx), [['<em>a <strong>b</strong></em>'], '']);
|
|
44
45
|
assert.deepStrictEqual(inspect(parser('*a\\ *b**'), ctx), [['<em>a <em>b</em></em>'], '']);
|
|
45
46
|
assert.deepStrictEqual(inspect(parser('*a	*b**'), ctx), [['<em>a\t<em>b</em></em>'], '']);
|