wikiparser-node 1.13.9 → 1.14.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/bundle/bundle.min.js +31 -31
- package/dist/addon/transclude.js +10 -1
- package/dist/base.d.ts +1 -3
- package/dist/lib/text.js +15 -23
- package/dist/src/arg.js +3 -11
- package/dist/src/attribute.js +8 -19
- package/dist/src/attributes.js +20 -10
- package/dist/src/converterFlags.js +1 -7
- package/dist/src/gallery.js +2 -10
- package/dist/src/heading.js +41 -7
- package/dist/src/html.js +47 -27
- package/dist/src/imageParameter.js +3 -1
- package/dist/src/imagemap.js +8 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +12 -24
- package/dist/src/link/base.js +7 -4
- package/dist/src/link/file.js +5 -1
- package/dist/src/link/galleryImage.js +3 -1
- package/dist/src/magicLink.js +3 -17
- package/dist/src/nested.js +2 -10
- package/dist/src/nowiki/comment.js +1 -1
- package/dist/src/nowiki/quote.js +10 -8
- package/dist/src/paramTag/index.js +1 -7
- package/dist/src/tagPair/include.js +2 -14
- package/dist/src/transclude.js +5 -1
- package/extensions/dist/base.js +1 -1
- package/i18n/zh-hans.json +1 -1
- package/i18n/zh-hant.json +1 -1
- package/package.json +2 -2
package/dist/addon/transclude.js
CHANGED
|
@@ -94,7 +94,16 @@ transclude_1.TranscludeToken.prototype.fixDuplication =
|
|
|
94
94
|
if (args.length <= 1) {
|
|
95
95
|
continue;
|
|
96
96
|
}
|
|
97
|
-
const values = Map
|
|
97
|
+
const values = new Map();
|
|
98
|
+
for (const arg of args) {
|
|
99
|
+
const val = arg.getValue().trim();
|
|
100
|
+
if (values.has(val)) {
|
|
101
|
+
values.get(val).push(arg);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
values.set(val, [arg]);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
98
107
|
let noMoreAnon = anonCount === 0 || !key.trim() || isNaN(key);
|
|
99
108
|
const emptyArgs = values.get('') ?? [], duplicatedArgs = [...values].filter(([val, { length }]) => val && length > 1).flatMap(([, curArgs]) => {
|
|
100
109
|
const anonIndex = noMoreAnon ? -1 : curArgs.findIndex(({ anon }) => anon);
|
package/dist/base.d.ts
CHANGED
|
@@ -63,9 +63,7 @@ export interface LintError {
|
|
|
63
63
|
endLine: number;
|
|
64
64
|
endCol: number;
|
|
65
65
|
fix?: LintError.Fix;
|
|
66
|
-
suggestions?:
|
|
67
|
-
desc: string;
|
|
68
|
-
})[];
|
|
66
|
+
suggestions?: LintError.Fix[];
|
|
69
67
|
}
|
|
70
68
|
export type AST = Record<string, string | number | boolean> & {
|
|
71
69
|
range: [number, number];
|
package/dist/lib/text.js
CHANGED
|
@@ -148,7 +148,7 @@ class AstText extends node_1.AstNode {
|
|
|
148
148
|
return [];
|
|
149
149
|
}
|
|
150
150
|
errorRegex.lastIndex = 0;
|
|
151
|
-
const errors = [], nextType = nextSibling?.type, nextName = nextSibling?.name, previousType = previousSibling?.type, root = this.getRootNode(), { ext, html } = root.getAttribute('config'), { top, left } = root.posFromIndex(start), tags = new Set(['onlyinclude', 'noinclude', 'includeonly', ext, html, disallowedTags].flat(2));
|
|
151
|
+
const errors = [], nextType = nextSibling?.type, nextName = nextSibling?.name, previousType = previousSibling?.type, root = this.getRootNode(), rootStr = root.toString(), { ext, html } = root.getAttribute('config'), { top, left } = root.posFromIndex(start), tags = new Set(['onlyinclude', 'noinclude', 'includeonly', ext, html, disallowedTags].flat(2));
|
|
152
152
|
for (let mt = errorRegex.exec(data); mt; mt = errorRegex.exec(data)) {
|
|
153
153
|
const [, tag, prefix] = mt;
|
|
154
154
|
let { index } = mt, error = mt[0].toLowerCase();
|
|
@@ -168,7 +168,7 @@ class AstText extends node_1.AstNode {
|
|
|
168
168
|
else if (char === ']' && (index || length > 1)) {
|
|
169
169
|
errorRegex.lastIndex--;
|
|
170
170
|
}
|
|
171
|
-
const startIndex = start + index, endIndex = startIndex + length,
|
|
171
|
+
const startIndex = start + index, endIndex = startIndex + length, nextChar = rootStr[endIndex], previousChar = rootStr[startIndex - 1], severity = length > 1 && !(char === '<' && !/[\s/>]/u.test(nextChar ?? '')
|
|
172
172
|
|| isHtmlAttrVal && (char === '[' || char === ']')
|
|
173
173
|
|| magicLink && type === 'parameter-value')
|
|
174
174
|
|| char === '{' && (nextChar === char || previousChar === '-')
|
|
@@ -213,39 +213,31 @@ class AstText extends node_1.AstNode {
|
|
|
213
213
|
endCol: startCol + length,
|
|
214
214
|
};
|
|
215
215
|
if (char === '<') {
|
|
216
|
-
e.suggestions = [
|
|
217
|
-
{
|
|
218
|
-
desc: 'escape',
|
|
219
|
-
range: [startIndex, startIndex + 1],
|
|
220
|
-
text: '<',
|
|
221
|
-
},
|
|
222
|
-
];
|
|
216
|
+
e.suggestions = [{ desc: 'escape', range: [startIndex, startIndex + 1], text: '<' }];
|
|
223
217
|
}
|
|
224
218
|
else if (char === 'h'
|
|
225
219
|
&& !(type === 'ext-link-text' || type === 'link-text')
|
|
226
220
|
&& /[\p{L}\d_]/u.test(previousChar || '')) {
|
|
227
|
-
e.suggestions = [
|
|
228
|
-
{
|
|
229
|
-
desc: 'whitespace',
|
|
230
|
-
range: [startIndex, startIndex],
|
|
231
|
-
text: ' ',
|
|
232
|
-
},
|
|
233
|
-
];
|
|
221
|
+
e.suggestions = [{ desc: 'whitespace', range: [startIndex, startIndex], text: ' ' }];
|
|
234
222
|
}
|
|
235
223
|
else if (char === '[' && type === 'ext-link-text') {
|
|
236
224
|
const i = parentNode.getAbsoluteIndex() + parentNode.toString().length;
|
|
237
|
-
e.suggestions = [
|
|
238
|
-
{
|
|
239
|
-
desc: 'escape',
|
|
240
|
-
range: [i, i + 1],
|
|
241
|
-
text: ']',
|
|
242
|
-
},
|
|
243
|
-
];
|
|
225
|
+
e.suggestions = [{ desc: 'escape', range: [i, i + 1], text: ']' }];
|
|
244
226
|
}
|
|
245
227
|
else if (char === ']' && previousType === 'free-ext-link' && severity === 'error') {
|
|
246
228
|
const i = start - previousSibling.toString().length;
|
|
247
229
|
e.fix = { range: [i, i], text: '[', desc: 'left bracket' };
|
|
248
230
|
}
|
|
231
|
+
else if (magicLink) {
|
|
232
|
+
e.suggestions = [
|
|
233
|
+
...mt[0] === error
|
|
234
|
+
? []
|
|
235
|
+
: [{ desc: 'uppercase', range: [startIndex, endIndex], text: error }],
|
|
236
|
+
...nextChar === ':' || nextChar === ':'
|
|
237
|
+
? [{ desc: 'whitespace', range: [endIndex, endIndex + 1], text: ' ' }]
|
|
238
|
+
: [],
|
|
239
|
+
];
|
|
240
|
+
}
|
|
249
241
|
errors.push(e);
|
|
250
242
|
}
|
|
251
243
|
return errors;
|
package/dist/src/arg.js
CHANGED
|
@@ -95,7 +95,7 @@ class ArgToken extends index_2.Token {
|
|
|
95
95
|
if (!this.getAttribute('include')) {
|
|
96
96
|
const e = (0, lint_1.generateForSelf)(this, { start }, 'no-arg', 'unexpected template argument');
|
|
97
97
|
if (argDefault) {
|
|
98
|
-
e.
|
|
98
|
+
e.suggestions = [{ range: [start, e.endIndex], text: argDefault.text(), desc: 'expand' }];
|
|
99
99
|
}
|
|
100
100
|
return [e];
|
|
101
101
|
}
|
|
@@ -110,16 +110,8 @@ class ArgToken extends index_2.Token {
|
|
|
110
110
|
e.startIndex--;
|
|
111
111
|
e.startCol--;
|
|
112
112
|
e.suggestions = [
|
|
113
|
-
{
|
|
114
|
-
|
|
115
|
-
range: [e.startIndex, e.endIndex],
|
|
116
|
-
text: '',
|
|
117
|
-
},
|
|
118
|
-
{
|
|
119
|
-
desc: 'escape',
|
|
120
|
-
range: [e.startIndex, e.startIndex + 1],
|
|
121
|
-
text: '{{!}}',
|
|
122
|
-
},
|
|
113
|
+
{ desc: 'remove', range: [e.startIndex, e.endIndex], text: '' },
|
|
114
|
+
{ desc: 'escape', range: [e.startIndex, e.startIndex + 1], text: '{{!}}' },
|
|
123
115
|
];
|
|
124
116
|
return e;
|
|
125
117
|
}));
|
package/dist/src/attribute.js
CHANGED
|
@@ -180,16 +180,10 @@ let AttributeToken = (() => {
|
|
|
180
180
|
const e = (0, lint_1.generateForChild)(lastChild, rect, 'unclosed-quote', index_1.default.msg('unclosed $1', 'quotes'), 'warning');
|
|
181
181
|
e.startIndex--;
|
|
182
182
|
e.startCol--;
|
|
183
|
-
|
|
184
|
-
if (lastChild.childNodes.some(({ type: t, data }) => t === 'text' && /\s/u.test(data))) {
|
|
185
|
-
e.suggestions = [fix];
|
|
186
|
-
}
|
|
187
|
-
else {
|
|
188
|
-
e.fix = fix;
|
|
189
|
-
}
|
|
183
|
+
e.suggestions = [{ range: [e.endIndex, e.endIndex], text: this.#quotes[0], desc: 'close' }];
|
|
190
184
|
errors.push(e);
|
|
191
185
|
}
|
|
192
|
-
const attrs = sharable_1.extAttrs[tag], attrs2 = sharable_1.htmlAttrs[tag];
|
|
186
|
+
const attrs = sharable_1.extAttrs[tag], attrs2 = sharable_1.htmlAttrs[tag], { length } = this.toString();
|
|
193
187
|
if (!attrs?.has(name)
|
|
194
188
|
&& !attrs2?.has(name)
|
|
195
189
|
// 不是未定义的扩展标签或包含嵌入的HTML标签
|
|
@@ -197,7 +191,10 @@ let AttributeToken = (() => {
|
|
|
197
191
|
&& (type === 'ext-attr' && !attrs2
|
|
198
192
|
|| !/^(?:xmlns:[\w:.-]+|data-(?!ooui|mw|parsoid)[^:]*)$/u.test(name)
|
|
199
193
|
&& (tag === 'meta' || tag === 'link' || !sharable_1.commonHtmlAttrs.has(name)))) {
|
|
200
|
-
errors.push(
|
|
194
|
+
errors.push({
|
|
195
|
+
...(0, lint_1.generateForChild)(firstChild, rect, 'illegal-attr', 'illegal attribute name'),
|
|
196
|
+
suggestions: [{ desc: 'remove', range: [start, start + length], text: '' }],
|
|
197
|
+
});
|
|
201
198
|
}
|
|
202
199
|
else if (sharable_1.obsoleteAttrs[tag]?.has(name)) {
|
|
203
200
|
errors.push((0, lint_1.generateForChild)(firstChild, rect, 'obsolete-attr', 'obsolete attribute', 'warning'));
|
|
@@ -208,16 +205,8 @@ let AttributeToken = (() => {
|
|
|
208
205
|
else if (name === 'tabindex' && typeof value === 'string' && value !== '0') {
|
|
209
206
|
const e = (0, lint_1.generateForChild)(lastChild, rect, 'illegal-attr', 'nonzero tabindex');
|
|
210
207
|
e.suggestions = [
|
|
211
|
-
{
|
|
212
|
-
|
|
213
|
-
range: [start, e.endIndex],
|
|
214
|
-
text: '',
|
|
215
|
-
},
|
|
216
|
-
{
|
|
217
|
-
desc: '0 tabindex',
|
|
218
|
-
range: [e.startIndex, e.endIndex],
|
|
219
|
-
text: '0',
|
|
220
|
-
},
|
|
208
|
+
{ desc: 'remove', range: [start, start + length], text: '' },
|
|
209
|
+
{ desc: '0 tabindex', range: [e.startIndex, e.endIndex], text: '0' },
|
|
221
210
|
];
|
|
222
211
|
errors.push(e);
|
|
223
212
|
}
|
package/dist/src/attributes.js
CHANGED
|
@@ -168,8 +168,11 @@ class AttributesToken extends index_2.Token {
|
|
|
168
168
|
lint(start = this.getAbsoluteIndex(), re) {
|
|
169
169
|
const errors = super.lint(start, re), { parentNode, childNodes } = this, attrs = new Map(), duplicated = new Set(), rect = new rect_1.BoundingRect(this, start);
|
|
170
170
|
if (parentNode?.type === 'html' && parentNode.closing && this.text().trim()) {
|
|
171
|
-
const e = (0, lint_1.generateForSelf)(this, rect, 'no-ignored', 'attributes of a closing tag');
|
|
172
|
-
e.
|
|
171
|
+
const e = (0, lint_1.generateForSelf)(this, rect, 'no-ignored', 'attributes of a closing tag'), index = parentNode.getAbsoluteIndex();
|
|
172
|
+
e.suggestions = [
|
|
173
|
+
{ desc: 'remove', range: [start, e.endIndex], text: '' },
|
|
174
|
+
{ desc: 'open', range: [index + 1, index + 2], text: '' },
|
|
175
|
+
];
|
|
173
176
|
errors.push(e);
|
|
174
177
|
}
|
|
175
178
|
for (const attr of childNodes) {
|
|
@@ -187,20 +190,27 @@ class AttributesToken extends index_2.Token {
|
|
|
187
190
|
const str = attr.text().trim();
|
|
188
191
|
if (str) {
|
|
189
192
|
const e = (0, lint_1.generateForChild)(attr, rect, 'no-ignored', 'containing invalid attribute', /[\p{L}\d]/u.test(str) ? 'error' : 'warning');
|
|
190
|
-
e.suggestions = [
|
|
191
|
-
{
|
|
192
|
-
desc: 'remove',
|
|
193
|
-
range: [e.startIndex, e.endIndex],
|
|
194
|
-
text: ' ',
|
|
195
|
-
},
|
|
196
|
-
];
|
|
193
|
+
e.suggestions = [{ desc: 'remove', range: [e.startIndex, e.endIndex], text: ' ' }];
|
|
197
194
|
errors.push(e);
|
|
198
195
|
}
|
|
199
196
|
}
|
|
200
197
|
}
|
|
201
198
|
if (duplicated.size > 0) {
|
|
202
199
|
for (const key of duplicated) {
|
|
203
|
-
|
|
200
|
+
const pairs = attrs.get(key).map(attr => {
|
|
201
|
+
const value = attr.getValue();
|
|
202
|
+
return [attr, value === true ? '' : value];
|
|
203
|
+
});
|
|
204
|
+
errors.push(...pairs.map(([attr, value], i) => {
|
|
205
|
+
const e = (0, lint_1.generateForChild)(attr, rect, 'no-duplicate', index_1.default.msg('duplicated $1 attribute', key)), remove = { desc: 'remove', range: [e.startIndex, e.endIndex], text: '' };
|
|
206
|
+
if (!value || pairs.slice(0, i).some(([, v]) => v === value)) {
|
|
207
|
+
e.fix = remove;
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
e.suggestions = [remove];
|
|
211
|
+
}
|
|
212
|
+
return e;
|
|
213
|
+
}));
|
|
204
214
|
}
|
|
205
215
|
}
|
|
206
216
|
return errors;
|
|
@@ -91,13 +91,7 @@ class ConverterFlagsToken extends index_2.Token {
|
|
|
91
91
|
e.fix = { range: [e.startIndex, e.endIndex], text: flag.toUpperCase(), desc: 'uppercase' };
|
|
92
92
|
}
|
|
93
93
|
else {
|
|
94
|
-
e.suggestions = [
|
|
95
|
-
{
|
|
96
|
-
desc: 'remove',
|
|
97
|
-
range: [e.startIndex - (i && 1), e.endIndex],
|
|
98
|
-
text: '',
|
|
99
|
-
},
|
|
100
|
-
];
|
|
94
|
+
e.suggestions = [{ desc: 'remove', range: [e.startIndex - (i && 1), e.endIndex], text: '' }];
|
|
101
95
|
}
|
|
102
96
|
errors.push(e);
|
|
103
97
|
}
|
package/dist/src/gallery.js
CHANGED
|
@@ -92,16 +92,8 @@ class GalleryToken extends index_2.Token {
|
|
|
92
92
|
startCol,
|
|
93
93
|
endCol: startCol + length,
|
|
94
94
|
suggestions: [
|
|
95
|
-
{
|
|
96
|
-
|
|
97
|
-
range: [start, endIndex],
|
|
98
|
-
text: '',
|
|
99
|
-
},
|
|
100
|
-
{
|
|
101
|
-
desc: 'comment',
|
|
102
|
-
range: [start, endIndex],
|
|
103
|
-
text: `<!--${str}-->`,
|
|
104
|
-
},
|
|
95
|
+
{ desc: 'remove', range: [start, endIndex], text: '' },
|
|
96
|
+
{ desc: 'comment', range: [start, endIndex], text: `<!--${str}-->` },
|
|
105
97
|
],
|
|
106
98
|
});
|
|
107
99
|
}
|
package/dist/src/heading.js
CHANGED
|
@@ -135,21 +135,55 @@ let HeadingToken = (() => {
|
|
|
135
135
|
}
|
|
136
136
|
/** @private */
|
|
137
137
|
lint(start = this.getAbsoluteIndex(), re) {
|
|
138
|
-
const errors = super.lint(start, re), { firstChild, level } = this, innerStr = firstChild.toString(), quotes = firstChild.childNodes.filter((0, debug_1.isToken)('quote')), boldQuotes = quotes.filter(({ bold }) => bold), italicQuotes = quotes.filter(({ italic }) => italic), rect = new rect_1.BoundingRect(this, start);
|
|
138
|
+
const errors = super.lint(start, re), { firstChild, level } = this, innerStr = firstChild.toString(), unbalancedStart = innerStr.startsWith('='), unbalanced = unbalancedStart || innerStr.endsWith('='), quotes = firstChild.childNodes.filter((0, debug_1.isToken)('quote')), boldQuotes = quotes.filter(({ bold }) => bold), italicQuotes = quotes.filter(({ italic }) => italic), rect = new rect_1.BoundingRect(this, start);
|
|
139
139
|
if (this.level === 1) {
|
|
140
|
-
|
|
140
|
+
const e = (0, lint_1.generateForChild)(firstChild, rect, 'h1', '<h1>');
|
|
141
|
+
if (!unbalanced) {
|
|
142
|
+
e.suggestions = [{ desc: 'h2', range: [e.startIndex, e.endIndex], text: `=${innerStr}=` }];
|
|
143
|
+
}
|
|
144
|
+
errors.push(e);
|
|
141
145
|
}
|
|
142
|
-
if (
|
|
143
|
-
|
|
146
|
+
if (unbalanced) {
|
|
147
|
+
const e = (0, lint_1.generateForChild)(firstChild, rect, 'unbalanced-header', index_1.default.msg('unbalanced $1 in a section header', '"="'));
|
|
148
|
+
if (innerStr === '=') {
|
|
149
|
+
//
|
|
150
|
+
}
|
|
151
|
+
else if (unbalancedStart) {
|
|
152
|
+
const [extra] = /^=+/u.exec(innerStr);
|
|
153
|
+
e.suggestions = [
|
|
154
|
+
{ desc: `h${level}`, range: [e.startIndex, e.startIndex + extra.length], text: '' },
|
|
155
|
+
{ desc: `h${level + extra.length}`, range: [e.endIndex, e.endIndex], text: extra },
|
|
156
|
+
];
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
const extra = /[^=](=+)$/u.exec(innerStr)[1];
|
|
160
|
+
e.suggestions = [
|
|
161
|
+
{ desc: `h${level}`, range: [e.endIndex - extra.length, e.endIndex], text: '' },
|
|
162
|
+
{ desc: `h${level + extra.length}`, range: [e.startIndex, e.startIndex], text: extra },
|
|
163
|
+
];
|
|
164
|
+
}
|
|
165
|
+
errors.push(e);
|
|
144
166
|
}
|
|
145
167
|
if (this.closest('html-attrs,table-attrs')) {
|
|
146
168
|
errors.push((0, lint_1.generateForSelf)(this, rect, 'parsing-order', 'section header in a HTML tag'));
|
|
147
169
|
}
|
|
170
|
+
const rootStr = this.getRootNode().toString();
|
|
148
171
|
if (boldQuotes.length % 2) {
|
|
149
|
-
|
|
172
|
+
const e = (0, lint_1.generateForChild)(boldQuotes[boldQuotes.length - 1], { ...rect, start: start + level, left: rect.left + level }, 'format-leakage', index_1.default.msg('unbalanced $1 in a section header', 'bold apostrophes')), end = start + level + innerStr.length;
|
|
173
|
+
if (rootStr.slice(e.endIndex, end).trim()) {
|
|
174
|
+
e.suggestions = [{ desc: 'close', range: [end, end], text: "'''" }];
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
e.fix = { desc: 'remove', range: [e.startIndex, e.endIndex], text: '' };
|
|
178
|
+
}
|
|
179
|
+
errors.push(e);
|
|
150
180
|
}
|
|
151
181
|
if (italicQuotes.length % 2) {
|
|
152
|
-
|
|
182
|
+
const e = (0, lint_1.generateForChild)(italicQuotes[italicQuotes.length - 1], { start: start + level }, 'format-leakage', index_1.default.msg('unbalanced $1 in a section header', 'italic apostrophes')), end = start + level + innerStr.length;
|
|
183
|
+
e.fix = rootStr.slice(e.endIndex, end).trim()
|
|
184
|
+
? { desc: 'close', range: [end, end], text: "''" }
|
|
185
|
+
: { desc: 'remove', range: [e.startIndex, e.endIndex], text: '' };
|
|
186
|
+
errors.push(e);
|
|
153
187
|
}
|
|
154
188
|
return errors;
|
|
155
189
|
}
|
|
@@ -205,7 +239,7 @@ let HeadingToken = (() => {
|
|
|
205
239
|
if (headings?.has(lcId)) {
|
|
206
240
|
let i = 2;
|
|
207
241
|
for (; headings.has(`${lcId}_${i}`); i++) {
|
|
208
|
-
//
|
|
242
|
+
//
|
|
209
243
|
}
|
|
210
244
|
id = `${id}_${i}`;
|
|
211
245
|
headings.add(`${lcId}_${i}`);
|
package/dist/src/html.js
CHANGED
|
@@ -182,10 +182,15 @@ let HtmlToken = (() => {
|
|
|
182
182
|
lint(start = this.getAbsoluteIndex(), re) {
|
|
183
183
|
const errors = super.lint(start, re), rect = new rect_1.BoundingRect(this, start);
|
|
184
184
|
if (this.name === 'h1' && !this.closing) {
|
|
185
|
-
errors.push(
|
|
185
|
+
errors.push({
|
|
186
|
+
...(0, lint_1.generateForSelf)(this, rect, 'h1', '<h1>'),
|
|
187
|
+
suggestions: [{ desc: 'h2', range: [start + 2, start + 3], text: '2' }],
|
|
188
|
+
});
|
|
186
189
|
}
|
|
187
190
|
if (this.closest('table-attrs')) {
|
|
188
|
-
|
|
191
|
+
const e = (0, lint_1.generateForSelf)(this, rect, 'parsing-order', 'HTML tag in table attributes');
|
|
192
|
+
e.fix = { desc: 'remove', range: [start, e.endIndex], text: '' };
|
|
193
|
+
errors.push(e);
|
|
189
194
|
}
|
|
190
195
|
try {
|
|
191
196
|
this.findMatchingTag();
|
|
@@ -193,38 +198,53 @@ let HtmlToken = (() => {
|
|
|
193
198
|
catch (e) {
|
|
194
199
|
if (e instanceof SyntaxError) {
|
|
195
200
|
const { message } = e;
|
|
196
|
-
const msg = message.split(':')[0].toLowerCase(), error = (0, lint_1.generateForSelf)(this, rect, 'unmatched-tag', msg)
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
+
const msg = message.split(':')[0].toLowerCase(), error = (0, lint_1.generateForSelf)(this, rect, 'unmatched-tag', msg), noSelfClosing = {
|
|
202
|
+
desc: 'no self-closing',
|
|
203
|
+
range: [error.endIndex - 2, error.endIndex - 1],
|
|
204
|
+
text: '',
|
|
205
|
+
};
|
|
206
|
+
switch (msg) {
|
|
207
|
+
case 'unclosed tag': {
|
|
208
|
+
const childNodes = this.parentNode?.childNodes;
|
|
209
|
+
if (formattingTags.has(this.name)
|
|
210
|
+
&& childNodes?.slice(0, childNodes.indexOf(this))
|
|
211
|
+
.some(({ type, name }) => type === 'html' && name === this.name)) {
|
|
212
|
+
error.suggestions = [{ desc: 'close', range: [start + 1, start + 1], text: '/' }];
|
|
213
|
+
}
|
|
214
|
+
else if (!this.closest('heading-title')) {
|
|
201
215
|
error.severity = 'warning';
|
|
202
216
|
}
|
|
217
|
+
break;
|
|
203
218
|
}
|
|
204
|
-
|
|
205
|
-
|
|
219
|
+
case 'unmatched closing tag': {
|
|
220
|
+
const ancestor = this.closest('magic-word');
|
|
221
|
+
if (ancestor && magicWords.has(ancestor.name)) {
|
|
222
|
+
error.severity = 'warning';
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
error.suggestions = [{ desc: 'remove', range: [start, error.endIndex], text: '' }];
|
|
226
|
+
}
|
|
227
|
+
break;
|
|
206
228
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
229
|
+
case 'tag that is both closing and self-closing': {
|
|
230
|
+
const { html: [normalTags, , voidTags] } = this.getAttribute('config'), open = { desc: 'open', range: [start + 1, start + 2], text: '' };
|
|
231
|
+
if (voidTags.includes(this.name)) {
|
|
232
|
+
error.fix = open;
|
|
233
|
+
}
|
|
234
|
+
else if (normalTags.includes(this.name)) {
|
|
235
|
+
error.fix = noSelfClosing;
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
error.suggestions = [open, noSelfClosing];
|
|
239
|
+
}
|
|
240
|
+
break;
|
|
212
241
|
}
|
|
213
|
-
|
|
242
|
+
case 'invalid self-closing tag':
|
|
214
243
|
error.suggestions = [
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
range: [start, error.endIndex],
|
|
218
|
-
text: '',
|
|
219
|
-
},
|
|
244
|
+
noSelfClosing,
|
|
245
|
+
{ desc: 'close', range: [error.endIndex - 2, error.endIndex], text: `></${this.name}>` },
|
|
220
246
|
];
|
|
221
|
-
|
|
222
|
-
}
|
|
223
|
-
else if (msg === 'tag that is both closing and self-closing') {
|
|
224
|
-
const { html: [, , voidTags] } = this.getAttribute('config');
|
|
225
|
-
if (voidTags.includes(this.name)) {
|
|
226
|
-
error.fix = { range: [start + 1, start + 2], text: '', desc: 'open' };
|
|
227
|
-
}
|
|
247
|
+
// no default
|
|
228
248
|
}
|
|
229
249
|
errors.push(error);
|
|
230
250
|
}
|
|
@@ -185,7 +185,9 @@ class ImageParameterToken extends index_2.Token {
|
|
|
185
185
|
errors.push(e);
|
|
186
186
|
}
|
|
187
187
|
else if (typeof link === 'object' && link.encoded) {
|
|
188
|
-
|
|
188
|
+
const e = (0, lint_1.generateForSelf)(this, { start }, 'url-encoding', 'unnecessary URL encoding in an internal link');
|
|
189
|
+
e.suggestions = [{ desc: 'decode', range: [start, e.endIndex], text: (0, string_1.rawurldecode)(this.text()) }];
|
|
190
|
+
errors.push(e);
|
|
189
191
|
}
|
|
190
192
|
return errors;
|
|
191
193
|
}
|
package/dist/src/imagemap.js
CHANGED
|
@@ -101,7 +101,14 @@ class ImagemapToken extends index_2.Token {
|
|
|
101
101
|
errors.push(...this.childNodes.filter(child => {
|
|
102
102
|
const str = child.toString().trim();
|
|
103
103
|
return child.type === 'noinclude' && str && !str.startsWith('#');
|
|
104
|
-
}).map(child =>
|
|
104
|
+
}).map(child => {
|
|
105
|
+
const e = (0, lint_1.generateForChild)(child, rect, 'invalid-imagemap', 'invalid link in <imagemap>');
|
|
106
|
+
e.suggestions = [
|
|
107
|
+
{ desc: 'remove', range: [e.startIndex - 1, e.endIndex], text: '' },
|
|
108
|
+
{ desc: 'comment', range: [e.startIndex, e.startIndex], text: '# ' },
|
|
109
|
+
];
|
|
110
|
+
return e;
|
|
111
|
+
}));
|
|
105
112
|
}
|
|
106
113
|
else {
|
|
107
114
|
errors.push((0, lint_1.generateForSelf)(this, rect, 'invalid-imagemap', '<imagemap> without an image'));
|
package/dist/src/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { AstElement } from '../lib/element';
|
|
|
3
3
|
import { AstText } from '../lib/text';
|
|
4
4
|
import type { LintError, TokenTypes } from '../base';
|
|
5
5
|
import type { Title } from '../lib/title';
|
|
6
|
-
import type { AstNodes,
|
|
6
|
+
import type { AstNodes, IncludeToken, HtmlToken, ExtToken, TranscludeToken, CommentToken, FileToken, LinkToken, RedirectTargetToken, ExtLinkToken, MagicLinkToken, ImageParameterToken } from '../internal';
|
|
7
7
|
import { Ranges } from '../lib/ranges';
|
|
8
8
|
import { AstRange } from '../lib/range';
|
|
9
9
|
import type { Range } from '../lib/ranges';
|
package/dist/src/index.js
CHANGED
|
@@ -446,47 +446,35 @@ class Token extends element_1.AstElement {
|
|
|
446
446
|
index_1.default.viewOnly = true;
|
|
447
447
|
let errors = super.lint(start, re);
|
|
448
448
|
if (this.type === 'root') {
|
|
449
|
-
const record = new Map(), selector = 'category,html-attr#id,ext-attr#id,table-attr#id
|
|
449
|
+
const record = new Map(), selector = 'category,html-attr#id,ext-attr#id,table-attr#id';
|
|
450
450
|
for (const cat of this.querySelectorAll(selector)) {
|
|
451
451
|
let key;
|
|
452
452
|
if (cat.type === 'category') {
|
|
453
453
|
key = cat.name;
|
|
454
454
|
}
|
|
455
455
|
else {
|
|
456
|
-
const value = cat.getValue()
|
|
457
|
-
if (
|
|
458
|
-
key = `#${value
|
|
456
|
+
const value = cat.getValue();
|
|
457
|
+
if (value && value !== true) {
|
|
458
|
+
key = `#${value}`;
|
|
459
459
|
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
460
|
+
}
|
|
461
|
+
if (key) {
|
|
462
|
+
const thisCat = record.get(key);
|
|
463
|
+
if (thisCat) {
|
|
464
|
+
thisCat.add(cat);
|
|
464
465
|
}
|
|
465
466
|
else {
|
|
466
|
-
|
|
467
|
+
record.set(key, new Set([cat]));
|
|
467
468
|
}
|
|
468
469
|
}
|
|
469
|
-
const thisCat = record.get(key);
|
|
470
|
-
if (thisCat) {
|
|
471
|
-
thisCat.add(cat);
|
|
472
|
-
}
|
|
473
|
-
else {
|
|
474
|
-
record.set(key, new Set([cat]));
|
|
475
|
-
}
|
|
476
470
|
}
|
|
477
471
|
for (const [key, value] of record) {
|
|
478
472
|
if (value.size > 1 && !key.startsWith('#mw-customcollapsible-')) {
|
|
479
|
-
const isCat = !key.
|
|
473
|
+
const isCat = !key.startsWith('#'), msg = `duplicated ${isCat ? 'category' : 'id'}`, severity = isCat ? 'error' : 'warning';
|
|
480
474
|
errors.push(...[...value].map(cat => {
|
|
481
475
|
const e = (0, lint_1.generateForSelf)(cat, { start: cat.getAbsoluteIndex() }, 'no-duplicate', msg, severity);
|
|
482
476
|
if (isCat) {
|
|
483
|
-
e.suggestions = [
|
|
484
|
-
{
|
|
485
|
-
desc: 'remove',
|
|
486
|
-
range: [e.startIndex, e.endIndex],
|
|
487
|
-
text: '',
|
|
488
|
-
},
|
|
489
|
-
];
|
|
477
|
+
e.suggestions = [{ desc: 'remove', range: [e.startIndex, e.endIndex], text: '' }];
|
|
490
478
|
}
|
|
491
479
|
return e;
|
|
492
480
|
}));
|
package/dist/src/link/base.js
CHANGED
|
@@ -3,13 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.LinkBaseToken = void 0;
|
|
4
4
|
const lint_1 = require("../../util/lint");
|
|
5
5
|
const constants_1 = require("../../util/constants");
|
|
6
|
+
const string_1 = require("../../util/string");
|
|
6
7
|
const rect_1 = require("../../lib/rect");
|
|
7
8
|
const index_1 = require("../../index");
|
|
8
9
|
const index_2 = require("../index");
|
|
9
10
|
const atom_1 = require("../atom");
|
|
10
11
|
/* NOT FOR BROWSER */
|
|
11
12
|
const debug_1 = require("../../util/debug");
|
|
12
|
-
const
|
|
13
|
+
const string_2 = require("../../util/string");
|
|
13
14
|
const html_1 = require("../../util/html");
|
|
14
15
|
/* NOT FOR BROWSER END */
|
|
15
16
|
/**
|
|
@@ -156,7 +157,9 @@ class LinkBaseToken extends index_2.Token {
|
|
|
156
157
|
errors.push((0, lint_1.generateForChild)(target, rect, 'unknown-page', 'template in an internal link target', 'warning'));
|
|
157
158
|
}
|
|
158
159
|
if (encoded) {
|
|
159
|
-
|
|
160
|
+
const e = (0, lint_1.generateForChild)(target, rect, 'url-encoding', 'unnecessary URL encoding in an internal link');
|
|
161
|
+
e.suggestions = [{ desc: 'decode', range: [e.startIndex, e.endIndex], text: (0, string_1.rawurldecode)(target.text()) }];
|
|
162
|
+
errors.push(e);
|
|
160
163
|
}
|
|
161
164
|
if (type === 'link' || type === 'category') {
|
|
162
165
|
const textNode = linkText?.childNodes.find((c) => c.type === 'text' && c.data.includes('|'));
|
|
@@ -221,7 +224,7 @@ class LinkBaseToken extends index_2.Token {
|
|
|
221
224
|
setFragment(fragment) {
|
|
222
225
|
const { type, name } = this;
|
|
223
226
|
if (fragment === undefined || isLink(type)) {
|
|
224
|
-
fragment &&= (0,
|
|
227
|
+
fragment &&= (0, string_2.encode)(fragment);
|
|
225
228
|
this.setTarget(`${name}${fragment === undefined ? '' : `#${fragment}`}`);
|
|
226
229
|
}
|
|
227
230
|
}
|
|
@@ -252,7 +255,7 @@ class LinkBaseToken extends index_2.Token {
|
|
|
252
255
|
const { link, length, lastChild, type } = this, title = link.getTitleAttr();
|
|
253
256
|
return (0, html_1.font)(this, `<a${link.interwiki && ' class="extiw"'} href="${link.getUrl()}"${title && ` title="${title}"`}>${type === 'link' && length > 1
|
|
254
257
|
? lastChild.toHtmlInternal({ ...opt, nowrap: true })
|
|
255
|
-
: (0,
|
|
258
|
+
: (0, string_2.sanitize)(this.innerText)}</a>`);
|
|
256
259
|
}
|
|
257
260
|
return '';
|
|
258
261
|
}
|
package/dist/src/link/file.js
CHANGED
|
@@ -150,7 +150,11 @@ class FileToken extends base_1.LinkBaseToken {
|
|
|
150
150
|
* @param msg 消息键
|
|
151
151
|
* @param p1 替换$1
|
|
152
152
|
*/
|
|
153
|
-
const generate = (msg, p1) => (arg) =>
|
|
153
|
+
const generate = (msg, p1) => (arg) => {
|
|
154
|
+
const e = (0, lint_1.generateForChild)(arg, rect, 'no-duplicate', index_1.default.msg(`${msg} image $1 parameter`, p1));
|
|
155
|
+
e.suggestions = [{ desc: 'remove', range: [e.startIndex - 1, e.endIndex], text: '' }];
|
|
156
|
+
return e;
|
|
157
|
+
};
|
|
154
158
|
for (const key of keys) {
|
|
155
159
|
if (key === 'invalid' || key === 'width' && unscaled) {
|
|
156
160
|
continue;
|
|
@@ -108,7 +108,9 @@ let GalleryImageToken = (() => {
|
|
|
108
108
|
lint(start = this.getAbsoluteIndex(), re) {
|
|
109
109
|
const errors = super.lint(start, re), { ns, interwiki } = this.getAttribute('title');
|
|
110
110
|
if (interwiki || ns !== 6) {
|
|
111
|
-
|
|
111
|
+
const e = (0, lint_1.generateForSelf)(this, { start }, 'invalid-gallery', 'invalid gallery image');
|
|
112
|
+
e.suggestions = [{ desc: 'prefix', range: [start, start], text: 'File:' }];
|
|
113
|
+
errors.push(e);
|
|
112
114
|
}
|
|
113
115
|
return errors;
|
|
114
116
|
}
|