wikilint 2.31.0 → 2.32.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/dist/base.d.mts +9 -3
- package/dist/base.d.ts +9 -3
- package/dist/bin/cli.js +2 -2
- package/dist/bin/config.js +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +24 -58
- package/dist/lib/document.d.ts +9 -7
- package/dist/lib/document.js +90 -65
- package/dist/lib/element.d.ts +0 -6
- package/dist/lib/element.js +2 -29
- package/dist/lib/lintConfig.js +1 -1
- package/dist/lib/lsp.js +114 -56
- package/dist/lib/node.js +1 -1
- package/dist/mixin/elementLike.js +2 -4
- package/dist/parser/commentAndExt.js +3 -3
- package/dist/src/attribute.js +20 -18
- package/dist/src/attributes.d.ts +5 -0
- package/dist/src/attributes.js +4 -3
- package/dist/src/imageParameter.d.ts +0 -1
- package/dist/src/imageParameter.js +16 -14
- package/dist/src/index.js +4 -5
- package/dist/src/link/base.js +2 -6
- package/dist/src/link/file.js +3 -2
- package/dist/src/nowiki/index.js +34 -31
- package/dist/src/table/base.js +4 -1
- package/dist/src/table/index.d.ts +0 -5
- package/dist/src/table/index.js +4 -10
- package/dist/src/transclude.d.ts +0 -6
- package/dist/src/transclude.js +6 -22
- package/dist/util/constants.js +3 -1
- package/dist/util/debug.js +42 -4
- package/dist/util/diff.js +17 -15
- package/dist/{parser → util}/selector.js +9 -3
- package/dist/util/sharable.d.mts +4 -1
- package/dist/util/sharable.js +7 -7
- package/dist/util/sharable.mjs +7 -7
- package/dist/util/string.js +15 -11
- package/i18n/zh-hans.json +29 -29
- package/i18n/zh-hant.json +30 -30
- package/package.json +12 -12
package/dist/lib/lsp.js
CHANGED
|
@@ -10,7 +10,10 @@ const base_1 = require("../base");
|
|
|
10
10
|
const sharable_1 = require("../util/sharable");
|
|
11
11
|
const lint_1 = require("../util/lint");
|
|
12
12
|
const string_1 = require("../util/string");
|
|
13
|
+
const debug_1 = require("../util/debug");
|
|
14
|
+
const constants_1 = require("../util/constants");
|
|
13
15
|
const index_1 = __importDefault(require("../index"));
|
|
16
|
+
const index_2 = require("../src/index");
|
|
14
17
|
/* NOT FOR BROWSER ONLY */
|
|
15
18
|
const fs_1 = __importDefault(require("fs"));
|
|
16
19
|
const path_1 = __importDefault(require("path"));
|
|
@@ -19,7 +22,6 @@ const child_process_1 = require("child_process");
|
|
|
19
22
|
const crypto_1 = require("crypto");
|
|
20
23
|
const stylelint_util_1 = require("@bhsd/stylelint-util");
|
|
21
24
|
const search_1 = __importDefault(require("../util/search"));
|
|
22
|
-
const constants_1 = require("../util/constants");
|
|
23
25
|
const document_1 = require("./document");
|
|
24
26
|
exports.tasks = new WeakMap();
|
|
25
27
|
const refTags = new Set(['ref']), referencesTags = new Set(['ref', 'references']), nameAttrs = new Set(['name', 'follow']), groupAttrs = new Set(['group']), renameTypes = new Set([
|
|
@@ -50,7 +52,7 @@ const getLinkRegex = (0, common_1.getRegex)(protocol => new RegExp(`^(?:${protoc
|
|
|
50
52
|
const isAttr = ({ type, parentNode, length, firstChild }, style) => type === 'attr-value' && length === 1 && firstChild.type === 'text'
|
|
51
53
|
&& (!style
|
|
52
54
|
|| parentNode.name === 'style'
|
|
53
|
-
&& Boolean(document_1.
|
|
55
|
+
&& Boolean((0, document_1.loadCssLSP)()));
|
|
54
56
|
/**
|
|
55
57
|
* Check if a token is an HTML attribute.
|
|
56
58
|
* @param token
|
|
@@ -226,6 +228,54 @@ const getFixAll = (root, rule) => {
|
|
|
226
228
|
},
|
|
227
229
|
];
|
|
228
230
|
};
|
|
231
|
+
/**
|
|
232
|
+
* Partially parse wikitext.
|
|
233
|
+
* @param wikitext
|
|
234
|
+
* @param watch function to watch for changes
|
|
235
|
+
* @param include
|
|
236
|
+
* @param config
|
|
237
|
+
*/
|
|
238
|
+
const partialParse = async (wikitext, watch, include, config = index_1.default.getConfig()) => {
|
|
239
|
+
const set = typeof setImmediate === 'function' ? setImmediate : /* istanbul ignore next */ setTimeout, { running } = debug_1.Shadow;
|
|
240
|
+
debug_1.Shadow.running = true;
|
|
241
|
+
/** restore state before exit */
|
|
242
|
+
const finish = () => {
|
|
243
|
+
debug_1.Shadow.running = running;
|
|
244
|
+
};
|
|
245
|
+
const token = new index_2.Token((0, string_1.tidy)(wikitext), config);
|
|
246
|
+
token.type = 'root';
|
|
247
|
+
let i = 0;
|
|
248
|
+
try {
|
|
249
|
+
await new Promise(resolve => {
|
|
250
|
+
const /** @ignore */ check = () => {
|
|
251
|
+
if (watch() === wikitext) {
|
|
252
|
+
i++;
|
|
253
|
+
set(parseOnce, 0);
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
resolve();
|
|
257
|
+
}
|
|
258
|
+
},
|
|
259
|
+
/** @ignore */ parseOnce = () => {
|
|
260
|
+
if (i === constants_1.MAX_STAGE + 1) {
|
|
261
|
+
token.afterBuild();
|
|
262
|
+
resolve();
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
token[i === constants_1.MAX_STAGE ? 'build' : 'parseOnce'](i, include);
|
|
266
|
+
check();
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
set(parseOnce, 0);
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
catch (e) /* istanbul ignore next */ {
|
|
273
|
+
finish();
|
|
274
|
+
throw e;
|
|
275
|
+
}
|
|
276
|
+
finish();
|
|
277
|
+
return token;
|
|
278
|
+
};
|
|
229
279
|
/* NOT FOR BROWSER ONLY */
|
|
230
280
|
/** @see https://www.npmjs.com/package/stylelint-config-recommended */
|
|
231
281
|
const cssRules = { 'block-no-empty': null }, sources = { 'invalid-css': 'css', 'invalid-math': 'texvc' }, jsonSelector = document_1.jsonTags.map(s => `ext#${s}`).join(), scores = new Map();
|
|
@@ -380,7 +430,7 @@ class LanguageService {
|
|
|
380
430
|
this.config ??= index_1.default.getConfig();
|
|
381
431
|
this.#config = this.config;
|
|
382
432
|
this.#include = this.include;
|
|
383
|
-
const text = this.#text, root = await
|
|
433
|
+
const text = this.#text, root = await partialParse(text, () => this.#text, this.include, this.config);
|
|
384
434
|
if (this.#checkConfig() && this.#text === text) {
|
|
385
435
|
this.#done = root;
|
|
386
436
|
this.#running = undefined;
|
|
@@ -418,7 +468,7 @@ class LanguageService {
|
|
|
418
468
|
this.config ??= index_1.default.getConfig();
|
|
419
469
|
this.#config = this.config;
|
|
420
470
|
this.#include = this.include;
|
|
421
|
-
const text = this.#text2, root = await
|
|
471
|
+
const text = this.#text2, root = await partialParse(text, () => this.#text2, this.include, this.config);
|
|
422
472
|
if (this.#checkConfig() && this.#text2 === text) {
|
|
423
473
|
this.#done2 = root;
|
|
424
474
|
this.#running2 = undefined;
|
|
@@ -460,7 +510,7 @@ class LanguageService {
|
|
|
460
510
|
}
|
|
461
511
|
else if (isAttr(token, true)) {
|
|
462
512
|
const textDoc = new document_1.EmbeddedCSSDocument(root, token);
|
|
463
|
-
return document_1.
|
|
513
|
+
return (0, document_1.loadCssLSP)().findDocumentColors(textDoc, textDoc.styleSheet);
|
|
464
514
|
/* NOT FOR BROWSER ONLY END */
|
|
465
515
|
}
|
|
466
516
|
/* NOT FOR BROWSER ONLY */
|
|
@@ -488,7 +538,7 @@ class LanguageService {
|
|
|
488
538
|
},
|
|
489
539
|
range: createRange(root, start + from, start + to),
|
|
490
540
|
};
|
|
491
|
-
}).filter(
|
|
541
|
+
}).filter(info => info !== false);
|
|
492
542
|
});
|
|
493
543
|
});
|
|
494
544
|
}
|
|
@@ -536,11 +586,7 @@ class LanguageService {
|
|
|
536
586
|
ext,
|
|
537
587
|
tags,
|
|
538
588
|
allTags: [...tags, 'onlyinclude', 'includeonly', 'noinclude'],
|
|
539
|
-
functions: [
|
|
540
|
-
Object.keys(insensitive),
|
|
541
|
-
Array.isArray(sensitive) ? /* istanbul ignore next */ sensitive : Object.keys(sensitive),
|
|
542
|
-
other,
|
|
543
|
-
].flat(2),
|
|
589
|
+
functions: [Object.keys(insensitive), Object.keys(sensitive), other].flat(2),
|
|
544
590
|
switches: allSwitches.filter(cm_util_1.isUnderscore).map(w => `__${w}__`),
|
|
545
591
|
jaSwitches: allSwitches.filter(w => !(0, cm_util_1.isUnderscore)(w)),
|
|
546
592
|
protocols: protocol.split('|'),
|
|
@@ -596,7 +642,7 @@ class LanguageService {
|
|
|
596
642
|
return getCompletion(root.querySelectorAll('arg').filter(token => token.name && token !== cur)
|
|
597
643
|
.map(({ name }) => name), 'Variable', match, position);
|
|
598
644
|
}
|
|
599
|
-
const [insensitive, sensitive] = this.config.parserFunction,
|
|
645
|
+
const [insensitive, sensitive] = this.config.parserFunction, next = curLine.charAt(character), colon = match.startsWith(':'), str = colon ? match.slice(1).trimStart() : match;
|
|
600
646
|
if (mt[2] === '[[') { // link
|
|
601
647
|
return getCompletion(root.querySelectorAll('link,file,category,redirect-target').filter(token => token !== cur).map(({ name }) => name), 'Folder', str, position);
|
|
602
648
|
}
|
|
@@ -616,7 +662,7 @@ class LanguageService {
|
|
|
616
662
|
else if (name in insensitive) {
|
|
617
663
|
name = insensitive[name];
|
|
618
664
|
}
|
|
619
|
-
else if (
|
|
665
|
+
else if (name in sensitive) {
|
|
620
666
|
name = sensitive[name];
|
|
621
667
|
}
|
|
622
668
|
return this.#getParserFunction(name.toLowerCase());
|
|
@@ -699,7 +745,8 @@ class LanguageService {
|
|
|
699
745
|
}
|
|
700
746
|
else if (isAttr(cur, true)) {
|
|
701
747
|
const textDoc = new document_1.EmbeddedCSSDocument(root, cur);
|
|
702
|
-
return document_1.
|
|
748
|
+
return (0, document_1.loadCssLSP)().doComplete(textDoc, position, textDoc.styleSheet).items
|
|
749
|
+
.map((item) => ({
|
|
703
750
|
...item,
|
|
704
751
|
textEdit: {
|
|
705
752
|
range: item.textEdit.range,
|
|
@@ -707,9 +754,13 @@ class LanguageService {
|
|
|
707
754
|
},
|
|
708
755
|
}));
|
|
709
756
|
}
|
|
710
|
-
else if (
|
|
757
|
+
else if (type === 'ext-inner' && document_1.jsonTags.includes(cur.name)) {
|
|
758
|
+
const jsonLSP = (0, document_1.loadJsonLSP)();
|
|
759
|
+
if (!jsonLSP) {
|
|
760
|
+
return undefined;
|
|
761
|
+
}
|
|
711
762
|
const textDoc = new document_1.EmbeddedJSONDocument(root, cur);
|
|
712
|
-
return (await
|
|
763
|
+
return (await jsonLSP.doComplete(textDoc, position, textDoc.jsonDoc))?.items;
|
|
713
764
|
}
|
|
714
765
|
else if (type === 'ext-inner' && cur.name === 'score') {
|
|
715
766
|
const lang = parentNode.getAttr('lang');
|
|
@@ -785,15 +836,18 @@ class LanguageService {
|
|
|
785
836
|
...suggestions ? suggestions.map(suggestion => getQuickFix(root, suggestion)) : [],
|
|
786
837
|
],
|
|
787
838
|
})),
|
|
839
|
+
/* NOT FOR BROWSER ONLY */
|
|
840
|
+
stylelint = await (0, document_1.loadStylelint)(), jsonLSP = (0, document_1.loadJsonLSP)(),
|
|
841
|
+
/* NOT FOR BROWSER ONLY END */
|
|
788
842
|
/* eslint-disable @stylistic/operator-linebreak */
|
|
789
|
-
cssDiagnostics =
|
|
843
|
+
cssDiagnostics = stylelint ?
|
|
790
844
|
await (async () => {
|
|
791
845
|
NPM: {
|
|
792
846
|
const tokens = this.findStyleTokens();
|
|
793
847
|
if (tokens.length === 0) {
|
|
794
848
|
return [];
|
|
795
849
|
}
|
|
796
|
-
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)(
|
|
850
|
+
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)(stylelint, code, cssRules);
|
|
797
851
|
if (cssErrors.length === 0) {
|
|
798
852
|
return [];
|
|
799
853
|
}
|
|
@@ -830,12 +884,12 @@ class LanguageService {
|
|
|
830
884
|
});
|
|
831
885
|
}
|
|
832
886
|
})() :
|
|
833
|
-
[], jsonDiagnostics =
|
|
887
|
+
[], jsonDiagnostics = jsonLSP ?
|
|
834
888
|
await Promise.all(root.querySelectorAll(jsonSelector).map(async ({ name, lastChild, selfClosing }) => {
|
|
835
889
|
if (selfClosing) {
|
|
836
890
|
return [];
|
|
837
891
|
}
|
|
838
|
-
const textDoc = new document_1.EmbeddedJSONDocument(root, lastChild), severityLevel = name === 'templatedata' ? 'error' : 'ignore', e = (await
|
|
892
|
+
const textDoc = new document_1.EmbeddedJSONDocument(root, lastChild), severityLevel = name === 'templatedata' ? 'error' : 'ignore', e = (await jsonLSP.doValidation(textDoc, textDoc.jsonDoc, {
|
|
839
893
|
comments: severityLevel,
|
|
840
894
|
trailingCommas: severityLevel,
|
|
841
895
|
})).map((error) => ({
|
|
@@ -969,10 +1023,11 @@ class LanguageService {
|
|
|
969
1023
|
}
|
|
970
1024
|
}
|
|
971
1025
|
/* NOT FOR BROWSER ONLY */
|
|
972
|
-
|
|
1026
|
+
const jsonLSP = (0, document_1.loadJsonLSP)();
|
|
1027
|
+
if (jsonLSP) {
|
|
973
1028
|
for (const { selfClosing, lastChild } of root.querySelectorAll(jsonSelector)) {
|
|
974
1029
|
if (!selfClosing) {
|
|
975
|
-
const foldingRanges =
|
|
1030
|
+
const foldingRanges = jsonLSP.getFoldingRanges(new document_1.EmbeddedJSONDocument(root, lastChild));
|
|
976
1031
|
if (foldingRanges.length > 0) {
|
|
977
1032
|
Array.prototype.push.apply(ranges, foldingRanges);
|
|
978
1033
|
}
|
|
@@ -1082,7 +1137,7 @@ class LanguageService {
|
|
|
1082
1137
|
return false;
|
|
1083
1138
|
}
|
|
1084
1139
|
})
|
|
1085
|
-
.filter(
|
|
1140
|
+
.filter(link => link !== false);
|
|
1086
1141
|
}
|
|
1087
1142
|
/**
|
|
1088
1143
|
* Provide references
|
|
@@ -1238,41 +1293,43 @@ class LanguageService {
|
|
|
1238
1293
|
}
|
|
1239
1294
|
else if (isAttr(offsetNode, true)) {
|
|
1240
1295
|
const textDoc = new document_1.EmbeddedCSSDocument(root, offsetNode);
|
|
1241
|
-
return document_1.
|
|
1296
|
+
return (0, document_1.loadCssLSP)().doHover(textDoc, position, textDoc.styleSheet) ?? undefined;
|
|
1242
1297
|
}
|
|
1243
|
-
else if (
|
|
1298
|
+
else if (type === 'ext-inner' && document_1.jsonTags.includes(name)) {
|
|
1299
|
+
const jsonLSP = (0, document_1.loadJsonLSP)();
|
|
1300
|
+
if (!jsonLSP) {
|
|
1301
|
+
return undefined;
|
|
1302
|
+
}
|
|
1244
1303
|
const textDoc = new document_1.EmbeddedJSONDocument(root, offsetNode);
|
|
1245
|
-
return await
|
|
1304
|
+
return await jsonLSP.doHover(textDoc, position, textDoc.jsonDoc) ?? undefined;
|
|
1246
1305
|
}
|
|
1247
|
-
else if (
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
character: start.character + token.getRelativeIndex(0),
|
|
1260
|
-
},
|
|
1306
|
+
else if (type === 'html' && offset <= offsetNode.getRelativeIndex(0)
|
|
1307
|
+
|| type === 'html-attr-dirty' && offset === 0 && parentNode.firstChild === offsetNode) {
|
|
1308
|
+
const token = type === 'html' ? offsetNode : parentNode.parentNode, data = (0, document_1.loadHtmlData)()?.provideTags().find(({ name: n }) => n === token.name);
|
|
1309
|
+
if (data?.description) {
|
|
1310
|
+
const start = positionAt(root, token.getAbsoluteIndex());
|
|
1311
|
+
return {
|
|
1312
|
+
contents: data.description,
|
|
1313
|
+
range: {
|
|
1314
|
+
start,
|
|
1315
|
+
end: {
|
|
1316
|
+
line: start.line,
|
|
1317
|
+
character: start.character + token.getRelativeIndex(0),
|
|
1261
1318
|
},
|
|
1262
|
-
}
|
|
1263
|
-
}
|
|
1319
|
+
},
|
|
1320
|
+
};
|
|
1264
1321
|
}
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
}
|
|
1322
|
+
}
|
|
1323
|
+
else if (type === 'attr-key' && isHtmlAttr(parentNode)) {
|
|
1324
|
+
const data = (0, document_1.loadHtmlData)()?.provideAttributes(parentNode.tag).find(({ name: n }) => n === parentNode.name);
|
|
1325
|
+
if (data?.description) {
|
|
1326
|
+
return {
|
|
1327
|
+
contents: data.description,
|
|
1328
|
+
range: createNodeRange(offsetNode),
|
|
1329
|
+
};
|
|
1273
1330
|
}
|
|
1274
|
-
/* NOT FOR BROWSER ONLY END */
|
|
1275
1331
|
}
|
|
1332
|
+
/* NOT FOR BROWSER ONLY END */
|
|
1276
1333
|
return info && {
|
|
1277
1334
|
contents: {
|
|
1278
1335
|
kind: 'markdown',
|
|
@@ -1392,10 +1449,11 @@ class LanguageService {
|
|
|
1392
1449
|
else {
|
|
1393
1450
|
return [];
|
|
1394
1451
|
}
|
|
1395
|
-
const root = await this.#queueSignature(selected);
|
|
1396
|
-
const { viewOnly } = index_1.default;
|
|
1452
|
+
const root = await this.#queueSignature(selected), { viewOnly } = index_1.default;
|
|
1397
1453
|
index_1.default.viewOnly = false;
|
|
1398
|
-
|
|
1454
|
+
debug_1.Shadow.internal(() => {
|
|
1455
|
+
root.escape();
|
|
1456
|
+
}, index_1.default);
|
|
1399
1457
|
index_1.default.viewOnly = viewOnly;
|
|
1400
1458
|
return [
|
|
1401
1459
|
{
|
|
@@ -1463,9 +1521,9 @@ class LanguageService {
|
|
|
1463
1521
|
sections[i] = undefined;
|
|
1464
1522
|
}
|
|
1465
1523
|
const section = token.text().trim() || ' ', name = names.has(section)
|
|
1466
|
-
?
|
|
1524
|
+
? Array.from({ length: names.size }, (_, i) => `${section.trim()}_${i + 2}`)
|
|
1467
1525
|
.find(s => !names.has(s))
|
|
1468
|
-
: section, container = sections.slice(0, level - 1).reverse().find(
|
|
1526
|
+
: section, container = sections.slice(0, level - 1).reverse().find(symbol => symbol !== undefined), selectionRange = {
|
|
1469
1527
|
start: { line: top, character: left - level },
|
|
1470
1528
|
end: (0, lint_1.getEndPos)(top, left, height, width + level),
|
|
1471
1529
|
}, info = {
|
package/dist/lib/node.js
CHANGED
|
@@ -2,15 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.elementLike = void 0;
|
|
4
4
|
const debug_1 = require("../util/debug");
|
|
5
|
-
const selector_1 = require("../
|
|
5
|
+
const selector_1 = require("../util/selector");
|
|
6
6
|
/** @ignore */
|
|
7
7
|
const elementLike = (constructor) => {
|
|
8
8
|
LINT: {
|
|
9
9
|
class ElementLike extends constructor {
|
|
10
10
|
#getCondition(selector) {
|
|
11
|
-
return (0, selector_1.getCondition)(selector,
|
|
12
|
-
// @ts-expect-error only AstElement
|
|
13
|
-
this);
|
|
11
|
+
return (0, selector_1.getCondition)(selector, this);
|
|
14
12
|
}
|
|
15
13
|
getElementBy(condition) {
|
|
16
14
|
const stack = [...this.childNodes].reverse();
|
|
@@ -5,7 +5,6 @@ const common_1 = require("@bhsd/common");
|
|
|
5
5
|
const string_1 = require("../util/string");
|
|
6
6
|
const onlyinclude_1 = require("../src/onlyinclude");
|
|
7
7
|
const noinclude_1 = require("../src/nowiki/noinclude");
|
|
8
|
-
const translate_1 = require("../src/tagPair/translate");
|
|
9
8
|
const include_1 = require("../src/tagPair/include");
|
|
10
9
|
const ext_1 = require("../src/tagPair/ext");
|
|
11
10
|
const comment_1 = require("../src/nowiki/comment");
|
|
@@ -62,16 +61,17 @@ const parseCommentAndExt = (wikitext, config, accum, includeOnly) => {
|
|
|
62
61
|
const { ext } = config;
|
|
63
62
|
let newExt = ext, newConfig = config;
|
|
64
63
|
if (ext.includes('translate')) {
|
|
64
|
+
const { TranslateToken } = require('../src/tagPair/translate');
|
|
65
|
+
const stack = [];
|
|
65
66
|
newExt = ext.filter(e => e !== 'translate' && e !== 'tvar');
|
|
66
67
|
newConfig = { ...config, ext: newExt };
|
|
67
|
-
const stack = [];
|
|
68
68
|
wikitext = wikitext.replace(/<nowiki>[\s\S]*?<\/nowiki>/giu, m => {
|
|
69
69
|
stack.push(m);
|
|
70
70
|
return `\0${stack.length - 1}\x7F`;
|
|
71
71
|
}).replace(/<translate( nowrap)?>([\s\S]*?)<\/translate>/gu, (_, p1, p2) => {
|
|
72
72
|
const l = accum.length;
|
|
73
73
|
// @ts-expect-error abstract class
|
|
74
|
-
new
|
|
74
|
+
new TranslateToken(p1, p2 && (0, string_1.restore)(p2, stack), newConfig, accum);
|
|
75
75
|
return `\0${l}g\x7F`;
|
|
76
76
|
});
|
|
77
77
|
wikitext = (0, string_1.restore)(wikitext, stack);
|
package/dist/src/attribute.js
CHANGED
|
@@ -212,26 +212,28 @@ class AttributeToken extends index_2.Token {
|
|
|
212
212
|
}
|
|
213
213
|
/* NOT FOR BROWSER ONLY */
|
|
214
214
|
const rule = 'invalid-css', sError = lintConfig.getSeverity(rule), sWarn = lintConfig.getSeverity(rule, 'warn');
|
|
215
|
-
if (
|
|
216
|
-
&& (sError || sWarn)
|
|
215
|
+
if ((sError || sWarn)
|
|
217
216
|
&& name === 'style'
|
|
218
217
|
&& lastChild.length === 1 && lastChild.firstChild.type === 'text') {
|
|
219
|
-
const
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
218
|
+
const cssLSP = (0, document_1.loadCssLSP)();
|
|
219
|
+
if (cssLSP) {
|
|
220
|
+
const root = this.getRootNode(), textDoc = new document_1.EmbeddedCSSDocument(root, lastChild);
|
|
221
|
+
Array.prototype.push.apply(errors, cssLSP.doValidation(textDoc, textDoc.styleSheet)
|
|
222
|
+
.filter(({ code, severity }) => code !== 'css-ruleorselectorexpected' && code !== 'emptyRules'
|
|
223
|
+
&& (severity === 1 ? sError : sWarn))
|
|
224
|
+
.map(({ range: { start: { line, character }, end }, message, severity, code }) => ({
|
|
225
|
+
code: code,
|
|
226
|
+
rule,
|
|
227
|
+
message,
|
|
228
|
+
severity: (severity === 1 ? sError : sWarn),
|
|
229
|
+
startLine: line,
|
|
230
|
+
startCol: character,
|
|
231
|
+
startIndex: root.indexFromPos(line, character),
|
|
232
|
+
endLine: end.line,
|
|
233
|
+
endCol: end.character,
|
|
234
|
+
endIndex: root.indexFromPos(end.line, end.character),
|
|
235
|
+
})));
|
|
236
|
+
}
|
|
235
237
|
}
|
|
236
238
|
/* NOT FOR BROWSER ONLY END */
|
|
237
239
|
return errors;
|
package/dist/src/attributes.d.ts
CHANGED
|
@@ -6,6 +6,11 @@ import type { ExtToken, HtmlToken, SyntaxToken } from '../internal';
|
|
|
6
6
|
import type { AttributeTypes } from './attribute';
|
|
7
7
|
import type { TableTokens } from './table/index';
|
|
8
8
|
declare type AttributesTypes = `${AttributeTypes}s`;
|
|
9
|
+
/**
|
|
10
|
+
* 将属性类型转换为单属性类型
|
|
11
|
+
* @param type 属性类型
|
|
12
|
+
*/
|
|
13
|
+
export declare const toAttributeType: (type: AttributesTypes) => AttributeTypes;
|
|
9
14
|
/**
|
|
10
15
|
* attributes of extension and HTML tags
|
|
11
16
|
*
|
package/dist/src/attributes.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.AttributesToken = void 0;
|
|
6
|
+
exports.AttributesToken = exports.toAttributeType = void 0;
|
|
7
7
|
const lint_1 = require("../util/lint");
|
|
8
8
|
const string_1 = require("../util/string");
|
|
9
9
|
const rect_1 = require("../lib/rect");
|
|
@@ -16,11 +16,12 @@ const attribute_1 = require("./attribute");
|
|
|
16
16
|
* @param type 属性类型
|
|
17
17
|
*/
|
|
18
18
|
const toAttributeType = (type) => type.slice(0, -1);
|
|
19
|
+
exports.toAttributeType = toAttributeType;
|
|
19
20
|
/**
|
|
20
21
|
* 将属性类型转换为无效属性类型
|
|
21
22
|
* @param type 属性类型
|
|
22
23
|
*/
|
|
23
|
-
const toDirty = (type) => `${toAttributeType(type)}-dirty`;
|
|
24
|
+
const toDirty = (type) => `${(0, exports.toAttributeType)(type)}-dirty`;
|
|
24
25
|
const wordRegex = /* #__PURE__ */ (() => {
|
|
25
26
|
try {
|
|
26
27
|
// eslint-disable-next-line prefer-regex-literals
|
|
@@ -65,7 +66,7 @@ class AttributesToken extends index_2.Token {
|
|
|
65
66
|
if (/^(?:[\w:]|\0\d+t\x7F)(?:[\w:.-]|\0\d+t\x7F)*$/u.test((0, string_1.removeComment)(key).trim())) {
|
|
66
67
|
const value = quoted ?? unquoted, quotes = [quoteStart, quoteEnd],
|
|
67
68
|
// @ts-expect-error abstract class
|
|
68
|
-
token = new attribute_1.AttributeToken(toAttributeType(type), name, key, equal, value, quotes, config, accum);
|
|
69
|
+
token = new attribute_1.AttributeToken((0, exports.toAttributeType)(type), name, key, equal, value, quotes, config, accum);
|
|
69
70
|
insertDirty();
|
|
70
71
|
super.insertAt(token);
|
|
71
72
|
}
|
|
@@ -2,7 +2,6 @@ import { Token } from './index';
|
|
|
2
2
|
import type { LintError, Config } from '../base';
|
|
3
3
|
import type { Title } from '../lib/title';
|
|
4
4
|
import type { AtomToken, FileToken } from '../internal';
|
|
5
|
-
export declare const galleryParams: Set<string>, extensions: Set<string>;
|
|
6
5
|
/**
|
|
7
6
|
* image parameter
|
|
8
7
|
*
|
|
@@ -37,7 +37,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
37
37
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
38
38
|
};
|
|
39
39
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
-
exports.ImageParameterToken =
|
|
40
|
+
exports.ImageParameterToken = void 0;
|
|
41
41
|
const common_1 = require("@bhsd/common");
|
|
42
42
|
const string_1 = require("../util/string");
|
|
43
43
|
const lint_1 = require("../util/lint");
|
|
@@ -49,7 +49,6 @@ const index_2 = require("./index");
|
|
|
49
49
|
const getUrlLikeRegex = (0, common_1.getRegex)(protocol => new RegExp(String.raw `^(?:${protocol}|//|\0\d+m\x7F)`, 'iu'));
|
|
50
50
|
const getUrlRegex = (0, common_1.getRegex)(protocol => new RegExp(String.raw `^(?:(?:${protocol}|//)${string_1.extUrlCharFirst}|\0\d+m\x7F)${string_1.extUrlChar}$`, 'iu'));
|
|
51
51
|
const getSyntaxRegex = (0, common_1.getRegex)(syntax => new RegExp(String.raw `^(\s*(?!\s))${syntax.replace('$1', '(.*)')}${syntax.endsWith('$1') ? '(?=$|\n)' : ''}(\s*)$`, 'u'));
|
|
52
|
-
exports.galleryParams = new Set(['alt', 'link', 'lang', 'page', 'caption']), exports.extensions = new Set(['tiff', 'tif', 'png', 'gif', 'jpg', 'jpeg', 'webp', 'xcf', 'pdf', 'svg', 'djvu']);
|
|
53
52
|
/**
|
|
54
53
|
* 获取网址
|
|
55
54
|
* @param link 外链
|
|
@@ -63,33 +62,34 @@ const getUrl = (link) => {
|
|
|
63
62
|
}
|
|
64
63
|
return new URL(link).href;
|
|
65
64
|
};
|
|
66
|
-
function validate(key, val, config,
|
|
65
|
+
function validate(key, val, config, extOrType, halfParsed) {
|
|
67
66
|
val = (0, string_1.removeComment)(val).trim();
|
|
68
67
|
let value = val.replace(key === 'link' ? /\0\d+[tq]\x7F/gu : /\0\d+t\x7F/gu, '').trim();
|
|
69
68
|
switch (key) {
|
|
70
69
|
case 'width':
|
|
71
70
|
return !value && Boolean(val) || /^(?:\d+x?|\d*x\d+)(?:\s*px)?$/u.test(value);
|
|
72
71
|
case 'link': {
|
|
72
|
+
const isGalleryImage = extOrType === 'gallery-image';
|
|
73
73
|
if (!value) {
|
|
74
74
|
return val;
|
|
75
75
|
}
|
|
76
76
|
else if (getUrlLikeRegex(config.protocol).test(value)) {
|
|
77
|
-
return getUrlRegex(config.protocol).test(value)
|
|
77
|
+
return getUrlRegex(config.protocol).test(value) ? val : isGalleryImage;
|
|
78
78
|
}
|
|
79
79
|
else if (value.startsWith('[[') && value.endsWith(']]')) {
|
|
80
80
|
value = value.slice(2, -2);
|
|
81
81
|
}
|
|
82
82
|
const title = index_1.default.normalizeTitle(value, 0, false, config, { halfParsed, decode: true, selfLink: true, page: '' });
|
|
83
|
-
return title.valid
|
|
83
|
+
return title.valid ? title : isGalleryImage;
|
|
84
84
|
}
|
|
85
85
|
case 'lang':
|
|
86
|
-
return (
|
|
86
|
+
return (extOrType === 'svg' || extOrType === 'svgz') && !/[^a-z\d-]/u.test(value);
|
|
87
87
|
case 'alt':
|
|
88
88
|
case 'class':
|
|
89
89
|
case 'manualthumb':
|
|
90
90
|
return true;
|
|
91
91
|
case 'page':
|
|
92
|
-
return (
|
|
92
|
+
return (extOrType === 'djvu' || extOrType === 'djv' || extOrType === 'pdf') && Number(value) > 0;
|
|
93
93
|
default:
|
|
94
94
|
return Boolean(value) && !isNaN(value);
|
|
95
95
|
}
|
|
@@ -139,10 +139,12 @@ let ImageParameterToken = (() => {
|
|
|
139
139
|
return debug_1.Shadow.run(() => {
|
|
140
140
|
const token = new index_2.Token(value, this.getAttribute('config'));
|
|
141
141
|
token.parseOnce(0, this.getAttribute('include')).parseOnce();
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
142
|
+
if (/^\0\d+m\x7F/u.test(token.firstChild.toString())) {
|
|
143
|
+
return value;
|
|
144
|
+
}
|
|
145
|
+
const link = validate('link', value, this.getAttribute('config'), this.parentNode?.type);
|
|
146
|
+
return link === true ? undefined : link;
|
|
147
|
+
}, index_1.default);
|
|
146
148
|
}
|
|
147
149
|
}
|
|
148
150
|
/** @param str 图片参数 */
|
|
@@ -153,7 +155,7 @@ let ImageParameterToken = (() => {
|
|
|
153
155
|
mt = regex.exec(str);
|
|
154
156
|
return mt
|
|
155
157
|
&& (mt.length !== 4
|
|
156
|
-
|| validate(key, mt[2], config,
|
|
158
|
+
|| validate(key, mt[2], config, extension, true) !== false);
|
|
157
159
|
});
|
|
158
160
|
// @ts-expect-error mt already assigned
|
|
159
161
|
if (param && mt) {
|
|
@@ -182,7 +184,7 @@ let ImageParameterToken = (() => {
|
|
|
182
184
|
}
|
|
183
185
|
/** @private */
|
|
184
186
|
afterBuild() {
|
|
185
|
-
if (this.parentNode?.is('gallery-image') && !
|
|
187
|
+
if (this.parentNode?.is('gallery-image') && !constants_1.galleryParams.has(this.name)) {
|
|
186
188
|
this.setAttribute('name', 'invalid');
|
|
187
189
|
}
|
|
188
190
|
super.afterBuild();
|
|
@@ -246,7 +248,7 @@ let ImageParameterToken = (() => {
|
|
|
246
248
|
const rule = 'invalid-gallery', s = lintConfig.getSeverity(rule, 'thumb');
|
|
247
249
|
if (s && !this.querySelector('arg,magic-word,template')) {
|
|
248
250
|
const { valid, ns, extension, } = this.thumb;
|
|
249
|
-
if (!valid || ns !== 6 || !
|
|
251
|
+
if (!valid || ns !== 6 || !constants_1.extensions.has(extension)) {
|
|
250
252
|
errors.push((0, lint_1.generateForSelf)(this, { start }, rule, 'invalid-thumb', s));
|
|
251
253
|
}
|
|
252
254
|
}
|
package/dist/src/index.js
CHANGED
|
@@ -109,7 +109,7 @@ class Token extends element_1.AstElement {
|
|
|
109
109
|
}
|
|
110
110
|
/** @private */
|
|
111
111
|
parseOnce(n = this.#stage, include = false, tidy) {
|
|
112
|
-
if (n < this.#stage || this.length
|
|
112
|
+
if (n < this.#stage || this.length !== 1 || !this.isPlain()) {
|
|
113
113
|
return this;
|
|
114
114
|
}
|
|
115
115
|
else if (this.#stage >= constants_1.MAX_STAGE) {
|
|
@@ -168,13 +168,13 @@ class Token extends element_1.AstElement {
|
|
|
168
168
|
buildFromStr(str, type) {
|
|
169
169
|
const nodes = str.split(/[\0\x7F]/u).map((s, i) => {
|
|
170
170
|
if (i % 2 === 0) {
|
|
171
|
-
return new text_1.AstText(s);
|
|
171
|
+
return s && new text_1.AstText(s);
|
|
172
172
|
}
|
|
173
173
|
else if (isNaN(s.slice(-1))) {
|
|
174
174
|
return this.#accum[Number(s.slice(0, -1))];
|
|
175
175
|
}
|
|
176
176
|
throw new Error(`Failed to build! Unrecognized token: ${s}`);
|
|
177
|
-
});
|
|
177
|
+
}).filter(node => node !== '');
|
|
178
178
|
if (type === constants_1.BuildMethod.String) {
|
|
179
179
|
return nodes.map(String).join('');
|
|
180
180
|
}
|
|
@@ -189,7 +189,6 @@ class Token extends element_1.AstElement {
|
|
|
189
189
|
const { length, firstChild } = this, str = firstChild?.toString();
|
|
190
190
|
if (length === 1 && firstChild.type === 'text' && str.includes('\0')) {
|
|
191
191
|
(0, debug_1.setChildNodes)(this, 0, 1, this.buildFromStr(str));
|
|
192
|
-
this.normalize();
|
|
193
192
|
if (this.type === 'root') {
|
|
194
193
|
for (const token of this.#accum) {
|
|
195
194
|
token?.build(); // eslint-disable-line @typescript-eslint/no-unnecessary-condition
|
|
@@ -462,7 +461,7 @@ class Token extends element_1.AstElement {
|
|
|
462
461
|
}
|
|
463
462
|
if (needFix && errors.some(({ fix }) => fix)) {
|
|
464
463
|
// 倒序修复,跳过嵌套的修复
|
|
465
|
-
const fixable = errors.map(({ fix }) => fix).filter(
|
|
464
|
+
const fixable = errors.map(({ fix }) => fix).filter(fix => fix !== undefined).sort(({ range: [aFrom, aTo] }, { range: [bFrom, bTo] }) => aTo === bTo ? bFrom - aFrom : bTo - aTo);
|
|
466
465
|
let i = Infinity, output = wikitext;
|
|
467
466
|
for (const { range: [from, to], text: t } of fixable) {
|
|
468
467
|
if (to <= i) {
|