securemark 0.274.2 → 0.274.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.eslintrc.json CHANGED
@@ -20,8 +20,6 @@
20
20
  "maxSimpleRepeatCount": 256,
21
21
  "attackTimeout": null,
22
22
  "incubationTimeout": null,
23
- "recallTimeout": null,
24
- "seedingTimeout": null,
25
23
  "timeout": 1e6
26
24
  }
27
25
  ]
package/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.274.3
4
+
5
+ - Fix abbr parser.
6
+
3
7
  ## 0.274.2
4
8
 
5
9
  - Fix identifiers of notes.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! securemark v0.274.2 https://github.com/falsandtru/securemark | (c) 2017, falsandtru | UNLICENSED License */
1
+ /*! securemark v0.274.3 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"));
@@ -6581,14 +6581,14 @@ const visibility_1 = __webpack_require__(7618);
6581
6581
  const array_1 = __webpack_require__(8112);
6582
6582
  const dom_1 = __webpack_require__(3252);
6583
6583
  exports.mark = (0, combinator_1.lazy)(() => (0, combinator_1.surround)((0, source_1.str)('==', '='), (0, combinator_1.constraint)(4 /* State.mark */, false, (0, combinator_1.syntax)(0 /* Syntax.none */, 1, 1, 0 /* State.none */, (0, visibility_1.startTight)((0, combinator_1.some)((0, combinator_1.union)([(0, combinator_1.some)(inline_1.inline, (0, visibility_1.blankWith)('=='), [[/^\\?\n/, 9]]), (0, combinator_1.open)((0, combinator_1.some)(inline_1.inline, '=', [[/^\\?\n/, 9]]), exports.mark)]))))), (0, source_1.str)('=='), false, ([, bs], rest, {
6584
- id
6584
+ id,
6585
+ state
6585
6586
  }) => {
6586
6587
  const el = (0, dom_1.html)('mark', (0, dom_1.defrag)(bs));
6587
- (0, dom_1.define)(el, {
6588
- id: (0, indexee_1.identity)(id, (0, indexee_1.text)(el), 'mark')
6589
- });
6590
- return [[el, (0, dom_1.html)('a', {
6591
- href: el.id ? `#${el.id}` : undefined
6588
+ return [[(0, dom_1.define)(el, {
6589
+ id: state & (256 /* State.annotation */ | 128 /* State.reference */) ? undefined : (0, indexee_1.identity)(id, (0, indexee_1.text)(el), 'mark')
6590
+ }), el.id && (0, dom_1.html)('a', {
6591
+ href: `#${el.id}`
6592
6592
  })], rest];
6593
6593
  }, ([as, bs], rest) => [(0, array_1.unshift)(as, bs), rest]));
6594
6594
 
@@ -6727,22 +6727,31 @@ const combinator_1 = __webpack_require__(2087);
6727
6727
  const inline_1 = __webpack_require__(1160);
6728
6728
  const source_1 = __webpack_require__(6743);
6729
6729
  const visibility_1 = __webpack_require__(7618);
6730
- const util_1 = __webpack_require__(9437);
6731
6730
  const dom_1 = __webpack_require__(3252);
6732
6731
  exports.reference = (0, combinator_1.lazy)(() => (0, combinator_1.surround)('[[', (0, combinator_1.constraint)(128 /* State.reference */, false, (0, combinator_1.syntax)(256 /* Syntax.reference */, 6, 1, 256 /* State.annotation */ | 128 /* State.reference */ | 8 /* State.media */, (0, visibility_1.startLoose)((0, combinator_1.subsequence)([abbr, (0, combinator_1.fmap)((0, source_1.str)('^'), ns => ['', ...ns]), (0, combinator_1.some)(inline_1.inline, ']', [[/^\\?\n/, 9], [']', 2], [']]', 6]])]), ']'))), ']]', false, ([, ns], rest) => [[(0, dom_1.html)('sup', attributes(ns), [(0, dom_1.html)('span', (0, visibility_1.trimNode)((0, dom_1.defrag)(ns)))])], rest]));
6733
- const abbr = (0, combinator_1.creation)((0, combinator_1.bind)((0, combinator_1.surround)('^', (0, combinator_1.union)([(0, source_1.str)(/^(?![0-9]+\s?[|\]])[0-9A-Za-z]+(?:(?:-|(?=\W)(?!'\d)'?(?!\.\d)\.?(?!,\S),? ?)[0-9A-Za-z]+)*(?:-|'?\.?,? ?)?/)]), /^\|?(?=]])|^\|[^\S\n]*/), ([source], rest) => [[(0, dom_1.html)('abbr', source)], rest.replace(visibility_1.regBlankStart, '')]));
6732
+ // Chicago-Style
6733
+ const abbr = (0, combinator_1.creation)((0, combinator_1.bind)((0, combinator_1.surround)('^', (0, combinator_1.union)([(0, source_1.str)(/^(?=[A-Z])(?:[0-9A-Za-z]'?|(?:[-.:]|\.?\??,? ?)(?!['\-.:?, ]))+/)]), /^\|?(?=]])|^\|[^\S\n]*/), ([source], rest) => [['\n', source.trimEnd()], rest.replace(visibility_1.regBlankStart, '')]));
6734
6734
  function attributes(ns) {
6735
- return typeof ns[0] === 'object' && ns[0].tagName === 'ABBR' ? {
6736
- class: 'reference',
6737
- 'data-abbr': (0, util_1.stringify)([ns.shift()]).trimEnd()
6738
- } : ns[0] === '' ? {
6739
- class: 'invalid',
6740
- 'data-invalid-syntax': 'reference',
6741
- 'data-invalid-type': 'syntax',
6742
- 'data-invalid-message': 'Invalid abbr'
6743
- } : {
6744
- class: 'reference'
6745
- };
6735
+ switch (ns[0]) {
6736
+ case '':
6737
+ return {
6738
+ class: 'invalid',
6739
+ 'data-invalid-syntax': 'reference',
6740
+ 'data-invalid-type': 'syntax',
6741
+ 'data-invalid-message': 'Invalid abbreviation'
6742
+ };
6743
+ case '\n':
6744
+ const abbr = ns[1];
6745
+ ns[0] = ns[1] = '';
6746
+ return {
6747
+ class: 'reference',
6748
+ 'data-abbr': abbr
6749
+ };
6750
+ default:
6751
+ return {
6752
+ class: 'reference'
6753
+ };
6754
+ }
6746
6755
  }
6747
6756
 
6748
6757
  /***/ }),
@@ -7069,39 +7078,35 @@ function build(syntax, marker, splitter = '') {
7069
7078
  // 構文ごとに各1回の処理では不可能
7070
7079
  return function* (target, note, opts = {}, bottom = null) {
7071
7080
  const defs = new Map();
7072
- const splitters = [];
7073
- for (let es = target.querySelectorAll(splitter || '_'), len = es.length, i = 0; i < len; ++i) {
7074
- if (i % 100 === 0) yield;
7075
- const el = es[i];
7076
- el.parentNode === target && splitters.push(el);
7077
- }
7078
7081
  const refs = target.querySelectorAll(`sup.${syntax}:not(.disabled)`);
7079
7082
  const titles = new Map();
7080
7083
  const defIndexes = new Map();
7081
7084
  const refSubindexes = new Map();
7082
- const defSubindexes = splitter ? new Map() : undefined;
7085
+ const defSubindexes = splitter && refs.length > 0 ? new Map() : undefined;
7086
+ const splitters = splitter && refs.length > 0 ? target.querySelectorAll(splitter) : [];
7087
+ let iSplitters = 0;
7083
7088
  let total = 0;
7084
7089
  let format;
7085
7090
  let refIndex = 0;
7086
7091
  for (let len = refs.length, i = 0; i < len; ++i) {
7087
7092
  const ref = refs[i];
7088
- if (ref.closest('[hidden]')) {
7093
+ if (ref.closest('sup > [hidden]')) {
7089
7094
  yield;
7090
7095
  continue;
7091
7096
  }
7092
- while (splitters.length > 0 && splitters[0].compareDocumentPosition(ref) & Node.DOCUMENT_POSITION_FOLLOWING) {
7097
+ if (splitter) for (let el; (el = splitters[iSplitters])?.compareDocumentPosition(ref) & Node.DOCUMENT_POSITION_FOLLOWING; ++iSplitters) {
7098
+ if (el.parentNode !== target) continue;
7093
7099
  if (defs.size > 0) {
7094
7100
  total += defs.size;
7095
7101
  yield* proc(defs, target.insertBefore((0, dom_1.html)('ol', {
7096
7102
  class: `${syntax}s`
7097
- }), splitters[0]));
7098
- } else if (splitters.length % 100 === 0) {
7103
+ }), el));
7104
+ } else if (~iSplitters % 128 === 0) {
7099
7105
  yield;
7100
7106
  }
7101
- splitters.shift();
7102
7107
  }
7103
7108
  const abbr = ref.getAttribute('data-abbr') || undefined;
7104
- const identifier = abbr || (0, indexee_1.identity)(undefined, (0, indexee_1.text)(ref.firstElementChild), 'mark')?.slice(6) || '';
7109
+ const identifier = (0, indexee_1.identity)(undefined, abbr ? abbr.match(/^(?:\S+ )+?(?:(?:January|February|March|April|May|June|August|September|October|November|December) \d{1,2}(?:-\d{0,2})?, \d{1,4}(?:-\d{0,4})?[a-z]?|n\.d\.)(?=,|$)/)?.[0] ?? abbr.match(/^[^,\s]+(?:,? [^,\s]+)*?(?: \d{1,4}(?:-\d{0,4})?[a-z]?(?=,|$)|(?=,(?: [a-z]+\.?)? [0-9]))/)?.[0] ?? abbr : (0, indexee_1.text)(ref.firstElementChild), 'mark')?.slice(6) || '';
7105
7110
  const refSubindex = refSubindexes.get(identifier) + 1 || 1;
7106
7111
  refSubindexes.set(identifier, refSubindex);
7107
7112
  const refId = opts.id !== '' ? `${syntax}:${opts.id ?? ''}:ref:${identifier}:${refSubindex}` : undefined;
@@ -7120,28 +7125,26 @@ function build(syntax, marker, splitter = '') {
7120
7125
  initial && defIndexes.set(def, defIndex);
7121
7126
  const title = initial ? (0, indexee_1.text)(ref.firstElementChild) : titles.get(identifier);
7122
7127
  initial && titles.set(identifier, title);
7123
- format ??= abbr ? 'abbr' : 'number';
7124
- if (!ref.classList.contains('invalid')) {
7125
- if (format === 'number' ? abbr : !abbr) {
7126
- (0, util_1.markInvalid)(ref, syntax, 'format', 'Notation format must be consistent with numbers or abbreviations');
7127
- }
7128
- } else switch (ref.getAttribute('data-invalid-syntax')) {
7129
- case 'format':
7130
- case 'content':
7131
- (0, util_1.unmarkInvalid)(ref);
7132
- }
7133
7128
  ref.firstElementChild.hasAttribute('hidden') ? ref.lastElementChild.remove() : ref.firstElementChild.setAttribute('hidden', '');
7134
7129
  (0, dom_1.define)(ref, {
7135
7130
  id: refId,
7136
7131
  class: opts.id !== '' ? undefined : void ref.classList.add('disabled'),
7137
- title,
7138
- ...(!title && {
7139
- class: void ref.classList.add('invalid'),
7140
- 'data-invalid-syntax': syntax,
7141
- 'data-invalid-type': 'content',
7142
- 'data-invalid-message': 'Missing the content'
7143
- })
7132
+ title
7144
7133
  });
7134
+ switch (ref.getAttribute('data-invalid-syntax')) {
7135
+ case 'format':
7136
+ case 'content':
7137
+ (0, util_1.unmarkInvalid)(ref);
7138
+ }
7139
+ format ??= abbr ? 'abbr' : 'number';
7140
+ if (!ref.classList.contains('invalid')) switch (true) {
7141
+ case format === 'number' ? !!abbr : !abbr:
7142
+ (0, util_1.markInvalid)(ref, syntax, 'format', 'Notation format must be consistent with numbers or abbreviations');
7143
+ break;
7144
+ case !title:
7145
+ (0, util_1.markInvalid)(ref, syntax, 'content', 'Missing the content');
7146
+ break;
7147
+ }
7145
7148
  yield ref.appendChild((0, dom_1.html)('a', {
7146
7149
  href: refId && defId && `#${defId}`
7147
7150
  }, marker(defIndex, abbr)));
@@ -7153,7 +7156,7 @@ function build(syntax, marker, splitter = '') {
7153
7156
  if (note || defs.size > 0) {
7154
7157
  yield* proc(defs, note ?? target.insertBefore((0, dom_1.html)('ol', {
7155
7158
  class: `${syntax}s`
7156
- }), splitters[0] ?? bottom));
7159
+ }), splitters[iSplitters] ?? bottom));
7157
7160
  }
7158
7161
  return;
7159
7162
  };
package/markdown.d.ts CHANGED
@@ -658,8 +658,8 @@ export namespace MarkdownParser {
658
658
  }
659
659
  export interface ReferenceParser extends
660
660
  // [[abc]]
661
- // [[^abbr]]
662
- // [[^abbr| abc]]
661
+ // [[^Abbr]]
662
+ // [[^Abbr| abc]]
663
663
  Inline<'reference'>,
664
664
  Parser<HTMLElement, Context, [
665
665
  ReferenceParser.AbbrParser,
@@ -669,11 +669,10 @@ export namespace MarkdownParser {
669
669
  }
670
670
  export namespace ReferenceParser {
671
671
  export interface AbbrParser extends
672
- // ^Xyz2020
673
- // ^X, 2020, p1-2
674
- // ^X. Y., Z et al., 2020, p1-2
672
+ // ^X 2020, 1-2
673
+ // ^X. Y., and Z et al. 2020, 1-2
675
674
  Inline<'reference/abbr'>,
676
- Parser<HTMLElement, Context, [
675
+ Parser<string, Context, [
677
676
  SourceParser.StrParser,
678
677
  ]> {
679
678
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "securemark",
3
- "version": "0.274.2",
3
+ "version": "0.274.3",
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",
@@ -204,15 +204,80 @@ describe('Unit: parser/api/parse', () => {
204
204
  it('note', () => {
205
205
  const notes = { references: html('ol') };
206
206
  assert.deepStrictEqual(
207
- [...parse('$-a\n$$\n$$\n\n(($-a[[^b]]))[[^b|$-a]]', { notes }).children].map(el => el.outerHTML),
207
+ [...parse('$-a\n$$\n$$\n\n(($-a[[^B]]))[[^B|$-a]]', { notes }).children].map(el => el.outerHTML),
208
208
  [
209
209
  '<figure data-type="math" data-label="$-a" data-group="$" data-number="1" id="label:$-a"><figcaption><span class="figindex">(1)</span><span class="figtext"></span></figcaption><div><div class="math" translate="no">$$\n$$</div></div></figure>',
210
- '<p><sup class="annotation" id="annotation::ref:(1):1" title="(1)"><span hidden=""><a class="label" data-label="$-a" href="#label:$-a">(1)</a><sup class="reference" data-abbr="b"><span></span></sup></span><a href="#annotation::def:(1):1">*1</a></sup><sup class="reference" data-abbr="b" id="reference::ref:b:1" title="(1)"><span hidden=""><a class="label" data-label="$-a" href="#label:$-a">(1)</a></span><a href="#reference::def:b">[b]</a></sup></p>',
211
- '<ol class="annotations"><li id="annotation::def:(1):1" data-marker="*1"><span><a class="label" data-label="$-a" href="#label:$-a">(1)</a><sup class="reference" data-abbr="b" id="reference::ref:b:2" title="(1)"><span hidden=""></span><a href="#reference::def:b">[b]</a></sup></span><sup><a href="#annotation::ref:(1):1">^1</a></sup></li></ol>',
210
+ '<p><sup class="annotation" id="annotation::ref:(1):1" title="(1)"><span hidden=""><a class="label" data-label="$-a" href="#label:$-a">(1)</a><sup class="reference" data-abbr="B"><span></span></sup></span><a href="#annotation::def:(1):1">*1</a></sup><sup class="reference" data-abbr="B" id="reference::ref:B:1" title="(1)"><span hidden=""><a class="label" data-label="$-a" href="#label:$-a">(1)</a></span><a href="#reference::def:B">[B]</a></sup></p>',
211
+ '<ol class="annotations"><li id="annotation::def:(1):1" data-marker="*1"><span><a class="label" data-label="$-a" href="#label:$-a">(1)</a><sup class="reference" data-abbr="B" id="reference::ref:B:2" title="(1)"><span hidden=""></span><a href="#reference::def:B">[B]</a></sup></span><sup><a href="#annotation::ref:(1):1">^1</a></sup></li></ol>',
212
212
  ]);
213
213
  assert.deepStrictEqual(
214
214
  notes.references.outerHTML,
215
- '<ol><li id="reference::def:b"><span><a class="label" data-label="$-a" href="#label:$-a">(1)</a></span><sup><a href="#reference::ref:b:1" title="(1)">^1</a><a href="#reference::ref:b:2">^2</a></sup></li></ol>');
215
+ '<ol><li id="reference::def:B"><span><a class="label" data-label="$-a" href="#label:$-a">(1)</a></span><sup><a href="#reference::ref:B:1" title="(1)">^1</a><a href="#reference::ref:B:2">^2</a></sup></li></ol>');
216
+ assert.deepStrictEqual(
217
+ [...parse([
218
+ '[[^A 1|b]]',
219
+ '[[^A 1,|b]]',
220
+ '[[^A 1, |b]]',
221
+ '[[^Xyz 2020|b]]',
222
+ '[[^Xyz 2020, 1|b]]',
223
+ '[[^Xyz 2020, 1, 2|b]]',
224
+ '[[^Xyz 2020, 1, fig. 1.1|b]]',
225
+ '[[^Xyz 2020, 1, fig. 1.1-2.1b|b]]',
226
+ '[[^Xyz 2020, 1, fig. 1.1a-b|b]]',
227
+ '[[^Xyz 2020, 1-2|b]]',
228
+ '[[^Xyz 2020, 1:1-2|b]]',
229
+ '[[^Xyz 2020, 1n|b]]',
230
+ '[[^Xyz 2020, 1n1|b]]',
231
+ '[[^Xyz 2020, 1nn1-2|b]]',
232
+ '[[^Xyz 2020, i|b]]',
233
+ '[[^Xyz 2020, capter 1|b]]',
234
+ '[[^Xyz 2020, cap. 1|b]]',
235
+ '[[^Xyz 2020a|b]]',
236
+ '[[^Xyz 2020a, 1|b]]',
237
+ '[[^Xyz 2020-2021a|b]]',
238
+ '[[^Xyz 2020-2021a, 1|b]]',
239
+ '[[^Xyz, April 1, 2020|b]]',
240
+ '[[^Xyz, April 1, 2020, 1|b]]',
241
+ '[[^Xyz n.d.|b]]',
242
+ '[[^Xyz n.d., 1|b]]',
243
+ '[[^X. Y., and Z et al. 2020, 1-2|b]]',
244
+ '[[^A title 2020|b]]',
245
+ '[[^A title 2020, 1|b]]',
246
+ '[[^Constitution, art. 2|b]]',
247
+ '[[^Constitution, art. 2, sec. 1|b]]',
248
+ ].join('\n\n'), { notes }).children].map(el => el.outerHTML),
249
+ [
250
+ '<p><sup class="reference" data-abbr="A 1" id="reference::ref:A_1:1" title="b"><span hidden="">b</span><a href="#reference::def:A_1">[A 1]</a></sup></p>',
251
+ '<p><sup class="reference" data-abbr="A 1," id="reference::ref:A_1:2" title="b"><span hidden="">b</span><a href="#reference::def:A_1">[A 1,]</a></sup></p>',
252
+ '<p><sup class="reference" data-abbr="A 1," id="reference::ref:A_1:3" title="b"><span hidden="">b</span><a href="#reference::def:A_1">[A 1,]</a></sup></p>',
253
+ '<p><sup class="reference" data-abbr="Xyz 2020" id="reference::ref:Xyz_2020:1" title="b"><span hidden="">b</span><a href="#reference::def:Xyz_2020">[Xyz 2020]</a></sup></p>',
254
+ '<p><sup class="reference" data-abbr="Xyz 2020, 1" id="reference::ref:Xyz_2020:2" title="b"><span hidden="">b</span><a href="#reference::def:Xyz_2020">[Xyz 2020, 1]</a></sup></p>',
255
+ '<p><sup class="reference" data-abbr="Xyz 2020, 1, 2" id="reference::ref:Xyz_2020:3" title="b"><span hidden="">b</span><a href="#reference::def:Xyz_2020">[Xyz 2020, 1, 2]</a></sup></p>',
256
+ '<p><sup class="reference" data-abbr="Xyz 2020, 1, fig. 1.1" id="reference::ref:Xyz_2020:4" title="b"><span hidden="">b</span><a href="#reference::def:Xyz_2020">[Xyz 2020, 1, fig. 1.1]</a></sup></p>',
257
+ '<p><sup class="reference" data-abbr="Xyz 2020, 1, fig. 1.1-2.1b" id="reference::ref:Xyz_2020:5" title="b"><span hidden="">b</span><a href="#reference::def:Xyz_2020">[Xyz 2020, 1, fig. 1.1-2.1b]</a></sup></p>',
258
+ '<p><sup class="reference" data-abbr="Xyz 2020, 1, fig. 1.1a-b" id="reference::ref:Xyz_2020:6" title="b"><span hidden="">b</span><a href="#reference::def:Xyz_2020">[Xyz 2020, 1, fig. 1.1a-b]</a></sup></p>',
259
+ '<p><sup class="reference" data-abbr="Xyz 2020, 1-2" id="reference::ref:Xyz_2020:7" title="b"><span hidden="">b</span><a href="#reference::def:Xyz_2020">[Xyz 2020, 1-2]</a></sup></p>',
260
+ '<p><sup class="reference" data-abbr="Xyz 2020, 1:1-2" id="reference::ref:Xyz_2020:8" title="b"><span hidden="">b</span><a href="#reference::def:Xyz_2020">[Xyz 2020, 1:1-2]</a></sup></p>',
261
+ '<p><sup class="reference" data-abbr="Xyz 2020, 1n" id="reference::ref:Xyz_2020:9" title="b"><span hidden="">b</span><a href="#reference::def:Xyz_2020">[Xyz 2020, 1n]</a></sup></p>',
262
+ '<p><sup class="reference" data-abbr="Xyz 2020, 1n1" id="reference::ref:Xyz_2020:10" title="b"><span hidden="">b</span><a href="#reference::def:Xyz_2020">[Xyz 2020, 1n1]</a></sup></p>',
263
+ '<p><sup class="reference" data-abbr="Xyz 2020, 1nn1-2" id="reference::ref:Xyz_2020:11" title="b"><span hidden="">b</span><a href="#reference::def:Xyz_2020">[Xyz 2020, 1nn1-2]</a></sup></p>',
264
+ '<p><sup class="reference" data-abbr="Xyz 2020, i" id="reference::ref:Xyz_2020:12" title="b"><span hidden="">b</span><a href="#reference::def:Xyz_2020">[Xyz 2020, i]</a></sup></p>',
265
+ '<p><sup class="reference" data-abbr="Xyz 2020, capter 1" id="reference::ref:Xyz_2020:13" title="b"><span hidden="">b</span><a href="#reference::def:Xyz_2020">[Xyz 2020, capter 1]</a></sup></p>',
266
+ '<p><sup class="reference" data-abbr="Xyz 2020, cap. 1" id="reference::ref:Xyz_2020:14" title="b"><span hidden="">b</span><a href="#reference::def:Xyz_2020">[Xyz 2020, cap. 1]</a></sup></p>',
267
+ '<p><sup class="reference" data-abbr="Xyz 2020a" id="reference::ref:Xyz_2020a:1" title="b"><span hidden="">b</span><a href="#reference::def:Xyz_2020a">[Xyz 2020a]</a></sup></p>',
268
+ '<p><sup class="reference" data-abbr="Xyz 2020a, 1" id="reference::ref:Xyz_2020a:2" title="b"><span hidden="">b</span><a href="#reference::def:Xyz_2020a">[Xyz 2020a, 1]</a></sup></p>',
269
+ '<p><sup class="reference" data-abbr="Xyz 2020-2021a" id="reference::ref:Xyz_2020-2021a:1" title="b"><span hidden="">b</span><a href="#reference::def:Xyz_2020-2021a">[Xyz 2020-2021a]</a></sup></p>',
270
+ '<p><sup class="reference" data-abbr="Xyz 2020-2021a, 1" id="reference::ref:Xyz_2020-2021a:2" title="b"><span hidden="">b</span><a href="#reference::def:Xyz_2020-2021a">[Xyz 2020-2021a, 1]</a></sup></p>',
271
+ '<p><sup class="reference" data-abbr="Xyz, April 1, 2020" id="reference::ref:Xyz,_April_1,_2020:1" title="b"><span hidden="">b</span><a href="#reference::def:Xyz,_April_1,_2020">[Xyz, April 1, 2020]</a></sup></p>',
272
+ '<p><sup class="reference" data-abbr="Xyz, April 1, 2020, 1" id="reference::ref:Xyz,_April_1,_2020:2" title="b"><span hidden="">b</span><a href="#reference::def:Xyz,_April_1,_2020">[Xyz, April 1, 2020, 1]</a></sup></p>',
273
+ '<p><sup class="reference" data-abbr="Xyz n.d." id="reference::ref:Xyz_n.d.:1" title="b"><span hidden="">b</span><a href="#reference::def:Xyz_n.d.">[Xyz n.d.]</a></sup></p>',
274
+ '<p><sup class="reference" data-abbr="Xyz n.d., 1" id="reference::ref:Xyz_n.d.:2" title="b"><span hidden="">b</span><a href="#reference::def:Xyz_n.d.">[Xyz n.d., 1]</a></sup></p>',
275
+ '<p><sup class="reference" data-abbr="X. Y., and Z et al. 2020, 1-2" id="reference::ref:X._Y.,_and_Z_et_al._2020:1" title="b"><span hidden="">b</span><a href="#reference::def:X._Y.,_and_Z_et_al._2020">[X. Y., and Z et al. 2020, 1-2]</a></sup></p>',
276
+ '<p><sup class="reference" data-abbr="A title 2020" id="reference::ref:A_title_2020:1" title="b"><span hidden="">b</span><a href="#reference::def:A_title_2020">[A title 2020]</a></sup></p>',
277
+ '<p><sup class="reference" data-abbr="A title 2020, 1" id="reference::ref:A_title_2020:2" title="b"><span hidden="">b</span><a href="#reference::def:A_title_2020">[A title 2020, 1]</a></sup></p>',
278
+ '<p><sup class="reference" data-abbr="Constitution, art. 2" id="reference::ref:Constitution:1" title="b"><span hidden="">b</span><a href="#reference::def:Constitution">[Constitution, art. 2]</a></sup></p>',
279
+ '<p><sup class="reference" data-abbr="Constitution, art. 2, sec. 1" id="reference::ref:Constitution:2" title="b"><span hidden="">b</span><a href="#reference::def:Constitution">[Constitution, art. 2, sec. 1]</a></sup></p>',
280
+ ]);
216
281
  });
217
282
 
218
283
  it('normalize', () => {
@@ -17,9 +17,15 @@ export const mark: MarkParser = lazy(() => surround(
17
17
  open(some(inline, '=', [[/^\\?\n/, 9]]), mark),
18
18
  ]))))),
19
19
  str('=='), false,
20
- ([, bs], rest, { id }) => {
20
+ ([, bs], rest, { id, state }) => {
21
21
  const el = html('mark', defrag(bs));
22
- define(el, { id: identity(id, text(el), 'mark') });
23
- return [[el, html('a', { href: el.id ? `#${el.id}` : undefined })], rest];
22
+ return [[
23
+ define(el, {
24
+ id: state! & (State.annotation | State.reference)
25
+ ? undefined
26
+ : identity(id, text(el), 'mark'),
27
+ }),
28
+ el.id && html('a', { href: `#${el.id}` }),
29
+ ], rest];
24
30
  },
25
31
  ([as, bs], rest) => [unshift(as, bs), rest]));
@@ -54,41 +54,68 @@ describe('Unit: parser/inline/reference', () => {
54
54
 
55
55
  it('abbr', () => {
56
56
  assert.deepStrictEqual(inspect(parser('[[^]]')), [['<sup class="invalid"><span>^</span></sup>'], '']);
57
- assert.deepStrictEqual(inspect(parser('[[^a]]')), [['<sup class="reference" data-abbr="a"><span></span></sup>'], '']);
58
- assert.deepStrictEqual(inspect(parser('[[^a,]]')), [['<sup class="reference" data-abbr="a,"><span></span></sup>'], '']);
59
- assert.deepStrictEqual(inspect(parser('[[^a, ]]')), [['<sup class="reference" data-abbr="a,"><span></span></sup>'], '']);
60
- assert.deepStrictEqual(inspect(parser('[[^a ]]')), [['<sup class="reference" data-abbr="a"><span></span></sup>'], '']);
61
- assert.deepStrictEqual(inspect(parser('[[^a ]]')), [['<sup class="invalid"><span>^a</span></sup>'], '']);
62
- assert.deepStrictEqual(inspect(parser('[[^a b]]')), [['<sup class="reference" data-abbr="a b"><span></span></sup>'], '']);
63
- assert.deepStrictEqual(inspect(parser('[[^a b]]')), [['<sup class="invalid"><span>^a b</span></sup>'], '']);
64
- assert.deepStrictEqual(inspect(parser('[[^a|]]')), [['<sup class="reference" data-abbr="a"><span></span></sup>'], '']);
65
- assert.deepStrictEqual(inspect(parser('[[^a,|]]')), [['<sup class="reference" data-abbr="a,"><span></span></sup>'], '']);
66
- assert.deepStrictEqual(inspect(parser('[[^a |]]')), [['<sup class="reference" data-abbr="a"><span></span></sup>'], '']);
67
- assert.deepStrictEqual(inspect(parser('[[^a|b]]')), [['<sup class="reference" data-abbr="a"><span>b</span></sup>'], '']);
68
- assert.deepStrictEqual(inspect(parser('[[^a|b]]')), [['<sup class="reference" data-abbr="a"><span>b</span></sup>'], '']);
69
- assert.deepStrictEqual(inspect(parser('[[^a|b ]]')), [['<sup class="reference" data-abbr="a"><span>b</span></sup>'], '']);
70
- assert.deepStrictEqual(inspect(parser('[[^a|b ]]')), [['<sup class="reference" data-abbr="a"><span>b</span></sup>'], '']);
71
- assert.deepStrictEqual(inspect(parser('[[^a|<wbr>]]')), [['<sup class="reference" data-abbr="a"><span></span></sup>'], '']);
72
- assert.deepStrictEqual(inspect(parser('[[^a|<wbr>b]]')), [['<sup class="reference" data-abbr="a"><span>b</span></sup>'], '']);
73
- assert.deepStrictEqual(inspect(parser('[[^a|^b]]')), [['<sup class="reference" data-abbr="a"><span>^b</span></sup>'], '']);
74
- assert.deepStrictEqual(inspect(parser('[[^a| ]]')), [['<sup class="reference" data-abbr="a"><span></span></sup>'], '']);
75
- assert.deepStrictEqual(inspect(parser('[[^a| b]]')), [['<sup class="reference" data-abbr="a"><span>b</span></sup>'], '']);
76
- assert.deepStrictEqual(inspect(parser('[[^a| ]]')), [['<sup class="reference" data-abbr="a"><span></span></sup>'], '']);
57
+ assert.deepStrictEqual(inspect(parser('[[^A]]')), [['<sup class="reference" data-abbr="A"><span></span></sup>'], '']);
58
+ assert.deepStrictEqual(inspect(parser('[[^A,]]')), [['<sup class="reference" data-abbr="A,"><span></span></sup>'], '']);
59
+ assert.deepStrictEqual(inspect(parser('[[^A, ]]')), [['<sup class="reference" data-abbr="A,"><span></span></sup>'], '']);
60
+ assert.deepStrictEqual(inspect(parser('[[^A.]]')), [['<sup class="reference" data-abbr="A."><span></span></sup>'], '']);
61
+ assert.deepStrictEqual(inspect(parser('[[^A.,]]')), [['<sup class="reference" data-abbr="A.,"><span></span></sup>'], '']);
62
+ assert.deepStrictEqual(inspect(parser('[[^A?]]')), [['<sup class="reference" data-abbr="A?"><span></span></sup>'], '']);
63
+ assert.deepStrictEqual(inspect(parser('[[^A?,]]')), [['<sup class="reference" data-abbr="A?,"><span></span></sup>'], '']);
64
+ assert.deepStrictEqual(inspect(parser('[[^A ]]')), [['<sup class="reference" data-abbr="A"><span></span></sup>'], '']);
65
+ assert.deepStrictEqual(inspect(parser('[[^A ]]')), [['<sup class="invalid"><span>^A</span></sup>'], '']);
66
+ assert.deepStrictEqual(inspect(parser('[[^A B]]')), [['<sup class="reference" data-abbr="A B"><span></span></sup>'], '']);
67
+ assert.deepStrictEqual(inspect(parser('[[^A B]]')), [['<sup class="invalid"><span>^A B</span></sup>'], '']);
68
+ assert.deepStrictEqual(inspect(parser('[[^A|]]')), [['<sup class="reference" data-abbr="A"><span></span></sup>'], '']);
69
+ assert.deepStrictEqual(inspect(parser('[[^A,|]]')), [['<sup class="reference" data-abbr="A,"><span></span></sup>'], '']);
70
+ assert.deepStrictEqual(inspect(parser('[[^A |]]')), [['<sup class="reference" data-abbr="A"><span></span></sup>'], '']);
71
+ assert.deepStrictEqual(inspect(parser('[[^A|b]]')), [['<sup class="reference" data-abbr="A"><span>b</span></sup>'], '']);
72
+ assert.deepStrictEqual(inspect(parser('[[^A|b]]')), [['<sup class="reference" data-abbr="A"><span>b</span></sup>'], '']);
73
+ assert.deepStrictEqual(inspect(parser('[[^A|b ]]')), [['<sup class="reference" data-abbr="A"><span>b</span></sup>'], '']);
74
+ assert.deepStrictEqual(inspect(parser('[[^A|b ]]')), [['<sup class="reference" data-abbr="A"><span>b</span></sup>'], '']);
75
+ assert.deepStrictEqual(inspect(parser('[[^A|<wbr>]]')), [['<sup class="reference" data-abbr="A"><span></span></sup>'], '']);
76
+ assert.deepStrictEqual(inspect(parser('[[^A|<wbr>b]]')), [['<sup class="reference" data-abbr="A"><span>b</span></sup>'], '']);
77
+ assert.deepStrictEqual(inspect(parser('[[^A| ]]')), [['<sup class="reference" data-abbr="A"><span></span></sup>'], '']);
78
+ assert.deepStrictEqual(inspect(parser('[[^A| b]]')), [['<sup class="reference" data-abbr="A"><span>b</span></sup>'], '']);
79
+ assert.deepStrictEqual(inspect(parser('[[^A| ]]')), [['<sup class="reference" data-abbr="A"><span></span></sup>'], '']);
80
+ assert.deepStrictEqual(inspect(parser('[[^A|^]]')), [['<sup class="reference" data-abbr="A"><span>^</span></sup>'], '']);
81
+ assert.deepStrictEqual(inspect(parser('[[^A|^B]]')), [['<sup class="reference" data-abbr="A"><span>^B</span></sup>'], '']);
77
82
  assert.deepStrictEqual(inspect(parser('[[^1]]')), [['<sup class="invalid"><span>^1</span></sup>'], '']);
78
- assert.deepStrictEqual(inspect(parser('[[^1a]]')), [['<sup class="reference" data-abbr="1a"><span></span></sup>'], '']);
83
+ assert.deepStrictEqual(inspect(parser('[[^1A]]')), [['<sup class="invalid"><span>^1A</span></sup>'], '']);
79
84
  assert.deepStrictEqual(inspect(parser('[[^1 ]]')), [['<sup class="invalid"><span>^1</span></sup>'], '']);
80
- assert.deepStrictEqual(inspect(parser('[[^1 a]]')), [['<sup class="reference" data-abbr="1 a"><span></span></sup>'], '']);
85
+ assert.deepStrictEqual(inspect(parser('[[^1 A]]')), [['<sup class="invalid"><span>^1 A</span></sup>'], '']);
81
86
  assert.deepStrictEqual(inspect(parser('[[^1|]]')), [['<sup class="invalid"><span>^1|</span></sup>'], '']);
82
87
  assert.deepStrictEqual(inspect(parser('[[^1 |]]')), [['<sup class="invalid"><span>^1 |</span></sup>'], '']);
83
- assert.deepStrictEqual(inspect(parser('[[^Xyz2020]]')), [['<sup class="reference" data-abbr="Xyz2020"><span></span></sup>'], '']);
84
- assert.deepStrictEqual(inspect(parser('[[^Xyz 2020]]')), [['<sup class="reference" data-abbr="Xyz 2020"><span></span></sup>'], '']);
85
- assert.deepStrictEqual(inspect(parser('[[^Xyz, 2020, p1-2]]')), [['<sup class="reference" data-abbr="Xyz, 2020, p1-2"><span></span></sup>'], '']);
86
- assert.deepStrictEqual(inspect(parser('[[^X. Y., Z et al., 2020, p1-2]]')), [['<sup class="reference" data-abbr="X. Y., Z et al., 2020, p1-2"><span></span></sup>'], '']);
88
+ assert.deepStrictEqual(inspect(parser('[[^Abc]]')), [['<sup class="reference" data-abbr="Abc"><span></span></sup>'], '']);
89
+ assert.deepStrictEqual(inspect(parser('[[^A, B]]')), [['<sup class="reference" data-abbr="A, B"><span></span></sup>'], '']);
87
90
  assert.deepStrictEqual(inspect(parser(`[[^A's, Aces']]`)), [[`<sup class="reference" data-abbr="A's, Aces'"><span></span></sup>`], '']);
91
+ assert.deepStrictEqual(inspect(parser('[[^Xyz 2020]]')), [['<sup class="reference" data-abbr="Xyz 2020"><span></span></sup>'], '']);
92
+ assert.deepStrictEqual(inspect(parser('[[^Xyz 2020, 1]]')), [['<sup class="reference" data-abbr="Xyz 2020, 1"><span></span></sup>'], '']);
93
+ assert.deepStrictEqual(inspect(parser('[[^Xyz 2020, 1, 2]]')), [['<sup class="reference" data-abbr="Xyz 2020, 1, 2"><span></span></sup>'], '']);
94
+ assert.deepStrictEqual(inspect(parser('[[^Xyz 2020, 1, fig. 1]]')), [['<sup class="reference" data-abbr="Xyz 2020, 1, fig. 1"><span></span></sup>'], '']);
95
+ assert.deepStrictEqual(inspect(parser('[[^Xyz 2020, 1, fig. 1.1]]')), [['<sup class="reference" data-abbr="Xyz 2020, 1, fig. 1.1"><span></span></sup>'], '']);
96
+ assert.deepStrictEqual(inspect(parser('[[^Xyz 2020, 1, fig. 1.1-2.1b]]')), [['<sup class="reference" data-abbr="Xyz 2020, 1, fig. 1.1-2.1b"><span></span></sup>'], '']);
97
+ assert.deepStrictEqual(inspect(parser('[[^Xyz 2020, 1, fig. 1.1a-b]]')), [['<sup class="reference" data-abbr="Xyz 2020, 1, fig. 1.1a-b"><span></span></sup>'], '']);
98
+ assert.deepStrictEqual(inspect(parser('[[^Xyz 2020, 1-2]]')), [['<sup class="reference" data-abbr="Xyz 2020, 1-2"><span></span></sup>'], '']);
99
+ assert.deepStrictEqual(inspect(parser('[[^Xyz 2020, 1:1-2]]')), [['<sup class="reference" data-abbr="Xyz 2020, 1:1-2"><span></span></sup>'], '']);
100
+ assert.deepStrictEqual(inspect(parser('[[^Xyz 2020, 1n]]')), [['<sup class="reference" data-abbr="Xyz 2020, 1n"><span></span></sup>'], '']);
101
+ assert.deepStrictEqual(inspect(parser('[[^Xyz 2020, 1n1]]')), [['<sup class="reference" data-abbr="Xyz 2020, 1n1"><span></span></sup>'], '']);
102
+ assert.deepStrictEqual(inspect(parser('[[^Xyz 2020, 1nn1-2]]')), [['<sup class="reference" data-abbr="Xyz 2020, 1nn1-2"><span></span></sup>'], '']);
103
+ assert.deepStrictEqual(inspect(parser('[[^Xyz 2020, i]]')), [['<sup class="reference" data-abbr="Xyz 2020, i"><span></span></sup>'], '']);
104
+ assert.deepStrictEqual(inspect(parser('[[^Xyz 2020, capter 1]]')), [['<sup class="reference" data-abbr="Xyz 2020, capter 1"><span></span></sup>'], '']);
105
+ assert.deepStrictEqual(inspect(parser('[[^Xyz 2020, cap. 1]]')), [['<sup class="reference" data-abbr="Xyz 2020, cap. 1"><span></span></sup>'], '']);
106
+ assert.deepStrictEqual(inspect(parser('[[^Xyz 2020a]]')), [['<sup class="reference" data-abbr="Xyz 2020a"><span></span></sup>'], '']);
107
+ assert.deepStrictEqual(inspect(parser('[[^Xyz 2020a, 1]]')), [['<sup class="reference" data-abbr="Xyz 2020a, 1"><span></span></sup>'], '']);
108
+ assert.deepStrictEqual(inspect(parser('[[^Xyz 2020-2021a]]')), [['<sup class="reference" data-abbr="Xyz 2020-2021a"><span></span></sup>'], '']);
109
+ assert.deepStrictEqual(inspect(parser('[[^Xyz 2020-2021a, 1]]')), [['<sup class="reference" data-abbr="Xyz 2020-2021a, 1"><span></span></sup>'], '']);
110
+ assert.deepStrictEqual(inspect(parser('[[^Xyz, April 1, 2020]]')), [['<sup class="reference" data-abbr="Xyz, April 1, 2020"><span></span></sup>'], '']);
111
+ assert.deepStrictEqual(inspect(parser('[[^Xyz, April 1, 2020, 1]]')), [['<sup class="reference" data-abbr="Xyz, April 1, 2020, 1"><span></span></sup>'], '']);
112
+ assert.deepStrictEqual(inspect(parser('[[^Xyz n.d.]]')), [['<sup class="reference" data-abbr="Xyz n.d."><span></span></sup>'], '']);
113
+ assert.deepStrictEqual(inspect(parser('[[^Xyz n.d., 1]]')), [['<sup class="reference" data-abbr="Xyz n.d., 1"><span></span></sup>'], '']);
114
+ assert.deepStrictEqual(inspect(parser('[[^X. Y., and Z et al. 2020, 1-2]]')), [['<sup class="reference" data-abbr="X. Y., and Z et al. 2020, 1-2"><span></span></sup>'], '']);
88
115
  assert.deepStrictEqual(inspect(parser('[[^^]]')), [['<sup class="invalid"><span>^^</span></sup>'], '']);
89
116
  assert.deepStrictEqual(inspect(parser('[[\\^]]')), [['<sup class="reference"><span>^</span></sup>'], '']);
90
117
  assert.deepStrictEqual(inspect(parser('[[^ ]]')), [['<sup class="invalid"><span>^</span></sup>'], '']);
91
- assert.deepStrictEqual(inspect(parser('[[^ a]]')), [['<sup class="invalid"><span>^ a</span></sup>'], '']);
118
+ assert.deepStrictEqual(inspect(parser('[[^ A]]')), [['<sup class="invalid"><span>^ A</span></sup>'], '']);
92
119
  assert.deepStrictEqual(inspect(parser('[[^ |]]')), [['<sup class="invalid"><span>^ |</span></sup>'], '']);
93
120
  assert.deepStrictEqual(inspect(parser('[[^ |b]]')), [['<sup class="invalid"><span>^ |b</span></sup>'], '']);
94
121
  assert.deepStrictEqual(inspect(parser('[[^ | ]]')), [['<sup class="invalid"><span>^ |</span></sup>'], '']);
@@ -4,7 +4,6 @@ import { inline } from '../inline';
4
4
  import { str } from '../source';
5
5
  import { Syntax, State } from '../context';
6
6
  import { regBlankStart, startLoose, trimNode } from '../visibility';
7
- import { stringify } from '../util';
8
7
  import { html, defrag } from 'typed-dom/dom';
9
8
 
10
9
  export const reference: ReferenceParser = lazy(() => surround(
@@ -21,24 +20,30 @@ export const reference: ReferenceParser = lazy(() => surround(
21
20
  false,
22
21
  ([, ns], rest) => [[html('sup', attributes(ns), [html('span', trimNode(defrag(ns)))])], rest]));
23
22
 
23
+ // Chicago-Style
24
24
  const abbr: ReferenceParser.AbbrParser = creation(bind(surround(
25
25
  '^',
26
- union([str(/^(?![0-9]+\s?[|\]])[0-9A-Za-z]+(?:(?:-|(?=\W)(?!'\d)'?(?!\.\d)\.?(?!,\S),? ?)[0-9A-Za-z]+)*(?:-|'?\.?,? ?)?/)]),
26
+ union([str(/^(?=[A-Z])(?:[0-9A-Za-z]'?|(?:[-.:]|\.?\??,? ?)(?!['\-.:?, ]))+/)]),
27
27
  /^\|?(?=]])|^\|[^\S\n]*/),
28
- ([source], rest) => [[html('abbr', source)], rest.replace(regBlankStart, '')]));
28
+ ([source], rest) => [['\n', source.trimEnd()], rest.replace(regBlankStart, '')]));
29
29
 
30
30
  function attributes(ns: (string | HTMLElement)[]): Record<string, string | undefined> {
31
- return typeof ns[0] === 'object' && ns[0].tagName === 'ABBR'
32
- ? {
31
+ switch (ns[0]) {
32
+ case '':
33
+ return {
34
+ class: 'invalid',
35
+ 'data-invalid-syntax': 'reference',
36
+ 'data-invalid-type': 'syntax',
37
+ 'data-invalid-message': 'Invalid abbreviation',
38
+ };
39
+ case '\n':
40
+ const abbr = ns[1] as string;
41
+ ns[0] = ns[1] = '';
42
+ return {
33
43
  class: 'reference',
34
- 'data-abbr': stringify([ns.shift()!]).trimEnd(),
35
- }
36
- : ns[0] === ''
37
- ? {
38
- class: 'invalid',
39
- 'data-invalid-syntax': 'reference',
40
- 'data-invalid-type': 'syntax',
41
- 'data-invalid-message': 'Invalid abbr',
42
- }
43
- : { class: 'reference' };
44
+ 'data-abbr': abbr,
45
+ };
46
+ default:
47
+ return { class: 'reference' };
48
+ }
44
49
  }
@@ -289,7 +289,7 @@ describe('Unit: parser/processor/note', () => {
289
289
  });
290
290
 
291
291
  it('abbr', () => {
292
- const target = parse('[[^a|b]][[^a]][[^a]]');
292
+ const target = parse('[[^A 1|b]][[^A 1]][[^A 1]]');
293
293
  const note = html('ol');
294
294
  for (let i = 0; i < 3; ++i) {
295
295
  [...reference(target, note)];
@@ -297,29 +297,29 @@ describe('Unit: parser/processor/note', () => {
297
297
  [...target.children].map(el => el.outerHTML),
298
298
  [
299
299
  html('p', [
300
- html('sup', { class: 'reference', 'data-abbr': 'a', id: 'reference::ref:a:1', title: 'b' }, [
300
+ html('sup', { class: 'reference', 'data-abbr': 'A 1', id: 'reference::ref:A_1:1', title: 'b' }, [
301
301
  html('span', { hidden: '' }, 'b'),
302
- html('a', { href: '#reference::def:a' }, '[a]')
302
+ html('a', { href: '#reference::def:A_1' }, '[A 1]')
303
303
  ]),
304
- html('sup', { class: 'reference', 'data-abbr': 'a', id: 'reference::ref:a:2', title: 'b' }, [
304
+ html('sup', { class: 'reference', 'data-abbr': 'A 1', id: 'reference::ref:A_1:2', title: 'b' }, [
305
305
  html('span', { hidden: '' }),
306
- html('a', { href: '#reference::def:a' }, '[a]')
306
+ html('a', { href: '#reference::def:A_1' }, '[A 1]')
307
307
  ]),
308
- html('sup', { class: 'reference', 'data-abbr': 'a', id: 'reference::ref:a:3', title: 'b' }, [
308
+ html('sup', { class: 'reference', 'data-abbr': 'A 1', id: 'reference::ref:A_1:3', title: 'b' }, [
309
309
  html('span', { hidden: '' }),
310
- html('a', { href: '#reference::def:a' }, '[a]')
310
+ html('a', { href: '#reference::def:A_1' }, '[A 1]')
311
311
  ]),
312
312
  ]).outerHTML,
313
313
  ]);
314
314
  assert.deepStrictEqual(
315
315
  note.outerHTML,
316
316
  html('ol', [
317
- html('li', { id: 'reference::def:a' }, [
317
+ html('li', { id: 'reference::def:A_1' }, [
318
318
  html('span', 'b'),
319
319
  html('sup', [
320
- html('a', { href: '#reference::ref:a:1', title: 'b' }, '^1'),
321
- html('a', { href: '#reference::ref:a:2' }, '^2'),
322
- html('a', { href: '#reference::ref:a:3' }, '^3'),
320
+ html('a', { href: '#reference::ref:A_1:1', title: 'b' }, '^1'),
321
+ html('a', { href: '#reference::ref:A_1:2' }, '^2'),
322
+ html('a', { href: '#reference::ref:A_1:3' }, '^3'),
323
323
  ])
324
324
  ]),
325
325
  ]).outerHTML);
@@ -327,7 +327,7 @@ describe('Unit: parser/processor/note', () => {
327
327
  });
328
328
 
329
329
  it('nest', () => {
330
- const target = parse('((a[[^b]]))[[^b|c]]');
330
+ const target = parse('((a[[^B]]))[[^B|c]]');
331
331
  const note = html('ol');
332
332
  for (let i = 0; i < 3; ++i) {
333
333
  [...annotation(target)];
@@ -339,24 +339,24 @@ describe('Unit: parser/processor/note', () => {
339
339
  html('sup', { class: 'annotation', id: 'annotation::ref:a:1', title: 'a' }, [
340
340
  html('span', { hidden: '' }, [
341
341
  'a',
342
- html('sup', { class: 'reference', 'data-abbr': 'b' }, [
342
+ html('sup', { class: 'reference', 'data-abbr': 'B' }, [
343
343
  html('span'),
344
344
  ]),
345
345
  ]),
346
346
  html('a', { href: '#annotation::def:a:1' }, '*1')
347
347
  ]),
348
- html('sup', { class: 'reference', 'data-abbr': 'b', id: 'reference::ref:b:1', title: 'c' }, [
348
+ html('sup', { class: 'reference', 'data-abbr': 'B', id: 'reference::ref:B:1', title: 'c' }, [
349
349
  html('span', { hidden: '' }, 'c'),
350
- html('a', { href: '#reference::def:b' }, '[b]')
350
+ html('a', { href: '#reference::def:B' }, '[B]')
351
351
  ]),
352
352
  ]).outerHTML,
353
353
  html('ol', { class: 'annotations' }, [
354
354
  html('li', { id: 'annotation::def:a:1', 'data-marker': '*1' }, [
355
355
  html('span', [
356
356
  'a',
357
- html('sup', { class: 'reference', 'data-abbr': 'b', id: 'reference::ref:b:2', title: 'c' }, [
357
+ html('sup', { class: 'reference', 'data-abbr': 'B', id: 'reference::ref:B:2', title: 'c' }, [
358
358
  html('span', { hidden: '' }),
359
- html('a', { href: '#reference::def:b' }, '[b]')
359
+ html('a', { href: '#reference::def:B' }, '[B]')
360
360
  ]),
361
361
  ]),
362
362
  html('sup', [html('a', { href: '#annotation::ref:a:1' }, '^1')])
@@ -366,11 +366,11 @@ describe('Unit: parser/processor/note', () => {
366
366
  assert.deepStrictEqual(
367
367
  note.outerHTML,
368
368
  html('ol', [
369
- html('li', { id: 'reference::def:b' }, [
369
+ html('li', { id: 'reference::def:B' }, [
370
370
  html('span', 'c'),
371
371
  html('sup', [
372
- html('a', { href: '#reference::ref:b:1', title: 'c' }, '^1'),
373
- html('a', { href: '#reference::ref:b:2' }, '^2'),
372
+ html('a', { href: '#reference::ref:B:1', title: 'c' }, '^1'),
373
+ html('a', { href: '#reference::ref:B:2' }, '^2'),
374
374
  ]),
375
375
  ]),
376
376
  ]).outerHTML);
@@ -39,41 +39,46 @@ function build(
39
39
  bottom: Node | null = null,
40
40
  ): Generator<HTMLAnchorElement | HTMLLIElement | undefined, undefined, undefined> {
41
41
  const defs = new Map<string, HTMLLIElement>();
42
- const splitters: Element[] = [];
43
- for (let es = target.querySelectorAll(splitter || '_'),
44
- len = es.length, i = 0; i < len; ++i) {
45
- if (i % 100 === 0) yield;
46
- const el = es[i];
47
- el.parentNode === target && splitters.push(el);
48
- }
49
42
  const refs = target.querySelectorAll(`sup.${syntax}:not(.disabled)`);
50
43
  const titles = new Map<string, string>();
51
44
  const defIndexes = new Map<HTMLLIElement, number>();
52
45
  const refSubindexes = new Map<string, number>();
53
- const defSubindexes = splitter ? new Map<string, number>() : undefined;
46
+ const defSubindexes = splitter && refs.length > 0 ? new Map<string, number>() : undefined;
47
+ const splitters = splitter && refs.length > 0 ? target.querySelectorAll(splitter) : [];
48
+ let iSplitters = 0;
54
49
  let total = 0;
55
50
  let format: 'number' | 'abbr';
56
51
  let refIndex = 0;
57
52
  for (let len = refs.length, i = 0; i < len; ++i) {
58
53
  const ref = refs[i];
59
- if (ref.closest('[hidden]')) {
54
+ if (ref.closest('sup > [hidden]')) {
60
55
  yield;
61
56
  continue;
62
57
  }
63
- while (splitters.length > 0
64
- && splitters[0].compareDocumentPosition(ref) & Node.DOCUMENT_POSITION_FOLLOWING) {
58
+ if (splitter) for (
59
+ let el: Element;
60
+ (el = splitters[iSplitters])?.compareDocumentPosition(ref) & Node.DOCUMENT_POSITION_FOLLOWING;
61
+ ++iSplitters) {
62
+ if (el.parentNode !== target) continue;
65
63
  if (defs.size > 0) {
66
64
  total += defs.size;
67
- yield* proc(defs, target.insertBefore(html('ol', { class: `${syntax}s` }), splitters[0]));
65
+ yield* proc(defs, target.insertBefore(html('ol', { class: `${syntax}s` }), el));
68
66
  assert(defs.size === 0);
69
67
  }
70
- else if (splitters.length % 100 === 0) {
68
+ else if (~iSplitters % 128 === 0) {
71
69
  yield;
72
70
  }
73
- splitters.shift();
74
71
  }
75
72
  const abbr = ref.getAttribute('data-abbr') || undefined;
76
- const identifier = abbr || identity(undefined, text(ref.firstElementChild!), 'mark')?.slice(6) || '';
73
+ const identifier = identity(
74
+ undefined,
75
+ abbr
76
+ ? abbr.match(/^(?:\S+ )+?(?:(?:January|February|March|April|May|June|August|September|October|November|December) \d{1,2}(?:-\d{0,2})?, \d{1,4}(?:-\d{0,4})?[a-z]?|n\.d\.)(?=,|$)/)?.[0] ??
77
+ abbr.match(/^[^,\s]+(?:,? [^,\s]+)*?(?: \d{1,4}(?:-\d{0,4})?[a-z]?(?=,|$)|(?=,(?: [a-z]+\.?)? [0-9]))/)?.[0] ??
78
+ abbr
79
+ : text(ref.firstElementChild!),
80
+ 'mark')
81
+ ?.slice(6) || '';
77
82
  const refSubindex = refSubindexes.get(identifier)! + 1 || 1;
78
83
  refSubindexes.set(identifier, refSubindex);
79
84
  const refId = opts.id !== ''
@@ -106,17 +111,6 @@ function build(
106
111
  : titles.get(identifier)!;
107
112
  initial && titles.set(identifier, title);
108
113
  assert(syntax !== 'annotation' || title);
109
- format ??= abbr ? 'abbr' : 'number';
110
- if (!ref.classList.contains('invalid')) {
111
- if (format === 'number' ? abbr : !abbr) {
112
- markInvalid(ref, syntax, 'format', 'Notation format must be consistent with numbers or abbreviations');
113
- }
114
- }
115
- else switch (ref.getAttribute('data-invalid-syntax')) {
116
- case 'format':
117
- case 'content':
118
- unmarkInvalid(ref);
119
- }
120
114
  ref.firstElementChild!.hasAttribute('hidden')
121
115
  ? ref.lastElementChild!.remove()
122
116
  : ref.firstElementChild!.setAttribute('hidden', '');
@@ -124,13 +118,21 @@ function build(
124
118
  id: refId,
125
119
  class: opts.id !== '' ? undefined : void ref.classList.add('disabled'),
126
120
  title,
127
- ...!title && {
128
- class: void ref.classList.add('invalid'),
129
- 'data-invalid-syntax': syntax,
130
- 'data-invalid-type': 'content',
131
- 'data-invalid-message': 'Missing the content',
132
- },
133
121
  });
122
+ switch (ref.getAttribute('data-invalid-syntax')) {
123
+ case 'format':
124
+ case 'content':
125
+ unmarkInvalid(ref);
126
+ }
127
+ format ??= abbr ? 'abbr' : 'number';
128
+ if (!ref.classList.contains('invalid')) switch (true) {
129
+ case format === 'number' ? !!abbr : !abbr:
130
+ markInvalid(ref, syntax, 'format', 'Notation format must be consistent with numbers or abbreviations');
131
+ break;
132
+ case !title:
133
+ markInvalid(ref, syntax, 'content', 'Missing the content');
134
+ break;
135
+ }
134
136
  yield ref.appendChild(html('a', { href: refId && defId && `#${defId}` }, marker(defIndex, abbr)));
135
137
  assert(ref.title || ref.matches('.invalid'));
136
138
  def.lastElementChild!.appendChild(
@@ -142,7 +144,7 @@ function build(
142
144
  `^${++refIndex}`));
143
145
  }
144
146
  if (note || defs.size > 0) {
145
- yield* proc(defs, note ?? target.insertBefore(html('ol', { class: `${syntax}s` }), splitters[0] ?? bottom));
147
+ yield* proc(defs, note ?? target.insertBefore(html('ol', { class: `${syntax}s` }), splitters[iSplitters] ?? bottom));
146
148
  }
147
149
  return;
148
150
  }