wikiparser-node 1.41.0 → 1.43.0
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/README.md +43 -18
- package/bundle/bundle-es8.min.js +27 -27
- package/bundle/bundle-lsp.min.js +28 -28
- package/bundle/bundle.min.js +19 -19
- package/dist/addon/attribute.js +5 -7
- package/dist/addon/link.js +3 -2
- package/dist/addon/transclude.js +17 -29
- package/dist/bin/config.js +1 -1
- package/dist/extensions/typings.d.ts +1 -1
- package/dist/index.js +1 -2
- package/dist/lib/document.js +5 -5
- package/dist/lib/element.d.ts +3 -8
- package/dist/lib/element.js +2 -26
- package/dist/lib/lsp.d.ts +2 -0
- package/dist/lib/lsp.js +8 -20
- package/dist/lib/node.d.ts +2 -0
- package/dist/lib/node.js +0 -7
- package/dist/lib/range.d.ts +0 -7
- package/dist/lib/range.js +5 -14
- package/dist/lib/ranges.js +2 -2
- package/dist/lib/text.js +3 -5
- package/dist/map.d.ts +66 -0
- package/dist/map.js +2 -0
- package/dist/mixin/attributesParent.d.ts +4 -3
- package/dist/mixin/elementLike.d.ts +13 -0
- package/dist/mixin/elementLike.js +66 -53
- package/dist/parser/selector.js +3 -3
- package/dist/render/expand.js +4 -2
- package/dist/render/extension.js +139 -8
- package/dist/render/html.js +72 -3
- package/dist/render/magicWords.js +24 -131
- package/dist/src/arg.js +1 -2
- package/dist/src/atom.js +1 -1
- package/dist/src/attribute.d.ts +2 -2
- package/dist/src/attribute.js +17 -13
- package/dist/src/attributes.d.ts +3 -3
- package/dist/src/attributes.js +30 -14
- package/dist/src/converterRule.js +3 -5
- package/dist/src/extLink.js +5 -4
- package/dist/src/heading.js +12 -5
- package/dist/src/imageParameter.js +1 -2
- package/dist/src/index.js +4 -5
- package/dist/src/link/base.js +3 -5
- package/dist/src/link/file.js +7 -8
- package/dist/src/link/galleryImage.js +1 -3
- package/dist/src/magicLink.js +7 -7
- package/dist/src/multiLine/gallery.js +2 -3
- package/dist/src/nowiki/doubleUnderscore.d.ts +1 -0
- package/dist/src/nowiki/doubleUnderscore.js +4 -1
- package/dist/src/nowiki/quote.js +1 -3
- package/dist/src/onlyinclude.js +1 -2
- package/dist/src/parameter.js +6 -4
- package/dist/src/table/index.js +1 -2
- package/dist/src/table/td.d.ts +2 -2
- package/dist/src/table/td.js +5 -7
- package/dist/src/tag/html.js +29 -12
- package/dist/src/tagPair/ext.js +4 -1
- package/dist/src/tagPair/translate.d.ts +1 -1
- package/dist/src/tagPair/translate.js +1 -1
- package/dist/src/transclude.js +4 -2
- package/dist/util/debug.js +5 -7
- package/dist/util/html.js +3 -11
- package/extensions/dist/base.js +1 -1
- package/package.json +57 -21
|
@@ -7,30 +7,41 @@ const selector_1 = require("../util/selector");
|
|
|
7
7
|
const constants_1 = require("../util/constants");
|
|
8
8
|
/** @ignore */
|
|
9
9
|
const elementLike = (constructor) => {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
10
|
+
class ElementLike extends constructor {
|
|
11
|
+
/* NOT FOR BROWSER */
|
|
12
|
+
get children() {
|
|
13
|
+
return this.childNodes.filter((child) => child.type !== 'text');
|
|
14
|
+
}
|
|
15
|
+
get firstElementChild() {
|
|
16
|
+
return this.childNodes.find((child) => child.type !== 'text');
|
|
17
|
+
}
|
|
18
|
+
get lastElementChild() {
|
|
19
|
+
return this.childNodes.findLast((child) => child.type !== 'text');
|
|
20
|
+
}
|
|
21
|
+
get childElementCount() {
|
|
22
|
+
return this.children.length;
|
|
23
|
+
}
|
|
24
|
+
/* NOT FOR BROWSER END */
|
|
25
|
+
#getCondition(selector) {
|
|
26
|
+
return (0, selector_1.getCondition)(selector,
|
|
27
|
+
// eslint-disable-next-line unicorn/no-negated-condition
|
|
28
|
+
!('type' in this) ?
|
|
29
|
+
undefined :
|
|
30
|
+
this);
|
|
31
|
+
}
|
|
32
|
+
closest(selector) {
|
|
33
|
+
const condition = this.#getCondition(selector);
|
|
34
|
+
let { parentNode } = this;
|
|
35
|
+
while (parentNode) {
|
|
36
|
+
if (condition(parentNode)) {
|
|
37
|
+
return parentNode;
|
|
38
|
+
}
|
|
39
|
+
({ parentNode } = parentNode);
|
|
32
40
|
}
|
|
33
|
-
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
getElementBy(condition) {
|
|
44
|
+
LINT: {
|
|
34
45
|
const stack = [...this.childNodes].reverse();
|
|
35
46
|
while (stack.length > 0) {
|
|
36
47
|
const child = stack.pop(), { type, childNodes } = child;
|
|
@@ -46,10 +57,12 @@ const elementLike = (constructor) => {
|
|
|
46
57
|
}
|
|
47
58
|
return undefined;
|
|
48
59
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
60
|
+
}
|
|
61
|
+
querySelector(selector) {
|
|
62
|
+
LINT: return this.getElementBy(this.#getCondition(selector));
|
|
63
|
+
}
|
|
64
|
+
getElementsBy(condition) {
|
|
65
|
+
LINT: {
|
|
53
66
|
const stack = [...this.childNodes].reverse(), descendants = [];
|
|
54
67
|
while (stack.length > 0) {
|
|
55
68
|
const child = stack.pop(), { type, childNodes } = child;
|
|
@@ -65,36 +78,36 @@ const elementLike = (constructor) => {
|
|
|
65
78
|
}
|
|
66
79
|
return descendants;
|
|
67
80
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
/* NOT FOR BROWSER */
|
|
77
|
-
this.detach?.();
|
|
81
|
+
}
|
|
82
|
+
querySelectorAll(selector) {
|
|
83
|
+
LINT: return this.getElementsBy(this.#getCondition(selector));
|
|
84
|
+
}
|
|
85
|
+
escape() {
|
|
86
|
+
LSP: {
|
|
87
|
+
for (const child of this.childNodes) {
|
|
88
|
+
child.escape();
|
|
78
89
|
}
|
|
90
|
+
/* NOT FOR BROWSER */
|
|
91
|
+
this.detach?.();
|
|
79
92
|
}
|
|
80
|
-
/* NOT FOR BROWSER */
|
|
81
|
-
getElementByTypes(types) {
|
|
82
|
-
const typeSet = new Set(types.split(',').map(str => str.trim()));
|
|
83
|
-
return this.getElementBy((({ type }) => typeSet.has(type)));
|
|
84
|
-
}
|
|
85
|
-
getElementById(id) {
|
|
86
|
-
return this.getElementBy((token => 'id' in token && token.id === id));
|
|
87
|
-
}
|
|
88
|
-
getElementsByClassName(className) {
|
|
89
|
-
return this.getElementsBy((token => 'classList' in token && token.classList.has(className)));
|
|
90
|
-
}
|
|
91
|
-
getElementsByTagName(tag) {
|
|
92
|
-
return this.getElementsBy((({ type, name }) => name === tag && (type === 'html' || type === 'ext')));
|
|
93
|
-
}
|
|
94
93
|
}
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
/* NOT FOR BROWSER */
|
|
95
|
+
getElementByTypes(types) {
|
|
96
|
+
const typeSet = new Set(types.split(',').map(str => str.trim()));
|
|
97
|
+
return this.getElementBy((({ type }) => typeSet.has(type)));
|
|
98
|
+
}
|
|
99
|
+
getElementById(id) {
|
|
100
|
+
return this.getElementBy((token => 'id' in token && token.id === id));
|
|
101
|
+
}
|
|
102
|
+
getElementsByClassName(className) {
|
|
103
|
+
return this.getElementsBy((token => 'classList' in token && token.classList.has(className)));
|
|
104
|
+
}
|
|
105
|
+
getElementsByTagName(tag) {
|
|
106
|
+
return this.getElementsBy((({ type, name }) => name === tag && (type === 'html' || type === 'ext')));
|
|
107
|
+
}
|
|
97
108
|
}
|
|
109
|
+
(0, debug_1.mixin)(ElementLike, constructor);
|
|
110
|
+
return ElementLike;
|
|
98
111
|
};
|
|
99
112
|
exports.elementLike = elementLike;
|
|
100
113
|
constants_1.mixins['elementLike'] = __filename;
|
package/dist/parser/selector.js
CHANGED
|
@@ -163,8 +163,8 @@ const matches = (token, step, scope, has) => {
|
|
|
163
163
|
}
|
|
164
164
|
}
|
|
165
165
|
else if (selector.length === 4) { // 情形2:属性选择器
|
|
166
|
-
const [key, equal, val = '', i] = selector
|
|
167
|
-
if (!(key in token ||
|
|
166
|
+
const [key, equal, val = '', i] = selector;
|
|
167
|
+
if (!(key in token || typeof token.hasAttr === 'function' && token.hasAttr(key))) {
|
|
168
168
|
return equal === '!=';
|
|
169
169
|
}
|
|
170
170
|
const v = toCase(val, i), thisVal = getAttr(token, key);
|
|
@@ -234,7 +234,7 @@ const matches = (token, step, scope, has) => {
|
|
|
234
234
|
for (; node; node = node.parentNode) {
|
|
235
235
|
const lang = node.attributes?.['lang'];
|
|
236
236
|
if (lang !== undefined) {
|
|
237
|
-
return
|
|
237
|
+
return regex.test(lang);
|
|
238
238
|
}
|
|
239
239
|
}
|
|
240
240
|
return false;
|
package/dist/render/expand.js
CHANGED
|
@@ -186,7 +186,7 @@ const expand = (wikitext, page, callPage, config, include, context, now = index_
|
|
|
186
186
|
clean(accum, args);
|
|
187
187
|
return implicitNewLine(constants_1.functionHooks.get(name)(target, context || undefined), prev);
|
|
188
188
|
}
|
|
189
|
-
|
|
189
|
+
try {
|
|
190
190
|
const result = (0, magicWords_1.expandMagicWord)(name, args.map(({ anon, name: key, value }) => anon ? value : `${key}=${value}`), callPage, config, now, accum);
|
|
191
191
|
if (result === false) {
|
|
192
192
|
return m;
|
|
@@ -194,7 +194,9 @@ const expand = (wikitext, page, callPage, config, include, context, now = index_
|
|
|
194
194
|
clean(accum, args);
|
|
195
195
|
return implicitNewLine(result, prev);
|
|
196
196
|
}
|
|
197
|
-
|
|
197
|
+
catch {
|
|
198
|
+
return m;
|
|
199
|
+
}
|
|
198
200
|
});
|
|
199
201
|
plain.setText(expanded);
|
|
200
202
|
if (plain.type === 'parameter-key') {
|
package/dist/render/extension.js
CHANGED
|
@@ -3,6 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.renderExt = void 0;
|
|
4
4
|
const constants_1 = require("../util/constants");
|
|
5
5
|
const string_1 = require("../util/string");
|
|
6
|
+
const sharable_1 = require("../util/sharable");
|
|
7
|
+
/** @ignore */
|
|
8
|
+
const getCiteNoteId = (i, refName) => `cite_note${refName ? `-${(0, string_1.sanitizeAttr)(refName, true)}` : ''}-${i}`, getCiteRefId = (i, count, refName) => `cite_ref-${refName ? `${(0, string_1.sanitizeAttr)(refName, true)}_${i}-${count - 1}` : i}`, updateRef = (ref, content, dir) => {
|
|
9
|
+
if (!ref.content) {
|
|
10
|
+
ref.content = content;
|
|
11
|
+
ref.dir = dir;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
6
14
|
/**
|
|
7
15
|
* 将扩展标签渲染为HTML
|
|
8
16
|
* @param token 扩展标签节点
|
|
@@ -33,14 +41,16 @@ const renderExt = (token, opt) => {
|
|
|
33
41
|
.trim()}${padding}</div>`;
|
|
34
42
|
}
|
|
35
43
|
case 'gallery': {
|
|
36
|
-
const caption = firstChild.getAttrToken('caption'), perrow = parseInt(
|
|
44
|
+
const caption = firstChild.getAttrToken('caption'), perrow = parseInt(firstChild.getAttr('perrow') || ''), { classList } = firstChild, mode = firstChild.getAttr('mode')?.toLowerCase(), nolines = mode === 'nolines', padding = nolines ? 9 : 43;
|
|
37
45
|
classList.add('gallery');
|
|
38
46
|
if (nolines) {
|
|
39
47
|
classList.add('mw-gallery-nolines');
|
|
40
48
|
}
|
|
49
|
+
else if (!mode || mode === 'traditional') {
|
|
50
|
+
classList.add('mw-gallery-traditional');
|
|
51
|
+
}
|
|
41
52
|
if (perrow > 0) {
|
|
42
|
-
|
|
43
|
-
firstChild.setAttr('style', `max-width: ${(lastChild.widths + padding) * perrow}px;${typeof style === 'string' ? style : ''}`);
|
|
53
|
+
firstChild.setAttr('style', `max-width: ${(lastChild.widths + padding) * perrow}px;${firstChild.getAttr('style') || ''}`);
|
|
44
54
|
}
|
|
45
55
|
return `<ul${firstChild.toHtmlInternal()}>\n${caption
|
|
46
56
|
? `\t<li class="gallerycaption">${caption.lastChild.toHtmlInternal({ nowrap: true })}</li>\n`
|
|
@@ -51,7 +61,7 @@ const renderExt = (token, opt) => {
|
|
|
51
61
|
let html = lastChild.toHtmlInternal().trimEnd().replace(/^\n+/u, ''), lexer = firstChild.getAttr('lang');
|
|
52
62
|
const dir = firstChild.getAttr('dir') === 'rtl' ? ' rtl' : 'ltr', isInline = firstChild.getAttr('enclose') === 'none' || firstChild.hasAttr('inline'), showLines = firstChild.hasAttr('line'), { classList } = firstChild;
|
|
53
63
|
classList.add('mw-highlight');
|
|
54
|
-
if (lexer
|
|
64
|
+
if (lexer) {
|
|
55
65
|
const { Prism, loadLanguage } = require('./syntaxhighlight');
|
|
56
66
|
lexer = lexer.toLowerCase();
|
|
57
67
|
if (Prism) {
|
|
@@ -64,7 +74,7 @@ const renderExt = (token, opt) => {
|
|
|
64
74
|
}
|
|
65
75
|
catch { }
|
|
66
76
|
}
|
|
67
|
-
const highlight = firstChild.getAttr('highlight'), lines =
|
|
77
|
+
const highlight = firstChild.getAttr('highlight'), lines = highlight && new Set(highlight.split(',').flatMap((str) => {
|
|
68
78
|
const num = Number(str);
|
|
69
79
|
if (Number.isInteger(num) && num > 0) {
|
|
70
80
|
return num;
|
|
@@ -83,14 +93,14 @@ const renderExt = (token, opt) => {
|
|
|
83
93
|
if (linenos) {
|
|
84
94
|
const linelinks = firstChild.getAttr('linelinks'), startAttr = firstChild.getAttr('start');
|
|
85
95
|
lineReplace = '<span class="linenos" data-line="$1"></span>';
|
|
86
|
-
if (startAttr
|
|
96
|
+
if (startAttr) {
|
|
87
97
|
start = Number(startAttr);
|
|
88
98
|
if (!Number.isInteger(start) || start < 0) {
|
|
89
99
|
start = 1;
|
|
90
100
|
}
|
|
91
101
|
}
|
|
92
|
-
if (linelinks
|
|
93
|
-
lineReplace = `<a href="#${linelinks}-$1">${lineReplace}</a>`;
|
|
102
|
+
if (linelinks) {
|
|
103
|
+
lineReplace = `<a href="#${(0, string_1.sanitizeId)(linelinks)}-$1">${lineReplace}</a>`;
|
|
94
104
|
begin = `${linelinks}-`;
|
|
95
105
|
end = '</span>';
|
|
96
106
|
}
|
|
@@ -145,6 +155,127 @@ const renderExt = (token, opt) => {
|
|
|
145
155
|
? `<code${firstChild.toHtmlInternal()}>${html.trim().replaceAll('\n', ' ')}</code>`
|
|
146
156
|
: `<div${firstChild.toHtmlInternal()}>${html && `<pre>${(0, string_1.newline)(html)}</pre>`}</div>`;
|
|
147
157
|
}
|
|
158
|
+
case 'ref': {
|
|
159
|
+
const refs = constants_1.states.get(token.getRootNode())?.refs;
|
|
160
|
+
if (!refs) {
|
|
161
|
+
return '';
|
|
162
|
+
}
|
|
163
|
+
const follow = firstChild.getAttr('follow') || '';
|
|
164
|
+
if (/^\d+$/u.test(follow)) {
|
|
165
|
+
return '';
|
|
166
|
+
}
|
|
167
|
+
let refName = firstChild.getAttr('name') || '';
|
|
168
|
+
if (!/\D/u.test(refName)) {
|
|
169
|
+
refName = '';
|
|
170
|
+
}
|
|
171
|
+
else if (refName && follow) {
|
|
172
|
+
return '';
|
|
173
|
+
}
|
|
174
|
+
let dir = firstChild.getAttr('dir')?.toLowerCase();
|
|
175
|
+
if (dir !== 'ltr' && dir !== 'rtl') {
|
|
176
|
+
dir = undefined;
|
|
177
|
+
}
|
|
178
|
+
const text = token.innerText?.trim(), references = token.closest('ext#references');
|
|
179
|
+
if (references) {
|
|
180
|
+
const { referencesGroup } = refs.get(references.getAttr('group') || '');
|
|
181
|
+
if (refName && text) {
|
|
182
|
+
const ref = referencesGroup.find(({ name: n }) => n === refName);
|
|
183
|
+
if (ref) {
|
|
184
|
+
updateRef(ref, lastChild, dir);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return '';
|
|
188
|
+
}
|
|
189
|
+
else if (!refName && !text || text && /<references\b[^>]*>/iu.test(text)) {
|
|
190
|
+
return '';
|
|
191
|
+
}
|
|
192
|
+
else if (text && /<ref\b[^>]*>/iu.test(text)) {
|
|
193
|
+
const inner = lastChild.cloneNode();
|
|
194
|
+
for (const ref of inner.querySelectorAll('ext#ref')) {
|
|
195
|
+
ref.remove();
|
|
196
|
+
}
|
|
197
|
+
if (/<ref\b[^>]*>/iu.test(inner.toString())) {
|
|
198
|
+
return '';
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
const group = firstChild.getAttr('group') || '';
|
|
202
|
+
if (!refs.has(group)) {
|
|
203
|
+
refs.set(group, { referencesGroup: [], follows: [] });
|
|
204
|
+
}
|
|
205
|
+
const { referencesGroup, follows } = refs.get(group);
|
|
206
|
+
if (follow) {
|
|
207
|
+
const ref = referencesGroup.find(({ name: n }) => n === follow);
|
|
208
|
+
if (ref) {
|
|
209
|
+
if (ref.content) {
|
|
210
|
+
ref.content.safeAppend([' ', ...lastChild.childNodes]);
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
ref.content = lastChild;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
refs.id++;
|
|
218
|
+
follows.push({ content: lastChild });
|
|
219
|
+
}
|
|
220
|
+
return '';
|
|
221
|
+
}
|
|
222
|
+
let i = refName ? referencesGroup.findIndex(({ name: n }) => n === refName) : -1, count = 1, ref;
|
|
223
|
+
if (i === -1) {
|
|
224
|
+
i = referencesGroup.length;
|
|
225
|
+
ref = {
|
|
226
|
+
...refName && { name: refName },
|
|
227
|
+
...text && { content: lastChild },
|
|
228
|
+
dir,
|
|
229
|
+
count,
|
|
230
|
+
id: ++refs.id,
|
|
231
|
+
};
|
|
232
|
+
referencesGroup.push(ref);
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
ref = referencesGroup[i];
|
|
236
|
+
ref.count++;
|
|
237
|
+
({ count } = ref);
|
|
238
|
+
if (text) {
|
|
239
|
+
updateRef(ref, lastChild, dir);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return `<sup id="${getCiteRefId(ref.id, count, refName)}" class="reference"><a href="#${getCiteNoteId(ref.id, refName)}"><span class="cite-bracket">[</span>${group}${group && ' '}${i + 1}<span class="cite-bracket">]</span></a></sup>`;
|
|
243
|
+
}
|
|
244
|
+
case 'references': {
|
|
245
|
+
const refs = constants_1.states.get(token.getRootNode())?.refs;
|
|
246
|
+
if (!refs
|
|
247
|
+
|| firstChild.childNodes.filter(node => node.is('ext-attr'))
|
|
248
|
+
.some(({ name: key }) => !sharable_1.extAttrs['references'].has(key))) {
|
|
249
|
+
return '';
|
|
250
|
+
}
|
|
251
|
+
const group = firstChild.getAttr('group') || '';
|
|
252
|
+
if (!refs.has(group)) {
|
|
253
|
+
return '';
|
|
254
|
+
}
|
|
255
|
+
const html = lastChild.toHtmlInternal();
|
|
256
|
+
if (!refs.has(group)) { // 嵌套的`<ref>`
|
|
257
|
+
return html;
|
|
258
|
+
}
|
|
259
|
+
const { referencesGroup, follows } = refs.get(group);
|
|
260
|
+
if (referencesGroup.length === 0 && follows.length === 0) {
|
|
261
|
+
return '';
|
|
262
|
+
}
|
|
263
|
+
let ol = `<ol class="references"${group && ` data-mw-group="${group}"`}>`;
|
|
264
|
+
for (const { content } of follows) {
|
|
265
|
+
ol += `\n<p><span class="reference-text">${content.toHtmlInternal()}</span>\n</p>`;
|
|
266
|
+
}
|
|
267
|
+
for (let i = 0; i < referencesGroup.length; i++) {
|
|
268
|
+
const { content, count, dir, name: refName, id } = referencesGroup[i];
|
|
269
|
+
ol += `\n<li id="${getCiteNoteId(id, refName)}"${dir ? ` class="mw-cite-dir-${dir}"` : ''}><span class="mw-cite-backlink">${count === 1
|
|
270
|
+
? `<a href="#${getCiteRefId(id, 1, refName)}">↑</a>`
|
|
271
|
+
: `↑${Array.from({ length: count }, (_, j) => ` <sup><a href="#${getCiteRefId(id, j + 1, refName)}">${i + 1}.${j}</a></sup>`).join('')}`}</span> <span class="reference-text">${content?.toHtmlInternal() ?? ''}</span>\n</li>`;
|
|
272
|
+
}
|
|
273
|
+
ol += '\n</ol>';
|
|
274
|
+
refs.delete(group);
|
|
275
|
+
return firstChild.getAttr('responsive') === '0'
|
|
276
|
+
? ol
|
|
277
|
+
: `<div class="mw-references-wrap${referencesGroup.length > 10 ? ' mw-references-columns' : ''}">${ol}</div>`;
|
|
278
|
+
}
|
|
148
279
|
default:
|
|
149
280
|
return '';
|
|
150
281
|
}
|
package/dist/render/html.js
CHANGED
|
@@ -2,7 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.toHtml = void 0;
|
|
4
4
|
const constants_1 = require("../util/constants");
|
|
5
|
-
const blockElems = 'table|h[1-6]|pre|p|[uod]l', antiBlockElems = 't[dh]';
|
|
5
|
+
const blockElems = 'table|h[1-6]|pre|p|[uod]l', antiBlockElems = 't[dh]', allowed = new Set(['sup', 'sub', 'bdi', 'i', 'b', 's', 'strike', 'q']);
|
|
6
|
+
const tocContainer = '<div id="toc" class="toc" role="navigation" aria-labelledby="mw-toc-heading">'
|
|
7
|
+
+ '<input type="checkbox" role="button" id="toctogglecheckbox" class="toctogglecheckbox" style="display:none" />'
|
|
8
|
+
+ '<div class="toctitle">'
|
|
9
|
+
+ '<h2 id="mw-toc-heading">Contents</h2>'
|
|
10
|
+
+ '<span class="toctogglespan"><label class="toctogglelabel" for="toctogglecheckbox"></label></span>'
|
|
11
|
+
+ '</div>';
|
|
6
12
|
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
7
13
|
/<(?:table|\/t[dh]|\/?(?:tr|caption|d[td]|li))\b/iu;
|
|
8
14
|
const openRegex = new RegExp(String.raw `<(?:${blockElems}|\/${antiBlockElems}|\/?(?:tr|caption|d[td]|li))\b`, 'iu');
|
|
@@ -14,8 +20,70 @@ const closeRegex = new RegExp(String.raw `<(?:\/(?:${blockElems})|${antiBlockEle
|
|
|
14
20
|
* @param token 展开后的节点
|
|
15
21
|
*/
|
|
16
22
|
const toHtml = (token) => {
|
|
17
|
-
constants_1.states.set(token, {
|
|
23
|
+
constants_1.states.set(token, {
|
|
24
|
+
headings: new Set(),
|
|
25
|
+
categories: new Set(),
|
|
26
|
+
refs: Object.assign(new Map(), { id: 0 }),
|
|
27
|
+
});
|
|
28
|
+
// 前处理引用
|
|
29
|
+
const hasCite = token.getAttribute('config').ext.includes('references');
|
|
30
|
+
if (hasCite) {
|
|
31
|
+
token.append('\n', token.createElement('references', { selfClosing: true }));
|
|
32
|
+
}
|
|
33
|
+
// 处理目录
|
|
34
|
+
const tocSwitch = token.querySelector('double-underscore#toc'), forcetoc = tocSwitch || token.querySelector('double-underscore#forcetoc'), tocData = [];
|
|
35
|
+
if (forcetoc || !token.querySelector('double-underscore#notoc')) {
|
|
36
|
+
const headings = token.querySelectorAll('heading,html#h1,html#h2,html#h3,html#h4,html#h5,html#h6');
|
|
37
|
+
let firstHeading;
|
|
38
|
+
for (const heading of headings) {
|
|
39
|
+
if (heading.type === 'heading') {
|
|
40
|
+
tocData.push([heading.level, heading.getRenderedId(), heading.firstChild.toHtmlInternal().trim()]);
|
|
41
|
+
firstHeading ??= heading;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
const tocLine = heading.getTocLine();
|
|
45
|
+
if (tocLine) {
|
|
46
|
+
tocData.push([Number(heading.name.slice(1)), ...tocLine]);
|
|
47
|
+
firstHeading ??= heading;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const { length } = tocData;
|
|
52
|
+
if (forcetoc && length || length > 3) {
|
|
53
|
+
const levels = [], tocNumbers = [];
|
|
54
|
+
let toc = tocContainer, i = 0;
|
|
55
|
+
for (const [level, id, text] of tocData) {
|
|
56
|
+
const n = levels.length;
|
|
57
|
+
let j = levels.findIndex(l => l >= level), prefix;
|
|
58
|
+
if (j === -1) {
|
|
59
|
+
j = n;
|
|
60
|
+
prefix = '\n<ul>';
|
|
61
|
+
levels.push(level);
|
|
62
|
+
tocNumbers.push(1);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
prefix = `${'</li>\n</ul>\n'.repeat(n - j - 1)}</li>`;
|
|
66
|
+
levels.splice(j, Infinity, level);
|
|
67
|
+
tocNumbers.length = j + 1;
|
|
68
|
+
tocNumbers[j]++;
|
|
69
|
+
}
|
|
70
|
+
toc += `${prefix}\n<li class="toclevel-${j + 1} tocsection-${++i}"><a href="#${id}"><span class="tocnumber">${tocNumbers.join('.')}</span> <span class="toctext">${text.replaceAll(/<(\/?)([a-z]\w*)\b.*?>/gu, (_, slash, tag) => allowed.has(tag) ? `<${slash}${tag}>` : '').trim()}</span></a>`;
|
|
71
|
+
}
|
|
72
|
+
toc = i === 0 ? '' : `${toc}${'</li>\n</ul>\n'.repeat(levels.length)}</div>\n`;
|
|
73
|
+
if (tocSwitch) {
|
|
74
|
+
tocSwitch.tocData = toc;
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
firstHeading.tocData = toc;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// 后处理引用
|
|
18
82
|
const lines = token.toHtmlInternal().split('\n');
|
|
83
|
+
if (hasCite && lines.at(-1) === '') {
|
|
84
|
+
lines.pop();
|
|
85
|
+
}
|
|
86
|
+
// 处理正文
|
|
19
87
|
let output = '', inBlockElem = false, pendingPTag = false, inBlockquote = false, lastParagraph = '';
|
|
20
88
|
const /** @ignore */ closeParagraph = () => {
|
|
21
89
|
if (lastParagraph) {
|
|
@@ -78,9 +146,10 @@ const toHtml = (token) => {
|
|
|
78
146
|
}
|
|
79
147
|
}
|
|
80
148
|
output += closeParagraph();
|
|
149
|
+
let html = output.trimEnd();
|
|
150
|
+
// 处理分类
|
|
81
151
|
const { categories } = constants_1.states.get(token);
|
|
82
152
|
constants_1.states.delete(token);
|
|
83
|
-
let html = output.trimEnd();
|
|
84
153
|
if (categories.size > 0) {
|
|
85
154
|
html += `
|
|
86
155
|
<div id="catlinks" class="catlinks"><div><a href="${token.normalizeTitle('Special:Categories', -1, { temporary: true }).getUrl()}" title="Special:Categories">Categories</a>: <ul>${[...categories].map(catlink => `<li>${catlink}</li>`).join('')}</div></div>`;
|