securemark 0.276.3 → 0.276.5

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 CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.276.5
4
+
5
+ - Refactoring.
6
+
7
+ ## 0.276.4
8
+
9
+ - Refactoring.
10
+
3
11
  ## 0.276.3
4
12
 
5
13
  - Refactoring.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! securemark v0.276.3 https://github.com/falsandtru/securemark | (c) 2017, falsandtru | UNLICENSED License */
1
+ /*! securemark v0.276.5 https://github.com/falsandtru/securemark | (c) 2017, falsandtru | UNLICENSED License */
2
2
  (function webpackUniversalModuleDefinition(root, factory) {
3
3
  if(typeof exports === 'object' && typeof module === 'object')
4
4
  module.exports = factory(require("Prism"), require("DOMPurify"));
@@ -580,7 +580,7 @@ class Cache {
580
580
  LFU.unshift(this.overlap(entry));
581
581
  entry.partition = 'LFU';
582
582
  this.injection = 0;
583
- this.declination = this.overlapLRU * 100 < LFU.length * this.sample ? 1 : (0, alias_1.min)(this.declination * 1.5, 10);
583
+ this.declination = this.overlapLRU * 100 < LFU.length * this.sample ? 1 : (0, alias_1.min)(this.declination * 1.5, 5);
584
584
  }
585
585
  }
586
586
  if (this.sweeper.isActive()) {
@@ -634,7 +634,7 @@ class Cache {
634
634
  if (entry === LRU.head) return;
635
635
  entry.affiliation = 'LFU';
636
636
  } else {
637
- const delta = LRU.length > LFU.length && LRU.length >= this.capacity - this.partition ? LRU.length / (LFU.length || 1) * (0, alias_1.max)(this.overlapLRU / this.overlapLFU, 1) | 0 || 1 : 1;
637
+ const delta = LRU.length >= this.capacity - this.partition ? (0, alias_1.max)(LRU.length / (LFU.length || 1) * (0, alias_1.max)(this.overlapLRU / this.overlapLFU, 1) | 0, 1) : 0;
638
638
  this.partition = (0, alias_1.min)(this.partition + delta, this.capacity - this.window);
639
639
  --this.overlapLFU;
640
640
  }
@@ -643,7 +643,7 @@ class Cache {
643
643
  entry.partition = 'LFU';
644
644
  } else {
645
645
  if (entry.affiliation === 'LFU') {} else {
646
- const delta = LFU.length > LRU.length && LFU.length >= this.partition ? LFU.length / (LRU.length || 1) * (0, alias_1.max)(this.overlapLFU / this.overlapLRU, 1) | 0 || 1 : 1;
646
+ const delta = LFU.length >= this.partition ? (0, alias_1.max)(LFU.length / (LRU.length || 1) * (0, alias_1.max)(this.overlapLFU / this.overlapLRU, 1) | 0, 1) : 0;
647
647
  this.partition = (0, alias_1.max)(this.partition - delta, 0);
648
648
  entry.affiliation = 'LFU';
649
649
  --this.overlapLRU;
@@ -1522,9 +1522,9 @@ class Heap {
1522
1522
  this.$length = 0;
1523
1523
  }
1524
1524
  }
1525
+ exports.Heap = Heap;
1525
1526
  Heap.max = (a, b) => a > b ? -1 : a < b ? 1 : 0;
1526
1527
  Heap.min = (a, b) => a > b ? 1 : a < b ? -1 : 0;
1527
- exports.Heap = Heap;
1528
1528
  function sort(cmp, array, index, length, stable) {
1529
1529
  if (length === 0) return false;
1530
1530
  switch (index) {
@@ -1666,9 +1666,9 @@ class MultiHeap {
1666
1666
  this.$length = 0;
1667
1667
  }
1668
1668
  }
1669
+ exports.MultiHeap = MultiHeap;
1669
1670
  MultiHeap.max = Heap.max;
1670
1671
  MultiHeap.min = Heap.min;
1671
- exports.MultiHeap = MultiHeap;
1672
1672
 
1673
1673
  /***/ }),
1674
1674
 
@@ -1815,7 +1815,7 @@ exports.List = List;
1815
1815
  }
1816
1816
  }
