securemark 0.274.1 → 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 +0 -2
- package/CHANGELOG.md +8 -0
- package/dist/index.js +101 -129
- package/markdown.d.ts +5 -6
- package/package.json +1 -1
- package/src/parser/api/bind.test.ts +6 -6
- package/src/parser/api/parse.test.ts +69 -4
- package/src/parser/inline/mark.ts +9 -3
- package/src/parser/inline/media.ts +7 -19
- package/src/parser/inline/reference.test.ts +54 -27
- package/src/parser/inline/reference.ts +20 -15
- package/src/parser/processor/figure.ts +14 -53
- package/src/parser/processor/note.test.ts +36 -23
- package/src/parser/processor/note.ts +56 -56
- package/src/parser/util.ts +26 -0
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { identity, text } from '../inline/extension/indexee';
|
|
2
|
+
import { markInvalid, unmarkInvalid } from '../util';
|
|
2
3
|
import { frag, html, define } from 'typed-dom/dom';
|
|
3
4
|
|
|
4
5
|
export function* note(
|
|
5
6
|
target: ParentNode & Node,
|
|
6
|
-
notes?: {
|
|
7
|
+
notes?: {
|
|
8
|
+
readonly annotations?: HTMLOListElement;
|
|
9
|
+
readonly references: HTMLOListElement;
|
|
10
|
+
},
|
|
7
11
|
opts: { readonly id?: string; } = {},
|
|
8
12
|
bottom: Node | null = null,
|
|
9
13
|
): Generator<HTMLAnchorElement | HTMLLIElement | undefined, undefined, undefined> {
|
|
@@ -35,40 +39,46 @@ function build(
|
|
|
35
39
|
bottom: Node | null = null,
|
|
36
40
|
): Generator<HTMLAnchorElement | HTMLLIElement | undefined, undefined, undefined> {
|
|
37
41
|
const defs = new Map<string, HTMLLIElement>();
|
|
38
|
-
const splitters: Element[] = [];
|
|
39
|
-
for (let es = target.querySelectorAll(splitter || '_'),
|
|
40
|
-
len = es.length, i = 0; i < len; ++i) {
|
|
41
|
-
if (i % 100 === 0) yield;
|
|
42
|
-
const el = es[i];
|
|
43
|
-
el.parentNode === target && splitters.push(el);
|
|
44
|
-
}
|
|
45
42
|
const refs = target.querySelectorAll(`sup.${syntax}:not(.disabled)`);
|
|
46
43
|
const titles = new Map<string, string>();
|
|
47
44
|
const defIndexes = new Map<HTMLLIElement, number>();
|
|
48
45
|
const refSubindexes = new Map<string, number>();
|
|
49
|
-
const defSubindexes = new Map<string, number>();
|
|
50
|
-
|
|
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;
|
|
51
49
|
let total = 0;
|
|
52
|
-
let
|
|
50
|
+
let format: 'number' | 'abbr';
|
|
51
|
+
let refIndex = 0;
|
|
53
52
|
for (let len = refs.length, i = 0; i < len; ++i) {
|
|
54
53
|
const ref = refs[i];
|
|
55
|
-
if (ref.closest('[hidden]')) {
|
|
54
|
+
if (ref.closest('sup > [hidden]')) {
|
|
56
55
|
yield;
|
|
57
56
|
continue;
|
|
58
57
|
}
|
|
59
|
-
|
|
60
|
-
|
|
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;
|
|
61
63
|
if (defs.size > 0) {
|
|
62
64
|
total += defs.size;
|
|
63
|
-
yield* proc(defs, target.insertBefore(html('ol', { class: `${syntax}s` }),
|
|
65
|
+
yield* proc(defs, target.insertBefore(html('ol', { class: `${syntax}s` }), el));
|
|
66
|
+
assert(defs.size === 0);
|
|
64
67
|
}
|
|
65
|
-
else if (
|
|
68
|
+
else if (~iSplitters % 128 === 0) {
|
|
66
69
|
yield;
|
|
67
70
|
}
|
|
68
|
-
splitters.shift();
|
|
69
71
|
}
|
|
70
72
|
const abbr = ref.getAttribute('data-abbr') || undefined;
|
|
71
|
-
const identifier =
|
|
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) || '';
|
|
72
82
|
const refSubindex = refSubindexes.get(identifier)! + 1 || 1;
|
|
73
83
|
refSubindexes.set(identifier, refSubindex);
|
|
74
84
|
const refId = opts.id !== ''
|
|
@@ -77,65 +87,55 @@ function build(
|
|
|
77
87
|
const initial = splitter
|
|
78
88
|
? !defs.has(identifier)
|
|
79
89
|
: refSubindex === 1;
|
|
80
|
-
const defSubindex = defSubindexes
|
|
81
|
-
defSubindexes
|
|
90
|
+
const defSubindex = defSubindexes?.get(identifier)! + +initial || 1;
|
|
91
|
+
initial && defSubindexes?.set(identifier, defSubindex);
|
|
92
|
+
const defId = opts.id !== ''
|
|
93
|
+
? `${syntax}:${opts.id ?? ''}:def:${identifier}${splitter && `:${defSubindex}`}`
|
|
94
|
+
: undefined;
|
|
82
95
|
const def = initial
|
|
83
96
|
? html('li',
|
|
84
97
|
{
|
|
85
|
-
id:
|
|
86
|
-
'data-marker':
|
|
98
|
+
id: defId,
|
|
99
|
+
'data-marker': note ? undefined : marker(total + defs.size + 1, abbr),
|
|
87
100
|
},
|
|
88
101
|
[define(ref.firstElementChild!.cloneNode(true), { hidden: null }), html('sup')])
|
|
89
102
|
: defs.get(identifier)!;
|
|
90
103
|
initial && defs.set(identifier, def);
|
|
91
|
-
assert(def.
|
|
104
|
+
assert(def.lastElementChild?.matches('sup'));
|
|
92
105
|
const defIndex = initial
|
|
93
106
|
? total + defs.size
|
|
94
107
|
: defIndexes.get(def)!;
|
|
95
108
|
initial && defIndexes.set(def, defIndex);
|
|
96
|
-
const defId = def.id || undefined;
|
|
97
109
|
const title = initial
|
|
98
110
|
? text(ref.firstElementChild!)
|
|
99
111
|
: titles.get(identifier)!;
|
|
100
112
|
initial && titles.set(identifier, title);
|
|
101
113
|
assert(syntax !== 'annotation' || title);
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
class: void ref.classList.add('invalid'),
|
|
106
|
-
'data-invalid-syntax': syntax,
|
|
107
|
-
'data-invalid-type': 'style',
|
|
108
|
-
'data-invalid-message': `${syntax[0].toUpperCase() + syntax.slice(1)} style must be consistent`,
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
else if (ref.getAttribute('data-invalid-type') === 'style') {
|
|
112
|
-
define(ref, {
|
|
113
|
-
class: void ref.classList.remove('invalid'),
|
|
114
|
-
'data-invalid-syntax': null,
|
|
115
|
-
'data-invalid-type': null,
|
|
116
|
-
'data-invalid-message': null,
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
if (!ref.firstElementChild!.hasAttribute('hidden')) {
|
|
120
|
-
ref.firstElementChild!.setAttribute('hidden', '');
|
|
121
|
-
}
|
|
122
|
-
else {
|
|
123
|
-
ref.lastChild?.remove();
|
|
124
|
-
}
|
|
114
|
+
ref.firstElementChild!.hasAttribute('hidden')
|
|
115
|
+
? ref.lastElementChild!.remove()
|
|
116
|
+
: ref.firstElementChild!.setAttribute('hidden', '');
|
|
125
117
|
define(ref, {
|
|
126
118
|
id: refId,
|
|
127
119
|
class: opts.id !== '' ? undefined : void ref.classList.add('disabled'),
|
|
128
120
|
title,
|
|
129
|
-
...!title && {
|
|
130
|
-
class: void ref.classList.add('invalid'),
|
|
131
|
-
'data-invalid-syntax': syntax,
|
|
132
|
-
'data-invalid-type': 'content',
|
|
133
|
-
'data-invalid-message': 'Missing the content',
|
|
134
|
-
},
|
|
135
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
|
+
}
|
|
136
136
|
yield ref.appendChild(html('a', { href: refId && defId && `#${defId}` }, marker(defIndex, abbr)));
|
|
137
137
|
assert(ref.title || ref.matches('.invalid'));
|
|
138
|
-
def.
|
|
138
|
+
def.lastElementChild!.appendChild(
|
|
139
139
|
html('a',
|
|
140
140
|
{
|
|
141
141
|
href: refId && `#${refId}`,
|
|
@@ -143,8 +143,8 @@ function build(
|
|
|
143
143
|
},
|
|
144
144
|
`^${++refIndex}`));
|
|
145
145
|
}
|
|
146
|
-
if (defs.size > 0
|
|
147
|
-
yield* proc(defs, note ?? target.insertBefore(html('ol', { class: `${syntax}s` }), splitters[
|
|
146
|
+
if (note || defs.size > 0) {
|
|
147
|
+
yield* proc(defs, note ?? target.insertBefore(html('ol', { class: `${syntax}s` }), splitters[iSplitters] ?? bottom));
|
|
148
148
|
}
|
|
149
149
|
return;
|
|
150
150
|
}
|
package/src/parser/util.ts
CHANGED
|
@@ -1,3 +1,29 @@
|
|
|
1
|
+
import { define } from 'typed-dom/dom';
|
|
2
|
+
|
|
3
|
+
export function markInvalid<T extends Element>(
|
|
4
|
+
el: T,
|
|
5
|
+
syntax: string,
|
|
6
|
+
type: string,
|
|
7
|
+
message: string,
|
|
8
|
+
): T {
|
|
9
|
+
assert(!message.endsWith('.'));
|
|
10
|
+
return define(el, {
|
|
11
|
+
class: void el.classList.add('invalid'),
|
|
12
|
+
'data-invalid-syntax': syntax,
|
|
13
|
+
'data-invalid-type': type,
|
|
14
|
+
'data-invalid-message': message,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function unmarkInvalid<T extends Element>(el: T): T {
|
|
19
|
+
return define(el, {
|
|
20
|
+
class: void el.classList.remove('invalid'),
|
|
21
|
+
'data-invalid-syntax': null,
|
|
22
|
+
'data-invalid-type': null,
|
|
23
|
+
'data-invalid-message': null,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
1
27
|
export function stringify(nodes: readonly (HTMLElement | string)[]): string {
|
|
2
28
|
let acc = '';
|
|
3
29
|
for (let i = 0; i < nodes.length; ++i) {
|