securemark 0.300.4 → 0.300.6
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/dist/index.js +215 -151
- package/markdown.d.ts +36 -36
- package/package.json +1 -1
- package/src/api/bind.ts +5 -2
- package/src/api/header.ts +1 -1
- package/src/api/parse.test.ts +0 -27
- package/src/api/parse.ts +8 -2
- package/src/combinator/effect/backtrack.ts +19 -7
- package/src/combinator/parser/list.ts +13 -15
- package/src/combinator/parser.ts +3 -5
- package/src/debug.test.ts +3 -0
- package/src/parser/autolink.ts +2 -2
- package/src/parser/block/blockquote.test.ts +4 -4
- package/src/parser/block/blockquote.ts +2 -1
- package/src/parser/block/extension/aside.test.ts +3 -3
- package/src/parser/block/extension/aside.ts +2 -1
- package/src/parser/block/extension/example.test.ts +3 -3
- package/src/parser/block/extension/example.ts +3 -1
- package/src/parser/{header.test.ts → block/header.test.ts} +3 -3
- package/src/parser/{header.ts → block/header.ts} +7 -7
- package/src/parser/block/reply/cite.ts +2 -3
- package/src/parser/block/reply/quote.ts +1 -2
- package/src/parser/block/reply.ts +1 -2
- package/src/parser/block.ts +6 -5
- package/src/parser/context.ts +6 -4
- package/src/parser/document.ts +22 -11
- package/src/parser/inline/annotation.test.ts +24 -0
- package/src/parser/inline/annotation.ts +20 -7
- package/src/parser/inline/extension/index.ts +1 -2
- package/src/parser/inline/extension/indexee.ts +1 -2
- package/src/parser/inline/extension/label.ts +10 -6
- package/src/parser/inline/html.ts +1 -2
- package/src/parser/inline/htmlentity.ts +5 -4
- package/src/parser/inline/media.ts +2 -3
- package/src/parser/inline/reference.ts +3 -3
- package/src/parser/inline.ts +2 -2
- package/src/parser/node.ts +0 -5
- package/src/parser/segment.ts +2 -2
- package/src/parser/source/escapable.ts +5 -6
- package/src/parser/source/str.ts +3 -2
- package/src/parser/source/text.ts +3 -4
- package/src/parser/source/unescapable.ts +3 -4
- package/src/parser/source.ts +2 -2
- package/src/parser/util.ts +9 -0
- package/src/parser/visibility.ts +4 -5
- package/src/processor/figure.test.ts +35 -24
- package/src/processor/figure.ts +8 -23
- package/src/processor/note.test.ts +71 -25
- package/src/processor/note.ts +28 -24
- package/src/util/toc.ts +2 -3
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import { figure } from './figure';
|
|
2
|
-
import { ParserOptions } from '../..';
|
|
3
2
|
import { run, parse as parse_ } from '../api';
|
|
3
|
+
import { Opts } from '../api/parse';
|
|
4
|
+
import { List, Node } from '../combinator/parser';
|
|
4
5
|
import { html } from 'typed-dom/dom';
|
|
5
6
|
import { normalize } from '../debug.test';
|
|
6
7
|
|
|
7
|
-
const parse = (s: string, o?:
|
|
8
|
+
const parse = (s: string, o?: Opts) => parse_(s, { test: true, ...o });
|
|
8
9
|
|
|
9
10
|
describe('Unit: processor/figure', () => {
|
|
10
11
|
describe('figure', () => {
|
|
11
12
|
it('empty', () => {
|
|
12
|
-
const
|
|
13
|
+
const labels = new List<Node<HTMLAnchorElement>>();
|
|
14
|
+
const target = run(parse('', { labels }));
|
|
13
15
|
for (let i = 0; i < 3; ++i) {
|
|
14
|
-
[...figure(target)];
|
|
16
|
+
[...figure(target, labels)];
|
|
15
17
|
assert.deepStrictEqual(
|
|
16
18
|
[...target.children].map(el => normalize(el.outerHTML)),
|
|
17
19
|
[]);
|
|
@@ -19,14 +21,15 @@ describe('Unit: processor/figure', () => {
|
|
|
19
21
|
});
|
|
20
22
|
|
|
21
23
|
it('one', () => {
|
|
24
|
+
const labels = new List<Node<HTMLAnchorElement>>();
|
|
22
25
|
const target = run(parse([
|
|
23
26
|
'$test-a\n> ',
|
|
24
27
|
'$test-a',
|
|
25
28
|
'$test-b',
|
|
26
29
|
'$test-a',
|
|
27
|
-
].join('\n\n')));
|
|
30
|
+
].join('\n\n'), { labels }));
|
|
28
31
|
for (let i = 0; i < 3; ++i) {
|
|
29
|
-
[...figure(target)];
|
|
32
|
+
[...figure(target, labels)];
|
|
30
33
|
assert.deepStrictEqual(
|
|
31
34
|
[...target.children].map(el => normalize(el.outerHTML)),
|
|
32
35
|
[
|
|
@@ -39,6 +42,7 @@ describe('Unit: processor/figure', () => {
|
|
|
39
42
|
});
|
|
40
43
|
|
|
41
44
|
it('some', () => {
|
|
45
|
+
const labels = new List<Node<HTMLAnchorElement>>();
|
|
42
46
|
const target = run(parse([
|
|
43
47
|
'$test-a\n> ',
|
|
44
48
|
'## 0',
|
|
@@ -46,9 +50,9 @@ describe('Unit: processor/figure', () => {
|
|
|
46
50
|
'$quote-a\n> ',
|
|
47
51
|
'$test-b\n> ',
|
|
48
52
|
'$test-c\n> ',
|
|
49
|
-
].join('\n\n')));
|
|
53
|
+
].join('\n\n'), { labels }));
|
|
50
54
|
for (let i = 0; i < 3; ++i) {
|
|
51
|
-
[...figure(target)];
|
|
55
|
+
[...figure(target, labels)];
|
|
52
56
|
assert.deepStrictEqual(
|
|
53
57
|
[...target.children].map(el => normalize(el.outerHTML)),
|
|
54
58
|
[
|
|
@@ -63,12 +67,13 @@ describe('Unit: processor/figure', () => {
|
|
|
63
67
|
});
|
|
64
68
|
|
|
65
69
|
it('number', () => {
|
|
70
|
+
const labels = new List<Node<HTMLAnchorElement>>();
|
|
66
71
|
const target = run(parse([
|
|
67
72
|
'$-a\n$$\n$$',
|
|
68
73
|
'$-a',
|
|
69
|
-
].join('\n\n')));
|
|
74
|
+
].join('\n\n'), { labels }));
|
|
70
75
|
for (let i = 0; i < 3; ++i) {
|
|
71
|
-
[...figure(target)];
|
|
76
|
+
[...figure(target, labels)];
|
|
72
77
|
assert.deepStrictEqual(
|
|
73
78
|
[...target.children].map(el => normalize(el.outerHTML)),
|
|
74
79
|
[
|
|
@@ -79,6 +84,7 @@ describe('Unit: processor/figure', () => {
|
|
|
79
84
|
});
|
|
80
85
|
|
|
81
86
|
it('fixed', () => {
|
|
87
|
+
const labels = new List<Node<HTMLAnchorElement>>();
|
|
82
88
|
const target = run(parse([
|
|
83
89
|
'$test-2\n> ',
|
|
84
90
|
'$test-3.1\n> ',
|
|
@@ -88,9 +94,9 @@ describe('Unit: processor/figure', () => {
|
|
|
88
94
|
'$test-2',
|
|
89
95
|
'$-4.1.1',
|
|
90
96
|
'$test-1',
|
|
91
|
-
].join('\n\n')));
|
|
97
|
+
].join('\n\n'), { labels }));
|
|
92
98
|
for (let i = 0; i < 3; ++i) {
|
|
93
|
-
[...figure(target)];
|
|
99
|
+
[...figure(target, labels)];
|
|
94
100
|
assert.deepStrictEqual(
|
|
95
101
|
[...target.children].map(el => normalize(el.outerHTML)),
|
|
96
102
|
[
|
|
@@ -107,19 +113,20 @@ describe('Unit: processor/figure', () => {
|
|
|
107
113
|
});
|
|
108
114
|
|
|
109
115
|
it('separation', () => {
|
|
116
|
+
const labels = new List<Node<HTMLAnchorElement>>();
|
|
110
117
|
const target = html('blockquote', run(parse([
|
|
111
118
|
'!>> ~~~figure $test-a\n>> > \n>>\n~~~\n> ~~~figure $test-a\n> > \n>\n~~~',
|
|
112
119
|
'~~~~example/markdown\n~~~figure $test-a\n> \n\n~~~\n\n$test-a\n~~~~',
|
|
113
120
|
'~~~figure $test-b\n> \n\n~~~',
|
|
114
121
|
'~~~figure $test-a\n> \n\n~~~',
|
|
115
|
-
].join('\n\n'))).children);
|
|
122
|
+
].join('\n\n'), { labels })).children);
|
|
116
123
|
for (let i = 0; i < 3; ++i) {
|
|
117
|
-
[...figure(target)];
|
|
124
|
+
[...figure(target, labels)];
|
|
118
125
|
assert.deepStrictEqual(
|
|
119
126
|
[...target.children].map(el => normalize(el.outerHTML)),
|
|
120
127
|
[
|
|
121
128
|
'<blockquote><blockquote><section><figure data-type="quote" data-label="test-a" data-group="test" data-number="1" id="label:random:test-a"><figcaption><span class="figindex">Test 1. </span><span class="figtext"></span></figcaption><div><blockquote></blockquote></div></figure><h2>References</h2><ol class="references"></ol></section></blockquote><section><figure data-type="quote" data-label="test-a" data-group="test" data-number="1" id="label:random:test-a"><figcaption><span class="figindex">Test 1. </span><span class="figtext"></span></figcaption><div><blockquote></blockquote></div></figure><h2>References</h2><ol class="references"></ol></section></blockquote>',
|
|
122
|
-
'<aside class="example" data-type="markdown"><pre translate="no">~~~figure $test-a\n> \n\n~~~\n\n$test-a</pre><hr><section><figure data-type="quote" data-label="test-a" data-group="test" data-number="1" id="label:random:test-a"><figcaption><span class="figindex">Test 1. </span><span class="figtext"></span></figcaption><div><blockquote></blockquote></div></figure><p><a class="label
|
|
129
|
+
'<aside class="example" data-type="markdown"><pre translate="no">~~~figure $test-a\n> \n\n~~~\n\n$test-a</pre><hr><section><figure data-type="quote" data-label="test-a" data-group="test" data-number="1" id="label:random:test-a"><figcaption><span class="figindex">Test 1. </span><span class="figtext"></span></figcaption><div><blockquote></blockquote></div></figure><p><a class="label" data-label="test-a" href="#label:random:test-a">Test 1</a></p><h2>References</h2><ol class="references"></ol></section></aside>',
|
|
123
130
|
'<figure data-type="quote" data-label="test-b" data-group="test" data-number="1" id="label:test-b"><figcaption><span class="figindex">Test 1. </span><span class="figtext"></span></figcaption><div><blockquote></blockquote></div></figure>',
|
|
124
131
|
'<figure data-type="quote" data-label="test-a" data-group="test" data-number="2" id="label:test-a"><figcaption><span class="figindex">Test 2. </span><span class="figtext"></span></figcaption><div><blockquote></blockquote></div></figure>',
|
|
125
132
|
]);
|
|
@@ -127,6 +134,7 @@ describe('Unit: processor/figure', () => {
|
|
|
127
134
|
});
|
|
128
135
|
|
|
129
136
|
it('base', () => {
|
|
137
|
+
const labels = new List<Node<HTMLAnchorElement>>();
|
|
130
138
|
const target = run(parse([
|
|
131
139
|
'# 0',
|
|
132
140
|
'$-0.0',
|
|
@@ -163,9 +171,9 @@ describe('Unit: processor/figure', () => {
|
|
|
163
171
|
'$test-i\n> ',
|
|
164
172
|
'# 0',
|
|
165
173
|
'$test-j\n> ',
|
|
166
|
-
].join('\n\n')));
|
|
174
|
+
].join('\n\n'), { labels }));
|
|
167
175
|
for (let i = 0; i < 3; ++i) {
|
|
168
|
-
[...figure(target)];
|
|
176
|
+
[...figure(target, labels)];
|
|
169
177
|
assert.deepStrictEqual(
|
|
170
178
|
[...target.children].map(el => normalize(el.outerHTML)),
|
|
171
179
|
[
|
|
@@ -174,7 +182,7 @@ describe('Unit: processor/figure', () => {
|
|
|
174
182
|
'<h2 id="index::0">0</h2>',
|
|
175
183
|
'<figure data-type="quote" data-label="test-1" data-group="test" data-number="1" id="label:test-1"><figcaption><span class="figindex">Test 1. </span><span class="figtext"></span></figcaption><div><blockquote></blockquote></div></figure>',
|
|
176
184
|
'<h2 id="index::0">0</h2>',
|
|
177
|
-
'<blockquote><section><h2 id="index:random:0"
|
|
185
|
+
'<blockquote><section><h2 id="index:random:0">0</h2><h2>References</h2><ol class="references"></ol></section></blockquote>',
|
|
178
186
|
'<figure data-type="quote" data-label="test-b" data-group="test" data-number="2.1" id="label:test-b"><figcaption><span class="figindex">Test 2.1. </span><span class="figtext"></span></figcaption><div><blockquote></blockquote></div></figure>',
|
|
179
187
|
'<h2 id="index::0">0</h2>',
|
|
180
188
|
'<figure data-label="$-0.0.0" data-group="$" class="invalid"></figure>',
|
|
@@ -209,6 +217,7 @@ describe('Unit: processor/figure', () => {
|
|
|
209
217
|
});
|
|
210
218
|
|
|
211
219
|
it('concat', () => {
|
|
220
|
+
const labels = new List<Node<HTMLAnchorElement>>();
|
|
212
221
|
const target = run(parse([
|
|
213
222
|
'$-0.0',
|
|
214
223
|
'## 0',
|
|
@@ -229,9 +238,9 @@ describe('Unit: processor/figure', () => {
|
|
|
229
238
|
'## 0',
|
|
230
239
|
'$-9.0',
|
|
231
240
|
'$test-e\n> ',
|
|
232
|
-
].join('\n\n')));
|
|
241
|
+
].join('\n\n'), { labels }));
|
|
233
242
|
for (let i = 0; i < 3; ++i) {
|
|
234
|
-
[...figure(target)];
|
|
243
|
+
[...figure(target, labels)];
|
|
235
244
|
assert.deepStrictEqual(
|
|
236
245
|
[...target.children].map(el => normalize(el.outerHTML)),
|
|
237
246
|
[
|
|
@@ -259,13 +268,14 @@ describe('Unit: processor/figure', () => {
|
|
|
259
268
|
});
|
|
260
269
|
|
|
261
270
|
it('verbose', () => {
|
|
271
|
+
const labels = new List<Node<HTMLAnchorElement>>();
|
|
262
272
|
const target = run(parse([
|
|
263
273
|
'~~~figure [$test-a]\n> \n\n~~~',
|
|
264
274
|
'[$test-a]',
|
|
265
275
|
'[$test-a]',
|
|
266
|
-
].join('\n\n')));
|
|
276
|
+
].join('\n\n'), { labels }));
|
|
267
277
|
for (let i = 0; i < 3; ++i) {
|
|
268
|
-
[...figure(target)];
|
|
278
|
+
[...figure(target, labels)];
|
|
269
279
|
assert.deepStrictEqual(
|
|
270
280
|
[...target.children].map(el => normalize(el.outerHTML)),
|
|
271
281
|
[
|
|
@@ -277,13 +287,14 @@ describe('Unit: processor/figure', () => {
|
|
|
277
287
|
});
|
|
278
288
|
|
|
279
289
|
it('id', () => {
|
|
290
|
+
const labels = new List<Node<HTMLAnchorElement>>();
|
|
280
291
|
const target = run(parse([
|
|
281
292
|
'$test-a\n> ',
|
|
282
293
|
'==$test-a==',
|
|
283
294
|
'- $test-a',
|
|
284
|
-
].join('\n\n'), { id: '0' }));
|
|
295
|
+
].join('\n\n'), { id: '0', labels }));
|
|
285
296
|
for (let i = 0; i < 3; ++i) {
|
|
286
|
-
[...figure(target, undefined, { id: '0' })];
|
|
297
|
+
[...figure(target, labels, undefined, { id: '0' })];
|
|
287
298
|
assert.deepStrictEqual(
|
|
288
299
|
[...target.children].map(el => normalize(el.outerHTML)),
|
|
289
300
|
[
|
package/src/processor/figure.ts
CHANGED
|
@@ -1,38 +1,26 @@
|
|
|
1
|
+
import { List, Node } from '../combinator/parser';
|
|
1
2
|
import { number as calculate, isFixed } from '../parser/inline/extension/label';
|
|
2
|
-
import { markInvalid, unmarkInvalid } from '../parser/util';
|
|
3
|
+
import { markInvalid, unmarkInvalid, collect } from '../parser/util';
|
|
3
4
|
import { MultiQueue } from 'spica/queue';
|
|
4
|
-
import { push } from 'spica/array';
|
|
5
5
|
import { define } from 'typed-dom/dom';
|
|
6
6
|
|
|
7
7
|
export function* figure(
|
|
8
|
-
target: ParentNode & Node,
|
|
8
|
+
target: ParentNode & global.Node,
|
|
9
|
+
list: List<Node<HTMLAnchorElement>>,
|
|
9
10
|
notes?: { readonly references: HTMLOListElement; },
|
|
10
11
|
opts: {
|
|
11
12
|
readonly id?: string;
|
|
12
|
-
readonly local?: boolean;
|
|
13
13
|
} = {},
|
|
14
14
|
): Generator<undefined, undefined, undefined> {
|
|
15
|
-
const selector = ':is(figure[data-label], h1, h2)';
|
|
16
15
|
const refs = new MultiQueue<string, HTMLAnchorElement>(
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
target.querySelectorAll('a.label:not(.local)[data-label]'),
|
|
20
|
-
el => [el.getAttribute('data-label')!, el])
|
|
21
|
-
: push(
|
|
22
|
-
Array.from(
|
|
23
|
-
target.querySelectorAll('a.label:not(.local)[data-label]'),
|
|
24
|
-
el => [el.getAttribute('data-label')!, el] as const),
|
|
25
|
-
Array.from(
|
|
26
|
-
notes.references.querySelectorAll('a.label:not(.local)'),
|
|
27
|
-
el => [el.getAttribute('data-label')!, el] as const)));
|
|
16
|
+
list.foldl<[string, HTMLAnchorElement][]>((acc, { value: el }) =>
|
|
17
|
+
(acc.push([el.getAttribute('data-label')!, el] as const), acc), []));
|
|
28
18
|
const labels = new Set<string>();
|
|
29
19
|
const numbers = new Map<string, string>();
|
|
30
20
|
let base = '0';
|
|
31
21
|
let bases: readonly string[] = base.split('.');
|
|
32
22
|
for (
|
|
33
|
-
let defs = target
|
|
34
|
-
? target.querySelectorAll(`:scope > ${selector}`)
|
|
35
|
-
: target.querySelectorAll(`:not(* > *)${selector}`),
|
|
23
|
+
let defs = collect(target, 'figure[data-label], h1, h2'),
|
|
36
24
|
len = defs.length, i = 0; i < len; ++i) {
|
|
37
25
|
if (~i << 32 - 8 === 0) yield;
|
|
38
26
|
const def = defs[i];
|
|
@@ -128,10 +116,7 @@ export function* figure(
|
|
|
128
116
|
}
|
|
129
117
|
if (ref.hash.slice(1) === def.id && ref.innerText === figindex) continue;
|
|
130
118
|
define(ref,
|
|
131
|
-
{
|
|
132
|
-
class: opts.local ? `${ref.className} local` : undefined,
|
|
133
|
-
href: opts.id !== '' ? `#${def.id}` : undefined,
|
|
134
|
-
},
|
|
119
|
+
{ href: opts.id !== '' ? `#${def.id}` : undefined, },
|
|
135
120
|
figindex);
|
|
136
121
|
}
|
|
137
122
|
}
|
|
@@ -1,24 +1,34 @@
|
|
|
1
1
|
import { note } from './note';
|
|
2
2
|
import { run, parse as parse_ } from '../api';
|
|
3
|
+
import { Opts } from '../api/parse';
|
|
4
|
+
import { List, Node } from '../combinator/parser';
|
|
3
5
|
import { html } from 'typed-dom/dom';
|
|
4
6
|
import { normalize } from '../debug.test';
|
|
5
7
|
|
|
6
|
-
const parse = (s: string) => parse_(s, { test: true });
|
|
8
|
+
const parse = (s: string, o?: Opts) => parse_(s, { test: true, ...o });
|
|
7
9
|
|
|
8
10
|
describe('Unit: processor/note', () => {
|
|
9
11
|
describe('annotation', () => {
|
|
10
12
|
it('empty', () => {
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
+
const lists = {
|
|
14
|
+
annotations: new List<Node<HTMLElement>>(),
|
|
15
|
+
references: new List<Node<HTMLElement>>(),
|
|
16
|
+
};
|
|
17
|
+
const target = run(parse('', lists));
|
|
18
|
+
[...note(target, lists)];
|
|
13
19
|
assert.deepStrictEqual(
|
|
14
20
|
[...target.children].map(el => normalize(el.outerHTML)),
|
|
15
21
|
[]);
|
|
16
22
|
});
|
|
17
23
|
|
|
18
24
|
it('1', () => {
|
|
19
|
-
const
|
|
25
|
+
const lists = {
|
|
26
|
+
annotations: new List<Node<HTMLElement>>(),
|
|
27
|
+
references: new List<Node<HTMLElement>>(),
|
|
28
|
+
};
|
|
29
|
+
const target = run(parse('((a b))', lists));
|
|
20
30
|
for (let i = 0; i < 3; ++i) {
|
|
21
|
-
assert.deepStrictEqual([...note(target)].length, 1);
|
|
31
|
+
assert.deepStrictEqual([...note(target, lists)].length, 1);
|
|
22
32
|
assert.deepStrictEqual(
|
|
23
33
|
[...target.children].map(el => normalize(el.outerHTML)),
|
|
24
34
|
[
|
|
@@ -38,9 +48,13 @@ describe('Unit: processor/note', () => {
|
|
|
38
48
|
});
|
|
39
49
|
|
|
40
50
|
it('2', () => {
|
|
41
|
-
const
|
|
51
|
+
const lists = {
|
|
52
|
+
annotations: new List<Node<HTMLElement>>(),
|
|
53
|
+
references: new List<Node<HTMLElement>>(),
|
|
54
|
+
};
|
|
55
|
+
const target = run(parse('((1))((12345678901234567890))', lists));
|
|
42
56
|
for (let i = 0; i < 3; ++i) {
|
|
43
|
-
assert.deepStrictEqual([...note(target)].length, 1);
|
|
57
|
+
assert.deepStrictEqual([...note(target, lists)].length, 1);
|
|
44
58
|
assert.deepStrictEqual(
|
|
45
59
|
[...target.children].map(el => normalize(el.outerHTML)),
|
|
46
60
|
[
|
|
@@ -67,9 +81,13 @@ describe('Unit: processor/note', () => {
|
|
|
67
81
|
});
|
|
68
82
|
|
|
69
83
|
it('unify', () => {
|
|
70
|
-
const
|
|
84
|
+
const lists = {
|
|
85
|
+
annotations: new List<Node<HTMLElement>>(),
|
|
86
|
+
references: new List<Node<HTMLElement>>(),
|
|
87
|
+
};
|
|
88
|
+
const target = run(parse('((1))((2))((3))((2))((4))', lists));
|
|
71
89
|
for (let i = 0; i < 3; ++i) {
|
|
72
|
-
[...note(target)];
|
|
90
|
+
[...note(target, lists)];
|
|
73
91
|
assert.deepStrictEqual(
|
|
74
92
|
[...target.children].map(el => normalize(el.outerHTML)),
|
|
75
93
|
[
|
|
@@ -116,18 +134,22 @@ describe('Unit: processor/note', () => {
|
|
|
116
134
|
});
|
|
117
135
|
|
|
118
136
|
it('separation', () => {
|
|
137
|
+
const lists = {
|
|
138
|
+
annotations: new List<Node<HTMLElement>>(),
|
|
139
|
+
references: new List<Node<HTMLElement>>(),
|
|
140
|
+
};
|
|
119
141
|
const target = run(parse([
|
|
120
142
|
'!>> ((1))\n> ((2))\n~~~',
|
|
121
143
|
'~~~~example/markdown\n((3))\n~~~~',
|
|
122
144
|
'((4))',
|
|
123
|
-
].join('\n\n')));
|
|
145
|
+
].join('\n\n'), lists));
|
|
124
146
|
for (let i = 0; i < 3; ++i) {
|
|
125
|
-
[...note(target)];
|
|
147
|
+
[...note(target, lists)];
|
|
126
148
|
assert.deepStrictEqual(
|
|
127
149
|
[...target.children].map(el => normalize(el.outerHTML)),
|
|
128
150
|
[
|
|
129
|
-
'<blockquote><blockquote><section><p><sup class="annotation
|
|
130
|
-
'<aside class="example" data-type="markdown"><pre translate="no">((3))</pre><hr><section><p><sup class="annotation
|
|
151
|
+
'<blockquote><blockquote><section><p><sup class="annotation" id="annotation:random:ref:1:1" title="1"><a href="#annotation:random:def:1:1">*1</a></sup></p><ol class="annotations"><li id="annotation:random:def:1:1" data-marker="*1"><span>1</span><sup><a href="#annotation:random:ref:1:1">^1</a></sup></li></ol><h2>References</h2><ol class="references"></ol></section></blockquote><section><p><sup class="annotation" id="annotation:random:ref:2:1" title="2"><a href="#annotation:random:def:2:1">*1</a></sup><br>~~~</p><ol class="annotations"><li id="annotation:random:def:2:1" data-marker="*1"><span>2</span><sup><a href="#annotation:random:ref:2:1">^1</a></sup></li></ol><h2>References</h2><ol class="references"></ol></section></blockquote>',
|
|
152
|
+
'<aside class="example" data-type="markdown"><pre translate="no">((3))</pre><hr><section><p><sup class="annotation" id="annotation:random:ref:3:1" title="3"><a href="#annotation:random:def:3:1">*1</a></sup></p><ol class="annotations"><li id="annotation:random:def:3:1" data-marker="*1"><span>3</span><sup><a href="#annotation:random:ref:3:1">^1</a></sup></li></ol><h2>References</h2><ol class="references"></ol></section></aside>',
|
|
131
153
|
'<p><sup class="annotation" id="annotation::ref:4:1" title="4"><a href="#annotation::def:4:1">*1</a></sup></p>',
|
|
132
154
|
'<ol class="annotations"><li id="annotation::def:4:1" data-marker="*1"><span>4</span><sup><a href="#annotation::ref:4:1">^1</a></sup></li></ol>',
|
|
133
155
|
]);
|
|
@@ -135,9 +157,13 @@ describe('Unit: processor/note', () => {
|
|
|
135
157
|
});
|
|
136
158
|
|
|
137
159
|
it('split', () => {
|
|
138
|
-
const
|
|
160
|
+
const lists = {
|
|
161
|
+
annotations: new List<Node<HTMLElement>>(),
|
|
162
|
+
references: new List<Node<HTMLElement>>(),
|
|
163
|
+
};
|
|
164
|
+
const target = run(parse('((1))\n\n## a\n\n((2))((1))((3))((2))\n\n## b\n\n((2))', lists));
|
|
139
165
|
for (let i = 0; i < 3; ++i) {
|
|
140
|
-
[...note(target)];
|
|
166
|
+
[...note(target, lists)];
|
|
141
167
|
assert.deepStrictEqual(
|
|
142
168
|
[...target.children].map(el => normalize(el.outerHTML)),
|
|
143
169
|
[
|
|
@@ -201,9 +227,13 @@ describe('Unit: processor/note', () => {
|
|
|
201
227
|
});
|
|
202
228
|
|
|
203
229
|
it('id', () => {
|
|
204
|
-
const
|
|
230
|
+
const lists = {
|
|
231
|
+
annotations: new List<Node<HTMLElement>>(),
|
|
232
|
+
references: new List<Node<HTMLElement>>(),
|
|
233
|
+
};
|
|
234
|
+
const target = run(parse('((a b))', lists));
|
|
205
235
|
for (let i = 0; i < 3; ++i) {
|
|
206
|
-
assert.deepStrictEqual([...note(target, undefined, { id: '0' })].length, 1);
|
|
236
|
+
assert.deepStrictEqual([...note(target, lists, undefined, { id: '0' })].length, 1);
|
|
207
237
|
assert.deepStrictEqual(
|
|
208
238
|
[...target.children].map(el => normalize(el.outerHTML)),
|
|
209
239
|
[
|
|
@@ -223,9 +253,13 @@ describe('Unit: processor/note', () => {
|
|
|
223
253
|
});
|
|
224
254
|
|
|
225
255
|
it('nest', () => {
|
|
226
|
-
const
|
|
256
|
+
const lists = {
|
|
257
|
+
annotations: new List<Node<HTMLElement>>(),
|
|
258
|
+
references: new List<Node<HTMLElement>>(),
|
|
259
|
+
};
|
|
260
|
+
const target = run(parse('((a((b))))((a))((b))', lists));
|
|
227
261
|
for (let i = 0; i < 3; ++i) {
|
|
228
|
-
[...note(target)];
|
|
262
|
+
[...note(target, lists)];
|
|
229
263
|
assert.deepStrictEqual(
|
|
230
264
|
[...target.children].map(el => normalize(el.outerHTML)),
|
|
231
265
|
[
|
|
@@ -278,10 +312,14 @@ describe('Unit: processor/note', () => {
|
|
|
278
312
|
|
|
279
313
|
describe('reference', () => {
|
|
280
314
|
it('1', () => {
|
|
281
|
-
const
|
|
315
|
+
const lists = {
|
|
316
|
+
annotations: new List<Node<HTMLElement>>(),
|
|
317
|
+
references: new List<Node<HTMLElement>>(),
|
|
318
|
+
};
|
|
319
|
+
const target = run(parse('[[a b]]', lists));
|
|
282
320
|
const notes = { references: html('ol') };
|
|
283
321
|
for (let i = 0; i < 3; ++i) {
|
|
284
|
-
[...note(target, notes)];
|
|
322
|
+
[...note(target, lists, notes)];
|
|
285
323
|
assert.deepStrictEqual(
|
|
286
324
|
[...target.children].map(el => normalize(el.outerHTML)),
|
|
287
325
|
[
|
|
@@ -305,10 +343,14 @@ describe('Unit: processor/note', () => {
|
|
|
305
343
|
});
|
|
306
344
|
|
|
307
345
|
it('abbr', () => {
|
|
308
|
-
const
|
|
346
|
+
const lists = {
|
|
347
|
+
annotations: new List<Node<HTMLElement>>(),
|
|
348
|
+
references: new List<Node<HTMLElement>>(),
|
|
349
|
+
};
|
|
350
|
+
const target = run(parse('[[^A 1]][[^A 1|b]][[^A 1]]', lists));
|
|
309
351
|
const notes = { references: html('ol') };
|
|
310
352
|
for (let i = 0; i < 3; ++i) {
|
|
311
|
-
[...note(target, notes)];
|
|
353
|
+
[...note(target, lists, notes)];
|
|
312
354
|
assert.deepStrictEqual(
|
|
313
355
|
[...target.children].map(el => normalize(el.outerHTML)),
|
|
314
356
|
[
|
|
@@ -342,10 +384,14 @@ describe('Unit: processor/note', () => {
|
|
|
342
384
|
});
|
|
343
385
|
|
|
344
386
|
it('nest', () => {
|
|
345
|
-
const
|
|
387
|
+
const lists = {
|
|
388
|
+
annotations: new List<Node<HTMLElement>>(),
|
|
389
|
+
references: new List<Node<HTMLElement>>(),
|
|
390
|
+
};
|
|
391
|
+
const target = run(parse('((a[[^B]]))[[^B|c]]', lists));
|
|
346
392
|
const notes = { references: html('ol') };
|
|
347
393
|
for (let i = 0; i < 3; ++i) {
|
|
348
|
-
[...note(target, notes)];
|
|
394
|
+
[...note(target, lists, notes)];
|
|
349
395
|
assert.deepStrictEqual(
|
|
350
396
|
[...target.children].map(el => normalize(el.outerHTML)),
|
|
351
397
|
[
|
package/src/processor/note.ts
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
|
+
import { List, Node } from '../combinator/parser';
|
|
1
2
|
import { identity, signature, text } from '../parser/inline/extension/indexee';
|
|
2
|
-
import { markInvalid, unmarkInvalid } from '../parser/util';
|
|
3
|
+
import { markInvalid, unmarkInvalid, collect } from '../parser/util';
|
|
3
4
|
import { memoize } from 'spica/memoize';
|
|
4
5
|
import { html, define } from 'typed-dom/dom';
|
|
5
6
|
|
|
6
7
|
export function* note(
|
|
7
|
-
target: ParentNode & Node,
|
|
8
|
+
target: ParentNode & global.Node,
|
|
9
|
+
lists: {
|
|
10
|
+
readonly annotations: List<Node<HTMLElement>>;
|
|
11
|
+
readonly references: List<Node<HTMLElement>>;
|
|
12
|
+
},
|
|
8
13
|
notes?: {
|
|
9
14
|
readonly annotations?: HTMLOListElement;
|
|
10
15
|
readonly references: HTMLOListElement;
|
|
11
16
|
},
|
|
12
17
|
opts: {
|
|
13
18
|
readonly id?: string;
|
|
14
|
-
readonly local?: boolean;
|
|
15
19
|
} = {},
|
|
16
|
-
bottom: Node | null = null,
|
|
20
|
+
bottom: global.Node | null = null,
|
|
17
21
|
): Generator<HTMLOListElement | undefined, undefined, undefined> {
|
|
18
22
|
const referenceRefMemory = referenceRefsMemoryCaller(target);
|
|
19
23
|
const annotationRefMemory = annotationRefsMemoryCaller(target);
|
|
@@ -23,8 +27,18 @@ export function* note(
|
|
|
23
27
|
}
|
|
24
28
|
memory.clear();
|
|
25
29
|
}
|
|
26
|
-
yield* reference(
|
|
27
|
-
|
|
30
|
+
yield* reference(
|
|
31
|
+
referenceRefMemory,
|
|
32
|
+
target,
|
|
33
|
+
lists.references.foldl<HTMLElement[]>((acc, { value: el }) =>
|
|
34
|
+
(acc.push(el), acc), []),
|
|
35
|
+
notes?.references, opts, bottom);
|
|
36
|
+
yield* annotation(
|
|
37
|
+
annotationRefMemory,
|
|
38
|
+
target,
|
|
39
|
+
lists.annotations.foldl<HTMLElement[]>((acc, { value: el }) =>
|
|
40
|
+
(acc.push(el), acc), []),
|
|
41
|
+
notes?.annotations, opts, bottom);
|
|
28
42
|
}
|
|
29
43
|
|
|
30
44
|
interface RefMemory {
|
|
@@ -34,11 +48,11 @@ interface RefMemory {
|
|
|
34
48
|
readonly text: string;
|
|
35
49
|
}
|
|
36
50
|
|
|
37
|
-
const annotationRefsMemoryCaller = memoize((target: Node) =>
|
|
51
|
+
const annotationRefsMemoryCaller = memoize((target: global.Node) =>
|
|
38
52
|
new Map<HTMLElement, RefMemory>() ?? target,
|
|
39
53
|
new WeakMap());
|
|
40
54
|
|
|
41
|
-
const referenceRefsMemoryCaller = memoize((target: Node) =>
|
|
55
|
+
const referenceRefsMemoryCaller = memoize((target: global.Node) =>
|
|
42
56
|
new Map<HTMLElement, {
|
|
43
57
|
readonly content: Element;
|
|
44
58
|
readonly identifier: string;
|
|
@@ -50,19 +64,16 @@ const referenceRefsMemoryCaller = memoize((target: Node) =>
|
|
|
50
64
|
const annotation = build(
|
|
51
65
|
'annotation',
|
|
52
66
|
'annotations',
|
|
53
|
-
'.annotation:not(:is(.annotations, .references) &, .local)',
|
|
54
67
|
n => `*${n}`,
|
|
55
68
|
'h1, h2, h3, h4, h5, h6, aside.aside, hr, .references');
|
|
56
69
|
const reference = build(
|
|
57
70
|
'reference',
|
|
58
71
|
'references',
|
|
59
|
-
'.reference:not(:is(.annotations, .references) &, .local)',
|
|
60
72
|
(n, abbr) => `[${abbr || n}]`);
|
|
61
73
|
|
|
62
74
|
function build(
|
|
63
75
|
syntax: string,
|
|
64
76
|
list: string,
|
|
65
|
-
selector: string,
|
|
66
77
|
marker: (index: number, abbr: string) => string,
|
|
67
78
|
splitter: string = '',
|
|
68
79
|
) {
|
|
@@ -70,13 +81,13 @@ function build(
|
|
|
70
81
|
splitter &&= `${splitter}, .${list}`;
|
|
71
82
|
return function* (
|
|
72
83
|
memory: Map<HTMLElement, RefMemory>,
|
|
73
|
-
target: ParentNode & Node,
|
|
84
|
+
target: ParentNode & global.Node,
|
|
85
|
+
refs: readonly HTMLElement[],
|
|
74
86
|
note?: HTMLOListElement,
|
|
75
87
|
opts: {
|
|
76
88
|
readonly id?: string;
|
|
77
|
-
readonly local?: boolean;
|
|
78
89
|
} = {},
|
|
79
|
-
bottom: Node | null = null,
|
|
90
|
+
bottom: global.Node | null = null,
|
|
80
91
|
): Generator<HTMLOListElement | undefined, undefined, undefined> {
|
|
81
92
|
const refInfoCaller = memoize((ref: HTMLElement) => {
|
|
82
93
|
const content = ref.firstElementChild!;
|
|
@@ -101,7 +112,6 @@ function build(
|
|
|
101
112
|
};
|
|
102
113
|
}, memory);
|
|
103
114
|
const defs = new Map<string, HTMLLIElement>();
|
|
104
|
-
const refs = target.querySelectorAll<HTMLElement>(selector);
|
|
105
115
|
const identifierInfoCaller = memoize((identifier: string) => ({
|
|
106
116
|
defIndex: 0,
|
|
107
117
|
defSubindex: 0,
|
|
@@ -110,9 +120,7 @@ function build(
|
|
|
110
120
|
queue: [] as HTMLElement[],
|
|
111
121
|
}));
|
|
112
122
|
const splitters = splitter
|
|
113
|
-
? target
|
|
114
|
-
? target.querySelectorAll(`:scope > :is(${splitter}, .${list})`)
|
|
115
|
-
: target.querySelectorAll(`:not(* > *):is(${splitter}, .${list})`)
|
|
123
|
+
? collect(target, `${splitter}, .${list}`)
|
|
116
124
|
: [];
|
|
117
125
|
let iSplitters = 0;
|
|
118
126
|
let total = 0;
|
|
@@ -124,7 +132,7 @@ function build(
|
|
|
124
132
|
if (splitter) for (let splitter; splitter = splitters[iSplitters]; ++iSplitters) {
|
|
125
133
|
assert(splitter.parentNode === target || !splitter.parentNode);
|
|
126
134
|
const pos = splitter?.compareDocumentPosition(ref) ?? 0;
|
|
127
|
-
if (pos & (Node.DOCUMENT_POSITION_PRECEDING | Node.DOCUMENT_POSITION_DISCONNECTED)) break;
|
|
135
|
+
if (pos & (global.Node.DOCUMENT_POSITION_PRECEDING | global.Node.DOCUMENT_POSITION_DISCONNECTED)) break;
|
|
128
136
|
if (~iSplitters << 32 - 8 === 0) yield;
|
|
129
137
|
if (splitter.classList.contains(list) && splitter.nextElementSibling !== splitters[iSplitters + 1]) {
|
|
130
138
|
const note = splitter as HTMLOListElement;
|
|
@@ -176,11 +184,7 @@ function build(
|
|
|
176
184
|
: info.defIndex;
|
|
177
185
|
const title = info.title ||= text;
|
|
178
186
|
assert(syntax !== 'annotation' || title);
|
|
179
|
-
define(ref, {
|
|
180
|
-
id: refId,
|
|
181
|
-
class: opts.local ? `${ref.className} local` : undefined,
|
|
182
|
-
title,
|
|
183
|
-
}, []);
|
|
187
|
+
define(ref, { id: refId, title, }, []);
|
|
184
188
|
if (title && info.queue.length > 0) {
|
|
185
189
|
for (const ref of info.queue) {
|
|
186
190
|
define(ref, { title });
|
package/src/util/toc.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
+
import { collect } from '../parser/util';
|
|
1
2
|
import { push } from 'spica/array';
|
|
2
3
|
import { html } from 'typed-dom/dom';
|
|
3
4
|
|
|
4
|
-
const selector = ':is(h1, h2, h3, h4, h5, h6, aside.aside)[id]:not(.local)';
|
|
5
|
-
|
|
6
5
|
export function toc(source: DocumentFragment | HTMLElement | ShadowRoot): HTMLUListElement {
|
|
7
6
|
const hs: HTMLHeadingElement[] = [];
|
|
8
|
-
for (let es = source.
|
|
7
|
+
for (let es = collect(source, ':is(h1, h2, h3, h4, h5, h6, aside.aside)[id]'),
|
|
9
8
|
len = es.length, i = 0; i < len; ++i) {
|
|
10
9
|
const el = es[i];
|
|
11
10
|
assert(el.parentNode === source);
|