1817
1817
  List.Node = Node;
1818
- })(List = exports.List || (exports.List = {}));
1818
+ })(List || (exports.List = List = {}));
1819
1819
 
1820
1820
  /***/ }),
1821
1821
 
@@ -2028,10 +2028,10 @@ class PriorityQueue {
2028
2028
  return;
2029
2029
  }
2030
2030
  }
2031
+ exports.PriorityQueue = PriorityQueue;
2031
2032
  PriorityQueue.priority = Symbol('priority');
2032
2033
  PriorityQueue.max = heap_1.Heap.max;
2033
2034
  PriorityQueue.min = heap_1.Heap.min;
2034
- exports.PriorityQueue = PriorityQueue;
2035
2035
  class MultiQueue {
2036
2036
  constructor(entries) {
2037
2037
  this.dict = new Map();
@@ -2219,7 +2219,7 @@ function xorshift(seed = xorshift.seed()) {
2219
2219
  let x = seed;
2220
2220
  x ^= x << 13;
2221
2221
  x ^= x >> 17;
2222
- x ^= x << 5;
2222
+ x ^= x << 15;
2223
2223
  return seed = x >>> 0;
2224
2224
  };
2225
2225
  }
@@ -2235,7 +2235,7 @@ exports.xorshift = xorshift;
2235
2235
  return () => rng() / (max + 1);
2236
2236
  }
2237
2237
  xorshift.random = random;
2238
- })(xorshift = exports.xorshift || (exports.xorshift = {}));
2238
+ })(xorshift || (exports.xorshift = xorshift = {}));
2239
2239
  const uint32n = n => n & 2n ** 32n - 1n;
2240
2240
  const uint64n = n => n & 2n ** 64n - 1n;
2241
2241
  // https://www.pcg-random.org/download.html
@@ -2286,7 +2286,7 @@ exports.pcg32 = pcg32;
2286
2286
  return seed;
2287
2287
  }
2288
2288
  pcg32.advance = advance;
2289
- })(pcg32 = exports.pcg32 || (exports.pcg32 = {}));
2289
+ })(pcg32 || (exports.pcg32 = pcg32 = {}));
2290
2290
 
2291
2291
  /***/ }),
2292
2292
 
@@ -2605,6 +2605,7 @@ class ReadonlyURL {
2605
2605
  return this.href;
2606
2606
  }
2607
2607
  }
2608
+ exports.ReadonlyURL = ReadonlyURL;
2608
2609
  // Can't freeze URL object in the Firefox extension environment.
2609
2610
  // ref: https://github.com/falsandtru/pjax-api/issues/44#issuecomment-633915035
2610
2611
  // Bug: Error in dependents.
@@ -2612,7 +2613,6 @@ class ReadonlyURL {
2612
2613
  ReadonlyURL.get = (0, memoize_1.memoize)((url, base) => ({
2613
2614
  url: new __webpack_require__.g.URL(url, base)
2614
2615
  }), (url, base = '') => `${base.indexOf('\n') > -1 ? base.replace(/\n+/g, '') : base}\n${url}`, new cache_1.Cache(10000));
2615
- exports.ReadonlyURL = ReadonlyURL;
2616
2616
 
2617
2617
  /***/ }),
2618
2618
 
@@ -3575,6 +3575,7 @@ class Delimiters {
3575
3575
  return false;
3576
3576
  }
3577
3577
  }
3578
+ exports.Delimiters = Delimiters;
3578
3579
  _a = Delimiters;
3579
3580
  Delimiters.matcher = (0, memoize_1.memoize)(pattern => {
3580
3581
  switch (typeof pattern) {
@@ -3586,7 +3587,6 @@ Delimiters.matcher = (0, memoize_1.memoize)(pattern => {
3586
3587
  return (0, memoize_1.reduce)(source => pattern.test(source) || undefined);
3587
3588
  }
3588
3589
  }, _a.signature);
3589
- exports.Delimiters = Delimiters;
3590
3590
 
3591
3591
  /***/ }),
