wikilint 2.43.0 → 2.45.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/config/default.json +32 -2
- package/config/enwiki.json +1 -1
- package/config/jawiki.json +1 -1
- package/config/minimum.json +1 -1
- package/config/moegirl.json +39 -1
- package/config/zhwiki.json +1 -1
- package/data/ext/templatedata.json +13 -5
- package/data/signatures.json +38 -32
- package/dist/base.d.mts +5 -5
- package/dist/base.d.ts +5 -5
- package/dist/base.js +1 -0
- package/dist/base.mjs +1 -0
- package/dist/bin/config.js +6 -5
- package/dist/index.js +9 -6
- package/dist/internal.d.ts +6 -1
- package/dist/lib/document.d.ts +17 -14
- package/dist/lib/element.js +5 -5
- package/dist/lib/lintConfig.js +11 -1
- package/dist/lib/lsp.d.ts +1 -2
- package/dist/lib/lsp.js +18 -42
- package/dist/lib/node.js +2 -2
- package/dist/lib/text.js +2 -2
- package/dist/lib/title.d.ts +4 -1
- package/dist/lib/title.js +5 -1
- package/dist/map.d.ts +4 -1
- package/dist/mixin/attributesParent.js +1 -1
- package/dist/mixin/elementLike.js +29 -31
- package/dist/mixin/hidden.js +0 -1
- package/dist/mixin/paramLineParent.d.ts +26 -0
- package/dist/mixin/paramLineParent.js +51 -0
- package/dist/parser/converter.js +1 -1
- package/dist/src/arg.js +17 -35
- package/dist/src/atom.d.ts +1 -1
- package/dist/src/atom.js +2 -0
- package/dist/src/attribute.js +10 -5
- package/dist/src/attributes.d.ts +1 -0
- package/dist/src/attributes.js +41 -15
- package/dist/src/commented.d.ts +1 -0
- package/dist/src/commented.js +1 -3
- package/dist/src/converterFlags.js +17 -8
- package/dist/src/converterRule.js +3 -3
- package/dist/src/funcTag.d.ts +23 -0
- package/dist/src/funcTag.js +85 -0
- package/dist/src/heading.js +8 -3
- package/dist/src/hidden.d.ts +3 -2
- package/dist/src/hidden.js +29 -5
- package/dist/src/imageParameter.d.ts +4 -3
- package/dist/src/imageParameter.js +29 -9
- package/dist/src/index.js +2 -2
- package/dist/src/link/base.js +14 -2
- package/dist/src/link/categorytree.d.ts +2 -0
- package/dist/src/link/categorytree.js +8 -5
- package/dist/src/link/file.d.ts +5 -4
- package/dist/src/link/file.js +19 -13
- package/dist/src/multiLine/charinsert.d.ts +16 -0
- package/dist/src/multiLine/charinsert.js +84 -0
- package/dist/src/multiLine/gallery.js +4 -4
- package/dist/src/multiLine/imagemap.d.ts +1 -1
- package/dist/src/multiLine/imagemap.js +7 -7
- package/dist/src/multiLine/index.d.ts +3 -0
- package/dist/src/multiLine/index.js +79 -18
- package/dist/src/multiLine/inputbox.d.ts +1 -0
- package/dist/src/multiLine/paramTag.d.ts +3 -0
- package/dist/src/multiLine/paramTag.js +60 -13
- package/dist/src/nested.js +7 -7
- package/dist/src/nowiki/index.d.ts +1 -0
- package/dist/src/nowiki/index.js +39 -28
- package/dist/src/nowiki/quote.js +6 -5
- package/dist/src/paramLine.d.ts +17 -3
- package/dist/src/paramLine.js +123 -31
- package/dist/src/parameter.d.ts +6 -0
- package/dist/src/parameter.js +15 -1
- package/dist/src/singleLine/charinsertLine.d.ts +21 -0
- package/dist/src/singleLine/charinsertLine.js +69 -0
- package/dist/src/{imagemapLink.d.ts → singleLine/imagemapLink.d.ts} +8 -7
- package/dist/src/singleLine/imagemapLink.js +95 -0
- package/dist/src/singleLine/index.d.ts +10 -0
- package/dist/src/singleLine/index.js +16 -0
- package/dist/src/tag/html.js +26 -8
- package/dist/src/tag/index.js +18 -17
- package/dist/src/tagPair/ext.d.ts +1 -0
- package/dist/src/tagPair/ext.js +59 -5
- package/dist/src/tagPair/index.js +1 -10
- package/dist/src/transclude.js +13 -13
- package/dist/util/sharable.js +22 -0
- package/dist/util/sharable.mjs +22 -0
- package/dist/util/string.js +33 -2
- package/dist/vendor/search.js +34 -0
- package/i18n/en.json +11 -0
- package/i18n/zh-hans.json +11 -0
- package/i18n/zh-hant.json +11 -0
- package/package.json +16 -25
- package/dist/src/imagemapLink.js +0 -34
- package/dist/util/search.js +0 -16
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ImagemapLinkToken = void 0;
|
|
7
|
+
const lint_1 = require("../../util/lint");
|
|
8
|
+
const index_1 = __importDefault(require("../../index"));
|
|
9
|
+
const index_2 = require("./index");
|
|
10
|
+
const noinclude_1 = require("../nowiki/noinclude");
|
|
11
|
+
const index_3 = require("../link/index");
|
|
12
|
+
const extLink_1 = require("../extLink");
|
|
13
|
+
const shapes = new Set(['default', 'rect', 'circle', 'poly']);
|
|
14
|
+
/** @ignore */
|
|
15
|
+
const notNumeric = (s, allowNegative) => {
|
|
16
|
+
const n = Number(s);
|
|
17
|
+
return Number.isNaN(n) || n > 1e9 || !allowNegative && n < 0;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* link inside the `<imagemap>`
|
|
21
|
+
*
|
|
22
|
+
* `<imagemap>`内的链接
|
|
23
|
+
* @classdesc `{childNodes: [AstText, LinkToken|ExtLinkToken, NoincludeToken]}`
|
|
24
|
+
*/
|
|
25
|
+
class ImagemapLinkToken extends index_2.SingleLineToken {
|
|
26
|
+
get type() {
|
|
27
|
+
return 'imagemap-link';
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* @param pre 链接前的文本
|
|
31
|
+
* @param linkStuff 内外链接
|
|
32
|
+
* @param post 链接后的文本
|
|
33
|
+
*/
|
|
34
|
+
constructor(pre, linkStuff, post, config, accum = []) {
|
|
35
|
+
super(undefined, config, accum);
|
|
36
|
+
this.append(pre, linkStuff.length === 2
|
|
37
|
+
// @ts-expect-error abstract class
|
|
38
|
+
? new index_3.LinkToken(...linkStuff, config, accum)
|
|
39
|
+
// @ts-expect-error abstract class
|
|
40
|
+
: new extLink_1.ExtLinkToken(...linkStuff, config, accum),
|
|
41
|
+
// @ts-expect-error abstract class
|
|
42
|
+
new noinclude_1.NoincludeToken(post, config, accum));
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* 检查链接区域是否合法
|
|
46
|
+
* @param errors 错误列表
|
|
47
|
+
* @param coords 坐标字符串
|
|
48
|
+
* @param start 节点起始位置
|
|
49
|
+
* @param minCount 最少需要的坐标数量
|
|
50
|
+
* @param isPoly 是否为多边形
|
|
51
|
+
*/
|
|
52
|
+
#lintCoords(errors, coords, start, minCount, isPoly) {
|
|
53
|
+
LINT: {
|
|
54
|
+
const parts = coords.split(/[ \t]+/u).map(s => s.trim()).filter(Boolean), { length } = parts, rule = 'invalid-imagemap', s = index_1.default.lintConfig.getSeverity(rule, 'coord');
|
|
55
|
+
if (s && (length < minCount || isPoly && length % 2 || parts.some(part => notNumeric(part, isPoly)))) {
|
|
56
|
+
errors.push((0, lint_1.generateForChild)(this.firstChild, { start }, rule, 'invalid-coord', s));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/** 获取链接区域图形和坐标 */
|
|
61
|
+
#getShape() {
|
|
62
|
+
const area = this.firstChild.data.trim(), i = area.search(/[ \t]/u), shape = i === -1 ? area : area.slice(0, i);
|
|
63
|
+
return shapes.has(shape) && [shape, area.slice(i).trim()];
|
|
64
|
+
}
|
|
65
|
+
/** @private */
|
|
66
|
+
lint(start = this.getAbsoluteIndex(), re) {
|
|
67
|
+
LINT: {
|
|
68
|
+
const errors = super.lint(start, re), { firstChild } = this, shapeAndCoords = this.#getShape();
|
|
69
|
+
if (shapeAndCoords) {
|
|
70
|
+
const [shape, coords] = shapeAndCoords;
|
|
71
|
+
switch (shape) {
|
|
72
|
+
case 'default':
|
|
73
|
+
break;
|
|
74
|
+
case 'rect':
|
|
75
|
+
this.#lintCoords(errors, coords, start, 4);
|
|
76
|
+
break;
|
|
77
|
+
case 'circle':
|
|
78
|
+
this.#lintCoords(errors, coords, start, 3);
|
|
79
|
+
break;
|
|
80
|
+
case 'poly':
|
|
81
|
+
this.#lintCoords(errors, coords, start, 1, true);
|
|
82
|
+
// no default
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
const rule = 'invalid-imagemap', s = index_1.default.lintConfig.getSeverity(rule, 'shape');
|
|
87
|
+
if (s) {
|
|
88
|
+
errors.push((0, lint_1.generateForChild)(firstChild, { start }, rule, 'unrecognized-shape', s));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return errors;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
exports.ImagemapLinkToken = ImagemapLinkToken;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Token } from '../index';
|
|
2
|
+
import type { MultiLineToken } from '../multiLine/index';
|
|
3
|
+
/**
|
|
4
|
+
* single-line token inside specific extension tags, such as `<charinsert>` and `<imagemap>`
|
|
5
|
+
*
|
|
6
|
+
* 特定扩展标签内的单行节点,如 `<charinsert>` 和 `<imagemap>`
|
|
7
|
+
*/
|
|
8
|
+
export declare abstract class SingleLineToken extends Token {
|
|
9
|
+
abstract get parentNode(): MultiLineToken | undefined;
|
|
10
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SingleLineToken = void 0;
|
|
4
|
+
const index_1 = require("../index");
|
|
5
|
+
/**
|
|
6
|
+
* single-line token inside specific extension tags, such as `<charinsert>` and `<imagemap>`
|
|
7
|
+
*
|
|
8
|
+
* 特定扩展标签内的单行节点,如 `<charinsert>` 和 `<imagemap>`
|
|
9
|
+
*/
|
|
10
|
+
class SingleLineToken extends index_1.Token {
|
|
11
|
+
/** @private */
|
|
12
|
+
isPlain() {
|
|
13
|
+
return this.type === 'plain';
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
exports.SingleLineToken = SingleLineToken;
|
package/dist/src/tag/html.js
CHANGED
|
@@ -112,16 +112,34 @@ let HtmlToken = (() => {
|
|
|
112
112
|
}
|
|
113
113
|
/** @private */
|
|
114
114
|
text() {
|
|
115
|
-
const { closing, selfClosing, name } = this, [, , voidTags] = this.getAttribute('config').html;
|
|
115
|
+
const { closing, selfClosing, name } = this, [normalTags, , voidTags] = this.getAttribute('config').html;
|
|
116
|
+
let slash;
|
|
116
117
|
if (voidTags.includes(name)) {
|
|
117
|
-
|
|
118
|
+
if (closing && name !== 'br') {
|
|
119
|
+
return '';
|
|
120
|
+
}
|
|
121
|
+
slash = '/';
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
slash = selfClosing && !closing && !normalTags.includes(name) ? '/' : '';
|
|
125
|
+
}
|
|
126
|
+
return `<${closing && !slash ? '/' : ''}${name}${closing ? '' : super.text()}${slash}>`;
|
|
127
|
+
}
|
|
128
|
+
/** 是否是无效自封闭标签 */
|
|
129
|
+
#lint() {
|
|
130
|
+
const { name, closing, selfClosing } = this, [, flexibleTags, voidTags] = this.getAttribute('config').html, isVoid = voidTags.includes(name), isFlexible = flexibleTags.includes(name), isNormal = !isVoid && !isFlexible;
|
|
131
|
+
if (!(closing && (selfClosing || isVoid) || selfClosing && isNormal)) {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
else if (isVoid) {
|
|
135
|
+
return 2;
|
|
118
136
|
}
|
|
119
|
-
return
|
|
137
|
+
return isFlexible ? 1 : 0;
|
|
120
138
|
}
|
|
121
139
|
/** @private */
|
|
122
140
|
lint(start = this.getAbsoluteIndex(), re) {
|
|
123
141
|
LINT: {
|
|
124
|
-
const errors = super.lint(start, re), { name, parentNode, closing
|
|
142
|
+
const errors = super.lint(start, re), { name, parentNode, closing } = this, rect = new rect_1.BoundingRect(this, start), { lintConfig } = index_1.default, { computeEditInfo, fix } = lintConfig, severity = this.inTableAttrs();
|
|
125
143
|
let rule = 'h1', s = lintConfig.getSeverity(rule, 'html');
|
|
126
144
|
if (s && name === 'h1' && !closing) {
|
|
127
145
|
const e = (0, lint_1.generateForSelf)(this, rect, rule, '<h1>', s);
|
|
@@ -153,9 +171,9 @@ let HtmlToken = (() => {
|
|
|
153
171
|
}
|
|
154
172
|
errors.push(e);
|
|
155
173
|
}
|
|
156
|
-
const
|
|
174
|
+
const tagType = this.#lint();
|
|
157
175
|
rule = 'unmatched-tag';
|
|
158
|
-
if (
|
|
176
|
+
if (tagType !== false) {
|
|
159
177
|
s = lintConfig.getSeverity(rule, closing ? 'both' : 'selfClosing');
|
|
160
178
|
if (s) {
|
|
161
179
|
const e = (0, lint_1.generateForSelf)(this, rect, rule, closing ? 'closing-and-self-closing' : 'invalid-self-closing', s);
|
|
@@ -165,13 +183,13 @@ let HtmlToken = (() => {
|
|
|
165
183
|
range: [e.endIndex - 2, e.endIndex - 1],
|
|
166
184
|
text: '',
|
|
167
185
|
};
|
|
168
|
-
if (
|
|
186
|
+
if (tagType === 1) {
|
|
169
187
|
if (computeEditInfo) {
|
|
170
188
|
e.suggestions = [open, noSelfClosing];
|
|
171
189
|
}
|
|
172
190
|
}
|
|
173
191
|
else if (closing) {
|
|
174
|
-
e.fix =
|
|
192
|
+
e.fix = tagType === 2 ? open : noSelfClosing;
|
|
175
193
|
}
|
|
176
194
|
else if (computeEditInfo) {
|
|
177
195
|
e.suggestions = [
|
package/dist/src/tag/index.js
CHANGED
|
@@ -34,11 +34,6 @@ class TagToken extends index_1.Token {
|
|
|
34
34
|
return `<${this.#closing ? '/' : ''}${this.#tag}${super.toString(skip)}${this.selfClosing ? '/' : ''}>`;
|
|
35
35
|
}
|
|
36
36
|
/** @private */
|
|
37
|
-
text(separator = '') {
|
|
38
|
-
const { closing } = this;
|
|
39
|
-
return `<${closing && !separator ? '/' : ''}${this.#tag}${closing ? '' : super.text()}${separator}>`;
|
|
40
|
-
}
|
|
41
|
-
/** @private */
|
|
42
37
|
getAttribute(key) {
|
|
43
38
|
return key === 'padding'
|
|
44
39
|
? this.#tag.length + (this.#closing ? 2 : 1)
|
|
@@ -51,8 +46,9 @@ class TagToken extends index_1.Token {
|
|
|
51
46
|
*/
|
|
52
47
|
findMatchingTag() {
|
|
53
48
|
LINT: return (0, lint_1.cache)(this.#match, () => {
|
|
54
|
-
const { type, name,
|
|
55
|
-
|
|
49
|
+
const { type, name, closing, selfClosing, } = this;
|
|
50
|
+
// eslint-disable-next-line prefer-const
|
|
51
|
+
let { parentNode } = this, isVoid = false, isFlexible = false;
|
|
56
52
|
if (type === 'html') {
|
|
57
53
|
const [, flexibleTags, voidTags] = this.getAttribute('config').html;
|
|
58
54
|
isVoid = voidTags.includes(name);
|
|
@@ -65,27 +61,32 @@ class TagToken extends index_1.Token {
|
|
|
65
61
|
if (!parentNode) {
|
|
66
62
|
return undefined;
|
|
67
63
|
}
|
|
68
|
-
const { childNodes } = parentNode, i = childNodes.indexOf(this), siblings = closing ? childNodes.slice(0, i)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
64
|
+
const { childNodes } = parentNode, i = childNodes.indexOf(this), siblings = closing ? childNodes.slice(0, i) : childNodes.slice(i + 1).reverse(), stack = [this], { rev } = debug_1.Shadow;
|
|
65
|
+
let cur = siblings.pop();
|
|
66
|
+
while (cur) {
|
|
67
|
+
// eslint-disable-next-line no-empty, @typescript-eslint/no-unnecessary-condition
|
|
68
|
+
if (!cur) {
|
|
69
|
+
}
|
|
70
|
+
else if (!cur.is(type)
|
|
71
|
+
|| type === 'html' && (cur.name !== name || isFlexible && cur.selfClosing)) {
|
|
72
|
+
//
|
|
73
73
|
}
|
|
74
|
-
else if (
|
|
74
|
+
else if (cur.#closing === closing) {
|
|
75
75
|
/* c8 ignore next 3 */
|
|
76
76
|
if (type === 'tvar') {
|
|
77
77
|
return undefined;
|
|
78
78
|
}
|
|
79
|
-
stack.push(
|
|
79
|
+
stack.push(cur);
|
|
80
80
|
}
|
|
81
81
|
else {
|
|
82
82
|
const top = stack.pop();
|
|
83
83
|
if (top === this) {
|
|
84
|
-
return
|
|
84
|
+
return cur;
|
|
85
85
|
}
|
|
86
|
-
top.#match = [rev,
|
|
87
|
-
|
|
86
|
+
top.#match = [rev, cur];
|
|
87
|
+
cur.#match = [rev, top];
|
|
88
88
|
}
|
|
89
|
+
cur = siblings.pop();
|
|
89
90
|
}
|
|
90
91
|
for (const token of stack) {
|
|
91
92
|
token.#match = [rev, undefined];
|
package/dist/src/tagPair/ext.js
CHANGED
|
@@ -45,6 +45,7 @@ const attributesParent_1 = require("../../mixin/attributesParent");
|
|
|
45
45
|
const index_2 = require("../index");
|
|
46
46
|
const index_3 = require("./index");
|
|
47
47
|
const attributes_1 = require("../attributes");
|
|
48
|
+
const nonVoidExt = new Set(['dynamicpagelist', 'templatedata', 'rss']);
|
|
48
49
|
/**
|
|
49
50
|
* extension tag
|
|
50
51
|
*
|
|
@@ -103,8 +104,6 @@ let ExtToken = (() => {
|
|
|
103
104
|
case 'combooption':
|
|
104
105
|
case 'tab':
|
|
105
106
|
case 'tabs':
|
|
106
|
-
case 'poll':
|
|
107
|
-
case 'seo':
|
|
108
107
|
case 'langconvert':
|
|
109
108
|
case 'phonos':
|
|
110
109
|
switch (lcName) {
|
|
@@ -123,6 +122,12 @@ let ExtToken = (() => {
|
|
|
123
122
|
}
|
|
124
123
|
innerToken = new index_2.Token(inner, newConfig, accum);
|
|
125
124
|
break;
|
|
125
|
+
case 'poll': {
|
|
126
|
+
const { MultiLineToken } = require('../multiLine/index');
|
|
127
|
+
// @ts-expect-error abstract class
|
|
128
|
+
innerToken = new MultiLineToken(inner, newConfig, accum);
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
126
131
|
case 'dynamicpagelist': {
|
|
127
132
|
const { ParamTagToken } = require('../multiLine/paramTag');
|
|
128
133
|
// @ts-expect-error abstract class
|
|
@@ -181,6 +186,18 @@ let ExtToken = (() => {
|
|
|
181
186
|
innerToken = new CategorytreeToken(inner, undefined, newConfig, accum);
|
|
182
187
|
break;
|
|
183
188
|
}
|
|
189
|
+
case 'seo': {
|
|
190
|
+
const { FuncTagToken } = require('../funcTag');
|
|
191
|
+
// @ts-expect-error abstract class
|
|
192
|
+
innerToken = new FuncTagToken(inner, newConfig, accum);
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
case 'charinsert': {
|
|
196
|
+
const { CharinsertToken } = require('../multiLine/charinsert');
|
|
197
|
+
// @ts-expect-error abstract class
|
|
198
|
+
innerToken = new CharinsertToken(inner, newConfig, accum);
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
184
201
|
// 更多定制扩展的代码示例:
|
|
185
202
|
// ```
|
|
186
203
|
// case 'extensionName': {
|
|
@@ -202,16 +219,40 @@ let ExtToken = (() => {
|
|
|
202
219
|
super(name, attrToken, innerToken, closed, config, accum);
|
|
203
220
|
}
|
|
204
221
|
/** @private */
|
|
222
|
+
lintRef(rect, severity) {
|
|
223
|
+
LINT: {
|
|
224
|
+
const refName = this.getAttr('name'), text = this.innerText?.trim();
|
|
225
|
+
let msg = '';
|
|
226
|
+
if (this.closest('ext#references')) {
|
|
227
|
+
if (!refName) {
|
|
228
|
+
msg = 'no-named-in-references';
|
|
229
|
+
}
|
|
230
|
+
else if (!text) {
|
|
231
|
+
msg = 'no-empty-in-references';
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
else if (!refName && !text) {
|
|
235
|
+
msg = this.hasAttr('details') ? 'ref-details' : 'ref-no-name';
|
|
236
|
+
}
|
|
237
|
+
return msg && (rect ? (0, lint_1.generateForSelf)(this, rect, 'invalid-ref', msg, severity) : msg);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
/** @private */
|
|
241
|
+
text() {
|
|
242
|
+
const { name, firstChild, lastChild, selfClosing } = this;
|
|
243
|
+
return `<${name}${firstChild.text()}${selfClosing ? '/>' : `>${lastChild.text()}</${name}>`}`;
|
|
244
|
+
}
|
|
245
|
+
/** @private */
|
|
205
246
|
lint(start = this.getAbsoluteIndex(), re) {
|
|
206
247
|
LINT: {
|
|
207
|
-
const errors = super.lint(start, re), { lintConfig } = index_1.default, rect = new rect_1.BoundingRect(this, start);
|
|
208
|
-
if (
|
|
248
|
+
const errors = super.lint(start, re), { name } = this, { lintConfig } = index_1.default, rect = new rect_1.BoundingRect(this, start);
|
|
249
|
+
if (name !== 'nowiki') {
|
|
209
250
|
const s = this.inHtmlAttrs(), rule = 'parsing-order', severity = s && lintConfig.getSeverity(rule, s === 2 ? 'ext' : 'templateInTable');
|
|
210
251
|
if (severity) {
|
|
211
252
|
errors.push((0, lint_1.generateForSelf)(this, rect, rule, 'ext-in-html', severity));
|
|
212
253
|
}
|
|
213
254
|
}
|
|
214
|
-
if (
|
|
255
|
+
if (name === 'ref') {
|
|
215
256
|
let rule = 'var-anchor', s = lintConfig.getSeverity(rule, 'ref');
|
|
216
257
|
if (s && this.closest('heading-title')) {
|
|
217
258
|
errors.push((0, lint_1.generateForSelf)(this, rect, rule, 'variable-anchor', s));
|
|
@@ -221,6 +262,19 @@ let ExtToken = (() => {
|
|
|
221
262
|
if (s && this.closest('link-text,ext-link-text')) {
|
|
222
263
|
errors.push((0, lint_1.generateForSelf)(this, rect, rule, 'ref-in-link', s));
|
|
223
264
|
}
|
|
265
|
+
s = lintConfig.getSeverity('invalid-ref');
|
|
266
|
+
if (s) {
|
|
267
|
+
const e = this.lintRef(rect, s);
|
|
268
|
+
if (e) {
|
|
269
|
+
errors.push(e);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
const rule = 'void-ext', s = lintConfig.getSeverity(rule, name);
|
|
275
|
+
if (s && nonVoidExt.has(name) && !this.innerText) {
|
|
276
|
+
errors.push((0, lint_1.generateForSelf)(this, { start }, rule, index_1.default.msg('no-empty', name), s));
|
|
277
|
+
}
|
|
224
278
|
}
|
|
225
279
|
return errors;
|
|
226
280
|
}
|
|
@@ -88,16 +88,7 @@ let TagPairToken = (() => {
|
|
|
88
88
|
/** @private */
|
|
89
89
|
toString(skip) {
|
|
90
90
|
const { firstChild, lastChild, } = this, [opening, closing] = this.#tags;
|
|
91
|
-
return this.#selfClosing
|
|
92
|
-
? `<${opening}${firstChild.toString(skip)}/>`
|
|
93
|
-
: `<${opening}${firstChild.toString(skip)}>${lastChild.toString(skip)}${this.closed ? `</${closing}>` : ''}`;
|
|
94
|
-
}
|
|
95
|
-
/** @private */
|
|
96
|
-
text() {
|
|
97
|
-
const [opening, closing] = this.#tags;
|
|
98
|
-
return this.#selfClosing
|
|
99
|
-
? `<${opening}${this.firstChild.text()}/>`
|
|
100
|
-
: `<${opening}${super.text('>')}${this.closed ? `</${closing}>` : ''}`;
|
|
91
|
+
return `<${opening}${firstChild.toString(skip)}${this.#selfClosing ? '/>' : `>${lastChild.toString(skip)}${this.closed ? `</${closing}>` : ''}`}`;
|
|
101
92
|
}
|
|
102
93
|
/** @private */
|
|
103
94
|
getAttribute(key) {
|
package/dist/src/transclude.js
CHANGED
|
@@ -129,9 +129,7 @@ let TranscludeToken = (() => {
|
|
|
129
129
|
}
|
|
130
130
|
const colon = title.search(/[::]/u), fullWidth = title[colon] === ':', isFunction = colon !== -1;
|
|
131
131
|
if (isFunction || parts.length === 0 && !this.#raw) {
|
|
132
|
-
const magicWord = isFunction ? title.slice(0, colon) : title, arg = isFunction && title.slice(colon + 1), cleaned = (0, string_1.removeComment)(magicWord), name = isFunction
|
|
133
|
-
? cleaned.slice(cleaned.search(/\S/u)) + (fullWidth ? ':' : '')
|
|
134
|
-
: cleaned.trim(),
|
|
132
|
+
const magicWord = isFunction ? title.slice(0, colon) : title, arg = isFunction && title.slice(colon + 1), cleaned = (0, string_1.removeComment)(magicWord), name = isFunction ? (0, string_1.trimStart)(cleaned) + (fullWidth ? ':' : '') : cleaned.trim(),
|
|
135
133
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
136
134
|
[, isSensitive, canonicalName] = (0, debug_1.getMagicWordInfo)(name, parserFunction), isFunc = !('functionHook' in config) || functionHook.includes(canonicalName), isVar = variable.includes(canonicalName);
|
|
137
135
|
if (isFunction ? canonicalName && isFunc : isVar) {
|
|
@@ -254,11 +252,11 @@ let TranscludeToken = (() => {
|
|
|
254
252
|
if (type === 'magic-word' && name === 'vardefine') {
|
|
255
253
|
return '';
|
|
256
254
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
255
|
+
const delimiter = type === 'magic-word' ? this.#colon : '|';
|
|
256
|
+
return `{{${modifier.trim().toLowerCase()}${firstChild.text().trim()}${length === 1 ? '' : delimiter}${childNodes.slice(1).map(child => {
|
|
257
|
+
const str = child.text();
|
|
258
|
+
return child.type === 'parameter' ? str : str.trim();
|
|
259
|
+
}).join('|')}}}`;
|
|
262
260
|
}
|
|
263
261
|
/** @private */
|
|
264
262
|
getAttribute(key) {
|
|
@@ -312,15 +310,17 @@ let TranscludeToken = (() => {
|
|
|
312
310
|
s = lintConfig.getSeverity(rule, 'parameter');
|
|
313
311
|
if (s) {
|
|
314
312
|
const duplicatedArgs = this.getDuplicatedArgs()
|
|
315
|
-
.filter(([, parameter]) => !parameter[0].querySelector('ext'))
|
|
313
|
+
.filter(([, parameter]) => !parameter[0].querySelector('ext'));
|
|
316
314
|
for (const [, args] of duplicatedArgs) {
|
|
317
|
-
Array.
|
|
318
|
-
|
|
315
|
+
const duplication = Array.from({ length: args.length });
|
|
316
|
+
for (let i = args.length - 1; i >= 0; i--) {
|
|
317
|
+
const arg = args[i], e = (0, lint_1.generateForChild)(arg, rect, rule, 'duplicate-parameter', s);
|
|
319
318
|
if (computeEditInfo) {
|
|
320
319
|
e.suggestions = [(0, lint_1.fixByRemove)(e, -1)];
|
|
321
320
|
}
|
|
322
|
-
|
|
323
|
-
}
|
|
321
|
+
duplication[i] = e;
|
|
322
|
+
}
|
|
323
|
+
Array.prototype.push.apply(errors, duplication);
|
|
324
324
|
}
|
|
325
325
|
}
|
|
326
326
|
return errors;
|
package/dist/util/sharable.js
CHANGED
|
@@ -276,4 +276,26 @@ exports.extParams = (() => ({
|
|
|
276
276
|
'tour',
|
|
277
277
|
'arialabel',
|
|
278
278
|
],
|
|
279
|
+
seo: [
|
|
280
|
+
'hreflang_$1',
|
|
281
|
+
'title',
|
|
282
|
+
'title_mode',
|
|
283
|
+
'title_separator',
|
|
284
|
+
'keywords',
|
|
285
|
+
'description',
|
|
286
|
+
'canonical',
|
|
287
|
+
'robots',
|
|
288
|
+
'googlebot',
|
|
289
|
+
'image',
|
|
290
|
+
'image_width',
|
|
291
|
+
'image_height',
|
|
292
|
+
'image_alt',
|
|
293
|
+
'type',
|
|
294
|
+
'site_name',
|
|
295
|
+
'locale',
|
|
296
|
+
'section',
|
|
297
|
+
'author',
|
|
298
|
+
'published_time',
|
|
299
|
+
'twitter_site',
|
|
300
|
+
],
|
|
279
301
|
}))();
|
package/dist/util/sharable.mjs
CHANGED
|
@@ -273,6 +273,28 @@ const extParams = /* @__PURE__ */ (() => ({
|
|
|
273
273
|
"searchfilter",
|
|
274
274
|
"tour",
|
|
275
275
|
"arialabel"
|
|
276
|
+
],
|
|
277
|
+
seo: [
|
|
278
|
+
"hreflang_$1",
|
|
279
|
+
"title",
|
|
280
|
+
"title_mode",
|
|
281
|
+
"title_separator",
|
|
282
|
+
"keywords",
|
|
283
|
+
"description",
|
|
284
|
+
"canonical",
|
|
285
|
+
"robots",
|
|
286
|
+
"googlebot",
|
|
287
|
+
"image",
|
|
288
|
+
"image_width",
|
|
289
|
+
"image_height",
|
|
290
|
+
"image_alt",
|
|
291
|
+
"type",
|
|
292
|
+
"site_name",
|
|
293
|
+
"locale",
|
|
294
|
+
"section",
|
|
295
|
+
"author",
|
|
296
|
+
"published_time",
|
|
297
|
+
"twitter_site"
|
|
276
298
|
]
|
|
277
299
|
}))();
|
|
278
300
|
export {
|
package/dist/util/string.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.decodeNumber = exports.decodeHtml = exports.decodeHtmlBasic = exports.text = exports.removeComment = exports.tidy = exports.trimLc = exports.extUrlChar = exports.extUrlCharFirst = exports.zs = void 0;
|
|
3
|
+
exports.toLowerCase = exports.decodeNumber = exports.decodeHtml = exports.decodeHtmlBasic = exports.text = exports.removeCommentLine = exports.removeComment = exports.tidy = exports.trimStart = exports.trimLc = exports.extUrlChar = exports.extUrlCharFirst = exports.zs = void 0;
|
|
4
4
|
exports.restore = restore;
|
|
5
|
+
const common_1 = require("@bhsd/common");
|
|
5
6
|
exports.zs = String.raw ` \xA0\u1680\u2000-\u200A\u202F\u205F\u3000`;
|
|
6
7
|
const commonExtUrlChar = String.raw `[^[\]<>"\0-\x1F\x7F${exports.zs}\uFFFD]`;
|
|
7
8
|
exports.extUrlCharFirst = String.raw `(?:\[[\da-f:.]+\]|${commonExtUrlChar})`;
|
|
@@ -12,6 +13,12 @@ exports.extUrlChar = String.raw `(?:${commonExtUrlChar}|\0\d+[cn!~]\x7F)*`;
|
|
|
12
13
|
*/
|
|
13
14
|
const trimLc = (s) => s.trim().toLowerCase();
|
|
14
15
|
exports.trimLc = trimLc;
|
|
16
|
+
/**
|
|
17
|
+
* trim starting whitespaces
|
|
18
|
+
* @param s 字符串
|
|
19
|
+
*/
|
|
20
|
+
const trimStart = (s) => s.slice((0, common_1.numLeadingSpaces)(s));
|
|
21
|
+
exports.trimStart = trimStart;
|
|
15
22
|
function restore(s, stack, translate) {
|
|
16
23
|
if (translate === 1) {
|
|
17
24
|
return s.replace(/\0(\d+)g\x7F/gu, (_, p1) => restore(String(stack[p1]), stack, 2));
|
|
@@ -31,6 +38,24 @@ const factory = (regex, replace) => (str) => str.replace(regex, replace);
|
|
|
31
38
|
exports.tidy = factory(/[\0\x7F]|\r$/gmu, '');
|
|
32
39
|
/** remove half-parsed comment-like tokens */
|
|
33
40
|
exports.removeComment = factory(/\0\d+[cn]\x7F/gu, '');
|
|
41
|
+
/**
|
|
42
|
+
* remove lines that only contain comments
|
|
43
|
+
* @param str
|
|
44
|
+
* @param standalone whether for a standalone document
|
|
45
|
+
*/
|
|
46
|
+
const removeCommentLine = (str, standalone) => {
|
|
47
|
+
const lines = str.split('\n'), { length } = lines;
|
|
48
|
+
if (!standalone && length < 3) {
|
|
49
|
+
return (0, exports.removeComment)(str);
|
|
50
|
+
}
|
|
51
|
+
const offset = standalone ? 0 : 1, end = length - offset;
|
|
52
|
+
return (0, exports.removeComment)([
|
|
53
|
+
...lines.slice(0, offset),
|
|
54
|
+
...lines.slice(offset, end).filter(line => !/^(?!\s*$)(?:\s|\0\d+c\x7F)*$/u.test(line)),
|
|
55
|
+
...lines.slice(end),
|
|
56
|
+
].join('\n'));
|
|
57
|
+
};
|
|
58
|
+
exports.removeCommentLine = removeCommentLine;
|
|
34
59
|
/**
|
|
35
60
|
* extract effective wikitext
|
|
36
61
|
* @param childNodes a Token's contents
|
|
@@ -52,7 +77,7 @@ const decodeHtml = (str) => {
|
|
|
52
77
|
decodeHtmlResolved ??= (() => {
|
|
53
78
|
/* NOT FOR BROWSER ONLY */
|
|
54
79
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
55
|
-
if (typeof process === 'object' && typeof process.versions?.node === 'string') {
|
|
80
|
+
NPM: if (typeof process === 'object' && typeof process.versions?.node === 'string') {
|
|
56
81
|
try {
|
|
57
82
|
const { decodeHTMLStrict } = require('entities');
|
|
58
83
|
return (s) => decodeHTMLStrict(s).replaceAll('\xA0', ' ');
|
|
@@ -68,3 +93,9 @@ const decodeHtml = (str) => {
|
|
|
68
93
|
exports.decodeHtml = decodeHtml;
|
|
69
94
|
/** decode numbered HTML entities */
|
|
70
95
|
exports.decodeNumber = factory(/&#(\d+|x[\da-f]+);/giu, (_, code) => String.fromCodePoint(Number((/^x/iu.test(code) ? '0' : '') + code)));
|
|
96
|
+
/**
|
|
97
|
+
* Convert an array of strings to lowercase
|
|
98
|
+
* @param str array of strings
|
|
99
|
+
*/
|
|
100
|
+
const toLowerCase = (str) => str.map(s => s.toLowerCase());
|
|
101
|
+
exports.toLowerCase = toLowerCase;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/**
|
|
4
|
+
* 二分法查找索引
|
|
5
|
+
* @param haystack 数组
|
|
6
|
+
* @param needle 目标值
|
|
7
|
+
* @param comparator 比较函数
|
|
8
|
+
* @author The Dark Sky Company, LLC <support@darkskyapp.com>
|
|
9
|
+
* @license CC0-1.0
|
|
10
|
+
* @see https://github.com/darkskyapp/binary-search/blob/master/index.js
|
|
11
|
+
*/
|
|
12
|
+
exports.default = (haystack, needle, comparator) => {
|
|
13
|
+
let low = 0, high = haystack.length - 1;
|
|
14
|
+
while (low <= high) {
|
|
15
|
+
// The naive `low + high >>> 1` could fail for array lengths > 2**31
|
|
16
|
+
// because `>>>` converts its operands to int32. `low + (high - low >>> 1)`
|
|
17
|
+
// works for array lengths <= 2**32-1 which is also Javascript's max array
|
|
18
|
+
// length.
|
|
19
|
+
const mid = low + (high - low >>> 1), // eslint-disable-line no-bitwise
|
|
20
|
+
cmp = comparator(haystack[mid], needle);
|
|
21
|
+
if (cmp < 0) {
|
|
22
|
+
low = mid + 1;
|
|
23
|
+
}
|
|
24
|
+
else if (cmp > 0) {
|
|
25
|
+
high = mid - 1;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
// Key found.
|
|
29
|
+
return mid;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
// Key not found.
|
|
33
|
+
return low;
|
|
34
|
+
};
|