wikiparser-node 1.18.3 → 1.19.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/README.md +1 -1
- package/bundle/bundle-es7.min.js +29 -28
- package/bundle/bundle-lsp.min.js +27 -26
- package/bundle/bundle.min.js +30 -29
- package/dist/addon/token.js +27 -19
- package/dist/addon/transclude.js +2 -2
- package/dist/base.d.mts +3 -2
- package/dist/base.d.ts +3 -2
- package/dist/index.d.ts +11 -2
- package/dist/index.js +8 -1
- package/dist/lib/document.d.ts +4 -0
- package/dist/lib/document.js +22 -2
- package/dist/lib/lsp.js +42 -11
- package/dist/lib/text.js +4 -2
- package/dist/parser/braces.js +57 -29
- package/dist/parser/commentAndExt.js +1 -1
- package/dist/src/arg.js +1 -1
- package/dist/src/attribute.js +1 -1
- package/dist/src/imageParameter.js +7 -5
- package/dist/src/index.js +7 -7
- package/dist/src/link/base.js +2 -2
- package/dist/src/paramTag/inputbox.js +9 -4
- package/dist/src/redirect.js +1 -1
- package/dist/src/table/index.d.ts +1 -0
- package/dist/src/table/index.js +1 -1
- package/dist/src/table/trBase.js +31 -16
- package/dist/src/tagPair/ext.js +4 -2
- package/dist/src/transclude.js +14 -6
- package/dist/util/diff.js +1 -1
- package/dist/util/html.js +0 -3
- package/extensions/dist/base.js +1 -1
- package/extensions/es7/base.js +1 -1
- package/extensions/typings.d.ts +2 -2
- package/package.json +7 -6
package/dist/addon/token.js
CHANGED
|
@@ -143,42 +143,50 @@ const expand = (wikitext, config, include, context, accum = [], stack = []) => {
|
|
|
143
143
|
return parseIf(accum, prev, c[cmp(var1, var2) ? 3 : 4]);
|
|
144
144
|
}
|
|
145
145
|
else if (known && name === 'switch') {
|
|
146
|
-
let defaultVal = '',
|
|
147
|
-
|
|
146
|
+
let defaultVal = '', j = 2,
|
|
147
|
+
/**
|
|
148
|
+
* - `1` 表示默认值
|
|
149
|
+
* - `2` 表示匹配值
|
|
150
|
+
*/
|
|
151
|
+
found = 0, transclusion = false, defaultParam;
|
|
152
|
+
for (; j < length; j++) {
|
|
148
153
|
const { anon, value, lastChild, name: option } = c[j];
|
|
149
154
|
transclusion = /\0\d+t\x7F/u.test(anon ? value : option);
|
|
150
155
|
if (anon) {
|
|
151
|
-
if (j === length - 1) {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
return implicitNewLine(value, prev);
|
|
156
|
+
if (j === length - 1) { // 位于最后的匿名参数是默认值
|
|
157
|
+
defaultParam = lastChild;
|
|
158
|
+
defaultVal = value;
|
|
155
159
|
}
|
|
156
|
-
else if (transclusion) {
|
|
160
|
+
else if (transclusion) { // 不支持复杂参数
|
|
157
161
|
break;
|
|
158
162
|
}
|
|
159
|
-
else {
|
|
160
|
-
found
|
|
163
|
+
else if (cmp(var1, (0, string_1.decodeHtml)(value))) { // 下一个命名参数视为匹配值
|
|
164
|
+
found = 2;
|
|
165
|
+
}
|
|
166
|
+
else if (value === '#default' && found !== 2) { // 下一个命名参数视为默认值
|
|
167
|
+
found = 1;
|
|
161
168
|
}
|
|
162
169
|
}
|
|
163
|
-
else if (transclusion) {
|
|
170
|
+
else if (transclusion) { // 不支持复杂参数
|
|
164
171
|
break;
|
|
165
172
|
}
|
|
166
|
-
else if (found || cmp(var1, (0, string_1.decodeHtml)(option))) {
|
|
173
|
+
else if (found === 2 || cmp(var1, (0, string_1.decodeHtml)(option))) { // 第一个匹配值
|
|
167
174
|
// @ts-expect-error sparse array
|
|
168
175
|
accum[accum.indexOf(lastChild)] = undefined;
|
|
169
176
|
return implicitNewLine(value, prev);
|
|
170
177
|
}
|
|
171
|
-
else if (option.toLowerCase() === '#default') {
|
|
172
|
-
defaultVal = value;
|
|
178
|
+
else if (found === 1 || option.toLowerCase() === '#default') { // 更新默认值
|
|
173
179
|
defaultParam = lastChild;
|
|
180
|
+
defaultVal = value;
|
|
181
|
+
found = 0;
|
|
174
182
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
return implicitNewLine(defaultVal, prev);
|
|
183
|
+
}
|
|
184
|
+
if (j === length) { // 不含复杂参数
|
|
185
|
+
if (defaultParam) {
|
|
186
|
+
// @ts-expect-error sparse array
|
|
187
|
+
accum[accum.indexOf(defaultParam)] = undefined;
|
|
181
188
|
}
|
|
189
|
+
return implicitNewLine(defaultVal, prev);
|
|
182
190
|
}
|
|
183
191
|
}
|
|
184
192
|
return m;
|
package/dist/addon/transclude.js
CHANGED
|
@@ -110,7 +110,7 @@ transclude_1.TranscludeToken.prototype.fixDuplication =
|
|
|
110
110
|
values.set(val, [arg]);
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
|
-
let noMoreAnon = anonCount === 0 || !key.trim() ||
|
|
113
|
+
let noMoreAnon = anonCount === 0 || !key.trim() || !Number.isInteger(Number(key));
|
|
114
114
|
const emptyArgs = values.get('') ?? [], duplicatedArgs = [...values].filter(([val, { length }]) => val && length > 1).flatMap(([, curArgs]) => {
|
|
115
115
|
const anonIndex = noMoreAnon ? -1 : curArgs.findIndex(({ anon }) => anon);
|
|
116
116
|
if (anonIndex !== -1) {
|
|
@@ -157,7 +157,7 @@ transclude_1.TranscludeToken.prototype.fixDuplication =
|
|
|
157
157
|
if (remaining > 1) {
|
|
158
158
|
index_1.default.error(`${this.type === 'template'
|
|
159
159
|
? this.name
|
|
160
|
-
: this.normalizeTitle(this.childNodes[1].
|
|
160
|
+
: this.normalizeTitle(this.childNodes[1].text(), 828, { temporary: true })
|
|
161
161
|
.title} still has ${remaining} duplicated ${key} parameters:\n${[...this.getArgs(key)].map(arg => {
|
|
162
162
|
const { top, left } = arg.getBoundingClientRect();
|
|
163
163
|
return `Line ${String(top)} Column ${String(left)}`;
|
package/dist/base.d.mts
CHANGED
|
@@ -17,6 +17,7 @@ export interface Config {
|
|
|
17
17
|
readonly conversionTable?: [string, string][];
|
|
18
18
|
readonly redirects?: [string, string][];
|
|
19
19
|
}
|
|
20
|
+
export type ConfigData = Omit<Config, 'excludes'>;
|
|
20
21
|
export type TokenTypes = 'root' | 'plain' | 'redirect' | 'redirect-syntax' | 'redirect-target' | 'onlyinclude' | 'noinclude' | 'include' | 'comment' | 'ext' | 'ext-attrs' | 'ext-attr-dirty' | 'ext-attr' | 'attr-key' | 'attr-value' | 'ext-inner' | 'arg' | 'arg-name' | 'arg-default' | 'hidden' | 'magic-word' | 'magic-word-name' | 'invoke-function' | 'invoke-module' | 'template' | 'template-name' | 'parameter' | 'parameter-key' | 'parameter-value' | 'heading' | 'heading-title' | 'heading-trail' | 'html' | 'html-attrs' | 'html-attr-dirty' | 'html-attr' | 'table' | 'tr' | 'td' | 'table-syntax' | 'table-attrs' | 'table-attr-dirty' | 'table-attr' | 'table-inter' | 'td-inner' | 'hr' | 'double-underscore' | 'link' | 'link-target' | 'link-text' | 'category' | 'file' | 'gallery-image' | 'imagemap-image' | 'image-parameter' | 'quote' | 'ext-link' | 'ext-link-text' | 'ext-link-url' | 'free-ext-link' | 'magic-link' | 'list' | 'dd' | 'list-range' | 'converter' | 'converter-flags' | 'converter-flag' | 'converter-rule' | 'converter-rule-variant' | 'converter-rule-to' | 'converter-rule-from' | 'param-line' | 'imagemap-link';
|
|
21
22
|
export declare const stages: {
|
|
22
23
|
redirect: number;
|
|
@@ -278,7 +279,7 @@ export interface LanguageService {
|
|
|
278
279
|
setTargetWikipedia(wiki: string): Promise<void>;
|
|
279
280
|
}
|
|
280
281
|
export interface Parser {
|
|
281
|
-
config:
|
|
282
|
+
config: ConfigData | string;
|
|
282
283
|
i18n: Record<string, string> | string | undefined;
|
|
283
284
|
/** @since v1.9.0 */
|
|
284
285
|
viewOnly: boolean;
|
|
@@ -288,7 +289,7 @@ export interface Parser {
|
|
|
288
289
|
* 获取当前的解析设置
|
|
289
290
|
* @param config unprocessed parser configuration / 未处理的解析设置
|
|
290
291
|
*/
|
|
291
|
-
getConfig(config?:
|
|
292
|
+
getConfig(config?: ConfigData): Config;
|
|
292
293
|
/**
|
|
293
294
|
* Parse wikitext
|
|
294
295
|
*
|
package/dist/base.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export interface Config {
|
|
|
17
17
|
readonly conversionTable?: [string, string][];
|
|
18
18
|
readonly redirects?: [string, string][];
|
|
19
19
|
}
|
|
20
|
+
export type ConfigData = Omit<Config, 'excludes'>;
|
|
20
21
|
export type TokenTypes = 'root' | 'plain' | 'redirect' | 'redirect-syntax' | 'redirect-target' | 'onlyinclude' | 'noinclude' | 'include' | 'comment' | 'ext' | 'ext-attrs' | 'ext-attr-dirty' | 'ext-attr' | 'attr-key' | 'attr-value' | 'ext-inner' | 'arg' | 'arg-name' | 'arg-default' | 'hidden' | 'magic-word' | 'magic-word-name' | 'invoke-function' | 'invoke-module' | 'template' | 'template-name' | 'parameter' | 'parameter-key' | 'parameter-value' | 'heading' | 'heading-title' | 'heading-trail' | 'html' | 'html-attrs' | 'html-attr-dirty' | 'html-attr' | 'table' | 'tr' | 'td' | 'table-syntax' | 'table-attrs' | 'table-attr-dirty' | 'table-attr' | 'table-inter' | 'td-inner' | 'hr' | 'double-underscore' | 'link' | 'link-target' | 'link-text' | 'category' | 'file' | 'gallery-image' | 'imagemap-image' | 'image-parameter' | 'quote' | 'ext-link' | 'ext-link-text' | 'ext-link-url' | 'free-ext-link' | 'magic-link' | 'list' | 'dd' | 'list-range' | 'converter' | 'converter-flags' | 'converter-flag' | 'converter-rule' | 'converter-rule-variant' | 'converter-rule-to' | 'converter-rule-from' | 'param-line' | 'imagemap-link';
|
|
21
22
|
export declare const stages: {
|
|
22
23
|
redirect: number;
|
|
@@ -278,7 +279,7 @@ export interface LanguageService {
|
|
|
278
279
|
setTargetWikipedia(wiki: string): Promise<void>;
|
|
279
280
|
}
|
|
280
281
|
export interface Parser {
|
|
281
|
-
config:
|
|
282
|
+
config: ConfigData | string;
|
|
282
283
|
i18n: Record<string, string> | string | undefined;
|
|
283
284
|
/** @since v1.9.0 */
|
|
284
285
|
viewOnly: boolean;
|
|
@@ -288,7 +289,7 @@ export interface Parser {
|
|
|
288
289
|
* 获取当前的解析设置
|
|
289
290
|
* @param config unprocessed parser configuration / 未处理的解析设置
|
|
290
291
|
*/
|
|
291
|
-
getConfig(config?:
|
|
292
|
+
getConfig(config?: ConfigData): Config;
|
|
292
293
|
/**
|
|
293
294
|
* Parse wikitext
|
|
294
295
|
*
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Config, LintError, TokenTypes, Parser as ParserBase, Stage, AST } from './base';
|
|
1
|
+
import type { Config, ConfigData, LintError, TokenTypes, Parser as ParserBase, Stage, AST } from './base';
|
|
2
2
|
import type { Title, TitleOptions } from './lib/title';
|
|
3
3
|
import type { LanguageService, QuickFixData } from './lib/lsp';
|
|
4
4
|
import type { Token } from './internal';
|
|
@@ -31,6 +31,15 @@ declare interface Parser extends ParserBase {
|
|
|
31
31
|
* @since v1.16.1
|
|
32
32
|
*/
|
|
33
33
|
createLanguageService(uri: object): LanguageService;
|
|
34
|
+
/**
|
|
35
|
+
* Get the parser configuration for a MediaWiki project with Extension:CodeMirror installed
|
|
36
|
+
*
|
|
37
|
+
* 获取一个安装了CodeMirror扩展的MediaWiki项目的解析设置
|
|
38
|
+
* @param site site nickname / 网站别名
|
|
39
|
+
* @param url script path / 脚本路径
|
|
40
|
+
* @since v1.18.4
|
|
41
|
+
*/
|
|
42
|
+
fetchConfig(site: string, url: string): Promise<Config>;
|
|
34
43
|
/**
|
|
35
44
|
* Check if the title is an interwiki link
|
|
36
45
|
*
|
|
@@ -43,6 +52,6 @@ declare const Parser: Parser;
|
|
|
43
52
|
// @ts-expect-error mixed export styles
|
|
44
53
|
export = Parser;
|
|
45
54
|
export default Parser;
|
|
46
|
-
export type { Config, LintError, TokenTypes, LanguageService, QuickFixData, AST, };
|
|
55
|
+
export type { Config, ConfigData, LintError, TokenTypes, LanguageService, QuickFixData, AST, };
|
|
47
56
|
export type * from './internal';
|
|
48
57
|
declare global { type Acceptable = unknown; }
|
package/dist/index.js
CHANGED
|
@@ -15,6 +15,7 @@ const redirectMap_1 = require("./lib/redirectMap");
|
|
|
15
15
|
const fs_1 = __importDefault(require("fs"));
|
|
16
16
|
const path_1 = __importDefault(require("path"));
|
|
17
17
|
const diff_1 = require("./util/diff");
|
|
18
|
+
const config_1 = __importDefault(require("./bin/config"));
|
|
18
19
|
/* NOT FOR BROWSER ONLY */
|
|
19
20
|
/**
|
|
20
21
|
* 从根路径require
|
|
@@ -28,7 +29,7 @@ const rootRequire = (file, dir) => require(path_1.default.isAbsolute(file)
|
|
|
28
29
|
/* NOT FOR BROWSER */
|
|
29
30
|
const promises = [Promise.resolve()];
|
|
30
31
|
/^(zh|en)\s*:/diu; // eslint-disable-line @typescript-eslint/no-unused-expressions
|
|
31
|
-
const getInterwikiRegex = (0, common_1.
|
|
32
|
+
const getInterwikiRegex = (0, common_1.getRegex)(interwiki => new RegExp(String.raw `^(${interwiki.join('|')})\s*:`, 'diu'));
|
|
32
33
|
let viewOnly = false, redirectMap = new redirectMap_1.RedirectMap();
|
|
33
34
|
/* NOT FOR BROWSER END */
|
|
34
35
|
const Parser = {
|
|
@@ -245,6 +246,12 @@ const Parser = {
|
|
|
245
246
|
return tasks.get(uri) ?? new LanguageService(uri);
|
|
246
247
|
}
|
|
247
248
|
},
|
|
249
|
+
/* NOT FOR BROWSER ONLY */
|
|
250
|
+
/** @implements */
|
|
251
|
+
async fetchConfig(site, url) {
|
|
252
|
+
return this.getConfig(await (0, config_1.default)(site, url, false, true));
|
|
253
|
+
},
|
|
254
|
+
/* NOT FOR BROWSER ONLY */
|
|
248
255
|
/* NOT FOR BROWSER */
|
|
249
256
|
/** @implements */
|
|
250
257
|
warn(msg, ...args) {
|
package/dist/lib/document.d.ts
CHANGED
|
@@ -3,6 +3,10 @@ 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
|
+
declare interface Jax {
|
|
7
|
+
tex2mml(tex: string): string;
|
|
8
|
+
}
|
|
9
|
+
export declare const MathJax: Promise<Jax | undefined>;
|
|
6
10
|
export declare const jsonTags: string[];
|
|
7
11
|
export declare const jsonLSP: import("vscode-json-languageservice").LanguageService | undefined;
|
|
8
12
|
export declare const cssLSP: import("vscode-css-languageservice").LanguageService | undefined;
|
package/dist/lib/document.js
CHANGED
|
@@ -3,12 +3,32 @@ 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.cssLSP = exports.jsonLSP = exports.jsonTags = void 0;
|
|
6
|
+
exports.EmbeddedCSSDocument = exports.EmbeddedJSONDocument = exports.stylelint = exports.cssLSP = exports.jsonLSP = exports.jsonTags = exports.MathJax = void 0;
|
|
7
7
|
const path_1 = __importDefault(require("path"));
|
|
8
8
|
const common_1 = require("@bhsd/common");
|
|
9
9
|
/* NOT FOR BROWSER */
|
|
10
10
|
const constants_1 = require("../util/constants");
|
|
11
|
-
|
|
11
|
+
exports.MathJax = (async () => {
|
|
12
|
+
try {
|
|
13
|
+
const jax = require('mathjax');
|
|
14
|
+
return await jax.init({
|
|
15
|
+
loader: {
|
|
16
|
+
load: ['input/tex', '[tex]/mhchem'],
|
|
17
|
+
},
|
|
18
|
+
tex: {
|
|
19
|
+
packages: { '[+]': ['mhchem'] },
|
|
20
|
+
/** @ignore */
|
|
21
|
+
formatError(_, error) {
|
|
22
|
+
throw error;
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
startup: { typeset: false },
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
})();
|
|
12
32
|
exports.jsonTags = ['templatedata', 'mapframe', 'maplink'];
|
|
13
33
|
exports.jsonLSP = (() => {
|
|
14
34
|
try {
|
package/dist/lib/lsp.js
CHANGED
|
@@ -19,13 +19,12 @@ const util_1 = __importDefault(require("util"));
|
|
|
19
19
|
const child_process_1 = require("child_process");
|
|
20
20
|
const crypto_1 = require("crypto");
|
|
21
21
|
const stylelint_1 = require("@bhsd/common/dist/stylelint");
|
|
22
|
-
const config_1 = __importDefault(require("../bin/config"));
|
|
23
22
|
const document_1 = require("./document");
|
|
24
23
|
/** @see https://www.npmjs.com/package/stylelint-config-recommended */
|
|
25
24
|
const cssRules = {
|
|
26
25
|
'block-no-empty': null,
|
|
27
26
|
'property-no-unknown': null,
|
|
28
|
-
}, jsonSelector = document_1.jsonTags.map(s => `ext
|
|
27
|
+
}, jsonSelector = document_1.jsonTags.map(s => `ext#${s}`).join(), mathSelector = ['math', 'chem', 'ce'].map(s => `ext#${s}`).join(), scores = new Map();
|
|
29
28
|
let colors;
|
|
30
29
|
/* NOT FOR BROWSER ONLY END */
|
|
31
30
|
exports.tasks = new WeakMap();
|
|
@@ -775,8 +774,11 @@ class LanguageService {
|
|
|
775
774
|
});
|
|
776
775
|
})() :
|
|
777
776
|
[], jsonDiagnostics = document_1.jsonLSP ?
|
|
778
|
-
await Promise.all(root.querySelectorAll(jsonSelector).map(async (
|
|
779
|
-
|
|
777
|
+
await Promise.all(root.querySelectorAll(jsonSelector).map(async ({ name, lastChild, selfClosing }) => {
|
|
778
|
+
if (selfClosing) {
|
|
779
|
+
return [];
|
|
780
|
+
}
|
|
781
|
+
const textDoc = new document_1.EmbeddedJSONDocument(root, lastChild), severityLevel = name === 'templatedata' ? 'error' : 'ignore', e = (await document_1.jsonLSP.doValidation(textDoc, textDoc.jsonDoc, {
|
|
780
782
|
comments: severityLevel,
|
|
781
783
|
trailingCommas: severityLevel,
|
|
782
784
|
})).map((error) => ({
|
|
@@ -831,6 +833,32 @@ class LanguageService {
|
|
|
831
833
|
}));
|
|
832
834
|
}
|
|
833
835
|
}
|
|
836
|
+
const MathJax = await document_1.MathJax, mathDiagnostics = MathJax
|
|
837
|
+
? root.querySelectorAll(mathSelector)
|
|
838
|
+
.map(({ selfClosing, innerText, lastChild, name }) => {
|
|
839
|
+
if (selfClosing) {
|
|
840
|
+
return [];
|
|
841
|
+
}
|
|
842
|
+
try {
|
|
843
|
+
MathJax.tex2mml(name === 'math' ? innerText : String.raw `\ce{${innerText}}`);
|
|
844
|
+
return [];
|
|
845
|
+
}
|
|
846
|
+
catch (e) {
|
|
847
|
+
if (e && typeof e === 'object' && 'id' in e && 'message' in e) {
|
|
848
|
+
return [
|
|
849
|
+
{
|
|
850
|
+
range: createNodeRange(lastChild),
|
|
851
|
+
severity: 1,
|
|
852
|
+
source: 'MathJax',
|
|
853
|
+
code: e.id,
|
|
854
|
+
message: e.message,
|
|
855
|
+
},
|
|
856
|
+
];
|
|
857
|
+
}
|
|
858
|
+
return [];
|
|
859
|
+
}
|
|
860
|
+
})
|
|
861
|
+
: [];
|
|
834
862
|
/* NOT FOR BROWSER ONLY END */
|
|
835
863
|
return [
|
|
836
864
|
diagnostics,
|
|
@@ -838,6 +866,7 @@ class LanguageService {
|
|
|
838
866
|
jsonDiagnostics,
|
|
839
867
|
/* NOT FOR BROWSER ONLY */
|
|
840
868
|
lilypondDiagnostics,
|
|
869
|
+
mathDiagnostics,
|
|
841
870
|
].flat(2);
|
|
842
871
|
}
|
|
843
872
|
/**
|
|
@@ -890,8 +919,10 @@ class LanguageService {
|
|
|
890
919
|
}
|
|
891
920
|
/* NOT FOR BROWSER ONLY */
|
|
892
921
|
if (document_1.jsonLSP) {
|
|
893
|
-
for (const
|
|
894
|
-
|
|
922
|
+
for (const { selfClosing, lastChild } of root.querySelectorAll(jsonSelector)) {
|
|
923
|
+
if (!selfClosing) {
|
|
924
|
+
ranges.push(...document_1.jsonLSP.getFoldingRanges(new document_1.EmbeddedJSONDocument(root, lastChild)));
|
|
925
|
+
}
|
|
895
926
|
}
|
|
896
927
|
}
|
|
897
928
|
/* NOT FOR BROWSER ONLY END */
|
|
@@ -1122,13 +1153,13 @@ class LanguageService {
|
|
|
1122
1153
|
}
|
|
1123
1154
|
else if (type === 'magic-word-name') {
|
|
1124
1155
|
info = this.#getParserFunction(parentNode.name);
|
|
1125
|
-
f = offsetNode.
|
|
1156
|
+
f = offsetNode.text().trim();
|
|
1126
1157
|
colon = parentNode.getAttribute('colon');
|
|
1127
1158
|
}
|
|
1128
1159
|
else if (offsetNode.is('magic-word') && !offsetNode.modifier && length === 1
|
|
1129
1160
|
&& (offset > 0 || root.posFromIndex(offsetNode.getAbsoluteIndex()).left === position.character)) {
|
|
1130
1161
|
info = this.#getParserFunction(name);
|
|
1131
|
-
f = offsetNode.firstChild.
|
|
1162
|
+
f = offsetNode.firstChild.text().trim();
|
|
1132
1163
|
colon = offsetNode.getAttribute('colon');
|
|
1133
1164
|
}
|
|
1134
1165
|
else if ((offsetNode.is('magic-word') || offsetNode.is('template'))
|
|
@@ -1215,7 +1246,7 @@ class LanguageService {
|
|
|
1215
1246
|
}
|
|
1216
1247
|
const n = childNodes.length - 1, candidates = info.signatures.filter(params => (params.length >= n || params[params.length - 1]?.rest)
|
|
1217
1248
|
&& params.every(({ label, const: c }, i) => {
|
|
1218
|
-
const p = c && i < n && childNodes[i + 1]?.
|
|
1249
|
+
const p = c && i < n && childNodes[i + 1]?.text().trim();
|
|
1219
1250
|
return !p || label.toLowerCase().includes(p.toLowerCase());
|
|
1220
1251
|
}));
|
|
1221
1252
|
if (candidates.length === 0) {
|
|
@@ -1228,7 +1259,7 @@ class LanguageService {
|
|
|
1228
1259
|
break;
|
|
1229
1260
|
}
|
|
1230
1261
|
}
|
|
1231
|
-
const f = firstChild.
|
|
1262
|
+
const f = firstChild.text().trim(), colon = lastChild.getAttribute('colon');
|
|
1232
1263
|
return {
|
|
1233
1264
|
signatures: candidates.map((params) => ({
|
|
1234
1265
|
label: `{{${f}${params.length === 0 ? '' : colon}${params.map(({ label }) => label).join('|')}}}`,
|
|
@@ -1343,7 +1374,7 @@ class LanguageService {
|
|
|
1343
1374
|
this.config = index_1.default.getConfig(config);
|
|
1344
1375
|
}
|
|
1345
1376
|
catch {
|
|
1346
|
-
this.config = index_1.default.
|
|
1377
|
+
this.config = await index_1.default.fetchConfig(site, `${mt[0]}/w`);
|
|
1347
1378
|
}
|
|
1348
1379
|
Object.assign(this.config, { articlePath: `${mt[0]}/wiki/` });
|
|
1349
1380
|
}
|
package/dist/lib/text.js
CHANGED
|
@@ -177,12 +177,13 @@ let AstText = (() => {
|
|
|
177
177
|
constructor(text) {
|
|
178
178
|
super();
|
|
179
179
|
Object.defineProperties(this, {
|
|
180
|
-
childNodes: { enumerable: false, configurable: false },
|
|
181
180
|
data: {
|
|
182
181
|
value: text,
|
|
183
182
|
/* NOT FOR BROWSER */
|
|
184
183
|
writable: false,
|
|
185
184
|
},
|
|
185
|
+
/* NOT FOR BROWSER */
|
|
186
|
+
childNodes: { enumerable: false, configurable: false },
|
|
186
187
|
});
|
|
187
188
|
}
|
|
188
189
|
/** @private */
|
|
@@ -237,12 +238,13 @@ let AstText = (() => {
|
|
|
237
238
|
]);
|
|
238
239
|
for (let mt = errorRegex.exec(data); mt; mt = errorRegex.exec(data)) {
|
|
239
240
|
const [, tag, prefix] = mt;
|
|
240
|
-
let { index
|
|
241
|
+
let { index, 0: error } = mt;
|
|
241
242
|
if (prefix && prefix !== ']') {
|
|
242
243
|
const { length } = prefix;
|
|
243
244
|
index += length;
|
|
244
245
|
error = error.slice(length);
|
|
245
246
|
}
|
|
247
|
+
error = error.toLowerCase();
|
|
246
248
|
const { 0: char, length } = error, magicLink = char === 'r' || char === 'p' || char === 'i';
|
|
247
249
|
if (char === '<' && !tags.has(tag.toLowerCase())
|
|
248
250
|
|| char === '[' && type === 'ext-link-text' && (/&(?:rbrack|#93|#x5[Dd];);/u.test(data.slice(index + 1))
|
package/dist/parser/braces.js
CHANGED
|
@@ -11,14 +11,33 @@ const constants_1 = require("../util/constants");
|
|
|
11
11
|
/* NOT FOR BROWSER END */
|
|
12
12
|
/* NOT FOR BROWSER ONLY */
|
|
13
13
|
const v8_1 = require("v8");
|
|
14
|
-
const MAXHEAP = (0, v8_1.getHeapStatistics)().
|
|
14
|
+
const MAXHEAP = (0, v8_1.getHeapStatistics)().heap_size_limit * 0.9;
|
|
15
15
|
/* NOT FOR BROWSER ONLY END */
|
|
16
16
|
const closes = {
|
|
17
17
|
'=': String.raw `\n(?!(?:[^\S\n]|\0\d+[cn]\x7F)*\n)`,
|
|
18
18
|
'{': String.raw `\}{2,}|\|`,
|
|
19
19
|
'-': String.raw `\}-`,
|
|
20
20
|
'[': String.raw `\]\]`,
|
|
21
|
-
}, openBraces = String.raw `|\{{2,}`, marks = new Map([['!', '!'], ['!!', '+'], ['(!', '{'], ['!)', '}'], ['!-', '-'], ['=', '~'], ['server', 'm']]), getExecRegex = (0, common_1.getRegex)(s => new RegExp(s, 'gmu'));
|
|
21
|
+
}, lbrack = String.raw `\[(?!\[)`, newline = String.raw `\n(?![=\0])`, openBraces = String.raw `|\{{2,}`, marks = new Map([['!', '!'], ['!!', '+'], ['(!', '{'], ['!)', '}'], ['!-', '-'], ['=', '~'], ['server', 'm']]), getExecRegex = (0, common_1.getRegex)(s => new RegExp(s, 'gmu'));
|
|
22
|
+
let reReplace;
|
|
23
|
+
/* NOT FOR BROWSER ONLY */
|
|
24
|
+
try {
|
|
25
|
+
reReplace = new RegExp(String.raw `(?<!\{)\{\{((?:[^\n{}[]|${lbrack}|${newline})*)\}\}` // eslint-disable-line prefer-template
|
|
26
|
+
+ '|'
|
|
27
|
+
+ String.raw `\{\{((?:[^\n{}[]|${lbrack}|${newline})*)\}\}(?!\})`
|
|
28
|
+
+ '|'
|
|
29
|
+
+ String.raw `\[\[(?:[^\n[\]{]|${newline})*\]\]`
|
|
30
|
+
+ '|'
|
|
31
|
+
+ String.raw `-\{(?:[^\n{}[]|${lbrack}|${newline})*\}-`, 'gu');
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
/* NOT FOR BROWSER ONLY END */
|
|
35
|
+
reReplace = new RegExp(String.raw `\{\{((?:[^\n{}[]|${lbrack}|${newline})*)\}\}(?!\})` // eslint-disable-line prefer-template
|
|
36
|
+
+ '|'
|
|
37
|
+
+ String.raw `\[\[(?:[^\n[\]{]|${newline})*\]\]`
|
|
38
|
+
+ '|'
|
|
39
|
+
+ String.raw `-\{(?:[^\n{}[]|${lbrack}|${newline})*\}-`, 'gu');
|
|
40
|
+
}
|
|
22
41
|
/**
|
|
23
42
|
* 获取模板或魔术字对应的字符
|
|
24
43
|
* @param s 模板或魔术字名
|
|
@@ -45,7 +64,7 @@ const getSymbol = (s) => {
|
|
|
45
64
|
* @throws `TranscludeToken.constructor()`
|
|
46
65
|
*/
|
|
47
66
|
const parseBraces = (wikitext, config, accum) => {
|
|
48
|
-
const source = String.raw `${config.excludes
|
|
67
|
+
const source = String.raw `${config.excludes.includes('heading') ? '' : String.raw `^((?:\0\d+[cno]\x7F)*)={1,6}|`}\[\[|-\{(?!\{)`, { parserFunction: [, , , subst] } = config, stack = [], linkStack = [];
|
|
49
68
|
/**
|
|
50
69
|
* 恢复内链
|
|
51
70
|
* @param s 不含内链的字符串
|
|
@@ -61,38 +80,45 @@ const parseBraces = (wikitext, config, accum) => {
|
|
|
61
80
|
const push = (text, parts, lastIndex, index) => {
|
|
62
81
|
parts[parts.length - 1].push(restore(text.slice(lastIndex, index)));
|
|
63
82
|
};
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
83
|
+
let replaced;
|
|
84
|
+
do {
|
|
85
|
+
if (replaced !== undefined) {
|
|
86
|
+
wikitext = replaced;
|
|
87
|
+
}
|
|
88
|
+
replaced = wikitext.replace(reReplace, (m, p1, p2) => {
|
|
89
|
+
if (p1 !== undefined || typeof p2 === 'string') {
|
|
90
|
+
try {
|
|
91
|
+
const { length } = accum, parts = (p1 ?? p2).split('|');
|
|
92
|
+
// @ts-expect-error abstract class
|
|
93
|
+
new transclude_1.TranscludeToken(restore(parts[0]), parts.slice(1).map(part => {
|
|
94
|
+
const i = part.indexOf('=');
|
|
95
|
+
return (i === -1 ? [part] : [part.slice(0, i), part.slice(i + 1)]).map(restore);
|
|
96
|
+
}), config, accum);
|
|
97
|
+
return `\0${length}${getSymbol(parts[0])}\x7F`;
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
/* istanbul ignore if */
|
|
101
|
+
if (!(e instanceof SyntaxError) || e.message !== 'Invalid template name') {
|
|
102
|
+
throw e;
|
|
103
|
+
}
|
|
79
104
|
}
|
|
80
105
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
});
|
|
106
|
+
linkStack.push(restore(m));
|
|
107
|
+
return `\0${linkStack.length - 1}\x7F`;
|
|
108
|
+
});
|
|
109
|
+
} while (replaced !== wikitext);
|
|
110
|
+
wikitext = replaced;
|
|
85
111
|
const lastBraces = wikitext.lastIndexOf('}}') - wikitext.length;
|
|
86
112
|
let moreBraces = lastBraces + wikitext.length !== -1;
|
|
87
113
|
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
88
114
|
/^((?:\0\d+[cno]\x7F)*)={1,6}|\[\[|-\{(?!\{)|\{{2,}|\n(?!(?:[^\S\n]|\0\d+[cn]\x7F)*\n)|[|=]|\}{2,}|\}-|\]\]/gmu;
|
|
89
|
-
let regex = getExecRegex(source + (moreBraces ? openBraces : '')), mt = regex.exec(wikitext),
|
|
115
|
+
let regex = getExecRegex(source + (moreBraces ? openBraces : '')), mt = regex.exec(wikitext), lastIndex;
|
|
90
116
|
while (mt
|
|
91
117
|
|| lastIndex !== undefined && lastIndex <= wikitext.length
|
|
92
118
|
&& stack[stack.length - 1]?.[0]?.startsWith('=')) {
|
|
93
119
|
/* NOT FOR BROWSER ONLY */
|
|
94
|
-
if (
|
|
95
|
-
throw new RangeError('Maximum
|
|
120
|
+
if (process.memoryUsage().heapUsed > MAXHEAP) {
|
|
121
|
+
throw new RangeError('Maximum heap size exceeded');
|
|
96
122
|
}
|
|
97
123
|
/* NOT FOR BROWSER ONLY END */
|
|
98
124
|
if (mt?.[1]) {
|
|
@@ -111,11 +137,13 @@ const parseBraces = (wikitext, config, accum) => {
|
|
|
111
137
|
const rmt = /^(={1,6})(.+)\1((?:\s|\0\d+[cn]\x7F)*)$/u
|
|
112
138
|
.exec(wikitext.slice(index, curIndex));
|
|
113
139
|
if (rmt) {
|
|
114
|
-
wikitext = `${wikitext.slice(0, index)}\0${accum.length}h\x7F${wikitext.slice(curIndex)}`;
|
|
115
|
-
lastIndex = index + 4 + String(accum.length).length;
|
|
116
140
|
rmt[2] = restore(rmt[2]);
|
|
117
|
-
|
|
118
|
-
|
|
141
|
+
if (!rmt[2].includes('\n')) {
|
|
142
|
+
wikitext = `${wikitext.slice(0, index)}\0${accum.length}h\x7F${wikitext.slice(curIndex)}`;
|
|
143
|
+
lastIndex = index + 4 + String(accum.length).length;
|
|
144
|
+
// @ts-expect-error abstract class
|
|
145
|
+
new heading_1.HeadingToken(rmt[1].length, rmt.slice(2), config, accum);
|
|
146
|
+
}
|
|
119
147
|
}
|
|
120
148
|
}
|
|
121
149
|
}
|
|
@@ -14,7 +14,7 @@ const onlyincludeLeft = '<onlyinclude>', onlyincludeRight = '</onlyinclude>', {
|
|
|
14
14
|
const noincludeRegex = includeOnly ? 'includeonly' : '(?:no|only)include', includeRegex = includeOnly ? 'noinclude' : 'includeonly';
|
|
15
15
|
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
16
16
|
/<!--[\s\S]*?(?:-->|$)|<foo(?:\s[^>]*)?\/?>|<\/foo\s*>|<(bar)(\s[^>]*?)?(?:\/>|>([\s\S]*?)<\/(\1\s*)>)|<(baz)(\s[^>]*?)?(?:\/>|>([\s\S]*?)(?:<\/(baz\s*)>|$))/giu;
|
|
17
|
-
return (0, common_1.
|
|
17
|
+
return (0, common_1.getRegex)(ext => new RegExp(String.raw `<!--[\s\S]*?(?:-->|$)|<${noincludeRegex}(?:\s[^>]*)?/?>|</${noincludeRegex}\s*>|<(${ext.join('|')})(\s[^>]*?)?(?:/>|>([\s\S]*?)</(\1\s*)>)|<(${includeRegex})(\s[^>]*?)?(?:/>|>([\s\S]*?)(?:</(${includeRegex}\s*)>|$))`, 'giu'));
|
|
18
18
|
});
|
|
19
19
|
/**
|
|
20
20
|
* 更新`<onlyinclude>`和`</onlyinclude>`的位置
|
package/dist/src/arg.js
CHANGED
|
@@ -130,7 +130,7 @@ let ArgToken = (() => {
|
|
|
130
130
|
/** 设置name */
|
|
131
131
|
#setName() {
|
|
132
132
|
// eslint-disable-next-line no-unused-labels
|
|
133
|
-
LSP: this.setAttribute('name', this.firstChild.
|
|
133
|
+
LSP: this.setAttribute('name', this.firstChild.text().trim());
|
|
134
134
|
}
|
|
135
135
|
/** @private */
|
|
136
136
|
afterBuild() {
|
package/dist/src/attribute.js
CHANGED
|
@@ -163,7 +163,7 @@ let AttributeToken = (() => {
|
|
|
163
163
|
if (this.parentNode) {
|
|
164
164
|
this.#tag = this.parentNode.name;
|
|
165
165
|
}
|
|
166
|
-
this.setAttribute('name', this.firstChild.
|
|
166
|
+
this.setAttribute('name', this.firstChild.text().trim().toLowerCase());
|
|
167
167
|
super.afterBuild();
|
|
168
168
|
}
|
|
169
169
|
/** @private */
|
|
@@ -25,7 +25,7 @@ const getUrlRegex = (0, common_1.getRegex)(protocol => new RegExp(String.raw `^(
|
|
|
25
25
|
const getSyntaxRegex = (0, common_1.getRegex)(syntax => new RegExp(String.raw `^(\s*(?!\s))${syntax.replace('$1', '(.*)')}${syntax.endsWith('$1') ? '(?=$|\n)' : ''}(\s*)$`, 'u'));
|
|
26
26
|
exports.galleryParams = new Set(['alt', 'link', 'lang', 'page', 'caption']);
|
|
27
27
|
function validate(key, val, config, halfParsed, ext) {
|
|
28
|
-
val = val.trim();
|
|
28
|
+
val = (0, string_1.removeComment)(val).trim();
|
|
29
29
|
let value = val.replace(key === 'link' ? /\0\d+[tq]\x7F/gu : /\0\d+t\x7F/gu, '').trim();
|
|
30
30
|
switch (key) {
|
|
31
31
|
case 'width':
|
|
@@ -152,10 +152,12 @@ class ImageParameterToken extends index_2.Token {
|
|
|
152
152
|
this.setAttribute('name', param[1]);
|
|
153
153
|
return;
|
|
154
154
|
}
|
|
155
|
-
super(str,
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
155
|
+
super(str, config.excludes.includes('list')
|
|
156
|
+
? config
|
|
157
|
+
: {
|
|
158
|
+
...config,
|
|
159
|
+
excludes: [...config.excludes, 'list'],
|
|
160
|
+
}, accum);
|
|
159
161
|
this.setAttribute('name', 'caption');
|
|
160
162
|
this.setAttribute('stage', 7);
|
|
161
163
|
/* NOT FOR BROWSER */
|