3592
3592
 
@@ -4135,8 +4135,8 @@ exports.caches = void 0;
4135
4135
  const cache_1 = __webpack_require__(9210);
4136
4136
  // For rerendering in editing.
4137
4137
  exports.caches = {
4138
- code: new cache_1.Cache(100),
4139
- math: new cache_1.Cache(100),
4138
+ code: new cache_1.Cache(1000),
4139
+ math: new cache_1.Cache(10000),
4140
4140
  media: new cache_1.Cache(100)
4141
4141
  };
4142
4142
 
@@ -7133,10 +7133,6 @@ const util_1 = __webpack_require__(9437);
7133
7133
  const memoize_1 = __webpack_require__(1808);
7134
7134
  const dom_1 = __webpack_require__(3252);
7135
7135
  function* note(target, notes, opts = {}, bottom = null) {
7136
- for (let es = target.querySelectorAll(`.annotations`), len = es.length, i = 0; i < len; ++i) {
7137
- const el = es[i];
7138
- el.parentNode === target && el.remove();
7139
- }
7140
7136
  yield* (0, exports.annotation)(target, notes?.annotations, opts, bottom);
7141
7137
  yield* (0, exports.reference)(target, notes?.references, opts, bottom);
7142
7138
  return;
@@ -7145,6 +7141,7 @@ exports.note = note;
7145
7141
  exports.annotation = build('annotation', n => `*${n}`, 'h1, h2, h3, h4, h5, h6, aside.aside, hr');
7146
7142
  exports.reference = build('reference', (n, abbr) => `[${abbr || n}]`);
7147
7143
  function build(syntax, marker, splitter = '') {
7144
+ splitter &&= `${splitter}, .${syntax}s`;
7148
7145
  // Referenceを含むAnnotationの重複排除は両構文が互いに処理済みであることを必要とするため
7149
7146
  // 構文ごとに各1回の処理では不可能
7150
7147
  const memory = (0, memoize_1.memoize)(ref => {
@@ -7165,8 +7162,8 @@ function build(syntax, marker, splitter = '') {
7165
7162
  const titles = new Map();
7166
7163
  const defIndexes = new Map();
7167
7164
  const refSubindexes = new Map();
7168
- const defSubindexes = splitter && refs.length > 0 ? new Map() : undefined;
7169
- const splitters = splitter && refs.length > 0 ? target.querySelectorAll(splitter) : [];
7165
+ const defSubindexes = new Map();
7166
+ const splitters = splitter ? target.querySelectorAll(splitter) : [];
7170
7167
  let iSplitters = 0;
7171
7168
  let total = 0;
7172
7169
  let format;
@@ -7177,15 +7174,19 @@ function build(syntax, marker, splitter = '') {
7177
7174
  yield;
7178
7175
  continue;
7179
7176
  }
7180
- if (splitter) for (let el; (el = splitters[iSplitters])?.compareDocumentPosition(ref) & Node.DOCUMENT_POSITION_FOLLOWING; ++iSplitters) {
7177
+ if (splitter) for (let el; el = splitters[iSplitters], el?.compareDocumentPosition(ref) & Node.DOCUMENT_POSITION_FOLLOWING; ++iSplitters) {
7178
+ if (~iSplitters << 32 - 8 === 0) yield;
7181
7179
  if (el.parentNode !== target) continue;
7180
+ if (el.tagName === 'OL' && el.nextElementSibling !== splitters[iSplitters + 1]) {
7181
+ el.remove();
7182
+ continue;
7183
+ }
7182
7184
  if (defs.size > 0) {
7183
7185
  total += defs.size;
7184
- yield* proc(defs, target.insertBefore((0, dom_1.html)('ol', {
7186
+ const note = el.tagName === 'OL' ? el : target.insertBefore((0, dom_1.html)('ol', {
7185
7187
  class: `${syntax}s`
7186
- }), el));
7187
- } else if (~iSplitters % 128 === 0) {
7188
- yield;
7188
+ }), el);
7189
+ yield* proc(defs, note);
7189
7190
  }
7190
7191
  }
7191
7192
  const {
@@ -7239,9 +7240,18 @@ function build(syntax, marker, splitter = '') {
7239
7240
  }, `^${++refIndex}`));
7240
7241
  }
7241
7242
  if (note || defs.size > 0) {
7242
- yield* proc(defs, note ?? target.insertBefore((0, dom_1.html)('ol', {
7243
+ const el = splitters[iSplitters];
7244
+ note ??= el?.tagName === 'OL' && el.nextElementSibling == splitters[iSplitters + 1] ? (++iSplitters, el) : target.insertBefore((0, dom_1.html)('ol', {
7243
7245
  class: `${syntax}s`
7244
- }), splitters[iSplitters] ?? bottom));
7246
+ }), splitters[iSplitters] ?? bottom);
7247
+ yield* proc(defs, note);
7248
+ }
7249
+ if (splitter) for (let el; el = splitters[iSplitters]; ++iSplitters) {
7250
+ if (~iSplitters << 32 - 8 === 0) yield;
7251
+ if (el.parentNode !== target) continue;
7252
+ if (el.tagName === 'OL') {
7253
+ el.remove();
7254
+ }
7245
7255
  }
7246
7256
  return;
7247
7257
  };
@@ -7690,7 +7700,7 @@ var blank;
7690
7700
  (function (blank) {
7691
7701
  blank.line = new RegExp(/^(?:\\?[^\S\n]|&IHN;|<wbr[^\S\n]*>|\\$)+$/.source.replace('IHN', `(?:${normalize_1.invisibleHTMLEntityNames.join('|')})`), 'gm');
7692
7702
  blank.start = new RegExp(/^(?:\\?[^\S\n]|&IHN;|<wbr[^\S\n]*>)+/.source.replace('IHN', `(?:${normalize_1.invisibleHTMLEntityNames.join('|')})`));
7693
- })(blank = exports.blank || (exports.blank = {}));
7703
+ })(blank || (exports.blank = blank = {}));
7694
7704
  function visualize(parser) {
7695
7705
  return (0, combinator_1.union)([(0, combinator_1.convert)(source => source.replace(blank.line, line => line.replace(/[\\&<]/g, '\x1B$&')), (0, combinator_1.verify)(parser, (ns, rest, context) => !rest && hasVisible(ns, context))), (0, combinator_1.some)((0, combinator_1.union)([source_1.linebreak, source_1.unescsource]))]);
7696
7706
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "securemark",
3
- "version": "0.276.3",
3
+ "version": "0.276.5",
4
4
  "description": "Secure markdown renderer working on browsers for user input data.",
5
5
  "private": false,
6
6
  "homepage": "https://github.com/falsandtru/securemark",
@@ -34,11 +34,11 @@
34
34
  "@types/mocha": "10.0.1",
35
35
  "@types/power-assert": "1.5.8",
36
36
  "@types/prismjs": "1.26.0",
37
- "@typescript-eslint/parser": "^5.59.7",
37
+ "@typescript-eslint/parser": "^5.59.8",
38
38
  "babel-loader": "^9.1.2",
39
39
  "babel-plugin-unassert": "^3.2.0",
40
- "concurrently": "^8.0.1",
41
- "eslint": "^8.41.0",
40
+ "concurrently": "^8.1.0",
41
+ "eslint": "^8.42.0",
42
42
  "eslint-plugin-redos": "^4.4.5",
43
43
  "eslint-webpack-plugin": "^4.0.1",
44
44
  "glob": "^10.2.6",
@@ -51,12 +51,12 @@
51
51
  "mocha": "^10.2.0",
52
52
  "npm-check-updates": "^16.10.12",
53
53
  "semver": "^7.5.1",
54
- "spica": "0.0.728",
54
+ "spica": "0.0.731",
55
55
  "ts-loader": "^9.4.3",
56
56
  "typed-dom": "0.0.335",
57
- "typescript": "5.0.4",
58
- "webpack": "^5.84.1",
59
- "webpack-cli": "^5.1.1",
57
+ "typescript": "5.1.3",
58
+ "webpack": "^5.85.0",
59
+ "webpack-cli": "^5.1.3",
60
60
  "webpack-merge": "^5.9.0"
61
61
  },
62
62
  "scripts": {
@@ -4,7 +4,7 @@ import { Cache } from 'spica/cache';
4
4
  // For rerendering in editing.
5
5
 
6
6
  export const caches: Caches = {
7
- code: new Cache<string, HTMLElement>(100),
8
- math: new Cache<string, HTMLElement>(100),
7
+ code: new Cache<string, HTMLElement>(1000),
8
+ math: new Cache<string, HTMLElement>(10000),
9
9
  media: new Cache<string, HTMLElement>(100),
10
10
  } as const;
@@ -8,21 +8,16 @@ describe('Unit: parser/processor/note', () => {
8
8
  describe('annotation', () => {
9
9
  it('empty', () => {
10
10
  const target = parse('');
11
- const note = html('ol');
12
- [...annotation(target, note)];
11
+ [...annotation(target)];
13
12
  assert.deepStrictEqual(
14
13
  [...target.children].map(el => el.outerHTML),
15
14
  []);
16
- assert.deepStrictEqual(
17
- note.outerHTML,
18
- html('ol').outerHTML);
19
15
  });
20
16
 
21
17
  it('1', () => {
22
18
  const target = parse('((a b))');
23
- const note = html('ol');
24
19
  for (let i = 0; i < 3; ++i) {
25
- assert.deepStrictEqual([...annotation(target, note)].length, i === 0 ? 2 : 1);
20
+ assert.deepStrictEqual([...annotation(target)].length, i === 0 ? 2 : 1);
26
21
  assert.deepStrictEqual(
27
22
  [...target.children].map(el => el.outerHTML),
28
23
  [
@@ -32,23 +27,20 @@ describe('Unit: parser/processor/note', () => {
32
27
  html('a', { href: '#annotation::def:a_b:1' }, '*1')
33
28
  ]),
34
29
  ]).outerHTML,
30
+ html('ol', { class: 'annotations' }, [
31
+ html('li', { id: 'annotation::def:a_b:1', 'data-marker': '*1' }, [
32
+ html('span', 'a b'),
33
+ html('sup', [html('a', { href: '#annotation::ref:a_b:1' }, '^1')]),
34
+ ]),
35
+ ]).outerHTML,
35
36
  ]);
36
- assert.deepStrictEqual(
37
- note.outerHTML,
38
- html('ol', [
39
- html('li', { id: 'annotation::def:a_b:1' }, [
40
- html('span', 'a b'),
41
- html('sup', [html('a', { href: '#annotation::ref:a_b:1' }, '^1')]),
42
- ]),
43
- ]).outerHTML);
44
37
  }
45
38
  });
46
39
 
47
40
  it('2', () => {
48
41
  const target = parse('((1))((12345678901234567890))');
49
- const note = html('ol');
50
42
  for (let i = 0; i < 3; ++i) {
51
- assert.deepStrictEqual([...annotation(target, note)].length, i === 0 ? 4 : 2);
43
+ assert.deepStrictEqual([...annotation(target)].length, i === 0 ? 4 : 2);
52
44
  assert.deepStrictEqual(
53
45
  [...target.children].map(el => el.outerHTML),
54
46
  [
@@ -62,27 +54,24 @@ describe('Unit: parser/processor/note', () => {
62
54
  html('a', { href: '#annotation::def:12345678901234567890:1' }, '*2')
63
55
  ]),
64
56
  ]).outerHTML,
57
+ html('ol', { class: 'annotations' }, [
58
+ html('li', { id: 'annotation::def:1:1', 'data-marker': '*1' }, [
59
+ html('span', '1'),
60
+ html('sup', [html('a', { href: '#annotation::ref:1:1' }, '^1')]),
61
+ ]),
62
+ html('li', { id: 'annotation::def:12345678901234567890:1', 'data-marker': '*2' }, [
63
+ html('span', '12345678901234567890'),
64
+ html('sup', [html('a', { href: '#annotation::ref:12345678901234567890:1' }, '^2')]),
65
+ ]),
66
+ ]).outerHTML,
65
67
  ]);
66
- assert.deepStrictEqual(
67
- note.outerHTML,
68
- html('ol', [
69
- html('li', { id: 'annotation::def:1:1' }, [
70
- html('span', '1'),
71
- html('sup', [html('a', { href: '#annotation::ref:1:1' }, '^1')]),
72
- ]),
73
- html('li', { id: 'annotation::def:12345678901234567890:1' }, [
74
- html('span', '12345678901234567890'),
75
- html('sup', [html('a', { href: '#annotation::ref:12345678901234567890:1' }, '^2')]),
76
- ]),
77
- ]).outerHTML);
78
68
  }
79
69
  });
80
70
 
81
71
  it('unify', () => {
82
72
  const target = parse('((1))((2))((3))((2))((4))');
83
- const note = html('ol');
84
73
  for (let i = 0; i < 3; ++i) {
85
- [...annotation(target, note)];
74
+ [...annotation(target)];
86
75
  assert.deepStrictEqual(
87
76
  [...target.children].map(el => el.outerHTML),
88
77
  [
@@ -108,35 +97,29 @@ describe('Unit: parser/processor/note', () => {
108
97
  html('a', { href: '#annotation::def:4:1' }, '*4')
109
98
  ]),
110
99
  ]).outerHTML,
111
- ]);
112
- assert.deepStrictEqual(
113
- note.outerHTML,
114
- html('ol', [
115
- html('li', { id: 'annotation::def:1:1' }, [
116
- html('span', '1'),
117
- html('sup', [html('a', { href: '#annotation::ref:1:1' }, '^1')]),
118
- ]),
119
- html('li', { id: 'annotation::def:2:1' }, [
120
- html('span', '2'),
121
- html('sup', [
122
- html('a', { href: '#annotation::ref:2:1' }, '^2'),
123
- html('a', { href: '#annotation::ref:2:2' }, '^4'),
100
+ html('ol', { class: 'annotations' }, [
101
+ html('li', { id: 'annotation::def:1:1', 'data-marker': '*1' }, [
102
+ html('span', '1'),
103
+ html('sup', [html('a', { href: '#annotation::ref:1:1' }, '^1')]),
124
104
  ]),
125
- ]),
126
- html('li', { id: 'annotation::def:3:1' }, [
127
- html('span', '3'),
128
- html('sup', [html('a', { href: '#annotation::ref:3:1' }, '^3')]),
129
- ]),
130
- html('li', { id: 'annotation::def:4:1' }, [
131
- html('span', '4'),
132
- html('sup', [html('a', { href: '#annotation::ref:4:1' }, '^5')]),
133
- ]),
134
- ]).outerHTML);
105
+ html('li', { id: 'annotation::def:2:1', 'data-marker': '*2' }, [
106
+ html('span', '2'),
107
+ html('sup', [
108
+ html('a', { href: '#annotation::ref:2:1' }, '^2'),
109
+ html('a', { href: '#annotation::ref:2:2' }, '^4'),
110
+ ]),
111
+ ]),
112
+ html('li', { id: 'annotation::def:3:1', 'data-marker': '*3' }, [
113
+ html('span', '3'),
114
+ html('sup', [html('a', { href: '#annotation::ref:3:1' }, '^3')]),
115
+ ]),
116
+ html('li', { id: 'annotation::def:4:1', 'data-marker': '*4' }, [
117
+ html('span', '4'),
118
+ html('sup', [html('a', { href: '#annotation::ref:4:1' }, '^5')]),
119
+ ]),
120
+ ]).outerHTML,
121
+ ]);
135
122
  }
136
- [...annotation(parse(''), note)];
137
- assert.deepStrictEqual(
138
- note.outerHTML,
139
- html('ol').outerHTML);
140
123
  });
