wikilint 2.28.1 → 2.29.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/data/ext/ThirdPartyNotices.txt +33 -0
- package/data/ext/mapframe.json +489 -2
- package/dist/base.d.mts +4 -2
- package/dist/base.d.ts +4 -2
- package/dist/base.js +1 -0
- package/dist/base.mjs +2 -1
- package/dist/bin/config.js +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +23 -2
- package/dist/lib/document.d.ts +23 -7
- package/dist/lib/document.js +7 -27
- package/dist/lib/element.js +1 -1
- package/dist/lib/lintConfig.js +2 -0
- package/dist/lib/lsp.d.ts +1 -12
- package/dist/lib/lsp.js +41 -75
- package/dist/lib/node.js +23 -20
- package/dist/lib/title.d.ts +3 -1
- package/dist/lib/title.js +37 -9
- package/dist/mixin/elementLike.js +14 -9
- package/dist/parser/commentAndExt.js +30 -26
- package/dist/parser/links.js +4 -3
- package/dist/parser/redirect.js +1 -1
- package/dist/parser/selector.js +6 -8
- package/dist/src/arg.js +2 -2
- package/dist/src/attribute.js +27 -0
- package/dist/src/attributes.js +1 -1
- package/dist/src/converter.js +6 -3
- package/dist/src/imageParameter.d.ts +3 -1
- package/dist/src/imageParameter.js +18 -3
- package/dist/src/index.d.ts +8 -0
- package/dist/src/index.js +21 -28
- package/dist/src/link/file.js +7 -7
- package/dist/src/link/galleryImage.js +1 -1
- package/dist/src/link/redirectTarget.js +1 -1
- package/dist/src/multiLine/gallery.js +2 -2
- package/dist/src/multiLine/imagemap.js +3 -4
- package/dist/src/multiLine/paramTag.js +2 -2
- package/dist/src/nowiki/index.js +59 -2
- package/dist/src/table/base.js +1 -2
- package/dist/src/table/index.js +1 -2
- package/dist/src/transclude.js +3 -3
- package/dist/util/constants.js +3 -1
- package/dist/util/debug.js +1 -1
- package/dist/util/search.js +16 -0
- package/dist/util/sharable.js +27 -3
- package/dist/util/sharable.mjs +28 -4
- package/i18n/en.json +2 -0
- package/i18n/zh-hans.json +2 -0
- package/i18n/zh-hant.json +2 -0
- package/package.json +5 -3
- package/data/ext/maplink.json +0 -4
package/dist/lib/document.d.ts
CHANGED
|
@@ -3,14 +3,30 @@ import type { TextDocument } from 'vscode-languageserver-textdocument';
|
|
|
3
3
|
import type { JSONDocument } from 'vscode-json-languageservice';
|
|
4
4
|
import type { Stylesheet } from 'vscode-css-languageservice';
|
|
5
5
|
import type { Token } from '../internal';
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
export interface TexvcLocation {
|
|
7
|
+
offset: number;
|
|
8
|
+
line: number;
|
|
9
|
+
column: number;
|
|
8
10
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
declare interface Texvcjs {
|
|
12
|
+
check(input: string, options?: {
|
|
13
|
+
usemhchem?: boolean;
|
|
14
|
+
}): {
|
|
15
|
+
status: '+';
|
|
16
|
+
} | {
|
|
17
|
+
status: 'C';
|
|
18
|
+
} | {
|
|
19
|
+
status: 'F' | 'S';
|
|
20
|
+
error: {
|
|
21
|
+
message: string;
|
|
22
|
+
location: {
|
|
23
|
+
start: TexvcLocation;
|
|
24
|
+
end: TexvcLocation;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export declare const texvcjs: Texvcjs | undefined;
|
|
14
30
|
export declare const jsonTags: string[];
|
|
15
31
|
export declare const jsonLSP: import("vscode-json-languageservice").LanguageService | undefined;
|
|
16
32
|
export declare const cssLSP: import("vscode-css-languageservice").LanguageService | undefined;
|
package/dist/lib/document.js
CHANGED
|
@@ -3,38 +3,18 @@ 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.EmbeddedCSSDocument = exports.EmbeddedJSONDocument = exports.stylelint = exports.htmlData = exports.cssLSP = exports.jsonLSP = exports.jsonTags = exports.
|
|
6
|
+
exports.EmbeddedCSSDocument = exports.EmbeddedJSONDocument = exports.stylelint = exports.htmlData = exports.cssLSP = exports.jsonLSP = exports.jsonTags = exports.texvcjs = void 0;
|
|
7
7
|
const path_1 = __importDefault(require("path"));
|
|
8
8
|
const common_1 = require("@bhsd/common");
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Load MathJax
|
|
12
|
-
* @param id MathJax module ID
|
|
13
|
-
*/
|
|
14
|
-
const loadMathJax = (id = 'mathjax') => {
|
|
9
|
+
exports.texvcjs = (() => {
|
|
15
10
|
try {
|
|
16
|
-
|
|
17
|
-
MathJax ??= jax.init({
|
|
18
|
-
loader: {
|
|
19
|
-
load: ['input/tex', '[tex]/mhchem'],
|
|
20
|
-
},
|
|
21
|
-
tex: {
|
|
22
|
-
packages: { '[+]': ['mhchem'] },
|
|
23
|
-
/** @ignore */
|
|
24
|
-
formatError(_, error) {
|
|
25
|
-
throw error;
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
startup: { typeset: false },
|
|
29
|
-
});
|
|
30
|
-
return MathJax;
|
|
11
|
+
return require('mathoid-texvcjs');
|
|
31
12
|
}
|
|
32
13
|
catch {
|
|
33
14
|
/* istanbul ignore next */
|
|
34
15
|
return undefined;
|
|
35
16
|
}
|
|
36
|
-
};
|
|
37
|
-
exports.loadMathJax = loadMathJax;
|
|
17
|
+
})();
|
|
38
18
|
exports.jsonTags = ['templatedata', 'mapframe', 'maplink'];
|
|
39
19
|
exports.jsonLSP = (() => {
|
|
40
20
|
try {
|
|
@@ -44,12 +24,12 @@ exports.jsonLSP = (() => {
|
|
|
44
24
|
async schemaRequestService(uri) {
|
|
45
25
|
return (await fetch(uri)).text();
|
|
46
26
|
},
|
|
47
|
-
});
|
|
27
|
+
}), dir = path_1.default.join('..', '..', 'data', 'ext');
|
|
48
28
|
lsp.configure({
|
|
49
29
|
schemas: exports.jsonTags.map((tag) => {
|
|
50
|
-
const uri = path_1.default.join(
|
|
30
|
+
const uri = path_1.default.join(dir, tag);
|
|
51
31
|
try {
|
|
52
|
-
const schema = require(uri);
|
|
32
|
+
const schema = require(tag === 'maplink' ? path_1.default.join(dir, 'mapframe') : uri);
|
|
53
33
|
return {
|
|
54
34
|
uri,
|
|
55
35
|
fileMatch: [tag],
|
package/dist/lib/element.js
CHANGED
|
@@ -250,7 +250,7 @@ let AstElement = (() => {
|
|
|
250
250
|
child.setAttribute('aIndex', cur);
|
|
251
251
|
const childErrors = child.lint(cur, re);
|
|
252
252
|
if (childErrors.length > 0) {
|
|
253
|
-
|
|
253
|
+
Array.prototype.push.apply(errors, childErrors);
|
|
254
254
|
}
|
|
255
255
|
cur += child.toString().length + this.getGaps(i);
|
|
256
256
|
}
|
package/dist/lib/lintConfig.js
CHANGED
|
@@ -52,6 +52,7 @@ const defaultLintRuleConfig = {
|
|
|
52
52
|
// extension: 2,
|
|
53
53
|
// image: 2,
|
|
54
54
|
parameter: 1,
|
|
55
|
+
// thumb: 2,
|
|
55
56
|
},
|
|
56
57
|
],
|
|
57
58
|
'invalid-imagemap': [
|
|
@@ -217,6 +218,7 @@ const defaultLintRuleConfig = {
|
|
|
217
218
|
warn: 1,
|
|
218
219
|
},
|
|
219
220
|
],
|
|
221
|
+
'invalid-math': 2,
|
|
220
222
|
};
|
|
221
223
|
Object.freeze(defaultLintRuleConfig);
|
|
222
224
|
const defaultLintConfig = {
|
package/dist/lib/lsp.d.ts
CHANGED
|
@@ -1,28 +1,17 @@
|
|
|
1
1
|
import Parser from '../index';
|
|
2
2
|
import type { Range, Position, ColorInformation, ColorPresentation, FoldingRange, DocumentLink, Location, WorkspaceEdit, Diagnostic as DiagnosticBase, TextEdit, Hover, SignatureHelp, InlayHint, CodeAction, DocumentSymbol } from 'vscode-languageserver-types';
|
|
3
3
|
import type { Config, LanguageService as LanguageServiceBase, CompletionItem, SignatureData } from '../base';
|
|
4
|
-
import type {
|
|
4
|
+
import type { AttributeToken } from '../internal';
|
|
5
5
|
export interface QuickFixData extends TextEdit {
|
|
6
6
|
title: string;
|
|
7
7
|
fix: boolean;
|
|
8
8
|
}
|
|
9
9
|
export declare const tasks: WeakMap<object, Parser.LanguageService>;
|
|
10
|
-
/**
|
|
11
|
-
* Check if a token is a plain attribute.
|
|
12
|
-
* @param token
|
|
13
|
-
* @param token.type
|
|
14
|
-
* @param token.parentNode
|
|
15
|
-
* @param token.length
|
|
16
|
-
* @param token.firstChild
|
|
17
|
-
* @param style whether it is a style attribute
|
|
18
|
-
*/
|
|
19
|
-
export declare const isAttr: ({ type, parentNode, length, firstChild }: Token, style?: boolean) => boolean | undefined;
|
|
20
10
|
/** VSCode-style language service */
|
|
21
11
|
export declare class LanguageService implements LanguageServiceBase {
|
|
22
12
|
#private;
|
|
23
13
|
/** @since v1.17.1 */
|
|
24
14
|
include: boolean;
|
|
25
|
-
lilypond: string;
|
|
26
15
|
/** @param uri 任务标识 */
|
|
27
16
|
constructor(uri: object);
|
|
28
17
|
/** @implements */
|
package/dist/lib/lsp.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.LanguageService = exports.
|
|
6
|
+
exports.LanguageService = exports.tasks = void 0;
|
|
7
7
|
const common_1 = require("@bhsd/common");
|
|
8
8
|
const cm_util_1 = require("@bhsd/cm-util");
|
|
9
9
|
const base_1 = require("../base");
|
|
@@ -18,9 +18,11 @@ const util_1 = __importDefault(require("util"));
|
|
|
18
18
|
const child_process_1 = require("child_process");
|
|
19
19
|
const crypto_1 = require("crypto");
|
|
20
20
|
const stylelint_util_1 = require("@bhsd/stylelint-util");
|
|
21
|
+
const search_1 = __importDefault(require("../util/search"));
|
|
22
|
+
const constants_1 = require("../util/constants");
|
|
21
23
|
const document_1 = require("./document");
|
|
22
24
|
/** @see https://www.npmjs.com/package/stylelint-config-recommended */
|
|
23
|
-
const cssRules = { 'block-no-empty': null },
|
|
25
|
+
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();
|
|
24
26
|
let colors;
|
|
25
27
|
/* NOT FOR BROWSER ONLY END */
|
|
26
28
|
exports.tasks = new WeakMap();
|
|
@@ -53,7 +55,6 @@ const isAttr = ({ type, parentNode, length, firstChild }, style) => type === 'at
|
|
|
53
55
|
&& (!style
|
|
54
56
|
|| parentNode.name === 'style'
|
|
55
57
|
&& Boolean(document_1.cssLSP));
|
|
56
|
-
exports.isAttr = isAttr;
|
|
57
58
|
/**
|
|
58
59
|
* Check if a token is an HTML attribute.
|
|
59
60
|
* @param token
|
|
@@ -311,10 +312,11 @@ class LanguageService {
|
|
|
311
312
|
config;
|
|
312
313
|
/** @private */
|
|
313
314
|
data;
|
|
315
|
+
/* NOT FOR BROWSER ONLY */
|
|
316
|
+
/** @private */
|
|
314
317
|
lilypond;
|
|
315
318
|
#lilypondData;
|
|
316
319
|
#mathData;
|
|
317
|
-
#mathSet;
|
|
318
320
|
/* NOT FOR BROWSER ONLY END */
|
|
319
321
|
/** @param uri 任务标识 */
|
|
320
322
|
constructor(uri) {
|
|
@@ -323,7 +325,6 @@ class LanguageService {
|
|
|
323
325
|
const dataDir = path_1.default.join('..', '..', 'data'), extDir = path_1.default.join(dataDir, 'ext');
|
|
324
326
|
this.#lilypondData = require(path_1.default.join(extDir, 'score'));
|
|
325
327
|
this.#mathData = require(path_1.default.join(extDir, 'math'));
|
|
326
|
-
this.#mathSet = new Set(this.#mathData);
|
|
327
328
|
/* NOT FOR BROWSER ONLY END */
|
|
328
329
|
Object.defineProperties(this, {
|
|
329
330
|
config: { enumerable: false },
|
|
@@ -451,8 +452,7 @@ class LanguageService {
|
|
|
451
452
|
})();
|
|
452
453
|
const re = await colors;
|
|
453
454
|
/* NOT FOR BROWSER ONLY END */
|
|
454
|
-
return root.querySelectorAll('attr-value,parameter-value,arg-default').reverse()
|
|
455
|
-
.flatMap(token => {
|
|
455
|
+
return root.querySelectorAll('attr-value,parameter-value,arg-default').reverse().flatMap(token => {
|
|
456
456
|
const { type, childNodes,
|
|
457
457
|
/* NOT FOR BROWSER ONLY */
|
|
458
458
|
parentNode, } = token;
|
|
@@ -460,7 +460,7 @@ class LanguageService {
|
|
|
460
460
|
return [];
|
|
461
461
|
/* NOT FOR BROWSER ONLY */
|
|
462
462
|
}
|
|
463
|
-
else if (
|
|
463
|
+
else if (isAttr(token, true)) {
|
|
464
464
|
const textDoc = new document_1.EmbeddedCSSDocument(root, token);
|
|
465
465
|
return document_1.cssLSP.findDocumentColors(textDoc, textDoc.styleSheet);
|
|
466
466
|
/* NOT FOR BROWSER ONLY END */
|
|
@@ -468,8 +468,7 @@ class LanguageService {
|
|
|
468
468
|
/* NOT FOR BROWSER ONLY */
|
|
469
469
|
const isStyle = re && type === 'attr-value' && parentNode.name === 'style';
|
|
470
470
|
/* NOT FOR BROWSER ONLY END */
|
|
471
|
-
return childNodes.filter((child) => child.type === 'text').reverse()
|
|
472
|
-
.flatMap(child => {
|
|
471
|
+
return childNodes.filter((child) => child.type === 'text').reverse().flatMap(child => {
|
|
473
472
|
const { data } = child, parts = (0, common_1.splitColors)(data, hsl).filter(([, , , isColor]) => isColor);
|
|
474
473
|
/* NOT FOR BROWSER ONLY */
|
|
475
474
|
if (isStyle) {
|
|
@@ -697,7 +696,7 @@ class LanguageService {
|
|
|
697
696
|
: undefined;
|
|
698
697
|
/* NOT FOR BROWSER ONLY */
|
|
699
698
|
}
|
|
700
|
-
else if (
|
|
699
|
+
else if (isAttr(cur, true)) {
|
|
701
700
|
const textDoc = new document_1.EmbeddedCSSDocument(root, cur);
|
|
702
701
|
return document_1.cssLSP.doComplete(textDoc, position, textDoc.styleSheet).items.map((item) => ({
|
|
703
702
|
...item,
|
|
@@ -732,7 +731,7 @@ class LanguageService {
|
|
|
732
731
|
];
|
|
733
732
|
}
|
|
734
733
|
}
|
|
735
|
-
else if (type === 'ext-inner' && mathTags.
|
|
734
|
+
else if (type === 'ext-inner' && constants_1.mathTags.has(cur.name)) {
|
|
736
735
|
const word = /(?<!\\)\\[a-z]+$/iu.exec(curLine.slice(0, character))?.[0];
|
|
737
736
|
if (word) {
|
|
738
737
|
const data = this.#mathData;
|
|
@@ -742,7 +741,7 @@ class LanguageService {
|
|
|
742
741
|
}
|
|
743
742
|
/* NOT FOR BROWSER ONLY END */
|
|
744
743
|
}
|
|
745
|
-
else if (
|
|
744
|
+
else if (isAttr(cur) && isHtmlAttr(parentNode)) {
|
|
746
745
|
const data = (0, lint_1.provideValues)(parentNode.tag, parentNode.name);
|
|
747
746
|
if (data.length === 0) {
|
|
748
747
|
return undefined;
|
|
@@ -774,8 +773,7 @@ class LanguageService {
|
|
|
774
773
|
severity: severity === 'error' ? 1 : 2,
|
|
775
774
|
source:
|
|
776
775
|
/* eslint-disable @stylistic/operator-linebreak */
|
|
777
|
-
rule
|
|
778
|
-
'css' :
|
|
776
|
+
sources[rule] ??
|
|
779
777
|
'WikiLint',
|
|
780
778
|
code: code ??
|
|
781
779
|
/* eslint-enable @stylistic/operator-linebreak */
|
|
@@ -804,7 +802,7 @@ class LanguageService {
|
|
|
804
802
|
return acc;
|
|
805
803
|
});
|
|
806
804
|
return cssErrors.map(({ rule, text: msg, severity, line, column, endLine = line, endColumn = column, fix, }) => {
|
|
807
|
-
const i =
|
|
805
|
+
const i = (0, search_1.default)(bottoms, line, (bottom, needle) => bottom - needle);
|
|
808
806
|
return {
|
|
809
807
|
range: {
|
|
810
808
|
start: getStylelintPos(rects[i], bottoms[i], line, column - 1),
|
|
@@ -892,42 +890,6 @@ class LanguageService {
|
|
|
892
890
|
}));
|
|
893
891
|
}
|
|
894
892
|
}
|
|
895
|
-
const MathJax = await (0, document_1.loadMathJax)(this.mathjax), data = this.#mathSet, mathDiagnostics = root.querySelectorAll(mathSelector)
|
|
896
|
-
.map(token => {
|
|
897
|
-
const { selfClosing, innerText, lastChild, name } = token;
|
|
898
|
-
if (selfClosing) {
|
|
899
|
-
return [];
|
|
900
|
-
}
|
|
901
|
-
const hasCe = name === 'math' && token.hasAttr('chem'), mathErrors = [...innerText.matchAll(/(?<!\\)\\[a-z]+/giu)]
|
|
902
|
-
.filter(([macro]) => !(hasCe && macro === String.raw `\ce` || data.has(macro)))
|
|
903
|
-
.map(({ 0: macro, index }) => {
|
|
904
|
-
const aIndex = lastChild.getAbsoluteIndex() + index;
|
|
905
|
-
return {
|
|
906
|
-
range: createRange(root, aIndex, aIndex + macro.length),
|
|
907
|
-
severity: 2,
|
|
908
|
-
source: 'MathJax',
|
|
909
|
-
code: 'UnknownMacro',
|
|
910
|
-
message: `Unknown macro "${macro}"`,
|
|
911
|
-
};
|
|
912
|
-
});
|
|
913
|
-
if (MathJax) {
|
|
914
|
-
try {
|
|
915
|
-
MathJax.tex2mml(name === 'math' ? innerText : String.raw `\ce{${innerText}}`);
|
|
916
|
-
}
|
|
917
|
-
catch (e) {
|
|
918
|
-
if (e && typeof e === 'object' && 'id' in e && 'message' in e) {
|
|
919
|
-
mathErrors.push({
|
|
920
|
-
range: createNodeRange(lastChild),
|
|
921
|
-
severity: 2,
|
|
922
|
-
source: 'MathJax',
|
|
923
|
-
code: e.id,
|
|
924
|
-
message: e.message,
|
|
925
|
-
});
|
|
926
|
-
}
|
|
927
|
-
}
|
|
928
|
-
}
|
|
929
|
-
return mathErrors;
|
|
930
|
-
});
|
|
931
893
|
/* NOT FOR BROWSER ONLY END */
|
|
932
894
|
return [
|
|
933
895
|
diagnostics,
|
|
@@ -935,7 +897,6 @@ class LanguageService {
|
|
|
935
897
|
jsonDiagnostics,
|
|
936
898
|
/* NOT FOR BROWSER ONLY */
|
|
937
899
|
lilypondDiagnostics,
|
|
938
|
-
mathDiagnostics,
|
|
939
900
|
].flat(2);
|
|
940
901
|
}
|
|
941
902
|
/**
|
|
@@ -1013,7 +974,7 @@ class LanguageService {
|
|
|
1013
974
|
if (!selfClosing) {
|
|
1014
975
|
const foldingRanges = document_1.jsonLSP.getFoldingRanges(new document_1.EmbeddedJSONDocument(root, lastChild));
|
|
1015
976
|
if (foldingRanges.length > 0) {
|
|
1016
|
-
|
|
977
|
+
Array.prototype.push.apply(ranges, foldingRanges);
|
|
1017
978
|
}
|
|
1018
979
|
}
|
|
1019
980
|
}
|
|
@@ -1031,7 +992,7 @@ class LanguageService {
|
|
|
1031
992
|
this.config ??= index_1.default.getConfig();
|
|
1032
993
|
const { articlePath, protocol } = this.config, absolute = articlePath?.includes('//'), protocolRegex = getLinkRegex(protocol);
|
|
1033
994
|
return (await this.#queue(text))
|
|
1034
|
-
.querySelectorAll(`magic-link,ext-link-url,free-ext-link,attr-value
|
|
995
|
+
.querySelectorAll(`magic-link,ext-link-url,free-ext-link,attr-value${absolute ? ',link-target,template-name,invoke-module,magic-word#filepath,magic-word#widget' : ''},image-parameter#link,image-parameter#manualthumb`)
|
|
1035
996
|
.reverse()
|
|
1036
997
|
.map((token) => {
|
|
1037
998
|
let name;
|
|
@@ -1039,11 +1000,16 @@ class LanguageService {
|
|
|
1039
1000
|
({ name } = token);
|
|
1040
1001
|
token = token.childNodes[1].lastChild; // eslint-disable-line no-param-reassign
|
|
1041
1002
|
}
|
|
1003
|
+
else if (token.is('image-parameter')) {
|
|
1004
|
+
({ name } = token);
|
|
1005
|
+
}
|
|
1042
1006
|
const { type, parentNode, firstChild, lastChild, childNodes, length } = token, { tag } = parentNode;
|
|
1043
1007
|
name ??= parentNode.name;
|
|
1044
1008
|
if (!(type !== 'attr-value'
|
|
1009
|
+
|| name === 'cite' && ['blockquote', 'del', 'ins', 'q'].includes(tag)
|
|
1045
1010
|
|| name === 'src' && ['templatestyles', 'img'].includes(tag)
|
|
1046
|
-
|| name === '
|
|
1011
|
+
|| name === 'templatename' && tag === 'rss'
|
|
1012
|
+
|| name === 'file' && tag === 'phonos')
|
|
1047
1013
|
|| !isPlain(token)) {
|
|
1048
1014
|
return false;
|
|
1049
1015
|
}
|
|
@@ -1068,29 +1034,29 @@ class LanguageService {
|
|
|
1068
1034
|
}
|
|
1069
1035
|
target = parentNode.link.getUrl(articlePath);
|
|
1070
1036
|
}
|
|
1071
|
-
else if (type === 'template-name') {
|
|
1037
|
+
else if (type === 'link-target' || type === 'template-name') {
|
|
1072
1038
|
target = parentNode.getAttribute('title').getUrl(articlePath);
|
|
1073
1039
|
}
|
|
1074
|
-
else if (['
|
|
1075
|
-
|| type === 'attr-value' && name === 'src' && tag === 'templatestyles'
|
|
1076
|
-
|
|
1040
|
+
else if (['invoke-module', 'parameter-value'].includes(type)
|
|
1041
|
+
|| type === 'attr-value' && (name === 'src' && tag === 'templatestyles'
|
|
1042
|
+
|| name === 'templatename' && tag === 'rss'
|
|
1043
|
+
|| name === 'file' && tag === 'phonos')
|
|
1044
|
+
|| type === 'image-parameter' && (name === 'manualthumb' || !protocolRegex.test(target))) {
|
|
1077
1045
|
if (!absolute || target.startsWith('/')) {
|
|
1078
1046
|
return false;
|
|
1079
1047
|
}
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
// no default
|
|
1048
|
+
else if (type === 'image-parameter' && name === 'manualthumb'
|
|
1049
|
+
|| type === 'parameter-value' && name === 'filepath'
|
|
1050
|
+
|| type === 'attr-value' && tag === 'phonos') {
|
|
1051
|
+
target = `File:${target}`;
|
|
1052
|
+
}
|
|
1053
|
+
else if (type === 'parameter-value') {
|
|
1054
|
+
target = `Widget:${target}`;
|
|
1055
|
+
}
|
|
1056
|
+
else if (type === 'invoke-module') {
|
|
1057
|
+
target = `Module:${target}`;
|
|
1091
1058
|
}
|
|
1092
|
-
const title = index_1.default
|
|
1093
|
-
.normalizeTitle(target, ns, false, this.config, { temporary: true });
|
|
1059
|
+
const title = index_1.default.normalizeTitle(target, type === 'attr-value' ? 10 : 0, false, this.config, { temporary: true });
|
|
1094
1060
|
if (!title.valid) {
|
|
1095
1061
|
return false;
|
|
1096
1062
|
}
|
|
@@ -1269,7 +1235,7 @@ class LanguageService {
|
|
|
1269
1235
|
}
|
|
1270
1236
|
/* NOT FOR BROWSER ONLY */
|
|
1271
1237
|
}
|
|
1272
|
-
else if (
|
|
1238
|
+
else if (isAttr(offsetNode, true)) {
|
|
1273
1239
|
const textDoc = new document_1.EmbeddedCSSDocument(root, offsetNode);
|
|
1274
1240
|
return document_1.cssLSP.doHover(textDoc, position, textDoc.styleSheet) ?? undefined;
|
|
1275
1241
|
}
|
|
@@ -1392,7 +1358,7 @@ class LanguageService {
|
|
|
1392
1358
|
}
|
|
1393
1359
|
/** @private */
|
|
1394
1360
|
findStyleTokens() {
|
|
1395
|
-
return this.#done.querySelectorAll(cssSelector).filter(({ lastChild }) =>
|
|
1361
|
+
return this.#done.querySelectorAll(cssSelector).filter(({ lastChild }) => isAttr(lastChild));
|
|
1396
1362
|
}
|
|
1397
1363
|
/**
|
|
1398
1364
|
* Provide refactoring actions
|
package/dist/lib/node.js
CHANGED
|
@@ -33,9 +33,13 @@ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn,
|
|
|
33
33
|
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
34
34
|
done = true;
|
|
35
35
|
};
|
|
36
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
37
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
38
|
+
};
|
|
36
39
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
40
|
exports.AstNode = void 0;
|
|
38
41
|
/* eslint-disable @typescript-eslint/no-base-to-string */
|
|
42
|
+
const search_1 = __importDefault(require("../util/search"));
|
|
39
43
|
const lint_1 = require("../util/lint");
|
|
40
44
|
const debug_1 = require("../util/debug");
|
|
41
45
|
const cached_1 = require("../mixin/cached");
|
|
@@ -160,7 +164,7 @@ let AstNode = (() => {
|
|
|
160
164
|
const { length } = String(this);
|
|
161
165
|
index += index < 0 ? length : 0;
|
|
162
166
|
if (index >= 0 && index <= length) {
|
|
163
|
-
const lines = this.getLines(), top =
|
|
167
|
+
const lines = this.getLines(), top = (0, search_1.default)(lines, index, ([, , end], needle) => end - needle);
|
|
164
168
|
return { top, left: index - lines[top][1] };
|
|
165
169
|
}
|
|
166
170
|
return undefined;
|
|
@@ -184,25 +188,23 @@ let AstNode = (() => {
|
|
|
184
188
|
* @param j rank of the child node / 子节点序号
|
|
185
189
|
*/
|
|
186
190
|
getRelativeIndex(j) {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
: 0;
|
|
193
|
-
}
|
|
194
|
-
return (0, lint_1.cache)(this.#rIndex[j], () => {
|
|
195
|
-
const { childNodes } = this, n = j + (j < 0 ? childNodes.length : 0);
|
|
196
|
-
let acc = this.getAttribute('padding');
|
|
197
|
-
for (let i = 0; i < n; i++) {
|
|
198
|
-
this.#rIndex[i] = [debug_1.Shadow.rev, acc];
|
|
199
|
-
acc += childNodes[i].toString().length + this.getGaps(i);
|
|
200
|
-
}
|
|
201
|
-
return acc;
|
|
202
|
-
}, value => {
|
|
203
|
-
this.#rIndex[j] = value;
|
|
204
|
-
});
|
|
191
|
+
if (j === undefined) {
|
|
192
|
+
const { parentNode } = this;
|
|
193
|
+
return parentNode
|
|
194
|
+
? parentNode.getRelativeIndex(parentNode.childNodes.indexOf(this))
|
|
195
|
+
: 0;
|
|
205
196
|
}
|
|
197
|
+
return (0, lint_1.cache)(this.#rIndex[j], () => {
|
|
198
|
+
const { childNodes } = this, n = j + (j < 0 ? childNodes.length : 0);
|
|
199
|
+
let acc = this.getAttribute('padding');
|
|
200
|
+
for (let i = 0; i < n; i++) {
|
|
201
|
+
this.#rIndex[i] = [debug_1.Shadow.rev, acc];
|
|
202
|
+
acc += childNodes[i].toString().length + this.getGaps(i);
|
|
203
|
+
}
|
|
204
|
+
return acc;
|
|
205
|
+
}, value => {
|
|
206
|
+
this.#rIndex[j] = value;
|
|
207
|
+
});
|
|
206
208
|
}
|
|
207
209
|
/**
|
|
208
210
|
* Get the absolute character index of the current node
|
|
@@ -210,7 +212,8 @@ let AstNode = (() => {
|
|
|
210
212
|
* 获取当前节点的绝对位置
|
|
211
213
|
*/
|
|
212
214
|
getAbsoluteIndex() {
|
|
213
|
-
|
|
215
|
+
// 也用于Prism-Wiki
|
|
216
|
+
return (0, lint_1.cache)(// eslint-disable-line no-unused-labels
|
|
214
217
|
this.#aIndex, () => {
|
|
215
218
|
const { parentNode } = this;
|
|
216
219
|
return parentNode ? parentNode.getAbsoluteIndex() + this.getRelativeIndex() : 0;
|
package/dist/lib/title.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export interface TitleOptions {
|
|
|
4
4
|
decode?: boolean | undefined;
|
|
5
5
|
selfLink?: boolean | undefined;
|
|
6
6
|
halfParsed?: boolean | undefined;
|
|
7
|
+
page?: string | undefined;
|
|
7
8
|
}
|
|
8
9
|
/**
|
|
9
10
|
* title object of a MediaWiki page
|
|
@@ -41,8 +42,9 @@ export declare class Title {
|
|
|
41
42
|
* @param opt.temporary 是否是临时标题
|
|
42
43
|
* @param opt.decode 是否需要解码
|
|
43
44
|
* @param opt.selfLink 是否允许selfLink
|
|
45
|
+
* @param opt.page 当前页面标题
|
|
44
46
|
*/
|
|
45
|
-
constructor(title: string, defaultNs: number, config: Config, { temporary, decode, selfLink }?: TitleOptions);
|
|
47
|
+
constructor(title: string, defaultNs: number, config: Config, { temporary, decode, selfLink, page }?: TitleOptions);
|
|
46
48
|
/**
|
|
47
49
|
* Check if the title is a redirect
|
|
48
50
|
*
|
package/dist/lib/title.js
CHANGED
|
@@ -3,6 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Title = void 0;
|
|
4
4
|
const common_1 = require("@bhsd/common");
|
|
5
5
|
const string_1 = require("../util/string");
|
|
6
|
+
/**
|
|
7
|
+
* 解析标题的路径
|
|
8
|
+
* @param title 标题
|
|
9
|
+
*/
|
|
10
|
+
const resolve = (title) => {
|
|
11
|
+
const [, { length }, sub] = /^((?:\.\.\/)*)([\s\S]*)/u.exec(title);
|
|
12
|
+
return [length / 3, sub];
|
|
13
|
+
};
|
|
6
14
|
/**
|
|
7
15
|
* title object of a MediaWiki page
|
|
8
16
|
*
|
|
@@ -14,6 +22,8 @@ class Title {
|
|
|
14
22
|
#path;
|
|
15
23
|
#ns;
|
|
16
24
|
#fragment;
|
|
25
|
+
/** @private */
|
|
26
|
+
page;
|
|
17
27
|
valid;
|
|
18
28
|
/** @private */
|
|
19
29
|
encoded = false;
|
|
@@ -62,9 +72,11 @@ class Title {
|
|
|
62
72
|
* @param opt.temporary 是否是临时标题
|
|
63
73
|
* @param opt.decode 是否需要解码
|
|
64
74
|
* @param opt.selfLink 是否允许selfLink
|
|
75
|
+
* @param opt.page 当前页面标题
|
|
65
76
|
*/
|
|
66
|
-
constructor(title, defaultNs, config, { temporary, decode, selfLink } = {}) {
|
|
67
|
-
|
|
77
|
+
constructor(title, defaultNs, config, { temporary, decode, selfLink, page } = {}) {
|
|
78
|
+
this.page = page;
|
|
79
|
+
const trimmed = title.trim(), subpage = trimmed.startsWith('../');
|
|
68
80
|
if (decode && title.includes('%')) {
|
|
69
81
|
try {
|
|
70
82
|
const encoded = /%(?!21|3[ce]|5[bd]|7[b-d])[\da-f]{2}/iu.test(title);
|
|
@@ -74,7 +86,7 @@ class Title {
|
|
|
74
86
|
catch { }
|
|
75
87
|
}
|
|
76
88
|
title = (0, string_1.decodeHtml)(title).replace(/[_ ]+/gu, ' ').trim();
|
|
77
|
-
if (subpage) {
|
|
89
|
+
if (subpage || page && trimmed.startsWith('/')) {
|
|
78
90
|
this.#ns = 0;
|
|
79
91
|
}
|
|
80
92
|
else {
|
|
@@ -105,10 +117,12 @@ class Title {
|
|
|
105
117
|
this.#fragment = fragment.replace(/ /gu, '_');
|
|
106
118
|
title = title.slice(0, i).trim();
|
|
107
119
|
}
|
|
120
|
+
const [level, sub] = subpage ? resolve(title) : [0, title];
|
|
108
121
|
this.valid = Boolean(title
|
|
109
122
|
|| selfLink && this.ns === 0 && this.#fragment !== undefined)
|
|
110
123
|
&& (0, string_1.decodeHtml)(title) === title
|
|
111
|
-
&&
|
|
124
|
+
&& (level === 0 || page === undefined || page.split('/', level + 1).length > level)
|
|
125
|
+
&& !/^:|\0\d+[eh!+-]\x7F|[<>[\]{}|\n]|%[\da-f]{2}|(?:^|\/)\.{1,2}(?:$|\/)/iu.test(sub);
|
|
112
126
|
this.main = title;
|
|
113
127
|
this.#namespaces = config.namespaces;
|
|
114
128
|
this.#path = config.articlePath || '/wiki/$1';
|
|
@@ -116,6 +130,23 @@ class Title {
|
|
|
116
130
|
this.#path += `${this.#path.endsWith('/') ? '' : '/'}$1`;
|
|
117
131
|
}
|
|
118
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* 生成标题
|
|
135
|
+
* @param prefix 前缀
|
|
136
|
+
*/
|
|
137
|
+
#getTitle(prefix) {
|
|
138
|
+
let title = (prefix + this.main).replace(/ /gu, '_');
|
|
139
|
+
if (title.startsWith('/')) {
|
|
140
|
+
title = (this.page ?? '') + title.replace(/(.)\/$/u, '$1');
|
|
141
|
+
}
|
|
142
|
+
else if (title.startsWith('../') && this.page?.includes('/')) {
|
|
143
|
+
const [level, sub] = resolve(title), dirs = this.page.split('/');
|
|
144
|
+
if (dirs.length > level) {
|
|
145
|
+
title = dirs.slice(0, -level).join('/') + (sub && '/') + sub;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return [false, title];
|
|
149
|
+
}
|
|
119
150
|
/**
|
|
120
151
|
* Check if the title is a redirect
|
|
121
152
|
*
|
|
@@ -123,11 +154,8 @@ class Title {
|
|
|
123
154
|
* @since v1.12.2
|
|
124
155
|
*/
|
|
125
156
|
getRedirection() {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
// eslint-disable-next-line prefer-const
|
|
129
|
-
let title = (prefix + this.main).replace(/ /gu, '_');
|
|
130
|
-
return [false, title];
|
|
157
|
+
const { prefix, } = this, pre = prefix, result = this.#getTitle(pre);
|
|
158
|
+
return result;
|
|
131
159
|
}
|
|
132
160
|
/** @private */
|
|
133
161
|
setFragment(fragment) {
|