securemark 0.297.0 → 0.297.1

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,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.297.1
4
+
5
+ - Fix note processing.
6
+
3
7
  ## 0.297.0
4
8
 
5
9
  - Enhance annotation parser to allow nested annotations.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! securemark v0.297.0 https://github.com/falsandtru/securemark | (c) 2017, falsandtru | UNLICENSED License */
1
+ /*! securemark v0.297.1 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"));
@@ -7123,22 +7123,8 @@ function baseR(n, r) {
7123
7123
  return acc;
7124
7124
  }
7125
7125
  function signature(target) {
7126
- for (let es = target.querySelectorAll('code[data-src], .math[data-src], .remark, rt, rp, br, .annotation, .reference, .checkbox, ul, ol, .label[data-label]'), len = es.length, i = 0; i < len; ++i) {
7126
+ for (let es = target.querySelectorAll('code[data-src], .math[data-src], .remark, rt, rp, br, .annotation, .reference, :is(.annotation, .reference) > a, .checkbox, ul, ol, .label[data-label]'), len = es.length, i = 0; i < len; ++i) {
7127
7127
  const el = es[i];
7128
- switch (el.tagName) {
7129
- case 'CODE':
7130
- el.replaceWith(el.getAttribute('data-src'));
7131
- continue;
7132
- case 'RT':
7133
- case 'RP':
7134
- case 'UL':
7135
- case 'OL':
7136
- el.remove();
7137
- continue;
7138
- case 'BR':
7139
- el.replaceWith('\n');
7140
- continue;
7141
- }
7142
7128
  switch (el.className) {
7143
7129
  case 'math':
7144
7130
  el.replaceWith(el.getAttribute('data-src'));
@@ -7153,25 +7139,28 @@ function signature(target) {
7153
7139
  el.remove();
7154
7140
  continue;
7155
7141
  }
7156
- }
7157
- return target.textContent.trim();
7158
- }
7159
- exports.signature = signature;
7160
- function text(target) {
7161
- for (let es = target.querySelectorAll('code[data-src], .math[data-src], .remark, rt, rp, br, .annotation, .reference, .checkbox, ul, ol'), len = es.length, i = 0; i < len; ++i) {
7162
- const el = es[i];
7163
7142
  switch (el.tagName) {
7164
7143
  case 'CODE':
7165
7144
  el.replaceWith(el.getAttribute('data-src'));
7166
7145
  continue;
7167
- case 'RT':
7168
- case 'RP':
7169
- case 'BR':
7170
7146
  case 'UL':
7171
7147
  case 'OL':
7148
+ case 'RT':
7149
+ case 'RP':
7150
+ case 'A':
7172
7151
  el.remove();
7173
7152
  continue;
7153
+ case 'BR':
7154
+ el.replaceWith('\n');
7155
+ continue;
7174
7156
  }
7157
+ }
7158
+ return target.textContent.trim();
7159
+ }
7160
+ exports.signature = signature;
7161
+ function text(target) {
7162
+ for (let es = target.querySelectorAll('code[data-src], .math[data-src], .remark, rt, rp, br, .annotation, .reference, :is(.annotation, .reference) > a, .checkbox, ul, ol'), len = es.length, i = 0; i < len; ++i) {
7163
+ const el = es[i];
7175
7164
  switch (el.className) {
7176
7165
  case 'math':
7177
7166
  el.replaceWith(el.getAttribute('data-src'));
@@ -7183,6 +7172,19 @@ function text(target) {
7183
7172
  el.remove();
7184
7173
  continue;
7185
7174
  }
7175
+ switch (el.tagName) {
7176
+ case 'CODE':
7177
+ el.replaceWith(el.getAttribute('data-src'));
7178
+ continue;
7179
+ case 'UL':
7180
+ case 'OL':
7181
+ case 'RT':
7182
+ case 'RP':
7183
+ case 'A':
7184
+ case 'BR':
7185
+ el.remove();
7186
+ continue;
7187
+ }
7186
7188
  }
7187
7189
  return target.textContent;
7188
7190
  }
@@ -8273,19 +8275,19 @@ function* note(target, notes, opts = {}, bottom = null) {
8273
8275
  yield* (0, exports.reference)(target, notes?.references, opts, bottom);
8274
8276
  }
8275
8277
  exports.note = note;
8276
- exports.annotation = build('annotation', 'sup.annotation:not(.annotations .annotation)', n => `*${n}`, 'h1, h2, h3, h4, h5, h6, aside.aside, hr');
8277
- exports.reference = build('reference', 'sup.reference:not(.references .reference)', (n, abbr) => `[${abbr || n}]`);
8278
+ exports.annotation = build('annotation', 'annotations', n => `*${n}`, 'h1, h2, h3, h4, h5, h6, aside.aside, hr');
8279
+ exports.reference = build('reference', 'references', (n, abbr) => `[${abbr || n}]`);
8278
8280
  // Referenceを含むAnnotationの重複排除は両構文が互いに処理済みであることを必要とするため
8279
8281
  // 構文ごとに各1回の処理では不可能
8280
- function build(syntax, query, marker, splitter = '') {
8281
- splitter &&= `${splitter}, .${syntax}s`;
8282
+ function build(syntax, plural, marker, splitter = '') {
8283
+ splitter &&= `${splitter}, .${plural}`;
8282
8284
  const refMemoryCaller = (0, memoize_1.memoize)(target => new Map() ?? target, new WeakMap());
8283
8285
  return function* (target, note, opts = {}, bottom = null) {
8284
8286
  const refMemory = refMemoryCaller(target);
8285
8287
  const refInfoCaller = (0, memoize_1.memoize)(ref => {
8286
8288
  const content = ref.firstElementChild;
8287
8289
  const abbr = ref.getAttribute('data-abbr') ?? '';
8288
- const clone = content.cloneNode(true);
8290
+ const clone = ref.cloneNode(true);
8289
8291
  const txt = (0, indexee_1.text)(clone).trim();
8290
8292
  const identifier = abbr ? (0, indexee_1.identity)('', undefined, 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)?.slice(2) || '' : (0, indexee_1.identity)('mark', undefined, (0, indexee_1.signature)(clone))?.slice(6) || '';
8291
8293
  return {
@@ -8299,11 +8301,11 @@ function build(syntax, query, marker, splitter = '') {
8299
8301
  content
8300
8302
  }] of refMemory) {
8301
8303
  content.replaceWith(content.cloneNode(true));
8302
- ref.prepend(content);
8304
+ ref.replaceChildren(content);
8303
8305
  refMemory.delete(ref);
8304
8306
  }
8305
8307
  const defs = new Map();
8306
- const refs = target.querySelectorAll(`${query}:not(.disabled)`);
8308
+ const refs = target.querySelectorAll(`.${syntax}:not(.${plural} .${syntax}):not(.disabled)`);
8307
8309
  const identifierInfoCaller = (0, memoize_1.memoize)(identifier => ({
8308
8310
  defIndex: 0,
8309
8311
  defSubindex: 0,
@@ -8329,7 +8331,7 @@ function build(syntax, query, marker, splitter = '') {
8329
8331
  if (defs.size > 0) {
8330
8332
  total += defs.size;
8331
8333
  const note = el.tagName === 'OL' ? el : target.insertBefore((0, dom_1.html)('ol', {
8332
- class: `${syntax}s`
8334
+ class: plural
8333
8335
  }), el);
8334
8336
  yield* proc(defs, note);
8335
8337
  }
@@ -8394,7 +8396,7 @@ function build(syntax, query, marker, splitter = '') {
8394
8396
  if (note || defs.size > 0) {
8395
8397
  const el = splitters[iSplitters];
8396
8398
  note ??= el?.tagName === 'OL' && el.nextElementSibling == splitters[iSplitters + 1] ? (++iSplitters, el) : target.insertBefore((0, dom_1.html)('ol', {
8397
- class: `${syntax}s`
8399
+ class: plural
8398
8400
  }), splitters[iSplitters] ?? bottom);
8399
8401
  yield* proc(defs, note);
8400
8402
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "securemark",
3
- "version": "0.297.0",
3
+ "version": "0.297.1",
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",
@@ -109,23 +109,9 @@ assert(baseR(62, 62) === '10');
109
109
  export function signature(target: Element | DocumentFragment): string {
110
110
  assert(!target.parentNode);
111
111
  assert(!target.querySelector('br:not(:has(+ :is(ul, ol)))') || target.nodeName === 'MARK');
112
- for (let es = target.querySelectorAll('code[data-src], .math[data-src], .remark, rt, rp, br, .annotation, .reference, .checkbox, ul, ol, .label[data-label]'),
112
+ for (let es = target.querySelectorAll('code[data-src], .math[data-src], .remark, rt, rp, br, .annotation, .reference, :is(.annotation, .reference) > a, .checkbox, ul, ol, .label[data-label]'),
113
113
  len = es.length, i = 0; i < len; ++i) {
114
114
  const el = es[i];
115
- switch (el.tagName) {
116
- case 'CODE':
117
- el.replaceWith(el.getAttribute('data-src')!);
118
- continue;
119
- case 'RT':
120
- case 'RP':
121
- case 'UL':
122
- case 'OL':
123
- el.remove();
124
- continue;
125
- case 'BR':
126
- el.replaceWith('\n');
127
- continue;
128
- }
129
115
  switch (el.className) {
130
116
  case 'math':
131
117
  el.replaceWith(el.getAttribute('data-src')!);
@@ -140,28 +126,31 @@ export function signature(target: Element | DocumentFragment): string {
140
126
  el.remove();
141
127
  continue;
142
128
  }
143
- }
144
- return target.textContent!.trim();
145
- }
146
-
147
- export function text(target: Element | DocumentFragment): string {
148
- assert(!target.parentNode);
149
- assert(!target.querySelector('br:not(:has(+ :is(ul, ol)))'));
150
- for (let es = target.querySelectorAll('code[data-src], .math[data-src], .remark, rt, rp, br, .annotation, .reference, .checkbox, ul, ol'),
151
- len = es.length, i = 0; i < len; ++i) {
152
- const el = es[i];
153
129
  switch (el.tagName) {
154
130
  case 'CODE':
155
131
  el.replaceWith(el.getAttribute('data-src')!);
156
132
  continue;
157
- case 'RT':
158
- case 'RP':
159
- case 'BR':
160
133
  case 'UL':
161
134
  case 'OL':
135
+ case 'RT':
136
+ case 'RP':
137
+ case 'A':
162
138
  el.remove();
163
139
  continue;
140
+ case 'BR':
141
+ el.replaceWith('\n');
142
+ continue;
164
143
  }
144
+ }
145
+ return target.textContent!.trim();
146
+ }
147
+
148
+ export function text(target: Element | DocumentFragment): string {
149
+ assert(!target.parentNode);
150
+ assert(!target.querySelector('br:not(:has(+ :is(ul, ol)))'));
151
+ for (let es = target.querySelectorAll('code[data-src], .math[data-src], .remark, rt, rp, br, .annotation, .reference, :is(.annotation, .reference) > a, .checkbox, ul, ol'),
152
+ len = es.length, i = 0; i < len; ++i) {
153
+ const el = es[i];
165
154
  switch (el.className) {
166
155
  case 'math':
167
156
  el.replaceWith(el.getAttribute('data-src')!);
@@ -173,6 +162,19 @@ export function text(target: Element | DocumentFragment): string {
173
162
  el.remove();
174
163
  continue;
175
164
  }
165
+ switch (el.tagName) {
166
+ case 'CODE':
167
+ el.replaceWith(el.getAttribute('data-src')!);
168
+ continue;
169
+ case 'UL':
170
+ case 'OL':
171
+ case 'RT':
172
+ case 'RP':
173
+ case 'A':
174
+ case 'BR':
175
+ el.remove();
176
+ continue;
177
+ }
176
178
  }
177
179
  return target.textContent!;
178
180
  }
@@ -222,7 +222,7 @@ describe('Unit: parser/processor/note', () => {
222
222
  });
223
223
 
224
224
  it('nest', () => {
225
- const target = parse('((a((b))))((a))((b))');
225
+ const target = parse('((a((b((c))))))((a))((b))');
226
226
  for (let i = 0; i < 3; ++i) {
227
227
  [...annotation(target)];
228
228
  assert.deepStrictEqual(
@@ -249,21 +249,31 @@ describe('Unit: parser/processor/note', () => {
249
249
  ]),
250
250
  html('sup', [
251
251
  html('a', { href: '#annotation::ref:a:1' }, '^1'),
252
- html('a', { href: '#annotation::ref:a:2' }, '^3'),
252
+ html('a', { href: '#annotation::ref:a:2' }, '^4'),
253
253
  ])
254
254
  ]),
255
255
  html('li', { id: 'annotation::def:b:1', 'data-marker': '*2' }, [
256
256
  html('span', [
257
257
  'b',
258
+ html('sup', { class: 'annotation', id: 'annotation::ref:c:1', title: 'c' }, [
259
+ html('a', { href: '#annotation::def:c:1' }, '*3')
260
+ ]),
258
261
  ]),
259
262
  html('sup', [
260
263
  html('a', { href: '#annotation::ref:b:1' }, '^2'),
261
- html('a', { href: '#annotation::ref:b:2' }, '^4'),
264
+ html('a', { href: '#annotation::ref:b:2' }, '^5'),
265
+ ])
266
+ ]),
267
+ html('li', { id: 'annotation::def:c:1', 'data-marker': '*3' }, [
268
+ html('span', [
269
+ 'c',
270
+ ]),
271
+ html('sup', [
272
+ html('a', { href: '#annotation::ref:c:1' }, '^3'),
262
273
  ])
263
274
  ]),
264
275
  ]).outerHTML,
265
276
  ]);
266
- target.lastChild?.remove();
267
277
  }
268
278
  });
269
279
 
@@ -376,7 +386,6 @@ describe('Unit: parser/processor/note', () => {
376
386
  ]),
377
387
  ]).outerHTML,
378
388
  ]);
379
- target.lastChild?.remove();
380
389
  }
381
390
  });
382
391
 
@@ -18,24 +18,24 @@ export function* note(
18
18
 
19
19
  export const annotation = build(
20
20
  'annotation',
21
- 'sup.annotation:not(.annotations .annotation)',
21
+ 'annotations',
22
22
  n => `*${n}`,
23
23
  'h1, h2, h3, h4, h5, h6, aside.aside, hr');
24
24
  export const reference = build(
25
25
  'reference',
26
- 'sup.reference:not(.references .reference)',
26
+ 'references',
27
27
  (n, abbr) => `[${abbr || n}]`);
28
28
 
29
29
  // Referenceを含むAnnotationの重複排除は両構文が互いに処理済みであることを必要とするため
30
30
  // 構文ごとに各1回の処理では不可能
31
31
  function build(
32
- syntax: 'annotation' | 'reference',
33
- query: `${keyof HTMLElementTagNameMap}.${string}`,
32
+ syntax: string,
33
+ plural: string,
34
34
  marker: (index: number, abbr: string) => string,
35
35
  splitter: string = '',
36
36
  ) {
37
37
  assert(syntax.match(/^[a-z]+$/));
38
- splitter &&= `${splitter}, .${syntax}s`;
38
+ splitter &&= `${splitter}, .${plural}`;
39
39
  const refMemoryCaller = memoize((target: Node) =>
40
40
  new Map<HTMLElement, {
41
41
  readonly content: Element;
@@ -54,7 +54,7 @@ function build(
54
54
  const refInfoCaller = memoize((ref: HTMLElement) => {
55
55
  const content = ref.firstElementChild!;
56
56
  const abbr = ref.getAttribute('data-abbr') ?? '';
57
- const clone = content.cloneNode(true);
57
+ const clone = ref.cloneNode(true);
58
58
  const txt = text(clone).trim();
59
59
  const identifier = abbr
60
60
  ? identity(
@@ -75,12 +75,12 @@ function build(
75
75
  }, refMemory);
76
76
  for (const [ref, { content }] of refMemory) {
77
77
  content.replaceWith(content.cloneNode(true));
78
- ref.prepend(content);
78
+ ref.replaceChildren(content);
79
79
  refMemory.delete(ref);
80
80
  }
81
81
  assert(refMemory.size === 0);
82
82
  const defs = new Map<string, HTMLLIElement>();
83
- const refs = target.querySelectorAll(`${query}:not(.disabled)`);
83
+ const refs = target.querySelectorAll<HTMLElement>(`.${syntax}:not(.${plural} .${syntax}):not(.disabled)`);
84
84
  const identifierInfoCaller = memoize((identifier: string) => ({
85
85
  defIndex: 0,
86
86
  defSubindex: 0,
@@ -104,7 +104,7 @@ function build(
104
104
  if (~iSplitters << 32 - 8 === 0) yield;
105
105
  if (!scope && el.parentNode !== target) continue;
106
106
  if (el.tagName === 'OL' && (el.nextElementSibling !== splitters[iSplitters + 1] || defs.size === 0)) {
107
- assert(el.matches(`.${syntax}s`));
107
+ assert(el.matches(`.${plural}`));
108
108
  el.remove();
109
109
  continue;
110
110
  }
@@ -112,7 +112,7 @@ function build(
112
112
  total += defs.size;
113
113
  const note = el.tagName === 'OL'
114
114
  ? el as HTMLOListElement
115
- : target.insertBefore(html('ol', { class: `${syntax}s` }), el);
115
+ : target.insertBefore(html('ol', { class: plural }), el);
116
116
  assert(note.parentNode);
117
117
  yield* proc(defs, note);
118
118
  assert(defs.size === 0);
@@ -188,7 +188,7 @@ function build(
188
188
  const el = splitters[iSplitters];
189
189
  note ??= el?.tagName === 'OL' && el.nextElementSibling == splitters[iSplitters + 1]
190
190
  ? (++iSplitters, el as HTMLOListElement)
191
- : target.insertBefore(html('ol', { class: `${syntax}s` }), splitters[iSplitters] ?? bottom);
191
+ : target.insertBefore(html('ol', { class: plural }), splitters[iSplitters] ?? bottom);
192
192
  yield* proc(defs, note);
193
193
  assert(defs.size === 0);
194
194
  }
@@ -196,7 +196,7 @@ function build(
196
196
  if (~iSplitters << 32 - 8 === 0) yield;
197
197
  if (!scope && el.parentNode !== target) continue;
198
198
  if (el.tagName === 'OL') {
199
- assert(el.matches(`.${syntax}s`));
199
+ assert(el.matches(`.${plural}`));
200
200
  el.remove();
201
201
  }
202
202
  }