141
124
 
142
125
  it('separation', () => {
@@ -145,19 +128,16 @@ describe('Unit: parser/processor/note', () => {
145
128
  '~~~~example/markdown\n((3))\n~~~~',
146
129
  '((4))',
147
130
  ].join('\n\n')).children);
148
- const note = html('ol');
149
131
  for (let i = 0; i < 3; ++i) {
150
- [...annotation(target, note)];
132
+ [...annotation(target)];
151
133
  assert.deepStrictEqual(
152
134
  [...target.children].map(el => el.outerHTML),
153
135
  [
154
136
  '<blockquote><blockquote><section><p><sup class="annotation disabled" title="1"><span></span><a>*1</a></sup></p><ol class="annotations"><li data-marker="*1"><span>1</span><sup><a>^1</a></sup></li></ol><h2>References</h2><ol class="references"></ol></section></blockquote><section><p><sup class="annotation disabled" title="2"><span></span><a>*1</a></sup><br>~~~</p><ol class="annotations"><li data-marker="*1"><span>2</span><sup><a>^1</a></sup></li></ol><h2>References</h2><ol class="references"></ol></section></blockquote>',
155
137
  '<aside class="example" data-type="markdown"><pre translate="no">((3))</pre><hr><section><p><sup class="annotation disabled" title="3"><span></span><a>*1</a></sup></p><ol class="annotations"><li data-marker="*1"><span>3</span><sup><a>^1</a></sup></li></ol><h2>References</h2><ol class="references"></ol></section></aside>',
156
138
  '<p><sup class="annotation" id="annotation::ref:4:1" title="4"><span></span><a href="#annotation::def:4:1">*1</a></sup></p>',
139
+ '<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>',
157
140
  ]);
158
- assert.deepStrictEqual(
159
- note.outerHTML,
160
- '<ol><li id="annotation::def:4:1"><span>4</span><sup><a href="#annotation::ref:4:1">^1</a></sup></li></ol>');
161
141
  }
162
142
  });
