wikiparser-node 1.21.3 → 1.22.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 +6 -0
- package/bundle/bundle-es8.min.js +24 -24
- package/bundle/bundle-lsp.min.js +26 -26
- package/bundle/bundle.min.js +24 -24
- package/config/default.json +17 -11
- package/config/enwiki.json +1 -1
- package/config/jawiki.json +1 -1
- package/config/minimum.json +3 -3
- package/config/moegirl.json +154 -15
- package/config/zhwiki.json +1 -1
- package/dist/addon/token.js +3 -0
- package/dist/base.d.mts +10 -8
- package/dist/base.d.ts +10 -8
- package/dist/bin/config.js +23 -11
- package/dist/index.d.ts +31 -2
- package/dist/index.js +27 -1
- package/dist/lib/document.js +1 -1
- package/dist/lib/element.d.ts +4 -4
- package/dist/lib/element.js +7 -7
- package/dist/lib/lintConfig.js +123 -6
- package/dist/lib/lsp.d.ts +7 -7
- package/dist/lib/lsp.js +36 -23
- package/dist/lib/node.d.ts +1 -1
- package/dist/lib/node.js +1 -1
- package/dist/lib/range.d.ts +2 -2
- package/dist/lib/range.js +10 -4
- package/dist/lib/text.js +72 -62
- package/dist/lib/title.d.ts +11 -4
- package/dist/lib/title.js +16 -6
- package/dist/mixin/readOnly.js +3 -1
- package/dist/parser/commentAndExt.js +6 -4
- package/dist/parser/converter.js +1 -1
- package/dist/parser/selector.js +11 -9
- package/dist/src/arg.js +11 -10
- package/dist/src/attribute.js +31 -19
- package/dist/src/attributes.js +10 -8
- package/dist/src/commented.js +1 -1
- package/dist/src/converterRule.js +2 -2
- package/dist/src/gallery.js +26 -19
- package/dist/src/heading.js +32 -36
- package/dist/src/html.js +64 -51
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.js +10 -8
- package/dist/src/link/base.d.ts +1 -1
- package/dist/src/link/base.js +22 -15
- package/dist/src/link/file.js +22 -14
- package/dist/src/link/index.d.ts +1 -1
- package/dist/src/link/index.js +1 -1
- package/dist/src/magicLink.js +16 -12
- package/dist/src/nowiki/index.js +1 -1
- package/dist/src/nowiki/quote.js +19 -38
- package/dist/src/table/index.js +33 -27
- package/dist/src/table/td.d.ts +1 -1
- package/dist/src/table/td.js +27 -25
- package/dist/src/table/trBase.js +13 -10
- package/dist/src/tagPair/ext.js +6 -3
- package/dist/src/tagPair/index.js +2 -3
- package/dist/src/transclude.d.ts +15 -1
- package/dist/src/transclude.js +43 -13
- package/dist/util/lint.js +3 -5
- package/dist/util/sharable.js +1 -1
- package/dist/util/sharable.mjs +2 -2
- package/extensions/dist/base.js +8 -1
- package/extensions/typings.d.ts +2 -1
- package/i18n/zh-hans.json +1 -1
- package/i18n/zh-hant.json +1 -1
- package/package.json +8 -3
package/dist/lib/lsp.js
CHANGED
|
@@ -18,7 +18,7 @@ const path_1 = __importDefault(require("path"));
|
|
|
18
18
|
const util_1 = __importDefault(require("util"));
|
|
19
19
|
const child_process_1 = require("child_process");
|
|
20
20
|
const crypto_1 = require("crypto");
|
|
21
|
-
const
|
|
21
|
+
const stylelint_util_1 = require("@bhsd/stylelint-util");
|
|
22
22
|
const document_1 = require("./document");
|
|
23
23
|
/** @see https://www.npmjs.com/package/stylelint-config-recommended */
|
|
24
24
|
const cssRules = {
|
|
@@ -227,14 +227,16 @@ const adjustPos = (height, width, line, column) => {
|
|
|
227
227
|
* Get the position of a Stylelint error.
|
|
228
228
|
* @param rect bounding client rect of the token
|
|
229
229
|
* @param bottom bottom of the style block
|
|
230
|
-
* @param
|
|
231
|
-
* @param
|
|
230
|
+
* @param lineOrCode line number or code string
|
|
231
|
+
* @param columnOrOffset column number or offset in the code string
|
|
232
232
|
*/
|
|
233
|
-
const getStylelintPos = (rect, bottom,
|
|
233
|
+
const getStylelintPos = (rect, bottom, lineOrCode, columnOrOffset) => {
|
|
234
234
|
const { top, left, height, width } = rect, start = bottom - height - 1;
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
235
|
+
if (typeof lineOrCode === 'number') {
|
|
236
|
+
return (0, lint_1.getEndPos)(top, left, ...adjustPos(height, width, lineOrCode - start, columnOrOffset));
|
|
237
|
+
}
|
|
238
|
+
const lines = lineOrCode.slice(0, columnOrOffset).split(/\r?\n/u);
|
|
239
|
+
return getStylelintPos(rect, bottom, lines.length, lines.at(-1).length);
|
|
238
240
|
};
|
|
239
241
|
/**
|
|
240
242
|
* Convert LilyPond errors to VSCode diagnostics.
|
|
@@ -534,7 +536,7 @@ class LanguageService {
|
|
|
534
536
|
*
|
|
535
537
|
* 提供自动补全
|
|
536
538
|
* @param text source Wikitext / 源代码
|
|
537
|
-
* @param position 位置
|
|
539
|
+
* @param position position / 位置
|
|
538
540
|
*/
|
|
539
541
|
async provideCompletionItems(text, position) {
|
|
540
542
|
const { re, allTags, functions, switches, protocols, params, tags, ext } = this.#prepareCompletionConfig(), { line, character } = position, curLine = text.split(/\r?\n/u, line + 1)[line], mt = re.exec(curLine?.slice(0, character) ?? ''), [, , iAlias = {}, sAlias = {}] = this.config.doubleUnderscore;
|
|
@@ -762,7 +764,7 @@ class LanguageService {
|
|
|
762
764
|
if (tokens.length === 0) {
|
|
763
765
|
return [];
|
|
764
766
|
}
|
|
765
|
-
const
|
|
767
|
+
const code = tokens.map(({ type, tag, lastChild }, i) => `${type === 'ext-attr' ? 'div' : tag}#${i}{\n${(0, common_1.sanitizeInlineStyle)(lastChild.toString())}\n}`).join('\n'), cssErrors = await (0, stylelint_util_1.styleLint)((await document_1.stylelint), code, cssRules);
|
|
766
768
|
if (cssErrors.length === 0) {
|
|
767
769
|
return [];
|
|
768
770
|
}
|
|
@@ -772,7 +774,7 @@ class LanguageService {
|
|
|
772
774
|
acc += height + 2;
|
|
773
775
|
return acc;
|
|
774
776
|
});
|
|
775
|
-
return cssErrors.map(({ rule, text: msg, severity, line, column, endLine = line, endColumn = column, }) => {
|
|
777
|
+
return cssErrors.map(({ rule, text: msg, severity, line, column, endLine = line, endColumn = column, fix, }) => {
|
|
776
778
|
const i = bottoms.findIndex(bottom => bottom >= line);
|
|
777
779
|
return {
|
|
778
780
|
range: {
|
|
@@ -783,6 +785,21 @@ class LanguageService {
|
|
|
783
785
|
source: 'Stylelint',
|
|
784
786
|
code: rule,
|
|
785
787
|
message: msg.slice(0, msg.lastIndexOf('(') - 1),
|
|
788
|
+
...fix
|
|
789
|
+
? {
|
|
790
|
+
data: [
|
|
791
|
+
{
|
|
792
|
+
range: {
|
|
793
|
+
start: getStylelintPos(rects[i], bottoms[i], code, fix.range[0]),
|
|
794
|
+
end: getStylelintPos(rects[i], bottoms[i], code, fix.range[1]),
|
|
795
|
+
},
|
|
796
|
+
newText: fix.text,
|
|
797
|
+
title: `Fix: ${rule}`,
|
|
798
|
+
fix: true,
|
|
799
|
+
},
|
|
800
|
+
],
|
|
801
|
+
}
|
|
802
|
+
: {},
|
|
786
803
|
};
|
|
787
804
|
});
|
|
788
805
|
})() :
|
|
@@ -1056,7 +1073,7 @@ class LanguageService {
|
|
|
1056
1073
|
*
|
|
1057
1074
|
* 提供引用
|
|
1058
1075
|
* @param text source Wikitext / 源代码
|
|
1059
|
-
* @param position 位置
|
|
1076
|
+
* @param position position / 位置
|
|
1060
1077
|
*/
|
|
1061
1078
|
async provideReferences(text, position) {
|
|
1062
1079
|
const root = await this.#queue(text), { offsetNode, offset } = caretPositionFromWord(root, this.#text, position), element = offsetNode.type === 'text' ? offsetNode.parentNode : offsetNode, node = offset === 0 && (element.type === 'ext-attr-dirty' || element.type === 'html-attr-dirty')
|
|
@@ -1077,7 +1094,7 @@ class LanguageService {
|
|
|
1077
1094
|
*
|
|
1078
1095
|
* 提供定义
|
|
1079
1096
|
* @param text source Wikitext / 源代码
|
|
1080
|
-
* @param position 位置
|
|
1097
|
+
* @param position position / 位置
|
|
1081
1098
|
*/
|
|
1082
1099
|
async provideDefinition(text, position) {
|
|
1083
1100
|
const root = await this.#queue(text), node = root.elementFromPoint(position.character, position.line), ext = node.is('ext') && node.name === 'ref'
|
|
@@ -1098,7 +1115,7 @@ class LanguageService {
|
|
|
1098
1115
|
*
|
|
1099
1116
|
* 提供变量更名准备
|
|
1100
1117
|
* @param text source Wikitext / 源代码
|
|
1101
|
-
* @param position 位置
|
|
1118
|
+
* @param position position / 位置
|
|
1102
1119
|
*/
|
|
1103
1120
|
async resolveRenameLocation(text, position) {
|
|
1104
1121
|
const root = await this.#queue(text), node = root.elementFromPoint(position.character, position.line), { type } = node, refName = getRefName(node), refGroup = getRefGroup(node);
|
|
@@ -1113,7 +1130,7 @@ class LanguageService {
|
|
|
1113
1130
|
*
|
|
1114
1131
|
* 变量更名
|
|
1115
1132
|
* @param text source Wikitext / 源代码
|
|
1116
|
-
* @param position 位置
|
|
1133
|
+
* @param position position / 位置
|
|
1117
1134
|
* @param newName new name / 新名称
|
|
1118
1135
|
*/
|
|
1119
1136
|
async provideRenameEdits(text, position, newName) {
|
|
@@ -1159,7 +1176,7 @@ class LanguageService {
|
|
|
1159
1176
|
*
|
|
1160
1177
|
* 提供悬停信息
|
|
1161
1178
|
* @param text source Wikitext / 源代码
|
|
1162
|
-
* @param position 位置
|
|
1179
|
+
* @param position position / 位置
|
|
1163
1180
|
*/
|
|
1164
1181
|
async provideHover(text, position) {
|
|
1165
1182
|
/* istanbul ignore next */
|
|
@@ -1255,7 +1272,7 @@ class LanguageService {
|
|
|
1255
1272
|
*
|
|
1256
1273
|
* 提供魔术字帮助
|
|
1257
1274
|
* @param text source Wikitext / 源代码
|
|
1258
|
-
* @param position 位置
|
|
1275
|
+
* @param position position / 位置
|
|
1259
1276
|
*/
|
|
1260
1277
|
async provideSignatureHelp(text, position) {
|
|
1261
1278
|
/* istanbul ignore next */
|
|
@@ -1396,19 +1413,15 @@ class LanguageService {
|
|
|
1396
1413
|
* @since v1.18.1
|
|
1397
1414
|
*/
|
|
1398
1415
|
async setTargetWikipedia(wiki) {
|
|
1399
|
-
const
|
|
1400
|
-
if (!mt) {
|
|
1401
|
-
throw new RangeError('Invalid Wikipedia URL!');
|
|
1402
|
-
}
|
|
1403
|
-
const site = `${mt[1].toLowerCase()}wiki`;
|
|
1416
|
+
const [site, host] = index_1.default.getWMFSite(wiki);
|
|
1404
1417
|
try {
|
|
1405
1418
|
const config = require(path_1.default.join('..', '..', 'config', site));
|
|
1406
1419
|
this.config = index_1.default.getConfig(config);
|
|
1407
1420
|
}
|
|
1408
1421
|
catch {
|
|
1409
|
-
this.config = await index_1.default.fetchConfig(site, `${
|
|
1422
|
+
this.config = await index_1.default.fetchConfig(site, `${host}/w`);
|
|
1410
1423
|
}
|
|
1411
|
-
Object.assign(this.config, { articlePath: `${
|
|
1424
|
+
Object.assign(this.config, { articlePath: `${host}/wiki/` });
|
|
1412
1425
|
}
|
|
1413
1426
|
}
|
|
1414
1427
|
exports.LanguageService = LanguageService;
|
package/dist/lib/node.d.ts
CHANGED
|
@@ -197,7 +197,7 @@ export declare abstract class AstNode implements AstNodeBase {
|
|
|
197
197
|
* 添加事件监听
|
|
198
198
|
* @param types event type / 事件类型
|
|
199
199
|
* @param listener listener function / 监听函数
|
|
200
|
-
* @param options 选项
|
|
200
|
+
* @param options options / 选项
|
|
201
201
|
* @param options.once to be executed only once / 仅执行一次
|
|
202
202
|
*/
|
|
203
203
|
addEventListener(types: string | string[], listener: (...args: any[]) => void, options?: {
|
package/dist/lib/node.js
CHANGED
|
@@ -514,7 +514,7 @@ let AstNode = (() => {
|
|
|
514
514
|
* 添加事件监听
|
|
515
515
|
* @param types event type / 事件类型
|
|
516
516
|
* @param listener listener function / 监听函数
|
|
517
|
-
* @param options 选项
|
|
517
|
+
* @param options options / 选项
|
|
518
518
|
* @param options.once to be executed only once / 仅执行一次
|
|
519
519
|
*/
|
|
520
520
|
addEventListener(types, listener, options) {
|
package/dist/lib/range.d.ts
CHANGED
|
@@ -99,7 +99,7 @@ export declare class AstRange {
|
|
|
99
99
|
*
|
|
100
100
|
* 比较端点和Range的位置
|
|
101
101
|
* @param referenceNode node container / 端点容器
|
|
102
|
-
* @param offset 端点位置
|
|
102
|
+
* @param offset node offset / 端点位置
|
|
103
103
|
* @throws `RangeError` 不在同一个文档
|
|
104
104
|
*/
|
|
105
105
|
comparePoint(referenceNode: AstNodes, offset: number): -1 | 0 | 1;
|
|
@@ -108,7 +108,7 @@ export declare class AstRange {
|
|
|
108
108
|
*
|
|
109
109
|
* 端点是否在Range中
|
|
110
110
|
* @param referenceNode node container / 端点容器
|
|
111
|
-
* @param offset 端点位置
|
|
111
|
+
* @param offset node offset / 端点位置
|
|
112
112
|
*/
|
|
113
113
|
isPointInRange(referenceNode: AstNodes, offset: number): boolean;
|
|
114
114
|
/**
|
package/dist/lib/range.js
CHANGED
|
@@ -6,8 +6,13 @@ const constants_1 = require("../util/constants");
|
|
|
6
6
|
* 计算绝对位置
|
|
7
7
|
* @param referenceNode 容器
|
|
8
8
|
* @param offset 相对位置
|
|
9
|
+
* @param end 是否是终点
|
|
9
10
|
*/
|
|
10
|
-
const getIndex = (referenceNode, offset) =>
|
|
11
|
+
const getIndex = (referenceNode, offset, end) => {
|
|
12
|
+
end &&= referenceNode.type !== 'text';
|
|
13
|
+
return referenceNode.getAbsoluteIndex() + referenceNode.getRelativeIndex(offset - (end ? 1 : 0))
|
|
14
|
+
+ (end ? referenceNode.childNodes[offset - 1].toString().length : 0);
|
|
15
|
+
};
|
|
11
16
|
/**
|
|
12
17
|
* 获取父节点或抛出错误
|
|
13
18
|
* @param node 参考节点
|
|
@@ -66,7 +71,8 @@ class AstRange {
|
|
|
66
71
|
}
|
|
67
72
|
/** end character index / 终点绝对位置 */
|
|
68
73
|
get endIndex() {
|
|
69
|
-
|
|
74
|
+
const { endContainer, endOffset } = this;
|
|
75
|
+
return getIndex(endContainer, endOffset, this.#startContainer ? !this.collapsed : endOffset > 0);
|
|
70
76
|
}
|
|
71
77
|
/** end position / 终点行列位置 */
|
|
72
78
|
get endPos() {
|
|
@@ -277,7 +283,7 @@ class AstRange {
|
|
|
277
283
|
*
|
|
278
284
|
* 比较端点和Range的位置
|
|
279
285
|
* @param referenceNode node container / 端点容器
|
|
280
|
-
* @param offset 端点位置
|
|
286
|
+
* @param offset node offset / 端点位置
|
|
281
287
|
* @throws `RangeError` 不在同一个文档
|
|
282
288
|
*/
|
|
283
289
|
comparePoint(referenceNode, offset) {
|
|
@@ -297,7 +303,7 @@ class AstRange {
|
|
|
297
303
|
*
|
|
298
304
|
* 端点是否在Range中
|
|
299
305
|
* @param referenceNode node container / 端点容器
|
|
300
|
-
* @param offset 端点位置
|
|
306
|
+
* @param offset node offset / 端点位置
|
|
301
307
|
*/
|
|
302
308
|
isPointInRange(referenceNode, offset) {
|
|
303
309
|
return this.comparePoint(referenceNode, offset) === 0;
|
package/dist/lib/text.js
CHANGED
|
@@ -63,16 +63,6 @@ const errorSyntaxUrl = new RegExp(source, 'giu'), noLinkTypes = new Set(['attr-v
|
|
|
63
63
|
'{': /[{}]/u,
|
|
64
64
|
']': /[[\]](?=[^[\]]*$)/u,
|
|
65
65
|
'}': /[{}](?=[^{}]*$)/u,
|
|
66
|
-
}, ruleMap = {
|
|
67
|
-
'<': 'tag-like',
|
|
68
|
-
'[': 'lonely-bracket',
|
|
69
|
-
'{': 'lonely-bracket',
|
|
70
|
-
']': 'lonely-bracket',
|
|
71
|
-
'}': 'lonely-bracket',
|
|
72
|
-
h: 'lonely-http',
|
|
73
|
-
r: 'lonely-http',
|
|
74
|
-
p: 'lonely-http',
|
|
75
|
-
i: 'lonely-http',
|
|
76
66
|
}, disallowedTags = new Set([
|
|
77
67
|
'html',
|
|
78
68
|
'base',
|
|
@@ -210,13 +200,9 @@ let AstText = (() => {
|
|
|
210
200
|
throw new Error('An isolated text node cannot be linted!');
|
|
211
201
|
}
|
|
212
202
|
const { type, name, parentNode: grandparent } = parentNode;
|
|
213
|
-
let isHtmlAttrVal = false;
|
|
214
203
|
if (type === 'attr-value') {
|
|
215
|
-
const {
|
|
216
|
-
if (
|
|
217
|
-
isHtmlAttrVal = true;
|
|
218
|
-
}
|
|
219
|
-
else if (tag === 'ref' && (grandName === 'name' || grandName === 'extends' || grandName === 'follow')
|
|
204
|
+
const { name: grandName, tag } = grandparent;
|
|
205
|
+
if (tag === 'ref' && (grandName === 'name' || grandName === 'extends' || grandName === 'follow')
|
|
220
206
|
|| grandName === 'group' && (tag === 'ref' || tag === 'references')
|
|
221
207
|
|| tag === 'choose' && (grandName === 'before' || grandName === 'after')) {
|
|
222
208
|
return [];
|
|
@@ -226,7 +212,7 @@ let AstText = (() => {
|
|
|
226
212
|
|| type === 'ext-link-url'
|
|
227
213
|
|| type === 'ext-link-text'
|
|
228
214
|
|| type === 'image-parameter' && name === 'link'
|
|
229
|
-
||
|
|
215
|
+
|| type === 'attr-value'
|
|
230
216
|
? errorSyntaxUrl
|
|
231
217
|
: errorSyntax;
|
|
232
218
|
if (data.search(errorRegex) === -1) {
|
|
@@ -252,72 +238,95 @@ let AstText = (() => {
|
|
|
252
238
|
error = error.slice(length);
|
|
253
239
|
}
|
|
254
240
|
error = error.toLowerCase();
|
|
255
|
-
const [char] = error, magicLink = char === 'r' || char === 'p' || char === 'i';
|
|
241
|
+
const [char] = error, magicLink = char === 'r' || char === 'p' || char === 'i', lbrace = char === '{', rbrace = char === '}', lbrack = char === '[', rbrack = char === ']';
|
|
256
242
|
let { length } = error;
|
|
257
243
|
if (char === '<' && !tags.has(tag.toLowerCase())
|
|
258
|
-
||
|
|
244
|
+
|| lbrack && type === 'ext-link-text' && (/&(?:rbrack|#93|#x5[Dd];);/u.test(data.slice(index + 1))
|
|
259
245
|
|| nextSibling?.is('ext') && nextName === 'nowiki'
|
|
260
246
|
&& nextSibling.innerText?.includes(']'))
|
|
261
247
|
|| magicLink && (!parentNode.isPlain() || noLinkTypes.has(type))) {
|
|
262
248
|
continue;
|
|
263
249
|
}
|
|
264
|
-
else if (
|
|
250
|
+
else if (rbrack && (index || length > 1)) {
|
|
265
251
|
errorRegex.lastIndex--;
|
|
266
252
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
||
|
|
271
|
-
|
|
272
|
-
|| /^(?:rfc|pmid|isbn)$/iu.test(error))
|
|
273
|
-
|| char === '{' && (nextChar === char || previousChar === '-' && variants.length > 0)
|
|
274
|
-
|| char === '}' && (previousChar === char || nextChar === '-' && variants.length > 0)
|
|
275
|
-
|| char === '[' && (type === 'ext-link-text' || nextType === 'free-ext-link' && !data.slice(index + 1).trim())
|
|
276
|
-
|| char === ']' && previousType === 'free-ext-link'
|
|
277
|
-
&& !data.slice(0, index).includes(']')
|
|
278
|
-
? 'error'
|
|
279
|
-
: 'warning';
|
|
280
|
-
const leftBracket = char === '{' || char === '[', rightBracket = char === ']' || char === '}';
|
|
281
|
-
if (severity === 'warning' && (leftBracket || rightBracket)) {
|
|
282
|
-
const regex = regexes[char], remains = leftBracket ? data.slice(index + 1) : data.slice(0, index);
|
|
283
|
-
if (char === '{' && regex.exec(remains)?.[0] === '}'
|
|
284
|
-
|| char === '}' && regex.exec(remains)?.[0] === '{') {
|
|
285
|
-
continue;
|
|
286
|
-
}
|
|
287
|
-
else if (!remains.includes(char)) {
|
|
288
|
-
const sibling = leftBracket ? 'nextSibling' : 'previousSibling';
|
|
289
|
-
let cur = this[sibling];
|
|
290
|
-
while (cur && (cur.type !== 'text' || !regex.test(cur.data))) {
|
|
291
|
-
cur = cur[sibling];
|
|
292
|
-
}
|
|
293
|
-
if (cur && regex.exec(cur.data)[0] !== char) {
|
|
294
|
-
continue;
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
}
|
|
253
|
+
// Rule & Severity
|
|
254
|
+
let startIndex = start + index, endIndex = startIndex + length, rule, severity;
|
|
255
|
+
const nextChar = rootStr[endIndex], previousChar = rootStr[startIndex - 1], leftBracket = lbrace || lbrack, lConverter = lbrace && previousChar === '-' && variants.length > 0, rConverter = rbrace && nextChar === '-' && variants.length > 0, brokenExtLink = lbrack && nextType === 'free-ext-link' && !data.slice(index + 1).trim()
|
|
256
|
+
|| rbrack && previousType === 'free-ext-link'
|
|
257
|
+
&& !data.slice(0, index).includes(']');
|
|
298
258
|
if (magicLink) {
|
|
259
|
+
rule = 'lonely-http';
|
|
299
260
|
error = error.toUpperCase();
|
|
261
|
+
severity = index_1.default.lintConfig.getSeverity(rule, error);
|
|
300
262
|
}
|
|
301
|
-
else if (
|
|
302
|
-
|
|
303
|
-
|
|
263
|
+
else if (char === '<') {
|
|
264
|
+
rule = 'tag-like';
|
|
265
|
+
let key;
|
|
266
|
+
if (/^<\s/u.test(error) || !/[\s/>]/u.test(nextChar ?? '')) {
|
|
267
|
+
key = 'invalid';
|
|
268
|
+
}
|
|
269
|
+
else if (disallowedTags.has(tag)) {
|
|
270
|
+
key = 'disallowed';
|
|
271
|
+
}
|
|
272
|
+
severity = index_1.default.lintConfig.getSeverity(rule, key);
|
|
273
|
+
}
|
|
274
|
+
else if (lConverter || rConverter) {
|
|
275
|
+
rule = 'lonely-bracket';
|
|
276
|
+
severity = index_1.default.lintConfig.getSeverity(rule, 'converter');
|
|
277
|
+
if (lConverter && index > 0) {
|
|
304
278
|
error = '-{';
|
|
305
279
|
index--;
|
|
306
280
|
startIndex--;
|
|
307
281
|
length = 2;
|
|
308
282
|
}
|
|
309
|
-
|
|
310
|
-
else if (error === '}' && nextChar === '-' && severity === 'error') {
|
|
311
|
-
severity = 'warning';
|
|
312
|
-
if (index < data.length - 1) {
|
|
283
|
+
else if (rConverter && index < data.length - 1) {
|
|
313
284
|
error = '}-';
|
|
314
285
|
endIndex++;
|
|
315
286
|
length = 2;
|
|
316
287
|
}
|
|
317
288
|
}
|
|
289
|
+
else if (brokenExtLink) {
|
|
290
|
+
rule = 'lonely-bracket';
|
|
291
|
+
severity = index_1.default.lintConfig.getSeverity(rule, 'extLink');
|
|
292
|
+
}
|
|
293
|
+
else if (leftBracket || rbrace || rbrack) {
|
|
294
|
+
rule = 'lonely-bracket';
|
|
295
|
+
if (length > 1 || lbrace && nextChar === char || rbrace && previousChar === char) {
|
|
296
|
+
severity = index_1.default.lintConfig.getSeverity(rule, 'double');
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
if (!lbrack || type !== 'ext-link-text') {
|
|
300
|
+
const regex = regexes[char], remains = leftBracket ? data.slice(index + 1) : data.slice(0, index);
|
|
301
|
+
if (lbrace && regex.exec(remains)?.[0] === '}'
|
|
302
|
+
|| rbrace && regex.exec(remains)?.[0] === '{') {
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
else if (!remains.includes(char)) {
|
|
306
|
+
const sibling = leftBracket ? 'nextSibling' : 'previousSibling';
|
|
307
|
+
let cur = this[sibling];
|
|
308
|
+
while (cur && (cur.type !== 'text' || !regex.test(cur.data))) {
|
|
309
|
+
cur = cur[sibling];
|
|
310
|
+
}
|
|
311
|
+
if (cur && regex.exec(cur.data)[0] !== char) {
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
severity = index_1.default.lintConfig.getSeverity(rule, 'single');
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
else {
|
|
320
|
+
rule = 'lonely-http';
|
|
321
|
+
severity = index_1.default.lintConfig.getSeverity(rule);
|
|
322
|
+
}
|
|
323
|
+
if (!severity) {
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
// LintError
|
|
318
327
|
const pos = this.posFromIndex(index), { line: startLine, character: startCol } = (0, lint_1.getEndPos)(top, left, pos.top + 1, pos.left), e = {
|
|
319
|
-
rule
|
|
320
|
-
message: index_1.default.msg('lonely "$1"', magicLink || char === 'h' ||
|
|
328
|
+
rule,
|
|
329
|
+
message: index_1.default.msg('lonely "$1"', magicLink || char === 'h' || lConverter || rConverter ? error : char),
|
|
321
330
|
severity,
|
|
322
331
|
startIndex,
|
|
323
332
|
endIndex,
|
|
@@ -326,17 +335,18 @@ let AstText = (() => {
|
|
|
326
335
|
startCol,
|
|
327
336
|
endCol: startCol + length,
|
|
328
337
|
};
|
|
338
|
+
// Suggestions
|
|
329
339
|
if (char === '<') {
|
|
330
340
|
e.suggestions = [{ desc: 'escape', range: [startIndex, startIndex + 1], text: '<' }];
|
|
331
341
|
}
|
|
332
342
|
else if (char === 'h' && type !== 'link-text' && wordRegex.test(previousChar || '')) {
|
|
333
343
|
e.suggestions = [{ desc: 'whitespace', range: [startIndex, startIndex], text: ' ' }];
|
|
334
344
|
}
|
|
335
|
-
else if (
|
|
345
|
+
else if (lbrack && type === 'ext-link-text') {
|
|
336
346
|
const i = parentNode.getAbsoluteIndex() + parentNode.toString().length;
|
|
337
347
|
e.suggestions = [{ desc: 'escape', range: [i, i + 1], text: ']' }];
|
|
338
348
|
}
|
|
339
|
-
else if (
|
|
349
|
+
else if (rbrack && brokenExtLink) {
|
|
340
350
|
const i = start - previousSibling.toString().length;
|
|
341
351
|
e.suggestions = [{ desc: 'left bracket', range: [i, i], text: '[' }];
|
|
342
352
|
}
|
package/dist/lib/title.d.ts
CHANGED
|
@@ -36,6 +36,13 @@ export declare class Title {
|
|
|
36
36
|
/** @throws `RangeError` undefined namespace */
|
|
37
37
|
set ns(ns: number);
|
|
38
38
|
set fragment(fragment: string | undefined);
|
|
39
|
+
/**
|
|
40
|
+
* display title
|
|
41
|
+
*
|
|
42
|
+
* 用于显示的标题
|
|
43
|
+
* @since v1.22.0
|
|
44
|
+
*/
|
|
45
|
+
get displayTitle(): string;
|
|
39
46
|
/**
|
|
40
47
|
* @see MediaWikiTitleCodec::splitTitleString
|
|
41
48
|
*
|
|
@@ -75,14 +82,14 @@ export declare class Title {
|
|
|
75
82
|
* 转换为主页面
|
|
76
83
|
* @since v1.1.0
|
|
77
84
|
*/
|
|
78
|
-
toSubjectPage():
|
|
85
|
+
toSubjectPage(): this;
|
|
79
86
|
/**
|
|
80
87
|
* Get the title of its talk page
|
|
81
88
|
*
|
|
82
89
|
* 转换为讨论页面
|
|
83
90
|
* @since v1.1.0
|
|
84
91
|
*/
|
|
85
|
-
toTalkPage():
|
|
92
|
+
toTalkPage(): this;
|
|
86
93
|
/**
|
|
87
94
|
* Check if the title is a talk page
|
|
88
95
|
*
|
|
@@ -96,12 +103,12 @@ export declare class Title {
|
|
|
96
103
|
* 转换为上一级页面
|
|
97
104
|
* @since v1.1.0
|
|
98
105
|
*/
|
|
99
|
-
toBasePage():
|
|
106
|
+
toBasePage(): this;
|
|
100
107
|
/**
|
|
101
108
|
* Get the title of its root page
|
|
102
109
|
*
|
|
103
110
|
* 转换为根页面
|
|
104
111
|
* @since v1.1.0
|
|
105
112
|
*/
|
|
106
|
-
toRootPage():
|
|
113
|
+
toRootPage(): this;
|
|
107
114
|
}
|
package/dist/lib/title.js
CHANGED
|
@@ -94,6 +94,15 @@ class Title {
|
|
|
94
94
|
.replaceAll(' ', '_');
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* display title
|
|
99
|
+
*
|
|
100
|
+
* 用于显示的标题
|
|
101
|
+
* @since v1.22.0
|
|
102
|
+
*/
|
|
103
|
+
get displayTitle() {
|
|
104
|
+
return this.title.replaceAll('_', ' ');
|
|
105
|
+
}
|
|
97
106
|
/* NOT FOR BROWSER END */
|
|
98
107
|
/**
|
|
99
108
|
* @see MediaWikiTitleCodec::splitTitleString
|
|
@@ -236,12 +245,9 @@ class Title {
|
|
|
236
245
|
/* NOT FOR BROWSER */
|
|
237
246
|
/** @private */
|
|
238
247
|
toString(display) {
|
|
239
|
-
return (display ? this.title
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
? ''
|
|
243
|
-
: `#${this.#fragment
|
|
244
|
-
?? this.#redirectFragment}`);
|
|
248
|
+
return (display ? this.displayTitle : this.title) + (this.#fragment === undefined && this.#redirectFragment === undefined
|
|
249
|
+
? ''
|
|
250
|
+
: `#${this.#fragment ?? this.#redirectFragment}`);
|
|
245
251
|
}
|
|
246
252
|
/**
|
|
247
253
|
* 处理重定向
|
|
@@ -283,6 +289,7 @@ class Title {
|
|
|
283
289
|
if (this.isTalkPage()) {
|
|
284
290
|
this.#ns--;
|
|
285
291
|
}
|
|
292
|
+
return this;
|
|
286
293
|
}
|
|
287
294
|
/**
|
|
288
295
|
* Get the title of its talk page
|
|
@@ -294,6 +301,7 @@ class Title {
|
|
|
294
301
|
if (!this.isTalkPage()) {
|
|
295
302
|
this.#ns++;
|
|
296
303
|
}
|
|
304
|
+
return this;
|
|
297
305
|
}
|
|
298
306
|
/**
|
|
299
307
|
* Check if the title is a talk page
|
|
@@ -312,6 +320,7 @@ class Title {
|
|
|
312
320
|
*/
|
|
313
321
|
toBasePage() {
|
|
314
322
|
this.main = this.main.replace(/\/[^/]*$/u, '');
|
|
323
|
+
return this;
|
|
315
324
|
}
|
|
316
325
|
/**
|
|
317
326
|
* Get the title of its root page
|
|
@@ -321,6 +330,7 @@ class Title {
|
|
|
321
330
|
*/
|
|
322
331
|
toRootPage() {
|
|
323
332
|
this.main = this.main.replace(/\/.*/u, '');
|
|
333
|
+
return this;
|
|
324
334
|
}
|
|
325
335
|
/** @private */
|
|
326
336
|
getTitleAttr() {
|
package/dist/mixin/readOnly.js
CHANGED
|
@@ -19,7 +19,9 @@ const readOnly = (readonly = false) =>
|
|
|
19
19
|
index_1.default.viewOnly = readonly;
|
|
20
20
|
}
|
|
21
21
|
const result = method.apply(this, args);
|
|
22
|
-
|
|
22
|
+
if (!debug_1.Shadow.running) {
|
|
23
|
+
index_1.default.viewOnly = viewOnly;
|
|
24
|
+
}
|
|
23
25
|
return result;
|
|
24
26
|
};
|
|
25
27
|
exports.readOnly = readOnly;
|
|
@@ -16,7 +16,9 @@ const onlyincludeLeft = '<onlyinclude>', onlyincludeRight = '</onlyinclude>', {
|
|
|
16
16
|
const noincludeRegex = includeOnly ? 'includeonly' : '(?:no|only)include', includeRegex = includeOnly ? 'noinclude' : 'includeonly';
|
|
17
17
|
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
18
18
|
/<!--[\s\S]*?(?:-->|$)|<foo(?:\s[^>]*)?\/?>|<\/foo\s*>|<(bar)(\s[^>]*?)?(?:\/>|>([\s\S]*?)<\/(\1\s*)>)|<(baz)(\s[^>]*?)?(?:\/>|>([\s\S]*?)(?:<\/(baz\s*)>|$))/giu;
|
|
19
|
-
return (0, common_1.getObjRegex)(ext => new RegExp(String.raw `<!--[\s\S]*?(?:-->|$)|<${noincludeRegex}(?:\s[^>]*)?/?>|</${noincludeRegex}\s*>|<(${ext.
|
|
19
|
+
return (0, common_1.getObjRegex)(ext => new RegExp(String.raw `<!--[\s\S]*?(?:-->|$)|<${noincludeRegex}(?:\s[^>]*)?/?>|</${noincludeRegex}\s*>|<(${ext.filter(tag => tag !== 'img').join('|')
|
|
20
|
+
// eslint-disable-next-line unicorn/prefer-string-raw
|
|
21
|
+
})(\s[^>]*?)?(?:/>|>([\s\S]*?)</(${'\\1'}\s*)>)|<(${includeRegex})(\s[^>]*?)?(?:/>|>([\s\S]*?)(?:</(${includeRegex}\s*)>|$))${ext.includes('img') ? String.raw `|<img(\s[^>]*?)?(/?)>` : ''}`, 'giu'));
|
|
20
22
|
});
|
|
21
23
|
/**
|
|
22
24
|
* 更新`<onlyinclude>`和`</onlyinclude>`的位置
|
|
@@ -77,13 +79,13 @@ const parseCommentAndExt = (wikitext, config, accum, includeOnly) => {
|
|
|
77
79
|
});
|
|
78
80
|
wikitext = (0, string_1.restore)(wikitext, stack);
|
|
79
81
|
}
|
|
80
|
-
return wikitext.replace(getRegex[includeOnly ? 1 : 0](newExt), (substr, name, attr, inner, closing, include, includeAttr, includeInner, includeClosing) => {
|
|
82
|
+
return wikitext.replace(getRegex[includeOnly ? 1 : 0](newExt), (substr, name, attr, inner, closing, include, includeAttr, includeInner, includeClosing, imgAttr, imgClosing) => {
|
|
81
83
|
const l = accum.length;
|
|
82
84
|
let ch = 'n';
|
|
83
|
-
if (name) {
|
|
85
|
+
if (name || newExt.includes('img') && imgClosing !== undefined) {
|
|
84
86
|
ch = 'e';
|
|
85
87
|
// @ts-expect-error abstract class
|
|
86
|
-
new ext_1.ExtToken(name, attr, inner, closing, newConfig, include, accum);
|
|
88
|
+
new ext_1.ExtToken(name ?? 'img', name ? attr : imgAttr, inner, name ? closing : imgClosing && undefined, newConfig, include, accum);
|
|
87
89
|
}
|
|
88
90
|
else if (substr.startsWith('<!--')) {
|
|
89
91
|
ch = 'c';
|
package/dist/parser/converter.js
CHANGED
|
@@ -14,7 +14,7 @@ const constants_1 = require("../util/constants");
|
|
|
14
14
|
const parseConverter = (text, config, accum) => {
|
|
15
15
|
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
16
16
|
/;(?=(?:[^;]*?=>)?\s*zh\s*:|(?:\s|\0\d+[cn]\x7F)*$)/u;
|
|
17
|
-
config.regexConverter ??= new RegExp(String.raw `;(?=(?:[^;]*?=>)?\s*(?:${config.variants.join('|')})\s*:|(?:\s|\0\d+[cn]\x7F)*$)`, '
|
|
17
|
+
config.regexConverter ??= new RegExp(String.raw `;(?=(?:[^;]*?=>)?\s*(?:${config.variants.join('|')})\s*:|(?:\s|\0\d+[cn]\x7F)*$)`, 'iu');
|
|
18
18
|
const regex1 = /-\{/gu, regex2 = /-\{|\}-/gu, stack = [];
|
|
19
19
|
let regex = regex1, mt = regex.exec(text);
|
|
20
20
|
while (mt) {
|
package/dist/parser/selector.js
CHANGED
|
@@ -15,8 +15,8 @@ const attributes_1 = require("../lib/attributes");
|
|
|
15
15
|
*/
|
|
16
16
|
const basic = (selector, type, name) => {
|
|
17
17
|
if (selector.includes('#')) {
|
|
18
|
-
const
|
|
19
|
-
return (
|
|
18
|
+
const i = selector.indexOf('#');
|
|
19
|
+
return (i === 0 || selector.slice(0, i) === type) && selector.slice(i + 1) === name;
|
|
20
20
|
}
|
|
21
21
|
return !selector || selector === type;
|
|
22
22
|
};
|
|
@@ -450,12 +450,14 @@ const checkToken = (selector, scope, has) => (token) => {
|
|
|
450
450
|
* @param scope 作用对象
|
|
451
451
|
* @param has `:has()`伪选择器
|
|
452
452
|
*/
|
|
453
|
-
const getCondition = (selector, scope, has) =>
|
|
454
|
-
/*
|
|
455
|
-
/[^a-z\-,#\s]|(?<![\s,])\s+(?![\s,])/u.test(selector.trim())
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
/*
|
|
459
|
-
);
|
|
453
|
+
const getCondition = (selector, scope, has) => {
|
|
454
|
+
/* NOT FOR BROWSER */
|
|
455
|
+
if (/[^a-z\-,#\s]|(?<![\s,])\s+(?![\s,])/u.test(selector.trim())) {
|
|
456
|
+
return checkToken(selector, scope, has);
|
|
457
|
+
}
|
|
458
|
+
/* NOT FOR BROWSER END */
|
|
459
|
+
const parts = selector.split(',');
|
|
460
|
+
return (({ type, name }) => parts.some(str => basic(str.trim(), type, name)));
|
|
461
|
+
};
|
|
460
462
|
exports.getCondition = getCondition;
|
|
461
463
|
constants_1.parsers['parseSelector'] = __filename;
|