wikiparser-node 1.18.2 → 1.18.4
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 +6 -1
- package/bundle/bundle-es7.min.js +29 -28
- package/bundle/bundle-lsp.min.js +31 -30
- package/bundle/bundle.min.js +30 -29
- package/config/minimum.json +7 -0
- package/dist/addon/token.js +37 -28
- package/dist/addon/transclude.js +1 -3
- package/dist/base.d.mts +4 -0
- package/dist/base.d.ts +4 -0
- package/dist/base.js +1 -0
- package/dist/base.mjs +2 -1
- package/dist/bin/config.js +3 -2
- package/dist/index.d.ts +14 -1
- package/dist/index.js +72 -72
- package/dist/lib/element.d.ts +6 -0
- package/dist/lib/element.js +543 -466
- package/dist/lib/lsp.d.ts +1 -0
- package/dist/lib/lsp.js +20 -15
- package/dist/lib/redirectMap.d.ts +7 -0
- package/dist/lib/redirectMap.js +31 -0
- package/dist/lib/text.d.ts +2 -2
- package/dist/lib/text.js +385 -325
- package/dist/lib/title.d.ts +23 -4
- package/dist/lib/title.js +17 -5
- package/dist/mixin/noEscape.d.ts +4 -0
- package/dist/mixin/noEscape.js +22 -0
- package/dist/mixin/readOnly.d.ts +4 -0
- package/dist/mixin/readOnly.js +26 -0
- package/dist/parser/braces.js +79 -37
- package/dist/parser/commentAndExt.js +5 -16
- package/dist/parser/links.js +1 -1
- package/dist/parser/quotes.js +1 -1
- package/dist/parser/redirect.js +1 -3
- package/dist/src/arg.js +253 -202
- package/dist/src/attribute.d.ts +0 -5
- package/dist/src/attribute.js +4 -8
- package/dist/src/converter.js +213 -162
- package/dist/src/gallery.js +1 -2
- package/dist/src/heading.js +5 -6
- package/dist/src/imageParameter.js +16 -16
- package/dist/src/imagemap.js +3 -2
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +722 -694
- package/dist/src/link/base.js +292 -241
- package/dist/src/link/file.js +13 -17
- package/dist/src/link/galleryImage.js +1 -1
- package/dist/src/link/redirectTarget.js +1 -2
- package/dist/src/magicLink.d.ts +0 -6
- package/dist/src/magicLink.js +5 -15
- package/dist/src/nested.js +7 -7
- package/dist/src/nowiki/base.js +2 -1
- package/dist/src/nowiki/index.js +4 -3
- package/dist/src/onlyinclude.js +95 -44
- package/dist/src/parameter.d.ts +0 -6
- package/dist/src/parameter.js +1 -13
- package/dist/src/redirect.js +6 -6
- package/dist/src/syntax.d.ts +4 -1
- package/dist/src/syntax.js +4 -1
- package/dist/src/table/base.d.ts +0 -5
- package/dist/src/table/base.js +2 -9
- package/dist/src/table/index.d.ts +1 -0
- package/dist/src/table/index.js +7 -4
- package/dist/src/table/td.d.ts +1 -0
- package/dist/src/table/td.js +2 -3
- package/dist/src/table/trBase.js +31 -14
- package/dist/src/tagPair/index.js +2 -1
- package/dist/src/transclude.js +713 -657
- package/dist/util/debug.js +10 -3
- package/dist/util/diff.js +1 -1
- package/dist/util/string.js +4 -5
- package/extensions/dist/base.js +8 -6
- package/extensions/dist/lint.js +1 -1
- package/extensions/es7/base.js +8 -6
- package/extensions/es7/lint.js +1 -1
- package/extensions/ui.css +1 -1
- package/package.json +3 -3
package/dist/lib/title.d.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import type { Config } from '../base';
|
|
2
|
+
export interface TitleOptions {
|
|
3
|
+
temporary?: boolean | undefined;
|
|
4
|
+
decode?: boolean | undefined;
|
|
5
|
+
selfLink?: boolean | undefined;
|
|
6
|
+
halfParsed?: boolean | undefined;
|
|
7
|
+
}
|
|
2
8
|
/**
|
|
3
9
|
* title object of a MediaWiki page
|
|
4
10
|
*
|
|
@@ -19,7 +25,10 @@ export declare class Title {
|
|
|
19
25
|
get prefix(): string;
|
|
20
26
|
/** full title / 完整标题 */
|
|
21
27
|
get title(): string;
|
|
22
|
-
/**
|
|
28
|
+
/**
|
|
29
|
+
* file extension / 扩展名
|
|
30
|
+
* @since v1.1.0
|
|
31
|
+
*/
|
|
23
32
|
get extension(): string | undefined;
|
|
24
33
|
set extension(extension: string | undefined);
|
|
25
34
|
/** @throws `RangeError` undefined namespace */
|
|
@@ -30,14 +39,18 @@ export declare class Title {
|
|
|
30
39
|
*
|
|
31
40
|
* @param title 标题(含或不含命名空间前缀)
|
|
32
41
|
* @param defaultNs 命名空间
|
|
33
|
-
* @param
|
|
34
|
-
* @param
|
|
42
|
+
* @param config
|
|
43
|
+
* @param opt 选项
|
|
44
|
+
* @param opt.temporary 是否是临时标题
|
|
45
|
+
* @param opt.decode 是否需要解码
|
|
46
|
+
* @param opt.selfLink 是否允许selfLink
|
|
35
47
|
*/
|
|
36
|
-
constructor(title: string, defaultNs: number, config: Config, temporary
|
|
48
|
+
constructor(title: string, defaultNs: number, config: Config, { temporary, decode, selfLink }?: TitleOptions);
|
|
37
49
|
/**
|
|
38
50
|
* Check if the title is a redirect
|
|
39
51
|
*
|
|
40
52
|
* 检测是否是重定向
|
|
53
|
+
* @since v1.12.2
|
|
41
54
|
*/
|
|
42
55
|
getRedirection(): [boolean, string];
|
|
43
56
|
/**
|
|
@@ -45,6 +58,7 @@ export declare class Title {
|
|
|
45
58
|
*
|
|
46
59
|
* 生成URL
|
|
47
60
|
* @param articlePath article path / 条目路径
|
|
61
|
+
* @since v1.10.0
|
|
48
62
|
*/
|
|
49
63
|
getUrl(articlePath?: string): string;
|
|
50
64
|
/**
|
|
@@ -57,30 +71,35 @@ export declare class Title {
|
|
|
57
71
|
* Get the title of its subject page
|
|
58
72
|
*
|
|
59
73
|
* 转换为主页面
|
|
74
|
+
* @since v1.1.0
|
|
60
75
|
*/
|
|
61
76
|
toSubjectPage(): void;
|
|
62
77
|
/**
|
|
63
78
|
* Get the title of its talk page
|
|
64
79
|
*
|
|
65
80
|
* 转换为讨论页面
|
|
81
|
+
* @since v1.1.0
|
|
66
82
|
*/
|
|
67
83
|
toTalkPage(): void;
|
|
68
84
|
/**
|
|
69
85
|
* Check if the title is a talk page
|
|
70
86
|
*
|
|
71
87
|
* 是否是讨论页
|
|
88
|
+
* @since v1.1.0
|
|
72
89
|
*/
|
|
73
90
|
isTalkPage(): boolean;
|
|
74
91
|
/**
|
|
75
92
|
* Get the title of its base page
|
|
76
93
|
*
|
|
77
94
|
* 转换为上一级页面
|
|
95
|
+
* @since v1.1.0
|
|
78
96
|
*/
|
|
79
97
|
toBasePage(): void;
|
|
80
98
|
/**
|
|
81
99
|
* Get the title of its root page
|
|
82
100
|
*
|
|
83
101
|
* 转换为根页面
|
|
102
|
+
* @since v1.1.0
|
|
84
103
|
*/
|
|
85
104
|
toRootPage(): void;
|
|
86
105
|
}
|
package/dist/lib/title.js
CHANGED
|
@@ -8,7 +8,6 @@ const string_1 = require("../util/string");
|
|
|
8
8
|
/* NOT FOR BROWSER */
|
|
9
9
|
const constants_1 = require("../util/constants");
|
|
10
10
|
const index_1 = __importDefault(require("../index"));
|
|
11
|
-
/* NOT FOR BROWSER END */
|
|
12
11
|
/**
|
|
13
12
|
* title object of a MediaWiki page
|
|
14
13
|
*
|
|
@@ -56,7 +55,10 @@ class Title {
|
|
|
56
55
|
get title() {
|
|
57
56
|
return this.getRedirection()[1];
|
|
58
57
|
}
|
|
59
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* file extension / 扩展名
|
|
60
|
+
* @since v1.1.0
|
|
61
|
+
*/
|
|
60
62
|
get extension() {
|
|
61
63
|
const { main } = this, i = main.lastIndexOf('.');
|
|
62
64
|
return i === -1 ? undefined : main.slice(i + 1).toLowerCase();
|
|
@@ -97,10 +99,13 @@ class Title {
|
|
|
97
99
|
*
|
|
98
100
|
* @param title 标题(含或不含命名空间前缀)
|
|
99
101
|
* @param defaultNs 命名空间
|
|
100
|
-
* @param
|
|
101
|
-
* @param
|
|
102
|
+
* @param config
|
|
103
|
+
* @param opt 选项
|
|
104
|
+
* @param opt.temporary 是否是临时标题
|
|
105
|
+
* @param opt.decode 是否需要解码
|
|
106
|
+
* @param opt.selfLink 是否允许selfLink
|
|
102
107
|
*/
|
|
103
|
-
constructor(title, defaultNs, config, temporary, decode, selfLink) {
|
|
108
|
+
constructor(title, defaultNs, config, { temporary, decode, selfLink } = {}) {
|
|
104
109
|
const subpage = title.trim().startsWith('../');
|
|
105
110
|
if (decode && title.includes('%')) {
|
|
106
111
|
try {
|
|
@@ -174,6 +179,7 @@ class Title {
|
|
|
174
179
|
* Check if the title is a redirect
|
|
175
180
|
*
|
|
176
181
|
* 检测是否是重定向
|
|
182
|
+
* @since v1.12.2
|
|
177
183
|
*/
|
|
178
184
|
getRedirection() {
|
|
179
185
|
const prefix = this.interwiki + (this.interwiki && ':') + // eslint-disable-line @stylistic/operator-linebreak
|
|
@@ -202,6 +208,7 @@ class Title {
|
|
|
202
208
|
*
|
|
203
209
|
* 生成URL
|
|
204
210
|
* @param articlePath article path / 条目路径
|
|
211
|
+
* @since v1.10.0
|
|
205
212
|
*/
|
|
206
213
|
getUrl(articlePath) {
|
|
207
214
|
LSP: { // eslint-disable-line no-unused-labels
|
|
@@ -267,6 +274,7 @@ class Title {
|
|
|
267
274
|
* Get the title of its subject page
|
|
268
275
|
*
|
|
269
276
|
* 转换为主页面
|
|
277
|
+
* @since v1.1.0
|
|
270
278
|
*/
|
|
271
279
|
toSubjectPage() {
|
|
272
280
|
if (this.isTalkPage()) {
|
|
@@ -277,6 +285,7 @@ class Title {
|
|
|
277
285
|
* Get the title of its talk page
|
|
278
286
|
*
|
|
279
287
|
* 转换为讨论页面
|
|
288
|
+
* @since v1.1.0
|
|
280
289
|
*/
|
|
281
290
|
toTalkPage() {
|
|
282
291
|
if (!this.isTalkPage()) {
|
|
@@ -287,6 +296,7 @@ class Title {
|
|
|
287
296
|
* Check if the title is a talk page
|
|
288
297
|
*
|
|
289
298
|
* 是否是讨论页
|
|
299
|
+
* @since v1.1.0
|
|
290
300
|
*/
|
|
291
301
|
isTalkPage() {
|
|
292
302
|
return this.ns % 2 === 1;
|
|
@@ -295,6 +305,7 @@ class Title {
|
|
|
295
305
|
* Get the title of its base page
|
|
296
306
|
*
|
|
297
307
|
* 转换为上一级页面
|
|
308
|
+
* @since v1.1.0
|
|
298
309
|
*/
|
|
299
310
|
toBasePage() {
|
|
300
311
|
this.main = this.main.replace(/\/[^/]*$/u, '');
|
|
@@ -303,6 +314,7 @@ class Title {
|
|
|
303
314
|
* Get the title of its root page
|
|
304
315
|
*
|
|
305
316
|
* 转换为根页面
|
|
317
|
+
* @since v1.1.0
|
|
306
318
|
*/
|
|
307
319
|
toRootPage() {
|
|
308
320
|
this.main = this.main.replace(/\/.*/u, '');
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.noEscape = void 0;
|
|
4
|
+
const debug_1 = require("../util/debug");
|
|
5
|
+
const constants_1 = require("../util/constants");
|
|
6
|
+
/**
|
|
7
|
+
* 不需要转义的类
|
|
8
|
+
* @ignore
|
|
9
|
+
*/
|
|
10
|
+
const noEscape = (constructor, _) => {
|
|
11
|
+
/** 不可包含换行符的类 */
|
|
12
|
+
class NoEscapeToken extends constructor {
|
|
13
|
+
/** @private */
|
|
14
|
+
escape() {
|
|
15
|
+
//
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
(0, debug_1.mixin)(NoEscapeToken, constructor);
|
|
19
|
+
return NoEscapeToken;
|
|
20
|
+
};
|
|
21
|
+
exports.noEscape = noEscape;
|
|
22
|
+
constants_1.mixins['noEscape'] = __filename;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.readOnly = void 0;
|
|
7
|
+
const debug_1 = require("../util/debug");
|
|
8
|
+
const constants_1 = require("../util/constants");
|
|
9
|
+
const index_1 = __importDefault(require("../index"));
|
|
10
|
+
/**
|
|
11
|
+
* 只读或可写的方法
|
|
12
|
+
* @param readonly 是否只读
|
|
13
|
+
*/
|
|
14
|
+
const readOnly = (readonly = false) =>
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
16
|
+
(method) => function (...args) {
|
|
17
|
+
const { viewOnly } = index_1.default;
|
|
18
|
+
if (!debug_1.Shadow.running) {
|
|
19
|
+
index_1.default.viewOnly = readonly;
|
|
20
|
+
}
|
|
21
|
+
const result = method.apply(this, args);
|
|
22
|
+
index_1.default.viewOnly = viewOnly;
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
exports.readOnly = readOnly;
|
|
26
|
+
constants_1.mixins['readOnly'] = __filename;
|
package/dist/parser/braces.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.parseBraces = void 0;
|
|
4
|
+
const common_1 = require("@bhsd/common");
|
|
4
5
|
const string_1 = require("../util/string");
|
|
5
6
|
const heading_1 = require("../src/heading");
|
|
6
7
|
const transclude_1 = require("../src/transclude");
|
|
@@ -8,12 +9,35 @@ const arg_1 = require("../src/arg");
|
|
|
8
9
|
/* NOT FOR BROWSER */
|
|
9
10
|
const constants_1 = require("../util/constants");
|
|
10
11
|
/* NOT FOR BROWSER END */
|
|
12
|
+
/* NOT FOR BROWSER ONLY */
|
|
13
|
+
const v8_1 = require("v8");
|
|
14
|
+
const MAXHEAP = (0, v8_1.getHeapStatistics)().heap_size_limit * 0.9;
|
|
15
|
+
/* NOT FOR BROWSER ONLY END */
|
|
11
16
|
const closes = {
|
|
12
17
|
'=': String.raw `\n(?!(?:[^\S\n]|\0\d+[cn]\x7F)*\n)`,
|
|
13
18
|
'{': String.raw `\}{2,}|\|`,
|
|
14
19
|
'-': String.raw `\}-`,
|
|
15
20
|
'[': String.raw `\]\]`,
|
|
16
|
-
}, openBraces = String.raw `|\{{2,}`, marks = new Map([['!', '!'], ['!!', '+'], ['(!', '{'], ['!)', '}'], ['!-', '-'], ['=', '~'], ['server', 'm']]);
|
|
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
|
+
}
|
|
17
41
|
/**
|
|
18
42
|
* 获取模板或魔术字对应的字符
|
|
19
43
|
* @param s 模板或魔术字名
|
|
@@ -36,7 +60,8 @@ const getSymbol = (s) => {
|
|
|
36
60
|
* @param wikitext
|
|
37
61
|
* @param config
|
|
38
62
|
* @param accum
|
|
39
|
-
* @throws
|
|
63
|
+
* @throws `RangeError` Maximum iteration exceeded
|
|
64
|
+
* @throws `TranscludeToken.constructor()`
|
|
40
65
|
*/
|
|
41
66
|
const parseBraces = (wikitext, config, accum) => {
|
|
42
67
|
const source = String.raw `${config.excludes?.includes('heading') ? '' : String.raw `^((?:\0\d+[cno]\x7F)*)={1,6}|`}\[\[|-\{(?!\{)`, { parserFunction: [, , , subst] } = config, stack = [], linkStack = [];
|
|
@@ -45,48 +70,63 @@ const parseBraces = (wikitext, config, accum) => {
|
|
|
45
70
|
* @param s 不含内链的字符串
|
|
46
71
|
*/
|
|
47
72
|
const restore = (s) => s.replace(/\0(\d+)\x7F/gu, (_, p1) => linkStack[p1]);
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
73
|
+
/**
|
|
74
|
+
* 填入模板内容
|
|
75
|
+
* @param text wikitext全文
|
|
76
|
+
* @param parts 模板参数
|
|
77
|
+
* @param lastIndex 匹配的起始位置
|
|
78
|
+
* @param index 匹配位置
|
|
79
|
+
*/
|
|
80
|
+
const push = (text, parts, lastIndex, index) => {
|
|
81
|
+
parts[parts.length - 1].push(restore(text.slice(lastIndex, index)));
|
|
82
|
+
};
|
|
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
|
+
}
|
|
63
104
|
}
|
|
64
105
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
});
|
|
106
|
+
linkStack.push(restore(m));
|
|
107
|
+
return `\0${linkStack.length - 1}\x7F`;
|
|
108
|
+
});
|
|
109
|
+
} while (replaced !== wikitext);
|
|
110
|
+
wikitext = replaced;
|
|
69
111
|
const lastBraces = wikitext.lastIndexOf('}}') - wikitext.length;
|
|
70
112
|
let moreBraces = lastBraces + wikitext.length !== -1;
|
|
71
113
|
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
72
114
|
/^((?:\0\d+[cno]\x7F)*)={1,6}|\[\[|-\{(?!\{)|\{{2,}|\n(?!(?:[^\S\n]|\0\d+[cn]\x7F)*\n)|[|=]|\}{2,}|\}-|\]\]/gmu;
|
|
73
|
-
let regex =
|
|
115
|
+
let regex = getExecRegex(source + (moreBraces ? openBraces : '')), mt = regex.exec(wikitext), lastIndex;
|
|
74
116
|
while (mt
|
|
75
117
|
|| lastIndex !== undefined && lastIndex <= wikitext.length
|
|
76
118
|
&& stack[stack.length - 1]?.[0]?.startsWith('=')) {
|
|
119
|
+
/* NOT FOR BROWSER ONLY */
|
|
120
|
+
if (process.memoryUsage().heapUsed > MAXHEAP) {
|
|
121
|
+
throw new RangeError('Maximum heap size exceeded');
|
|
122
|
+
}
|
|
123
|
+
/* NOT FOR BROWSER ONLY END */
|
|
77
124
|
if (mt?.[1]) {
|
|
78
125
|
const [, { length }] = mt;
|
|
79
126
|
mt[0] = mt[0].slice(length);
|
|
80
127
|
mt.index += length;
|
|
81
128
|
}
|
|
82
129
|
const { 0: syntax, index: curIndex } = mt ?? { 0: '\n', index: wikitext.length }, top = stack.pop() ?? {}, { 0: open, index, parts, findEqual: topFindEqual, pos: topPos } = top, innerEqual = syntax === '=' && topFindEqual;
|
|
83
|
-
/**
|
|
84
|
-
* 填入模板内容
|
|
85
|
-
* @param text wikitext全文
|
|
86
|
-
*/
|
|
87
|
-
const push = (text) => {
|
|
88
|
-
parts[parts.length - 1].push(restore(text.slice(topPos, curIndex)));
|
|
89
|
-
};
|
|
90
130
|
if (syntax === ']]' || syntax === '}-') { // 情形1:闭合内链或转换
|
|
91
131
|
lastIndex = curIndex + 2;
|
|
92
132
|
}
|
|
@@ -97,17 +137,19 @@ const parseBraces = (wikitext, config, accum) => {
|
|
|
97
137
|
const rmt = /^(={1,6})(.+)\1((?:\s|\0\d+[cn]\x7F)*)$/u
|
|
98
138
|
.exec(wikitext.slice(index, curIndex));
|
|
99
139
|
if (rmt) {
|
|
100
|
-
wikitext = `${wikitext.slice(0, index)}\0${accum.length}h\x7F${wikitext.slice(curIndex)}`;
|
|
101
|
-
lastIndex = index + 4 + String(accum.length).length;
|
|
102
140
|
rmt[2] = restore(rmt[2]);
|
|
103
|
-
|
|
104
|
-
|
|
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
|
+
}
|
|
105
147
|
}
|
|
106
148
|
}
|
|
107
149
|
}
|
|
108
150
|
else if (syntax === '|' || innerEqual) { // 情形3:模板内部,含行首单个'='
|
|
109
151
|
lastIndex = curIndex + 1;
|
|
110
|
-
push(wikitext);
|
|
152
|
+
push(wikitext, parts, topPos, curIndex);
|
|
111
153
|
if (syntax === '|') {
|
|
112
154
|
parts.push([]);
|
|
113
155
|
}
|
|
@@ -118,7 +160,7 @@ const parseBraces = (wikitext, config, accum) => {
|
|
|
118
160
|
else if (syntax.startsWith('}}')) { // 情形4:闭合模板
|
|
119
161
|
const close = syntax.slice(0, Math.min(open.length, 3)), rest = open.length - close.length, { length } = accum;
|
|
120
162
|
lastIndex = curIndex + close.length; // 这不是最终的lastIndex
|
|
121
|
-
push(wikitext);
|
|
163
|
+
push(wikitext, parts, topPos, curIndex);
|
|
122
164
|
let skip = false, ch = 't';
|
|
123
165
|
if (close.length === 3) {
|
|
124
166
|
const argParts = parts.map(part => part.join('=')), str = argParts.length > 1 && (0, string_1.removeComment)(argParts[1]).trim();
|
|
@@ -173,9 +215,9 @@ const parseBraces = (wikitext, config, accum) => {
|
|
|
173
215
|
}
|
|
174
216
|
}
|
|
175
217
|
/\{\{\s*([!=]|!!|\(!|!\)|!-)\s*\}\}(?!\})/gu; // eslint-disable-line @typescript-eslint/no-unused-expressions
|
|
176
|
-
regex =
|
|
218
|
+
regex = getExecRegex(source
|
|
177
219
|
+ (moreBraces ? openBraces : '')
|
|
178
|
-
+ (curTop ? `|${closes[curTop[0][0]]}${curTop.findEqual ? '|=' : ''}` : '')
|
|
220
|
+
+ (curTop ? `|${closes[curTop[0][0]]}${curTop.findEqual ? '|=' : ''}` : ''));
|
|
179
221
|
regex.lastIndex = lastIndex;
|
|
180
222
|
mt = regex.exec(wikitext);
|
|
181
223
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.parseCommentAndExt = void 0;
|
|
4
|
+
const common_1 = require("@bhsd/common");
|
|
4
5
|
const onlyinclude_1 = require("../src/onlyinclude");
|
|
5
6
|
const noinclude_1 = require("../src/nowiki/noinclude");
|
|
6
7
|
const include_1 = require("../src/tagPair/include");
|
|
@@ -9,24 +10,12 @@ const comment_1 = require("../src/nowiki/comment");
|
|
|
9
10
|
/* NOT FOR BROWSER */
|
|
10
11
|
const constants_1 = require("../util/constants");
|
|
11
12
|
/* NOT FOR BROWSER END */
|
|
12
|
-
const onlyincludeLeft = '<onlyinclude>', onlyincludeRight = '</onlyinclude>', { length } = onlyincludeLeft,
|
|
13
|
-
/**
|
|
14
|
-
* 获取正则表达式
|
|
15
|
-
* @param ext 扩展标签
|
|
16
|
-
* @param includeOnly 是否嵌入
|
|
17
|
-
*/
|
|
18
|
-
const getRegex = (ext, includeOnly) => {
|
|
19
|
-
const regex = includeOnly ? regexInclude : regexNoinclude;
|
|
20
|
-
if (regex.has(ext)) {
|
|
21
|
-
return regex.get(ext);
|
|
22
|
-
}
|
|
13
|
+
const onlyincludeLeft = '<onlyinclude>', onlyincludeRight = '</onlyinclude>', { length } = onlyincludeLeft, getRegex = [false, true].map(includeOnly => {
|
|
23
14
|
const noincludeRegex = includeOnly ? 'includeonly' : '(?:no|only)include', includeRegex = includeOnly ? 'noinclude' : 'includeonly';
|
|
24
15
|
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
25
16
|
/<!--[\s\S]*?(?:-->|$)|<foo(?:\s[^>]*)?\/?>|<\/foo\s*>|<(bar)(\s[^>]*?)?(?:\/>|>([\s\S]*?)<\/(\1\s*)>)|<(baz)(\s[^>]*?)?(?:\/>|>([\s\S]*?)(?:<\/(baz\s*)>|$))/giu;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return re;
|
|
29
|
-
};
|
|
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
|
+
});
|
|
30
19
|
/**
|
|
31
20
|
* 更新`<onlyinclude>`和`</onlyinclude>`的位置
|
|
32
21
|
* @param wikitext
|
|
@@ -72,7 +61,7 @@ const parseCommentAndExt = (wikitext, config, accum, includeOnly) => {
|
|
|
72
61
|
return str;
|
|
73
62
|
}
|
|
74
63
|
}
|
|
75
|
-
return wikitext.replace(getRegex(config.ext
|
|
64
|
+
return wikitext.replace(getRegex[includeOnly ? 1 : 0](config.ext), (substr, name, attr, inner, closing, include, includeAttr, includeInner, includeClosing) => {
|
|
76
65
|
const l = accum.length;
|
|
77
66
|
let ch = 'n';
|
|
78
67
|
if (name) {
|
package/dist/parser/links.js
CHANGED
|
@@ -56,7 +56,7 @@ const parseLinks = (wikitext, config, accum, tidy) => {
|
|
|
56
56
|
}
|
|
57
57
|
const { ns, valid,
|
|
58
58
|
/* NOT FOR BROWSER */
|
|
59
|
-
interwiki, } = index_1.default.normalizeTitle(link, 0, false, config, true, true, true, true);
|
|
59
|
+
interwiki, } = index_1.default.normalizeTitle(link, 0, false, config, { halfParsed: true, temporary: true, decode: true, selfLink: true });
|
|
60
60
|
if (!valid) {
|
|
61
61
|
s += `[[${x}`;
|
|
62
62
|
continue;
|
package/dist/parser/quotes.js
CHANGED
|
@@ -79,7 +79,7 @@ const parseQuotes = (wikitext, config, accum, tidy) => {
|
|
|
79
79
|
/* NOT FOR BROWSER */
|
|
80
80
|
if (tidy && (!bold || !italic)) {
|
|
81
81
|
// @ts-expect-error abstract class
|
|
82
|
-
new quote_1.QuoteToken((bold ? '' :
|
|
82
|
+
new quote_1.QuoteToken((bold ? '' : `'''`) + (italic ? '' : `''`), { bold: !bold, italic: !italic }, config, accum);
|
|
83
83
|
arr.push(`\0${accum.length - 1}q\x7F`);
|
|
84
84
|
}
|
|
85
85
|
/* NOT FOR BROWSER END */
|
package/dist/parser/redirect.js
CHANGED
|
@@ -21,9 +21,7 @@ const parseRedirect = (text, config, accum) => {
|
|
|
21
21
|
config.regexRedirect ??= new RegExp(String.raw `^(\s*)((?:${config.redirection.join('|')})\s*(?::\s*)?)\[\[([^\n|\]]+)(\|.*?)?\]\](\s*)`, 'iu');
|
|
22
22
|
const mt = config.regexRedirect.exec(text);
|
|
23
23
|
if (mt
|
|
24
|
-
&& index_1.default
|
|
25
|
-
.normalizeTitle(mt[3], 0, false, config, true, true, true)
|
|
26
|
-
.valid) {
|
|
24
|
+
&& index_1.default.normalizeTitle(mt[3], 0, false, config, { halfParsed: true, temporary: true, decode: true }).valid) {
|
|
27
25
|
text = `\0${accum.length}o\x7F${text.slice(mt[0].length)}`;
|
|
28
26
|
// @ts-expect-error abstract class
|
|
29
27
|
new redirect_1.RedirectToken(...mt.slice(1), config, accum);
|