wikiparser-node 1.41.0 → 1.42.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 +5 -3
- 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 +1 -1
- package/dist/addon/transclude.js +1 -3
- package/dist/bin/config.js +1 -1
- package/dist/index.js +1 -2
- 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/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/extension.js +139 -8
- package/dist/render/html.js +72 -3
- 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/extLink.js +5 -4
- package/dist/src/heading.js +11 -3
- package/dist/src/index.js +3 -4
- package/dist/src/link/base.js +2 -4
- package/dist/src/link/file.js +5 -5
- package/dist/src/link/galleryImage.js +1 -3
- package/dist/src/magicLink.js +6 -5
- 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/parameter.js +5 -2
- package/dist/src/table/td.d.ts +2 -2
- package/dist/src/table/td.js +1 -1
- 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/util/debug.js +5 -7
- package/dist/util/html.js +3 -11
- package/extensions/dist/base.js +1 -1
- package/package.json +5 -5
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>`;
|
package/dist/src/attribute.d.ts
CHANGED
|
@@ -39,7 +39,7 @@ export declare abstract class AttributeToken extends Token {
|
|
|
39
39
|
get balanced(): boolean;
|
|
40
40
|
set balanced(value: boolean);
|
|
41
41
|
/** attribute value / 属性值 */
|
|
42
|
-
get value(): string
|
|
42
|
+
get value(): string;
|
|
43
43
|
set value(value: string | true);
|
|
44
44
|
/**
|
|
45
45
|
* @param type 标签类型
|
|
@@ -55,7 +55,7 @@ export declare abstract class AttributeToken extends Token {
|
|
|
55
55
|
*
|
|
56
56
|
* 获取属性值
|
|
57
57
|
*/
|
|
58
|
-
getValue(): string
|
|
58
|
+
getValue(): string;
|
|
59
59
|
cloneNode(): this;
|
|
60
60
|
/**
|
|
61
61
|
* Close the quote
|
package/dist/src/attribute.js
CHANGED
|
@@ -231,7 +231,7 @@ let AttributeToken = (() => {
|
|
|
231
231
|
&& !parentNode?.hasAttr('itemscope')) {
|
|
232
232
|
/* PRINT ONLY */
|
|
233
233
|
if (start === undefined) {
|
|
234
|
-
return
|
|
234
|
+
return 2;
|
|
235
235
|
}
|
|
236
236
|
/* PRINT ONLY END */
|
|
237
237
|
LINT: {
|
|
@@ -245,10 +245,10 @@ let AttributeToken = (() => {
|
|
|
245
245
|
}
|
|
246
246
|
}
|
|
247
247
|
}
|
|
248
|
-
else if (name === 'style' &&
|
|
248
|
+
else if (name === 'style' && insecureStyle.test(value)) {
|
|
249
249
|
/* PRINT ONLY */
|
|
250
250
|
if (start === undefined) {
|
|
251
|
-
return
|
|
251
|
+
return 1;
|
|
252
252
|
}
|
|
253
253
|
/* PRINT ONLY END */
|
|
254
254
|
LINT: {
|
|
@@ -257,10 +257,10 @@ let AttributeToken = (() => {
|
|
|
257
257
|
return s && (0, lint_1.generateForChild)(lastChild, rect, rule, 'insecure-style', s);
|
|
258
258
|
}
|
|
259
259
|
}
|
|
260
|
-
else if (name === 'tabindex' &&
|
|
260
|
+
else if (name === 'tabindex' && value !== '0') {
|
|
261
261
|
/* PRINT ONLY */
|
|
262
262
|
if (start === undefined) {
|
|
263
|
-
return
|
|
263
|
+
return 2;
|
|
264
264
|
}
|
|
265
265
|
/* PRINT ONLY END */
|
|
266
266
|
LINT: {
|
|
@@ -277,14 +277,14 @@ let AttributeToken = (() => {
|
|
|
277
277
|
}
|
|
278
278
|
}
|
|
279
279
|
}
|
|
280
|
-
else if (
|
|
280
|
+
else if ((/^xmlns:[\w:.-]+$/u.test(name) || urlAttrs.has(name)) && evil.test(value)
|
|
281
281
|
|| simple
|
|
282
282
|
&& (name === 'href' || type === 'ext-attr' && tag === 'img' && name === 'src')
|
|
283
283
|
&& !new RegExp(String.raw `^(?:${this.getAttribute('config').protocol}|//)\S+$`, 'iu')
|
|
284
|
-
.test(value))
|
|
284
|
+
.test(value)) {
|
|
285
285
|
/* PRINT ONLY */
|
|
286
286
|
if (start === undefined) {
|
|
287
|
-
return
|
|
287
|
+
return 2;
|
|
288
288
|
}
|
|
289
289
|
/* PRINT ONLY END */
|
|
290
290
|
LINT: {
|
|
@@ -293,11 +293,11 @@ let AttributeToken = (() => {
|
|
|
293
293
|
}
|
|
294
294
|
}
|
|
295
295
|
else if (simple && type !== 'ext-attr') {
|
|
296
|
-
const data = (0, lint_1.provideValues)(tag, name), v =
|
|
296
|
+
const data = (0, lint_1.provideValues)(tag, name), v = value.toLowerCase();
|
|
297
297
|
if (data.length > 0 && data.every(n => n !== v)) {
|
|
298
298
|
/* PRINT ONLY */
|
|
299
299
|
if (start === undefined) {
|
|
300
|
-
return
|
|
300
|
+
return 2;
|
|
301
301
|
}
|
|
302
302
|
/* PRINT ONLY END */
|
|
303
303
|
LINT: {
|
|
@@ -363,7 +363,7 @@ let AttributeToken = (() => {
|
|
|
363
363
|
* 获取属性值
|
|
364
364
|
*/
|
|
365
365
|
getValue() {
|
|
366
|
-
return this.#equal ? this.lastChild.text().
|
|
366
|
+
return this.#equal ? this.lastChild.text().replace(/[\t\r\n ]+/gu, ' ').trim() : '';
|
|
367
367
|
}
|
|
368
368
|
/** @private */
|
|
369
369
|
escape() {
|
|
@@ -380,7 +380,7 @@ let AttributeToken = (() => {
|
|
|
380
380
|
return this.#quotes;
|
|
381
381
|
}
|
|
382
382
|
/* NOT FOR BROWSER END */
|
|
383
|
-
return key === 'invalid' ? this.#lint() : super.getAttribute(key);
|
|
383
|
+
return key === 'invalid' ? Boolean(this.#lint()) : super.getAttribute(key);
|
|
384
384
|
}
|
|
385
385
|
/** @private */
|
|
386
386
|
print() {
|
|
@@ -464,9 +464,13 @@ let AttributeToken = (() => {
|
|
|
464
464
|
/** @private */
|
|
465
465
|
toHtmlInternal() {
|
|
466
466
|
const { type, name, tag, lastChild } = this;
|
|
467
|
-
if (type === 'ext-attr' && sharable_1.extAttrs[tag]?.has(name)
|
|
467
|
+
if (type === 'ext-attr' && sharable_1.extAttrs[tag]?.has(name)) {
|
|
468
468
|
return '';
|
|
469
469
|
}
|
|
470
|
+
const linted = this.#lint();
|
|
471
|
+
if (linted) {
|
|
472
|
+
return linted === 1 ? 'style="/* insecure input */"' : '';
|
|
473
|
+
}
|
|
470
474
|
const value = lastChild.toHtmlInternal().trim();
|
|
471
475
|
if (name === 'id' && !value) {
|
|
472
476
|
return '';
|
package/dist/src/attributes.d.ts
CHANGED
|
@@ -32,7 +32,7 @@ export declare abstract class AttributesToken extends Token {
|
|
|
32
32
|
abstract get previousElementSibling(): SyntaxToken | undefined;
|
|
33
33
|
get type(): AttributesTypes;
|
|
34
34
|
/** all attributes / 全部属性 */
|
|
35
|
-
get attributes(): Record<string, string
|
|
35
|
+
get attributes(): Record<string, string>;
|
|
36
36
|
set attributes(attrs: Record<string, string | true>);
|
|
37
37
|
/** class attribute in string / 以字符串表示的class属性 */
|
|
38
38
|
get className(): string;
|
|
@@ -78,7 +78,7 @@ export declare abstract class AttributesToken extends Token {
|
|
|
78
78
|
* 获取指定属性
|
|
79
79
|
* @param key attribute name / 属性键
|
|
80
80
|
*/
|
|
81
|
-
getAttr(key: string): string |
|
|
81
|
+
getAttr(key: string): string | undefined;
|
|
82
82
|
/**
|
|
83
83
|
* Sanitize invalid attributes
|
|
84
84
|
*
|
|
@@ -115,7 +115,7 @@ export declare abstract class AttributesToken extends Token {
|
|
|
115
115
|
*
|
|
116
116
|
* 获取全部属性
|
|
117
117
|
*/
|
|
118
|
-
getAttrs(): Record<string, string
|
|
118
|
+
getAttrs(): Record<string, string>;
|
|
119
119
|
/**
|
|
120
120
|
* Remove an attribute
|
|
121
121
|
*
|
package/dist/src/attributes.js
CHANGED
|
@@ -82,6 +82,17 @@ const required = new Map([
|
|
|
82
82
|
['section', [['begin', 'end']]],
|
|
83
83
|
['templatestyles', ['src']],
|
|
84
84
|
]);
|
|
85
|
+
/* NOT FOR BROWSER */
|
|
86
|
+
/**
|
|
87
|
+
* 处理不显示的`<ref>`
|
|
88
|
+
* @param token 不显示的节点
|
|
89
|
+
*/
|
|
90
|
+
const renderRefs = (token) => {
|
|
91
|
+
for (const ref of token.querySelectorAll('ext#ref')) {
|
|
92
|
+
ref.toHtmlInternal();
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
/* NOT FOR BROWSER END */
|
|
85
96
|
/**
|
|
86
97
|
* attributes of extension and HTML tags
|
|
87
98
|
*
|
|
@@ -120,8 +131,7 @@ let AttributesToken = (() => {
|
|
|
120
131
|
}
|
|
121
132
|
/** class attribute in string / 以字符串表示的class属性 */
|
|
122
133
|
get className() {
|
|
123
|
-
|
|
124
|
-
return typeof attr === 'string' ? attr : '';
|
|
134
|
+
return this.getAttr('class') || '';
|
|
125
135
|
}
|
|
126
136
|
set className(className) {
|
|
127
137
|
this.setAttr('class', className || false);
|
|
@@ -151,8 +161,7 @@ let AttributesToken = (() => {
|
|
|
151
161
|
}
|
|
152
162
|
/** id attribute / id属性 */
|
|
153
163
|
get id() {
|
|
154
|
-
|
|
155
|
-
return typeof attr === 'string' ? attr : '';
|
|
164
|
+
return this.getAttr('id') || '';
|
|
156
165
|
}
|
|
157
166
|
set id(id) {
|
|
158
167
|
this.setAttr('id', id || false);
|
|
@@ -302,11 +311,8 @@ let AttributesToken = (() => {
|
|
|
302
311
|
const severity = lintConfig.getSeverity(rules[1], tag);
|
|
303
312
|
if (severity) {
|
|
304
313
|
for (const key of required.get(tag)) {
|
|
305
|
-
const keys = typeof key === 'string' ? [key] : key
|
|
306
|
-
|
|
307
|
-
return value === true || !value;
|
|
308
|
-
});
|
|
309
|
-
if (missing) {
|
|
314
|
+
const keys = typeof key === 'string' ? [key] : key;
|
|
315
|
+
if (!keys.some(k => this.getAttr(k))) {
|
|
310
316
|
errors.push((0, lint_1.generateForSelf)(this, rect, rules[1], index_1.default.msg('required-attribute', keys.join('/')), severity));
|
|
311
317
|
}
|
|
312
318
|
}
|
|
@@ -315,10 +321,7 @@ let AttributesToken = (() => {
|
|
|
315
321
|
const severity = lintConfig.getSeverity(rules[2], 'attribute');
|
|
316
322
|
if (severity && duplicated.size > 0) {
|
|
317
323
|
for (const key of duplicated) {
|
|
318
|
-
const pairs = attrs.get(key).map(attr =>
|
|
319
|
-
const value = attr.getValue();
|
|
320
|
-
return [attr, value === true ? '' : value];
|
|
321
|
-
});
|
|
324
|
+
const pairs = attrs.get(key).map(attr => [attr, attr.getValue()]);
|
|
322
325
|
Array.prototype.push.apply(errors, pairs.map(([attr, value], i) => {
|
|
323
326
|
const e = (0, lint_1.generateForChild)(attr, rect, rules[2], index_1.default.msg('duplicate-attribute', key), severity);
|
|
324
327
|
if (computeEditInfo || fix) {
|
|
@@ -488,7 +491,20 @@ let AttributesToken = (() => {
|
|
|
488
491
|
}
|
|
489
492
|
/** @private */
|
|
490
493
|
toHtmlInternal() {
|
|
491
|
-
const map = new Map(
|
|
494
|
+
const map = new Map();
|
|
495
|
+
for (const child of this.childNodes) {
|
|
496
|
+
if (child instanceof attribute_1.AttributeToken) {
|
|
497
|
+
const last = map.get(child.name);
|
|
498
|
+
if (last) {
|
|
499
|
+
renderRefs(last);
|
|
500
|
+
}
|
|
501
|
+
map.set(child.name, child);
|
|
502
|
+
}
|
|
503
|
+
else {
|
|
504
|
+
renderRefs(child);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
const output = map.size === 0 ? '' : (0, html_1.html)([...map.values()], ' ', { removeBlank: true });
|
|
492
508
|
return output && ` ${output}`;
|
|
493
509
|
}
|
|
494
510
|
/* c8 ignore start */
|
package/dist/src/extLink.js
CHANGED
|
@@ -217,26 +217,27 @@ let ExtLinkToken = (() => {
|
|
|
217
217
|
/** @private */
|
|
218
218
|
toHtmlInternal(opt) {
|
|
219
219
|
const { length, lastChild } = this;
|
|
220
|
-
let innerText, href;
|
|
220
|
+
let innerText, linkType, href;
|
|
221
221
|
if (length > 1) {
|
|
222
222
|
lastChild.normalize();
|
|
223
223
|
const { childNodes } = lastChild, i = childNodes.findIndex(child => child.is('link')
|
|
224
|
-
|| child.is('file')
|
|
225
|
-
&& child.getValue('link')?.trim() !== '');
|
|
224
|
+
|| child.is('file') && child.getValue('link')?.trim() !== '');
|
|
226
225
|
if (i !== -1) {
|
|
227
226
|
const after = childNodes.slice(i);
|
|
228
227
|
this.insertAdjacent(after, 1);
|
|
229
228
|
}
|
|
230
229
|
innerText = lastChild.toHtmlInternal(opt);
|
|
230
|
+
linkType = 'text';
|
|
231
231
|
}
|
|
232
232
|
else {
|
|
233
233
|
({ innerText } = this);
|
|
234
|
+
linkType = 'autonumber';
|
|
234
235
|
}
|
|
235
236
|
try {
|
|
236
237
|
({ href } = this.getUrl());
|
|
237
238
|
}
|
|
238
239
|
catch { }
|
|
239
|
-
return `<a rel="nofollow" class="external"${href === undefined ? '' : ` href="${href}"`}>${innerText}</a>`;
|
|
240
|
+
return `<a rel="nofollow" class="external ${linkType}"${href === undefined ? '' : ` href="${href}"`}>${innerText}</a>`;
|
|
240
241
|
}
|
|
241
242
|
/**
|
|
242
243
|
* Get the URL
|
package/dist/src/heading.js
CHANGED
|
@@ -67,12 +67,15 @@ let HeadingToken = (() => {
|
|
|
67
67
|
let _classThis;
|
|
68
68
|
let _classSuper = index_2.Token;
|
|
69
69
|
let _instanceExtraInitializers = [];
|
|
70
|
+
let _getRenderedId_decorators;
|
|
70
71
|
let _toHtmlInternal_decorators;
|
|
71
72
|
var HeadingToken = class extends _classSuper {
|
|
72
73
|
static { _classThis = this; }
|
|
73
74
|
static {
|
|
74
75
|
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
76
|
+
_getRenderedId_decorators = [(0, cached_1.cached)()];
|
|
75
77
|
_toHtmlInternal_decorators = [(0, cached_1.cached)()];
|
|
78
|
+
__esDecorate(this, null, _getRenderedId_decorators, { kind: "method", name: "getRenderedId", static: false, private: false, access: { has: obj => "getRenderedId" in obj, get: obj => obj.getRenderedId }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
76
79
|
__esDecorate(this, null, _toHtmlInternal_decorators, { kind: "method", name: "toHtmlInternal", static: false, private: false, access: { has: obj => "toHtmlInternal" in obj, get: obj => obj.toHtmlInternal }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
77
80
|
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
78
81
|
HeadingToken = _classThis = _classDescriptor.value;
|
|
@@ -296,9 +299,9 @@ let HeadingToken = (() => {
|
|
|
296
299
|
return (0, html_1.getId)(this.firstChild[expand ? 'expand' : 'cloneNode']());
|
|
297
300
|
}
|
|
298
301
|
/** @private */
|
|
299
|
-
|
|
302
|
+
getRenderedId() {
|
|
300
303
|
let id = this.#getId();
|
|
301
|
-
const
|
|
304
|
+
const lcId = id.toLowerCase(), headings = constants_1.states.get(this.getRootNode())?.headings;
|
|
302
305
|
if (headings?.has(lcId)) {
|
|
303
306
|
let i = 2;
|
|
304
307
|
for (; headings.has(`${lcId}_${i}`); i++) {
|
|
@@ -310,7 +313,12 @@ let HeadingToken = (() => {
|
|
|
310
313
|
else {
|
|
311
314
|
headings?.add(lcId);
|
|
312
315
|
}
|
|
313
|
-
return
|
|
316
|
+
return (0, string_1.sanitizeId)(id);
|
|
317
|
+
}
|
|
318
|
+
/** @private */
|
|
319
|
+
toHtmlInternal() {
|
|
320
|
+
const { level, firstChild } = this;
|
|
321
|
+
return `${this.tocData ?? ''}<div class="mw-heading mw-heading${level}"><h${level} id="${this.getRenderedId()}">${firstChild.toHtmlInternal().trim()}</h${level}></div>`;
|
|
314
322
|
}
|
|
315
323
|
/**
|
|
316
324
|
* Get the section led by this heading
|
package/dist/src/index.js
CHANGED
|
@@ -532,9 +532,8 @@ let Token = (() => {
|
|
|
532
532
|
}
|
|
533
533
|
/** @private */
|
|
534
534
|
inTableAttrs() {
|
|
535
|
-
return this.isInside('table-attrs')
|
|
536
|
-
? 2
|
|
537
|
-
: 1);
|
|
535
|
+
return this.isInside('table-attrs')
|
|
536
|
+
&& (this.closest('table-attrs,arg,parameter')?.is('table-attrs') ? 2 : 1);
|
|
538
537
|
}
|
|
539
538
|
/** @private */
|
|
540
539
|
inHtmlAttrs() {
|
|
@@ -555,7 +554,7 @@ let Token = (() => {
|
|
|
555
554
|
}
|
|
556
555
|
else {
|
|
557
556
|
const value = cat.getValue();
|
|
558
|
-
if (value
|
|
557
|
+
if (value) {
|
|
559
558
|
key = `#${value}`;
|
|
560
559
|
}
|
|
561
560
|
}
|
package/dist/src/link/base.js
CHANGED
|
@@ -326,9 +326,7 @@ let LinkBaseToken = (() => {
|
|
|
326
326
|
}
|
|
327
327
|
/** @private */
|
|
328
328
|
toHtmlInternal(opt) {
|
|
329
|
-
if (this.is('link')
|
|
330
|
-
|| this.is('redirect-target')
|
|
331
|
-
|| this.is('category')) {
|
|
329
|
+
if (this.is('link') || this.is('redirect-target') || this.is('category')) {
|
|
332
330
|
const { link, length, lastChild, type, pageName } = this;
|
|
333
331
|
let attr;
|
|
334
332
|
if (type === 'link' && link.title === pageName && !link.fragment) {
|
|
@@ -336,7 +334,7 @@ let LinkBaseToken = (() => {
|
|
|
336
334
|
}
|
|
337
335
|
else {
|
|
338
336
|
const title = link.getTitleAttr();
|
|
339
|
-
attr = `${link.interwiki && 'class="extiw" '}href="${link.getUrl()}"${title && ` title="${title}"`}`;
|
|
337
|
+
attr = `${link.interwiki && 'class="extiw" '}href="${link.getUrl()}"${link.ns === -2 ? ' class="internal"' : ''}${title && ` title="${title}"`}`;
|
|
340
338
|
}
|
|
341
339
|
return `<a ${attr}>${type === 'link' && length > 1
|
|
342
340
|
? lastChild.toHtmlInternal({
|