163
143
 
@@ -235,9 +215,8 @@ describe('Unit: parser/processor/note', () => {
235
215
 
236
216
  it('id', () => {
237
217
  const target = parse('((a b))');
238
- const note = html('ol');
239
218
  for (let i = 0; i < 3; ++i) {
240
- assert.deepStrictEqual([...annotation(target, note, { id: '0' })].length, i === 0 ? 2 : 1);
219
+ assert.deepStrictEqual([...annotation(target, undefined, { id: '0' })].length, i === 0 ? 2 : 1);
241
220
  assert.deepStrictEqual(
242
221
  [...target.children].map(el => el.outerHTML),
243
222
  [
@@ -247,15 +226,13 @@ describe('Unit: parser/processor/note', () => {
247
226
  html('a', { href: '#annotation:0:def:a_b:1' }, '*1')
248
227
  ]),
249
228
  ]).outerHTML,
229
+ html('ol', { class: 'annotations' }, [
230
+ html('li', { id: 'annotation:0:def:a_b:1', 'data-marker': '*1' }, [
231
+ html('span', 'a b'),
232
+ html('sup', [html('a', { href: '#annotation:0:ref:a_b:1' }, '^1')]),
233
+ ]),
234
+ ]).outerHTML,
250
235
  ]);
251
- assert.deepStrictEqual(
252
- note.outerHTML,
253
- html('ol', [
254
- html('li', { id: 'annotation:0:def:a_b:1' }, [
255
- html('span', 'a b'),
256
- html('sup', [html('a', { href: '#annotation:0:ref:a_b:1' }, '^1')]),
257
- ]),
258
- ]).outerHTML);
259
236
  }
260
237
  });
