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.
Files changed (51) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/index.js +215 -151
  3. package/markdown.d.ts +36 -36
  4. package/package.json +1 -1
  5. package/src/api/bind.ts +5 -2
  6. package/src/api/header.ts +1 -1
  7. package/src/api/parse.test.ts +0 -27
  8. package/src/api/parse.ts +8 -2
  9. package/src/combinator/effect/backtrack.ts +19 -7
  10. package/src/combinator/parser/list.ts +13 -15
  11. package/src/combinator/parser.ts +3 -5
  12. package/src/debug.test.ts +3 -0
  13. package/src/parser/autolink.ts +2 -2
  14. package/src/parser/block/blockquote.test.ts +4 -4
  15. package/src/parser/block/blockquote.ts +2 -1
  16. package/src/parser/block/extension/aside.test.ts +3 -3
  17. package/src/parser/block/extension/aside.ts +2 -1
  18. package/src/parser/block/extension/example.test.ts +3 -3
  19. package/src/parser/block/extension/example.ts +3 -1
  20. package/src/parser/{header.test.ts → block/header.test.ts} +3 -3
  21. package/src/parser/{header.ts → block/header.ts} +7 -7
  22. package/src/parser/block/reply/cite.ts +2 -3
  23. package/src/parser/block/reply/quote.ts +1 -2
  24. package/src/parser/block/reply.ts +1 -2
  25. package/src/parser/block.ts +6 -5
  26. package/src/parser/context.ts +6 -4
  27. package/src/parser/document.ts +22 -11
  28. package/src/parser/inline/annotation.test.ts +24 -0
  29. package/src/parser/inline/annotation.ts +20 -7
  30. package/src/parser/inline/extension/index.ts +1 -2
  31. package/src/parser/inline/extension/indexee.ts +1 -2
  32. package/src/parser/inline/extension/label.ts +10 -6
  33. package/src/parser/inline/html.ts +1 -2
  34. package/src/parser/inline/htmlentity.ts +5 -4
  35. package/src/parser/inline/media.ts +2 -3
  36. package/src/parser/inline/reference.ts +3 -3
  37. package/src/parser/inline.ts +2 -2
  38. package/src/parser/node.ts +0 -5
  39. package/src/parser/segment.ts +2 -2
  40. package/src/parser/source/escapable.ts +5 -6
  41. package/src/parser/source/str.ts +3 -2
  42. package/src/parser/source/text.ts +3 -4
  43. package/src/parser/source/unescapable.ts +3 -4
  44. package/src/parser/source.ts +2 -2
  45. package/src/parser/util.ts +9 -0
  46. package/src/parser/visibility.ts +4 -5
  47. package/src/processor/figure.test.ts +35 -24
  48. package/src/processor/figure.ts +8 -23
  49. package/src/processor/note.test.ts +71 -25
  50. package/src/processor/note.ts +28 -24
  51. 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?: ParserOptions) => parse_(s, { test: true, ...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 target = run(parse(''));
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&gt; \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 local" data-label="test-a" href="#label:random:test-a">Test 1</a></p><h2>References</h2><ol class="references"></ol></section></aside>',
129
+ '<aside class="example" data-type="markdown"><pre translate="no">~~~figure $test-a\n&gt; \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" class="local">0</h2><h2>References</h2><ol class="references"></ol></section></blockquote>',
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
  [
@@ -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
- !notes || notes.references.parentNode === target
18
- ? Array.from(
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 instanceof Element
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 target = run(parse(''));
12
- [...note(target)];
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 target = run(parse('((a b))'));
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 target = run(parse('((1))((12345678901234567890))'));
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 target = run(parse('((1))((2))((3))((2))((4))'));
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 local" 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 local" 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>',
130
- '<aside class="example" data-type="markdown"><pre translate="no">((3))</pre><hr><section><p><sup class="annotation local" 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>',
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 target = run(parse('((1))\n\n## a\n\n((2))((1))((3))((2))\n\n## b\n\n((2))'));
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 target = run(parse('((a b))'));
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 target = run(parse('((a((b))))((a))((b))'));
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 target = run(parse('[[a b]]'));
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 target = run(parse('[[^A 1]][[^A 1|b]][[^A 1]]'));
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 target = run(parse('((a[[^B]]))[[^B|c]]'));
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
  [
@@ -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(referenceRefMemory, target, notes?.references, opts, bottom);
27
- yield* annotation(annotationRefMemory, target, notes?.annotations, opts, bottom);
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 instanceof Element
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.querySelectorAll(selector),
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);