wikiparser-node 1.14.1 → 1.15.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/README.md +17 -1
- package/bundle/bundle.es7.js +27 -27
- package/bundle/bundle.min.js +27 -27
- package/config/.schema.json +72 -29
- package/config/default.json +331 -241
- package/config/enwiki.json +206 -929
- package/config/llwiki.json +289 -241
- package/config/minimum.json +21 -11
- package/config/moegirl.json +290 -251
- package/config/zhwiki.json +330 -706
- package/coverage/badge.svg +1 -0
- package/dist/addon/table.js +1 -1
- package/dist/addon/token.js +18 -14
- package/dist/addon/transclude.js +5 -1
- package/dist/base.d.ts +4 -3
- package/dist/index.js +18 -6
- package/dist/lib/element.js +4 -0
- package/dist/lib/node.js +8 -3
- package/dist/lib/range.js +13 -6
- package/dist/lib/ranges.js +5 -2
- package/dist/lib/text.js +7 -6
- package/dist/lib/title.js +1 -0
- package/dist/mixin/attributesParent.d.ts +1 -1
- package/dist/parser/braces.js +1 -0
- package/dist/parser/externalLinks.js +1 -1
- package/dist/parser/hrAndDoubleUnderscore.js +1 -1
- package/dist/parser/magicLinks.js +1 -1
- package/dist/parser/selector.js +10 -2
- package/dist/src/atom.js +1 -0
- package/dist/src/attribute.d.ts +6 -4
- package/dist/src/attributes.js +3 -4
- package/dist/src/link/base.js +1 -0
- package/dist/src/link/file.js +3 -0
- package/dist/src/link/index.js +5 -6
- package/dist/src/link/redirectTarget.d.ts +2 -3
- package/dist/src/link/redirectTarget.js +1 -2
- package/dist/src/nowiki/comment.js +1 -0
- package/dist/src/onlyinclude.js +1 -0
- package/dist/src/table/index.d.ts +0 -3
- package/dist/src/table/index.js +2 -1
- package/dist/src/table/trBase.js +3 -2
- package/dist/src/transclude.js +5 -10
- package/dist/util/debug.js +10 -2
- package/dist/util/diff.js +5 -0
- package/dist/util/string.js +12 -1
- package/extensions/dist/base.js +1 -1
- package/extensions/dist/test-page.js +89 -0
- package/extensions/es7/base.js +1 -1
- package/package.json +12 -6
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="98" height="20" role="img" aria-label="Coverage: 85%"><title>Coverage: 85%</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="98" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="63" height="20" fill="#555"/><rect x="63" width="35" height="20" fill="#4c1"/><rect width="98" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="325" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="530">Coverage</text><text x="325" y="140" transform="scale(.1)" fill="#fff" textLength="530">Coverage</text><text aria-hidden="true" x="795" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="250">85%</text><text x="795" y="140" transform="scale(.1)" fill="#fff" textLength="250">85%</text></g></svg>
|
package/dist/addon/table.js
CHANGED
|
@@ -280,7 +280,7 @@ index_2.TableToken.prototype.removeTableCol =
|
|
|
280
280
|
index_2.TableToken.prototype.mergeCells =
|
|
281
281
|
/** @implements */
|
|
282
282
|
function (xlim, ylim) {
|
|
283
|
-
const layout = this.getLayout(), maxCol = Math.max(...layout.map(({ length }) => length)), [xmin, xmax] = xlim.map(x => x < 0 ? x + maxCol : x).sort(), [ymin, ymax] = ylim.map(y => y < 0 ? y + layout.length : y).sort(), set = new Set(layout.slice(ymin, ymax).flatMap(rowLayout => rowLayout.slice(xmin, xmax)));
|
|
283
|
+
const layout = this.getLayout(), maxCol = Math.max(...layout.map(({ length }) => length)), [xmin, xmax] = xlim.map(x => x < 0 ? x + maxCol : x).sort(debug_1.compare), [ymin, ymax] = ylim.map(y => y < 0 ? y + layout.length : y).sort(debug_1.compare), set = new Set(layout.slice(ymin, ymax).flatMap(rowLayout => rowLayout.slice(xmin, xmax)));
|
|
284
284
|
if ([...layout[ymin - 1] ?? [], ...layout[ymax] ?? []].some(coords => set.has(coords))
|
|
285
285
|
|| layout.some(rowLayout => set.has(rowLayout[xmin - 1]) || set.has(rowLayout[xmax]))) {
|
|
286
286
|
throw new RangeError('The area to be merged overlaps with the outer area!');
|
package/dist/addon/token.js
CHANGED
|
@@ -37,6 +37,7 @@ index_2.Token.prototype.createElement = /** @implements */ function (tagName, {
|
|
|
37
37
|
return new html_1.HtmlToken(tagName, attr, Boolean(closing), Boolean(selfClosing), config);
|
|
38
38
|
});
|
|
39
39
|
}
|
|
40
|
+
/* istanbul ignore next */
|
|
40
41
|
throw new RangeError(`Invalid tag name: ${tagName}`);
|
|
41
42
|
};
|
|
42
43
|
index_2.Token.prototype.caretPositionFromIndex = /** @implements */ function (index) {
|
|
@@ -103,6 +104,7 @@ index_2.Token.prototype.sections = /** @implements */ function () {
|
|
|
103
104
|
index_2.Token.prototype.findEnclosingHtml = /** @implements */ function (tag) {
|
|
104
105
|
tag &&= tag.toLowerCase();
|
|
105
106
|
const { html } = this.getAttribute('config'), normalTags = new Set(html[0]), voidTags = new Set(html[2]);
|
|
107
|
+
/* istanbul ignore next */
|
|
106
108
|
if (html[2].includes(tag)) {
|
|
107
109
|
throw new RangeError(`Void tag: ${tag}`);
|
|
108
110
|
}
|
|
@@ -159,6 +161,20 @@ const implicitNewLine = (str, prev) => prev + (prev !== '\n' && /^(?:\{\||[:;#*]
|
|
|
159
161
|
* @param b
|
|
160
162
|
*/
|
|
161
163
|
const cmp = (a, b) => a === b || Boolean(a && b) && Number(a) === Number(b);
|
|
164
|
+
/**
|
|
165
|
+
* 解析 if/ifexist/ifeq 解析器函数
|
|
166
|
+
* @param accum
|
|
167
|
+
* @param prev 解析器函数前的字符串
|
|
168
|
+
* @param effective 生效的参数
|
|
169
|
+
*/
|
|
170
|
+
const parseIf = (accum, prev, effective) => {
|
|
171
|
+
if (effective) {
|
|
172
|
+
// @ts-expect-error sparse array
|
|
173
|
+
accum[accum.indexOf(effective.lastChild)] = undefined;
|
|
174
|
+
return implicitNewLine(effective.value, prev);
|
|
175
|
+
}
|
|
176
|
+
return prev;
|
|
177
|
+
};
|
|
162
178
|
/**
|
|
163
179
|
* 展开模板
|
|
164
180
|
* @param wikitext
|
|
@@ -246,22 +262,10 @@ const expand = (wikitext, config, include, context, accum = [], stack = []) => {
|
|
|
246
262
|
const title = index_1.default.normalizeTitle(var1, 0, include, config, true);
|
|
247
263
|
bool = title.valid && !title.interwiki;
|
|
248
264
|
}
|
|
249
|
-
|
|
250
|
-
if (effective) {
|
|
251
|
-
// @ts-expect-error sparse array
|
|
252
|
-
accum[accum.indexOf(effective.lastChild)] = undefined;
|
|
253
|
-
return implicitNewLine(effective.value, prev);
|
|
254
|
-
}
|
|
255
|
-
return prev;
|
|
265
|
+
return parseIf(accum, prev, c[bool ? 2 : 3]);
|
|
256
266
|
}
|
|
257
267
|
else if (known && name === 'ifeq' && !/\0\d+t\x7F/u.test(var2)) {
|
|
258
|
-
|
|
259
|
-
if (effective) {
|
|
260
|
-
// @ts-expect-error sparse array
|
|
261
|
-
accum[accum.indexOf(effective.lastChild)] = undefined;
|
|
262
|
-
return implicitNewLine(effective.value, prev);
|
|
263
|
-
}
|
|
264
|
-
return prev;
|
|
268
|
+
return parseIf(accum, prev, c[cmp(var1, var2) ? 3 : 4]);
|
|
265
269
|
}
|
|
266
270
|
else if (known && name === 'switch') {
|
|
267
271
|
let defaultVal = '', found = false, transclusion = false, defaultParam;
|
package/dist/addon/transclude.js
CHANGED
|
@@ -22,6 +22,7 @@ transclude_1.TranscludeToken.prototype.newAnonArg =
|
|
|
22
22
|
transclude_1.TranscludeToken.prototype.setValue =
|
|
23
23
|
/** @implements */
|
|
24
24
|
function (key, value) {
|
|
25
|
+
/* istanbul ignore if */
|
|
25
26
|
if (!this.isTemplate()) {
|
|
26
27
|
throw new Error('TranscludeToken.setValue method is only for templates!');
|
|
27
28
|
}
|
|
@@ -41,6 +42,7 @@ transclude_1.TranscludeToken.prototype.setValue =
|
|
|
41
42
|
transclude_1.TranscludeToken.prototype.replaceTemplate =
|
|
42
43
|
/** @implements */
|
|
43
44
|
function (title) {
|
|
45
|
+
/* istanbul ignore if */
|
|
44
46
|
if (this.type === 'magic-word') {
|
|
45
47
|
throw new Error('TranscludeToken.replaceTemplate method is only for templates!');
|
|
46
48
|
}
|
|
@@ -50,6 +52,7 @@ transclude_1.TranscludeToken.prototype.replaceTemplate =
|
|
|
50
52
|
transclude_1.TranscludeToken.prototype.replaceModule =
|
|
51
53
|
/** @implements */
|
|
52
54
|
function (title) {
|
|
55
|
+
/* istanbul ignore if */
|
|
53
56
|
if (this.type !== 'magic-word' || this.name !== 'invoke') {
|
|
54
57
|
throw new Error('TranscludeToken.replaceModule method is only for modules!');
|
|
55
58
|
}
|
|
@@ -66,6 +69,7 @@ transclude_1.TranscludeToken.prototype.replaceModule =
|
|
|
66
69
|
transclude_1.TranscludeToken.prototype.replaceFunction =
|
|
67
70
|
/** @implements */
|
|
68
71
|
function (func) {
|
|
72
|
+
/* istanbul ignore next */
|
|
69
73
|
if (this.type !== 'magic-word' || this.name !== 'invoke') {
|
|
70
74
|
throw new Error('TranscludeToken.replaceModule method is only for modules!');
|
|
71
75
|
}
|
|
@@ -157,7 +161,6 @@ transclude_1.TranscludeToken.prototype.fixDuplication =
|
|
|
157
161
|
return `Line ${String(top)} Column ${String(left)}`;
|
|
158
162
|
}).join('\n')}`);
|
|
159
163
|
duplicatedKeys.push(key);
|
|
160
|
-
continue;
|
|
161
164
|
}
|
|
162
165
|
}
|
|
163
166
|
return duplicatedKeys;
|
|
@@ -175,6 +178,7 @@ transclude_1.TranscludeToken.prototype.escapeTables =
|
|
|
175
178
|
}
|
|
176
179
|
}
|
|
177
180
|
const { firstChild, length } = index_1.default.parse(`{{${parsed.toString()}}}`, include, undefined, config);
|
|
181
|
+
/* istanbul ignore if */
|
|
178
182
|
if (length !== 1 || !(firstChild instanceof transclude_1.TranscludeToken)) {
|
|
179
183
|
throw new Error('Failed to escape tables!');
|
|
180
184
|
}
|
package/dist/base.d.ts
CHANGED
|
@@ -3,13 +3,14 @@ export interface Config {
|
|
|
3
3
|
readonly html: [string[], string[], string[]];
|
|
4
4
|
readonly namespaces: Record<string, string>;
|
|
5
5
|
readonly nsid: Record<string, number>;
|
|
6
|
-
readonly
|
|
7
|
-
readonly
|
|
6
|
+
readonly variable: string[];
|
|
7
|
+
readonly parserFunction: [Record<string, string>, Record<string, string> | string[], string[], string[]];
|
|
8
|
+
readonly doubleUnderscore: [string[], string[], Record<string, string>?, Record<string, string>?];
|
|
8
9
|
readonly protocol: string;
|
|
10
|
+
readonly interwiki: string[];
|
|
9
11
|
readonly img: Record<string, string>;
|
|
10
12
|
readonly redirection: string[];
|
|
11
13
|
readonly variants: string[];
|
|
12
|
-
readonly interwiki: string[];
|
|
13
14
|
readonly conversionTable?: [string, string][];
|
|
14
15
|
readonly redirects?: [string, string][];
|
|
15
16
|
readonly articlePath?: string;
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ const chalk = require("chalk");
|
|
|
14
14
|
* @param file 文件名
|
|
15
15
|
* @param dir 子路径
|
|
16
16
|
*/
|
|
17
|
-
const rootRequire = (file, dir) => require(path.isAbsolute(file) ? file : path.join('..', file.includes('/') ? '' : dir, file));
|
|
17
|
+
const rootRequire = (file, dir) => require(path.isAbsolute(file) ? /* istanbul ignore next */ file : path.join('..', file.includes('/') ? '' : dir, file));
|
|
18
18
|
/* NOT FOR BROWSER */
|
|
19
19
|
/**
|
|
20
20
|
* 快速规范化页面标题
|
|
@@ -70,14 +70,17 @@ const Parser = {
|
|
|
70
70
|
getConfig() {
|
|
71
71
|
if (typeof this.config === 'string') {
|
|
72
72
|
this.config = rootRequire(this.config, 'config');
|
|
73
|
-
|
|
73
|
+
/* istanbul ignore if */
|
|
74
|
+
if (this.config.doubleUnderscore.length < 3 || Array.isArray(this.config.parserFunction[1])) {
|
|
74
75
|
(0, diff_1.error)(`The schema (${path.resolve(__dirname, '..', 'config', '.schema.json')}) of parser configuration is updated.`);
|
|
75
76
|
}
|
|
76
77
|
/* NOT FOR BROWSER */
|
|
77
78
|
const { config: { conversionTable, redirects } } = this;
|
|
79
|
+
/* istanbul ignore if */
|
|
78
80
|
if (conversionTable) {
|
|
79
81
|
this.conversionTable = new Map(conversionTable);
|
|
80
82
|
}
|
|
83
|
+
/* istanbul ignore if */
|
|
81
84
|
if (redirects) {
|
|
82
85
|
this.redirects = new Map(redirects);
|
|
83
86
|
}
|
|
@@ -85,8 +88,10 @@ const Parser = {
|
|
|
85
88
|
return this.getConfig();
|
|
86
89
|
}
|
|
87
90
|
const { doubleUnderscore } = this.config;
|
|
88
|
-
|
|
89
|
-
doubleUnderscore
|
|
91
|
+
for (let i = 0; i < 2; i++) {
|
|
92
|
+
if (doubleUnderscore.length > i + 2 && doubleUnderscore[i].length === 0) {
|
|
93
|
+
doubleUnderscore[i] = Object.keys(doubleUnderscore[i + 2]);
|
|
94
|
+
}
|
|
90
95
|
}
|
|
91
96
|
return {
|
|
92
97
|
...this.config,
|
|
@@ -150,11 +155,11 @@ const Parser = {
|
|
|
150
155
|
try {
|
|
151
156
|
return token.parse(maxStage, include);
|
|
152
157
|
}
|
|
153
|
-
catch (e) {
|
|
158
|
+
catch (e) /* istanbul ignore next */ {
|
|
154
159
|
if (e instanceof Error) {
|
|
155
160
|
const file = path.join(__dirname, '..', 'errors', new Date().toISOString()), stage = token.getAttribute('stage');
|
|
156
161
|
for (const k in config) {
|
|
157
|
-
if (k.startsWith('regex')) {
|
|
162
|
+
if (k.startsWith('regex') || config[k] instanceof Set) {
|
|
158
163
|
delete config[k];
|
|
159
164
|
}
|
|
160
165
|
}
|
|
@@ -166,6 +171,7 @@ const Parser = {
|
|
|
166
171
|
}
|
|
167
172
|
});
|
|
168
173
|
/* NOT FOR BROWSER */
|
|
174
|
+
/* istanbul ignore if */
|
|
169
175
|
if (this.debugging) {
|
|
170
176
|
let restored = root.toString(), process = 'parsing';
|
|
171
177
|
if (restored === wikitext) {
|
|
@@ -188,29 +194,34 @@ const Parser = {
|
|
|
188
194
|
/* NOT FOR BROWSER */
|
|
189
195
|
/** @implements */
|
|
190
196
|
warn(msg, ...args) {
|
|
197
|
+
/* istanbul ignore if */
|
|
191
198
|
if (this.warning) {
|
|
192
199
|
console.warn(chalk.yellow(msg), ...args);
|
|
193
200
|
}
|
|
194
201
|
},
|
|
195
202
|
/** @implements */
|
|
196
203
|
debug(msg, ...args) {
|
|
204
|
+
/* istanbul ignore if */
|
|
197
205
|
if (this.debugging) {
|
|
198
206
|
console.debug(chalk.blue(msg), ...args);
|
|
199
207
|
}
|
|
200
208
|
},
|
|
201
209
|
error: diff_1.error,
|
|
202
210
|
info: diff_1.info,
|
|
211
|
+
/* istanbul ignore next */
|
|
203
212
|
/** @implements */
|
|
204
213
|
log(f) {
|
|
205
214
|
if (typeof f === 'function') {
|
|
206
215
|
console.log(String(f));
|
|
207
216
|
}
|
|
208
217
|
},
|
|
218
|
+
/* istanbul ignore next */
|
|
209
219
|
/** @implements */
|
|
210
220
|
require(name) {
|
|
211
221
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
212
222
|
return Object.hasOwn(constants_1.classes, name) ? require(constants_1.classes[name])[name] : require(path.join(__dirname, name));
|
|
213
223
|
},
|
|
224
|
+
/* istanbul ignore next */
|
|
214
225
|
/** @implements */
|
|
215
226
|
async clearCache() {
|
|
216
227
|
await (0, diff_1.cmd)('npm', ['--prefix', path.join(__dirname, '..'), 'run', 'build:core']);
|
|
@@ -238,6 +249,7 @@ const Parser = {
|
|
|
238
249
|
.exec(title.replaceAll('_', ' ').replace(/^\s*:?\s*/u, ''))
|
|
239
250
|
: null;
|
|
240
251
|
},
|
|
252
|
+
/* istanbul ignore next */
|
|
241
253
|
/** @implements */
|
|
242
254
|
reparse(date = '') {
|
|
243
255
|
const main = fs.readdirSync(path.join(__dirname, '..', 'errors'))
|
package/dist/lib/element.js
CHANGED
|
@@ -124,6 +124,7 @@ class AstElement extends node_1.AstNode {
|
|
|
124
124
|
*/
|
|
125
125
|
insertAt(node, i = this.length) {
|
|
126
126
|
/* NOT FOR BROWSER */
|
|
127
|
+
/* istanbul ignore next */
|
|
127
128
|
if (node.contains(this)) {
|
|
128
129
|
throw new RangeError('Cannot insert an ancestor node!');
|
|
129
130
|
}
|
|
@@ -240,6 +241,7 @@ class AstElement extends node_1.AstNode {
|
|
|
240
241
|
return data;
|
|
241
242
|
}
|
|
242
243
|
/* NOT FOR BROWSER */
|
|
244
|
+
/* istanbul ignore next */
|
|
243
245
|
throw new RangeError(`The child node at position ${i} is ${oldText.constructor.name}!`);
|
|
244
246
|
}
|
|
245
247
|
/** @private */
|
|
@@ -285,6 +287,7 @@ class AstElement extends node_1.AstNode {
|
|
|
285
287
|
cur += length + this.getGaps(i);
|
|
286
288
|
}
|
|
287
289
|
/* NOT FOR BROWSER */
|
|
290
|
+
/* istanbul ignore if */
|
|
288
291
|
if (typeof file === 'string') {
|
|
289
292
|
fs.writeFileSync(path.join(__dirname, '..', '..', 'printed', file + (file.endsWith('.json') ? '' : '.json')), JSON.stringify(json, null, 2));
|
|
290
293
|
}
|
|
@@ -344,6 +347,7 @@ class AstElement extends node_1.AstNode {
|
|
|
344
347
|
*/
|
|
345
348
|
#getChildIndex(node) {
|
|
346
349
|
const i = this.childNodes.indexOf(node);
|
|
350
|
+
/* istanbul ignore if */
|
|
347
351
|
if (i === -1) {
|
|
348
352
|
throw new RangeError('Not a child node!');
|
|
349
353
|
}
|
package/dist/lib/node.js
CHANGED
|
@@ -21,6 +21,7 @@ const getDimension = (str) => {
|
|
|
21
21
|
const getIndex = (j, parent) => parent.childNodes.slice(0, j).reduce((acc, cur, i) => acc + cur.toString().length + parent.getGaps(i), 0)
|
|
22
22
|
+ parent.getAttribute('padding');
|
|
23
23
|
/* NOT FOR BROWSER */
|
|
24
|
+
/* istanbul ignore next */
|
|
24
25
|
/**
|
|
25
26
|
* 定制TypeError消息
|
|
26
27
|
* @param {Function} Constructor 类
|
|
@@ -54,12 +55,12 @@ class AstNode {
|
|
|
54
55
|
/** 后一个兄弟节点 */
|
|
55
56
|
get nextSibling() {
|
|
56
57
|
const childNodes = this.parentNode?.childNodes;
|
|
57
|
-
return childNodes
|
|
58
|
+
return childNodes?.[childNodes.indexOf(this) + 1];
|
|
58
59
|
}
|
|
59
60
|
/** 前一个兄弟节点 */
|
|
60
61
|
get previousSibling() {
|
|
61
62
|
const childNodes = this.parentNode?.childNodes;
|
|
62
|
-
return childNodes
|
|
63
|
+
return childNodes?.[childNodes.indexOf(this) - 1];
|
|
63
64
|
}
|
|
64
65
|
/** 行数 */
|
|
65
66
|
get offsetHeight() {
|
|
@@ -271,6 +272,7 @@ class AstNode {
|
|
|
271
272
|
return this.type === type;
|
|
272
273
|
}
|
|
273
274
|
/* NOT FOR BROWSER */
|
|
275
|
+
/* istanbul ignore next */
|
|
274
276
|
/** @private */
|
|
275
277
|
typeError(method, ...types) {
|
|
276
278
|
return typeError(this.constructor, method, ...types);
|
|
@@ -292,6 +294,7 @@ class AstNode {
|
|
|
292
294
|
if (e instanceof assert.AssertionError) {
|
|
293
295
|
return false;
|
|
294
296
|
}
|
|
297
|
+
/* istanbul ignore next */
|
|
295
298
|
throw e;
|
|
296
299
|
}
|
|
297
300
|
return true;
|
|
@@ -304,6 +307,7 @@ class AstNode {
|
|
|
304
307
|
*/
|
|
305
308
|
#insertAdjacent(nodes, offset) {
|
|
306
309
|
const { parentNode } = this;
|
|
310
|
+
/* istanbul ignore if */
|
|
307
311
|
if (!parentNode) {
|
|
308
312
|
throw new Error('There is no parent node!');
|
|
309
313
|
}
|
|
@@ -348,6 +352,7 @@ class AstNode {
|
|
|
348
352
|
/** @private */
|
|
349
353
|
verifyChild(i, addition = 0) {
|
|
350
354
|
const { childNodes: { length } } = this;
|
|
355
|
+
/* istanbul ignore if */
|
|
351
356
|
if (i < -length || i >= length + addition) {
|
|
352
357
|
throw new RangeError(`The child node at position ${i} does not exist!`);
|
|
353
358
|
}
|
|
@@ -448,7 +453,7 @@ class AstNode {
|
|
|
448
453
|
else if (other.contains(this)) {
|
|
449
454
|
return 1;
|
|
450
455
|
}
|
|
451
|
-
else if (this.getRootNode() !== other.getRootNode()) {
|
|
456
|
+
else /* istanbul ignore if */ if (this.getRootNode() !== other.getRootNode()) {
|
|
452
457
|
throw new RangeError('Nodes to be compared are not in the same document!');
|
|
453
458
|
}
|
|
454
459
|
const aAncestors = [...this.getAncestors().reverse(), this], bAncestors = [...other.getAncestors().reverse(), other], depth = aAncestors.findIndex((ancestor, i) => bAncestors[i] !== ancestor), { childNodes } = aAncestors[depth - 1];
|
package/dist/lib/range.js
CHANGED
|
@@ -18,8 +18,10 @@ const getParent = (node) => {
|
|
|
18
18
|
if (parentNode) {
|
|
19
19
|
return parentNode;
|
|
20
20
|
}
|
|
21
|
+
/* istanbul ignore next */
|
|
21
22
|
throw new RangeError('The reference node has no parent node!');
|
|
22
23
|
};
|
|
24
|
+
/* istanbul ignore next */
|
|
23
25
|
/**
|
|
24
26
|
* 未初始化时抛出错误
|
|
25
27
|
* @param start 是否未初始化起点
|
|
@@ -36,11 +38,11 @@ class AstRange {
|
|
|
36
38
|
#endOffset;
|
|
37
39
|
/** 起点容器 */
|
|
38
40
|
get startContainer() {
|
|
39
|
-
return this.#startContainer ?? notInit(true);
|
|
41
|
+
return this.#startContainer ?? /* istanbul ignore next */ notInit(true);
|
|
40
42
|
}
|
|
41
43
|
/** 起点位置 */
|
|
42
44
|
get startOffset() {
|
|
43
|
-
return this.#startOffset ?? notInit(true);
|
|
45
|
+
return this.#startOffset ?? /* istanbul ignore next */ notInit(true);
|
|
44
46
|
}
|
|
45
47
|
/** 起点绝对位置 */
|
|
46
48
|
get startIndex() {
|
|
@@ -52,11 +54,11 @@ class AstRange {
|
|
|
52
54
|
}
|
|
53
55
|
/** 终点容器 */
|
|
54
56
|
get endContainer() {
|
|
55
|
-
return this.#endContainer ?? notInit(false);
|
|
57
|
+
return this.#endContainer ?? /* istanbul ignore next */ notInit(false);
|
|
56
58
|
}
|
|
57
59
|
/** 终点位置 */
|
|
58
60
|
get endOffset() {
|
|
59
|
-
return this.#endOffset ?? notInit(false);
|
|
61
|
+
return this.#endOffset ?? /* istanbul ignore next */ notInit(false);
|
|
60
62
|
}
|
|
61
63
|
/** 终点绝对位置 */
|
|
62
64
|
get endIndex() {
|
|
@@ -83,12 +85,14 @@ class AstRange {
|
|
|
83
85
|
#check() {
|
|
84
86
|
const { startContainer, startOffset, endContainer, endOffset } = this, msg1 = 'The start and end positions are not siblings!', msg2 = 'The start position cannot be after the end position!';
|
|
85
87
|
if (startContainer === endContainer) {
|
|
88
|
+
/* istanbul ignore if */
|
|
86
89
|
if (startOffset > endOffset) {
|
|
87
90
|
throw new RangeError(msg2);
|
|
88
91
|
}
|
|
89
92
|
return;
|
|
90
93
|
}
|
|
91
94
|
const { type: startType, parentNode: startParent } = startContainer, { type: endType, parentNode: endParent } = endContainer;
|
|
95
|
+
/* istanbul ignore next */
|
|
92
96
|
if (startType !== 'text') {
|
|
93
97
|
if (endType !== 'text' || startContainer !== endParent) {
|
|
94
98
|
throw new RangeError(msg1);
|
|
@@ -121,6 +125,7 @@ class AstRange {
|
|
|
121
125
|
*/
|
|
122
126
|
setStart(startNode, offset) {
|
|
123
127
|
const { length } = startNode;
|
|
128
|
+
/* istanbul ignore if */
|
|
124
129
|
if (offset < 0 || offset > length) {
|
|
125
130
|
throw new RangeError(`The range of startOffset should be 0 ~ ${length}`);
|
|
126
131
|
}
|
|
@@ -131,7 +136,7 @@ class AstRange {
|
|
|
131
136
|
try {
|
|
132
137
|
this.#check();
|
|
133
138
|
}
|
|
134
|
-
catch (e) {
|
|
139
|
+
catch (e) /* istanbul ignore next */ {
|
|
135
140
|
this.#startContainer = startContainer;
|
|
136
141
|
this.#startOffset = startOffset;
|
|
137
142
|
throw e;
|
|
@@ -146,6 +151,7 @@ class AstRange {
|
|
|
146
151
|
*/
|
|
147
152
|
setEnd(endNode, offset) {
|
|
148
153
|
const { length } = endNode;
|
|
154
|
+
/* istanbul ignore if */
|
|
149
155
|
if (offset < 0 || offset > length) {
|
|
150
156
|
throw new RangeError(`The range of endOffset should be 0 ~ ${length}`);
|
|
151
157
|
}
|
|
@@ -156,7 +162,7 @@ class AstRange {
|
|
|
156
162
|
try {
|
|
157
163
|
this.#check();
|
|
158
164
|
}
|
|
159
|
-
catch (e) {
|
|
165
|
+
catch (e) /* istanbul ignore next */ {
|
|
160
166
|
this.#endContainer = endContainer;
|
|
161
167
|
this.#endOffset = endOffset;
|
|
162
168
|
throw e;
|
|
@@ -252,6 +258,7 @@ class AstRange {
|
|
|
252
258
|
*/
|
|
253
259
|
comparePoint(referenceNode, offset) {
|
|
254
260
|
const { startContainer, startIndex, endContainer, endIndex } = this;
|
|
261
|
+
/* istanbul ignore if */
|
|
255
262
|
if (startContainer.getRootNode() !== referenceNode.getRootNode()) {
|
|
256
263
|
throw new RangeError('The point to be compared is not in the same document!');
|
|
257
264
|
}
|
package/dist/lib/ranges.js
CHANGED
|
@@ -28,6 +28,7 @@ class Range {
|
|
|
28
28
|
this.start = Number(start);
|
|
29
29
|
this.end = Number(end?.trim() || Infinity);
|
|
30
30
|
this.step = Math.max(Number(step), 1);
|
|
31
|
+
/* istanbul ignore next */
|
|
31
32
|
if (!Number.isInteger(this.start)) {
|
|
32
33
|
throw new RangeError(`The start of a range, \`${start}\`, should be an integer!`);
|
|
33
34
|
}
|
|
@@ -41,9 +42,11 @@ class Range {
|
|
|
41
42
|
else {
|
|
42
43
|
const mt = /^([+-])?(\d+)?n(?:\s*([+-])\s*(\d+))?$/u
|
|
43
44
|
.exec(str);
|
|
45
|
+
/* istanbul ignore else */
|
|
44
46
|
if (mt) {
|
|
45
47
|
const [, sgnA = '+', a = 1, sgnB = '+'] = mt, b = Number(mt[4] ?? 0);
|
|
46
48
|
this.step = Number(a);
|
|
49
|
+
/* istanbul ignore if */
|
|
47
50
|
if (this.step === 0) {
|
|
48
51
|
throw new RangeError(`In the argument \`${str}\`, the coefficient of "n" must not be 0!`);
|
|
49
52
|
}
|
|
@@ -98,7 +101,7 @@ class Ranges extends Array {
|
|
|
98
101
|
try {
|
|
99
102
|
this.push(new Range(ele));
|
|
100
103
|
}
|
|
101
|
-
catch (e) {
|
|
104
|
+
catch (e) /* istanbul ignore next */ {
|
|
102
105
|
if (e instanceof RangeError) {
|
|
103
106
|
(0, diff_1.error)(e.message);
|
|
104
107
|
}
|
|
@@ -119,7 +122,7 @@ class Ranges extends Array {
|
|
|
119
122
|
}
|
|
120
123
|
return ele.applyTo(a);
|
|
121
124
|
})),
|
|
122
|
-
].filter(i => i >= 0 && i < length).sort();
|
|
125
|
+
].filter(i => i >= 0 && i < length).sort(debug_1.compare);
|
|
123
126
|
}
|
|
124
127
|
}
|
|
125
128
|
exports.Ranges = Ranges;
|
package/dist/lib/text.js
CHANGED
|
@@ -13,7 +13,7 @@ const html_1 = require("../util/html");
|
|
|
13
13
|
/<\s*(?:\/\s*)?([a-z]\w*)|\{+|\}+|\[{2,}|\[(?![^[]*?\])|((?:^|\])[^[]*?)\]+|https?[:/]\/+/giu;
|
|
14
14
|
/^https?:\/\/(?:\[[\da-f:.]+\]|[^[\]<>"\t\n\p{Zs}])[^[\]<>"\t\n\p{Zs}]*\.(?:gif|png|jpg|jpeg)$/iu;
|
|
15
15
|
/* eslint-enable @typescript-eslint/no-unused-expressions, es-x/no-regexp-unicode-property-escapes */
|
|
16
|
-
const sp = String.raw `[${string_1.zs}\t]*`, source = String.raw `<\s*(?:/\s*)?([a-z]\w*)|\{+|\}+|\[{2,}|\[(?![^[]*?\])|((?:^|\])[^[]*?)\]+|(?:rfc|pmid)(?=[-::]?${sp}\d)|isbn(?=[-::]?${sp}(?:\d(?:${sp}|-)){6})`, errorSyntax = new RegExp(String.raw `${source}|https?[:/]/+`, 'giu'), errorSyntaxUrl = new RegExp(source, 'giu'),
|
|
16
|
+
const sp = String.raw `[${string_1.zs}\t]*`, source = String.raw `<\s*(?:/\s*)?([a-z]\w*)|\{+|\}+|\[{2,}|\[(?![^[]*?\])|((?:^|\])[^[]*?)\]+|(?:rfc|pmid)(?=[-::]?${sp}\d)|isbn(?=[-::]?${sp}(?:\d(?:${sp}|-)){6})`, errorSyntax = new RegExp(String.raw `${source}|https?[:/]/+`, 'giu'), errorSyntaxUrl = new RegExp(source, 'giu'), noLinkTypes = new Set(['attr-value', 'ext-link-text', 'link-text']), regexes = {
|
|
17
17
|
'[': /[[\]]/u,
|
|
18
18
|
'{': /[{}]/u,
|
|
19
19
|
']': /[[\]](?=[^[\]]*$)/u,
|
|
@@ -85,7 +85,7 @@ try {
|
|
|
85
85
|
// eslint-disable-next-line prefer-regex-literals, es-x/no-regexp-unicode-property-escapes
|
|
86
86
|
wordRegex = new RegExp(String.raw `[\p{L}\d_]`, 'u');
|
|
87
87
|
}
|
|
88
|
-
catch {
|
|
88
|
+
catch /* istanbul ignore next */ {
|
|
89
89
|
wordRegex = /\w/u;
|
|
90
90
|
}
|
|
91
91
|
/** 文本节点 */
|
|
@@ -131,6 +131,7 @@ class AstText extends node_1.AstNode {
|
|
|
131
131
|
return [];
|
|
132
132
|
}
|
|
133
133
|
const { data, parentNode, nextSibling, previousSibling } = this;
|
|
134
|
+
/* istanbul ignore if */
|
|
134
135
|
if (!parentNode) {
|
|
135
136
|
throw new Error('An isolated text node cannot be linted!');
|
|
136
137
|
}
|
|
@@ -178,7 +179,6 @@ class AstText extends node_1.AstNode {
|
|
|
178
179
|
if (char === '<' && !tags.has(tag.toLowerCase())
|
|
179
180
|
|| char === '[' && type === 'ext-link-text' && (/&(?:rbrack|#93|#x5[Dd];);/u.test(data.slice(index + 1))
|
|
180
181
|
|| nextSibling?.is('ext') && nextName === 'nowiki' && nextSibling.innerText?.includes(']'))
|
|
181
|
-
|| char === 'h' && index === 0 && type === 'ext-link-text' && extImage.test(data)
|
|
182
182
|
|| magicLink && (!parentNode.getAttribute('plain') || noLinkTypes.has(type))) {
|
|
183
183
|
continue;
|
|
184
184
|
}
|
|
@@ -232,9 +232,7 @@ class AstText extends node_1.AstNode {
|
|
|
232
232
|
if (char === '<') {
|
|
233
233
|
e.suggestions = [{ desc: 'escape', range: [startIndex, startIndex + 1], text: '<' }];
|
|
234
234
|
}
|
|
235
|
-
else if (char === 'h'
|
|
236
|
-
&& !(type === 'ext-link-text' || type === 'link-text')
|
|
237
|
-
&& wordRegex.test(previousChar || '')) {
|
|
235
|
+
else if (char === 'h' && type !== 'link-text' && wordRegex.test(previousChar || '')) {
|
|
238
236
|
e.suggestions = [{ desc: 'whitespace', range: [startIndex, startIndex], text: ' ' }];
|
|
239
237
|
}
|
|
240
238
|
else if (char === '[' && type === 'ext-link-text') {
|
|
@@ -327,10 +325,12 @@ class AstText extends node_1.AstNode {
|
|
|
327
325
|
* @throws `Error` 没有父节点
|
|
328
326
|
*/
|
|
329
327
|
splitText(offset) {
|
|
328
|
+
/* istanbul ignore if */
|
|
330
329
|
if (offset > this.length || offset < -this.length) {
|
|
331
330
|
throw new RangeError(`Wrong offset to split: ${offset}`);
|
|
332
331
|
}
|
|
333
332
|
const { parentNode, data } = this;
|
|
333
|
+
/* istanbul ignore if */
|
|
334
334
|
if (!parentNode) {
|
|
335
335
|
throw new Error('The text node to be split has no parent node!');
|
|
336
336
|
}
|
|
@@ -341,6 +341,7 @@ class AstText extends node_1.AstNode {
|
|
|
341
341
|
}
|
|
342
342
|
/** @private */
|
|
343
343
|
getRelativeIndex(j) {
|
|
344
|
+
/* istanbul ignore else */
|
|
344
345
|
if (j === undefined) {
|
|
345
346
|
return super.getRelativeIndex();
|
|
346
347
|
}
|
package/dist/lib/title.js
CHANGED
package/dist/parser/braces.js
CHANGED
|
@@ -21,9 +21,9 @@ const parseExternalLinks = (wikitext, config, accum, inFile) => {
|
|
|
21
21
|
return wikitext.replace(config.regexExternalLinks, (_, url, space, text) => {
|
|
22
22
|
const { length } = accum, mt = /&[lg]t;/u.exec(url);
|
|
23
23
|
if (mt) {
|
|
24
|
-
url = url.slice(0, mt.index);
|
|
25
24
|
space = '';
|
|
26
25
|
text = url.slice(mt.index) + space + text;
|
|
26
|
+
url = url.slice(0, mt.index);
|
|
27
27
|
}
|
|
28
28
|
if (inFile) {
|
|
29
29
|
// @ts-expect-error abstract class
|
|
@@ -32,7 +32,7 @@ const parseHrAndDoubleUnderscore = ({ firstChild: { data }, type, name }, config
|
|
|
32
32
|
if (caseSensitive || caseInsensitive) {
|
|
33
33
|
// @ts-expect-error abstract class
|
|
34
34
|
new doubleUnderscore_1.DoubleUnderscoreToken(p1, caseSensitive, config, accum);
|
|
35
|
-
return `\0${accum.length - 1}${caseInsensitive && (aliases?.[lc] ?? lc) === 'toc' ? 'u' : 'n'}\x7F`;
|
|
35
|
+
return `\0${accum.length - 1}${caseInsensitive && (aliases?.[lc] ?? /* istanbul ignore next */ lc) === 'toc' ? 'u' : 'n'}\x7F`;
|
|
36
36
|
}
|
|
37
37
|
return m;
|
|
38
38
|
}).replace(/^((?:\0\d+[cn]\x7F)*)(={1,6})(.+)\2((?:\s|\0\d+[cn]\x7F)*)$/gmu, (_, lead, equals, heading, trail) => {
|
|
@@ -20,7 +20,7 @@ const parseMagicLinks = (wikitext, config, accum) => {
|
|
|
20
20
|
try {
|
|
21
21
|
config.regexMagicLinks = new RegExp(String.raw `(^|[^\p{L}\d_])(?:(?:${config.protocol})(${string_1.extUrlCharFirst}${string_1.extUrlChar})|${magicLinkPattern})`, 'giu');
|
|
22
22
|
}
|
|
23
|
-
catch {
|
|
23
|
+
catch /* istanbul ignore next */ {
|
|
24
24
|
config.regexMagicLinks = new RegExp(String.raw `(^|\W)(?:(?:${config.protocol})(${string_1.extUrlCharFirst}${string_1.extUrlChar})|${magicLinkPattern})`, 'giu');
|
|
25
25
|
}
|
|
26
26
|
}
|