261
238
 
@@ -12,11 +12,6 @@ export function* note(
12
12
  opts: { readonly id?: string; } = {},
13
13
  bottom: Node | null = null,
14
14
  ): Generator<HTMLAnchorElement | HTMLLIElement | undefined, undefined, undefined> {
15
- for (let es = target.querySelectorAll(`.annotations`),
16
- len = es.length, i = 0; i < len; ++i) {
17
- const el = es[i];
18
- el.parentNode === target && el.remove();
19
- }
20
15
  yield* annotation(target, notes?.annotations, opts, bottom);
21
16
  yield* reference(target, notes?.references, opts, bottom);
22
17
  return;
@@ -31,6 +26,7 @@ function build(
31
26
  splitter: string = '',
32
27
  ) {
33
28
  assert(syntax.match(/^[a-z]+$/));
29
+ splitter &&= `${splitter}, .${syntax}s`;
34
30
  // Referenceを含むAnnotationの重複排除は両構文が互いに処理済みであることを必要とするため
35
31
  // 構文ごとに各1回の処理では不可能
36
32
  const memory = memoize((ref: HTMLElement): {
@@ -70,8 +66,8 @@ function build(
70
66
  const titles = new Map<string, string>();
71
67
  const defIndexes = new Map<HTMLLIElement, number>();
72
68
  const refSubindexes = new Map<string, number>();
73
- const defSubindexes = splitter && refs.length > 0 ? new Map<string, number>() : undefined;
74
- const splitters = splitter && refs.length > 0 ? target.querySelectorAll(splitter) : [];
69
+ const defSubindexes = new Map<string, number>();
70
+ const splitters = splitter ? target.querySelectorAll(splitter) : [];
75
71
  let iSplitters = 0;
76
72
  let total = 0;
77
73
  let format: 'number' | 'abbr';
@@ -84,17 +80,25 @@ function build(
84
80
  }
85
81
  if (splitter) for (
86
82
  let el: Element;
87
- (el = splitters[iSplitters])?.compareDocumentPosition(ref) & Node.DOCUMENT_POSITION_FOLLOWING;
83
+ el = splitters[iSplitters],
84
+ el?.compareDocumentPosition(ref) & Node.DOCUMENT_POSITION_FOLLOWING;
88
85
  ++iSplitters) {
86
+ if (~iSplitters << 32 - 8 === 0) yield;
89
87
  if (el.parentNode !== target) continue;
88
+ if (el.tagName === 'OL' && el.nextElementSibling !== splitters[iSplitters + 1]) {
89
+ assert(el.matches(`.${syntax}s`));
90
+ el.remove();
91
+ continue;
92
+ }
90
93
  if (defs.size > 0) {
91
94
  total += defs.size;
92
- yield* proc(defs, target.insertBefore(html('ol', { class: `${syntax}s` }), el));
95
+ const note = el.tagName === 'OL'
96
+ ? el as HTMLOListElement
97
+ : target.insertBefore(html('ol', { class: `${syntax}s` }), el);
98
+ assert(note.parentNode);
99
+ yield* proc(defs, note);
93
100
  assert(defs.size === 0);
94
101
  }
95
- else if (~iSplitters % 128 === 0) {
96
- yield;
97
- }
98
102
  }
99
103
  const { content, identifier, abbr, text } = memory(ref);
100
104
  const refSubindex = refSubindexes.get(identifier)! + 1 || 1;
@@ -158,7 +162,22 @@ function build(
158
162
  `^${++refIndex}`));
159
163
  }
160
164
  if (note || defs.size > 0) {
161
- yield* proc(defs, note ?? target.insertBefore(html('ol', { class: `${syntax}s` }), splitters[iSplitters] ?? bottom));
165
+ const el = splitters[iSplitters];
166
+ note ??= el?.tagName === 'OL' && el.nextElementSibling == splitters[iSplitters + 1]
167
+ ? (++iSplitters, el as HTMLOListElement)
168
+ : target.insertBefore(html('ol', { class: `${syntax}s` }), splitters[iSplitters] ?? bottom);
169
+ yield* proc(defs, note);
170
+ }
171
+ if (splitter) for (
172
+ let el: Element;
173
+ el = splitters[iSplitters];
174
+ ++iSplitters) {
175
+ if (~iSplitters << 32 - 8 === 0) yield;
176
+ if (el.parentNode !== target) continue;
177
+ if (el.tagName === 'OL') {
178
+ assert(el.matches(`.${syntax}s`));
179
+ el.remove();
180
+ }
162
181
  }
163
182
  return;
164
183
  }