wikilint 2.18.2 → 2.18.3
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/bin/cli.js +1 -1
- package/config/minimum.json +7 -0
- package/dist/base.d.mts +2 -0
- package/dist/base.d.ts +2 -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 +3 -1
- package/dist/index.js +38 -28
- package/dist/lib/lsp.d.ts +1 -0
- package/dist/lib/lsp.js +15 -9
- package/dist/lib/title.d.ts +18 -4
- package/dist/lib/title.js +12 -4
- package/dist/parser/braces.js +29 -15
- package/dist/parser/commentAndExt.js +5 -16
- package/dist/parser/links.js +1 -1
- package/dist/parser/redirect.js +1 -3
- package/dist/src/converter.js +1 -1
- package/dist/src/gallery.js +1 -1
- package/dist/src/heading.js +3 -3
- package/dist/src/imageParameter.js +9 -9
- package/dist/src/imagemap.js +3 -2
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +7 -5
- package/dist/src/link/base.js +1 -1
- package/dist/src/link/file.d.ts +2 -0
- package/dist/src/link/file.js +15 -13
- package/dist/src/link/galleryImage.js +1 -1
- package/dist/src/link/redirectTarget.js +1 -2
- package/dist/src/magicLink.js +1 -1
- package/dist/src/nested.js +5 -5
- package/dist/src/nowiki/index.js +3 -2
- package/dist/src/redirect.js +1 -2
- package/dist/src/syntax.d.ts +4 -2
- package/dist/src/syntax.js +4 -2
- package/dist/src/table/base.js +1 -1
- package/dist/src/table/index.js +2 -5
- package/dist/src/table/trBase.js +3 -1
- package/dist/src/transclude.js +3 -3
- package/dist/util/debug.js +11 -1
- package/dist/util/string.js +3 -4
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
# WikiLint
|
|
8
8
|
|
|
9
|
-
This is a minimal version of [WikiParser-Node](https://www.npmjs.com/package/wikiparser-node)
|
|
9
|
+
This is a minimal version of [WikiParser-Node](https://www.npmjs.com/package/wikiparser-node). The [WikiParser Language Server](https://marketplace.visualstudio.com/items?itemName=Bhsd.vscode-extension-wikiparser) VSCode extension is written based on this package.
|
|
10
10
|
|
|
11
11
|
You can also directly lint Wikitext articles in the command line using this package:
|
|
12
12
|
|
package/bin/cli.js
CHANGED
package/config/minimum.json
CHANGED
|
@@ -98,6 +98,13 @@
|
|
|
98
98
|
],
|
|
99
99
|
"parserFunction": [
|
|
100
100
|
{
|
|
101
|
+
"msgnw": "msgnw",
|
|
102
|
+
"pageid": "pageid",
|
|
103
|
+
"articlepath": "articlepath",
|
|
104
|
+
"server": "server",
|
|
105
|
+
"servername": "servername",
|
|
106
|
+
"scriptpath": "scriptpath",
|
|
107
|
+
"stylepath": "stylepath",
|
|
101
108
|
"#language": "language",
|
|
102
109
|
"#special": "special",
|
|
103
110
|
"#speciale": "speciale",
|
package/dist/base.d.mts
CHANGED
|
@@ -41,6 +41,7 @@ export declare const stages: {
|
|
|
41
41
|
list: number;
|
|
42
42
|
dd: number;
|
|
43
43
|
converter: number;
|
|
44
|
+
'list-range': number;
|
|
44
45
|
};
|
|
45
46
|
export type Stage = keyof typeof stages;
|
|
46
47
|
export declare const rules: readonly ["bold-header", "format-leakage", "fostered-content", "h1", "illegal-attr", "insecure-style", "invalid-gallery", "invalid-imagemap", "invalid-invoke", "invalid-isbn", "lonely-apos", "lonely-bracket", "lonely-http", "nested-link", "no-arg", "no-duplicate", "no-ignored", "obsolete-attr", "obsolete-tag", "parsing-order", "pipe-like", "table-layout", "tag-like", "unbalanced-header", "unclosed-comment", "unclosed-quote", "unclosed-table", "unescaped", "unknown-page", "unmatched-tag", "unterminated-url", "url-encoding", "var-anchor", "void-ext", "invalid-css"];
|
|
@@ -271,6 +272,7 @@ export interface Parser {
|
|
|
271
272
|
*
|
|
272
273
|
* 创建语言服务
|
|
273
274
|
* @param uri document URI / 文档标识
|
|
275
|
+
* @since v1.16.1
|
|
274
276
|
*/
|
|
275
277
|
createLanguageService(uri: object): LanguageService;
|
|
276
278
|
}
|
package/dist/base.d.ts
CHANGED
|
@@ -41,6 +41,7 @@ export declare const stages: {
|
|
|
41
41
|
list: number;
|
|
42
42
|
dd: number;
|
|
43
43
|
converter: number;
|
|
44
|
+
'list-range': number;
|
|
44
45
|
};
|
|
45
46
|
export type Stage = keyof typeof stages;
|
|
46
47
|
export declare const rules: readonly ["bold-header", "format-leakage", "fostered-content", "h1", "illegal-attr", "insecure-style", "invalid-gallery", "invalid-imagemap", "invalid-invoke", "invalid-isbn", "lonely-apos", "lonely-bracket", "lonely-http", "nested-link", "no-arg", "no-duplicate", "no-ignored", "obsolete-attr", "obsolete-tag", "parsing-order", "pipe-like", "table-layout", "tag-like", "unbalanced-header", "unclosed-comment", "unclosed-quote", "unclosed-table", "unescaped", "unknown-page", "unmatched-tag", "unterminated-url", "url-encoding", "var-anchor", "void-ext", "invalid-css"];
|
|
@@ -271,6 +272,7 @@ export interface Parser {
|
|
|
271
272
|
*
|
|
272
273
|
* 创建语言服务
|
|
273
274
|
* @param uri document URI / 文档标识
|
|
275
|
+
* @since v1.16.1
|
|
274
276
|
*/
|
|
275
277
|
createLanguageService(uri: object): LanguageService;
|
|
276
278
|
}
|
package/dist/base.js
CHANGED
package/dist/base.mjs
CHANGED
package/dist/bin/config.js
CHANGED
|
@@ -81,8 +81,9 @@ let mwConfig;
|
|
|
81
81
|
* @param site site nickname
|
|
82
82
|
* @param url script path
|
|
83
83
|
* @param force whether to overwrite the existing configuration
|
|
84
|
+
* @param internal for internal use
|
|
84
85
|
*/
|
|
85
|
-
exports.default = async (site, url, force) => {
|
|
86
|
+
exports.default = async (site, url, force, internal) => {
|
|
86
87
|
if (!site || !url) {
|
|
87
88
|
console.error('Usage: npx getParserConfig <site> <script path> [force]');
|
|
88
89
|
process.exit(1);
|
|
@@ -133,7 +134,7 @@ exports.default = async (site, url, force) => {
|
|
|
133
134
|
if (force || !fs_1.default.existsSync(file)) {
|
|
134
135
|
fs_1.default.writeFileSync(file, `${JSON.stringify(config, null, '\t')}\n`);
|
|
135
136
|
}
|
|
136
|
-
else {
|
|
137
|
+
else if (!internal) {
|
|
137
138
|
assert_1.default.deepStrictEqual(arrToObj(require(file)), arrToObj(config));
|
|
138
139
|
}
|
|
139
140
|
return config;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { Config, LintError, TokenTypes, Parser as ParserBase, Stage } from './base';
|
|
2
|
-
import type { Title } from './lib/title';
|
|
2
|
+
import type { Title, TitleOptions } from './lib/title';
|
|
3
3
|
import type { LanguageService, QuickFixData } from './lib/lsp';
|
|
4
4
|
import type { Token } from './internal';
|
|
5
5
|
declare interface Parser extends ParserBase {
|
|
6
|
+
/** @since v1.5.1 */
|
|
6
7
|
rules: readonly LintError.Rule[];
|
|
7
8
|
/**
|
|
8
9
|
* Normalize page title
|
|
@@ -19,6 +20,7 @@ declare interface Parser extends ParserBase {
|
|
|
19
20
|
*
|
|
20
21
|
* 创建语言服务
|
|
21
22
|
* @param uri document URI / 文档标识
|
|
23
|
+
* @since v1.16.1
|
|
22
24
|
*/
|
|
23
25
|
createLanguageService(uri: object): LanguageService;
|
|
24
26
|
}
|
package/dist/index.js
CHANGED
|
@@ -25,6 +25,9 @@ const Parser = {
|
|
|
25
25
|
config: 'default',
|
|
26
26
|
i18n: undefined,
|
|
27
27
|
rules: base_1.rules,
|
|
28
|
+
/* NOT FOR BROWSER ONLY */
|
|
29
|
+
lintCSS: true,
|
|
30
|
+
/* NOT FOR BROWSER ONLY END */
|
|
28
31
|
/** @implements */
|
|
29
32
|
getConfig(config) {
|
|
30
33
|
/* NOT FOR BROWSER ONLY */
|
|
@@ -39,7 +42,7 @@ const Parser = {
|
|
|
39
42
|
return this.getConfig();
|
|
40
43
|
}
|
|
41
44
|
/* NOT FOR BROWSER ONLY END */
|
|
42
|
-
const parserConfig = config ?? this.config, { doubleUnderscore } = parserConfig;
|
|
45
|
+
const parserConfig = config ?? this.config, { doubleUnderscore, } = parserConfig;
|
|
43
46
|
for (let i = 0; i < 2; i++) {
|
|
44
47
|
if (doubleUnderscore.length > i + 2 && doubleUnderscore[i].length === 0) {
|
|
45
48
|
doubleUnderscore[i] = Object.keys(doubleUnderscore[i + 2]);
|
|
@@ -61,11 +64,11 @@ const Parser = {
|
|
|
61
64
|
return msg && (this.i18n?.[msg] ?? msg).replace('$1', this.msg(arg));
|
|
62
65
|
},
|
|
63
66
|
/** @implements */
|
|
64
|
-
normalizeTitle(title, defaultNs = 0, include, config = Parser.getConfig(),
|
|
67
|
+
normalizeTitle(title, defaultNs = 0, include, config = Parser.getConfig(), opt) {
|
|
65
68
|
const { Title } = require('./lib/title');
|
|
66
69
|
let titleObj;
|
|
67
|
-
if (halfParsed) {
|
|
68
|
-
titleObj = new Title(title, defaultNs, config,
|
|
70
|
+
if (opt?.halfParsed) {
|
|
71
|
+
titleObj = new Title(title, defaultNs, config, opt);
|
|
69
72
|
}
|
|
70
73
|
else {
|
|
71
74
|
const { Token } = require('./src/index');
|
|
@@ -73,7 +76,7 @@ const Parser = {
|
|
|
73
76
|
const root = new Token(title, config);
|
|
74
77
|
root.type = 'root';
|
|
75
78
|
root.parseOnce(0, include).parseOnce();
|
|
76
|
-
const t = new Title(root.toString(), defaultNs, config,
|
|
79
|
+
const t = new Title(root.toString(), defaultNs, config, opt);
|
|
77
80
|
for (const key of ['main', 'fragment']) {
|
|
78
81
|
const str = t[key];
|
|
79
82
|
if (str?.includes('\0')) {
|
|
@@ -94,8 +97,9 @@ const Parser = {
|
|
|
94
97
|
/** @implements */
|
|
95
98
|
parse(wikitext, include, maxStage = constants_1.MAX_STAGE, config = Parser.getConfig()) {
|
|
96
99
|
wikitext = (0, string_1.tidy)(wikitext);
|
|
100
|
+
let types;
|
|
97
101
|
if (typeof maxStage !== 'number') {
|
|
98
|
-
|
|
102
|
+
types = Array.isArray(maxStage) ? maxStage : [maxStage];
|
|
99
103
|
maxStage = Math.max(...types.map(t => base_1.stages[t] || constants_1.MAX_STAGE));
|
|
100
104
|
}
|
|
101
105
|
const { Token } = require('./src/index');
|
|
@@ -132,28 +136,34 @@ const Parser = {
|
|
|
132
136
|
const token = new Token((0, string_1.tidy)(wikitext), config);
|
|
133
137
|
token.type = 'root';
|
|
134
138
|
let i = 0;
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
139
|
+
try {
|
|
140
|
+
await new Promise(resolve => {
|
|
141
|
+
const /** @ignore */ check = () => {
|
|
142
|
+
if (watch() === wikitext) {
|
|
143
|
+
i++;
|
|
144
|
+
set(parseOnce, 0);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
resolve();
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
/** @ignore */ parseOnce = () => {
|
|
151
|
+
if (i === constants_1.MAX_STAGE + 1) {
|
|
152
|
+
token.afterBuild();
|
|
153
|
+
resolve();
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
token[i === constants_1.MAX_STAGE ? 'build' : 'parseOnce'](i, include);
|
|
157
|
+
check();
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
set(parseOnce, 0);
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
catch (e) /* istanbul ignore next */ {
|
|
164
|
+
debug_1.Shadow.running = running;
|
|
165
|
+
throw e;
|
|
166
|
+
}
|
|
157
167
|
debug_1.Shadow.running = running;
|
|
158
168
|
return token;
|
|
159
169
|
},
|
package/dist/lib/lsp.d.ts
CHANGED
|
@@ -20,6 +20,7 @@ export declare const isAttr: ({ type, parentNode, length, firstChild }: Token, s
|
|
|
20
20
|
/** VSCode-style language service */
|
|
21
21
|
export declare class LanguageService implements LanguageServiceBase {
|
|
22
22
|
#private;
|
|
23
|
+
/** @since v1.17.1 */
|
|
23
24
|
include: boolean;
|
|
24
25
|
lilypond: string;
|
|
25
26
|
/** @param uri 任务标识 */
|
package/dist/lib/lsp.js
CHANGED
|
@@ -23,6 +23,7 @@ const cssRules = {
|
|
|
23
23
|
'block-no-empty': null,
|
|
24
24
|
'property-no-unknown': null,
|
|
25
25
|
}, jsonSelector = document_1.jsonTags.map(s => `ext-inner#${s}`).join(), scores = new Map();
|
|
26
|
+
let colors;
|
|
26
27
|
/* NOT FOR BROWSER ONLY END */
|
|
27
28
|
exports.tasks = new WeakMap();
|
|
28
29
|
const refTags = new Set(['ref']), referencesTags = new Set(['ref', 'references']), nameAttrs = new Set(['name', 'extends', 'follow']), groupAttrs = new Set(['group']), renameTypes = new Set([
|
|
@@ -40,6 +41,7 @@ const refTags = new Set(['ref']), referencesTags = new Set(['ref', 'references']
|
|
|
40
41
|
'magic-word-name',
|
|
41
42
|
...renameTypes,
|
|
42
43
|
]), plainTypes = new Set(['text', 'comment', 'noinclude', 'include']), cssSelector = ['ext', 'html', 'table'].map(s => `${s}-attr#style`).join();
|
|
44
|
+
const getLinkRegex = (0, common_1.getRegex)(protocol => new RegExp(`^(?:${protocol}|//)`, 'iu'));
|
|
43
45
|
/**
|
|
44
46
|
* Check if a token is a plain attribute.
|
|
45
47
|
* @param token
|
|
@@ -273,6 +275,7 @@ class LanguageService {
|
|
|
273
275
|
#config;
|
|
274
276
|
#include;
|
|
275
277
|
#completionConfig;
|
|
278
|
+
/** @since v1.17.1 */
|
|
276
279
|
include = true;
|
|
277
280
|
/** @private */
|
|
278
281
|
config;
|
|
@@ -406,11 +409,14 @@ class LanguageService {
|
|
|
406
409
|
async provideDocumentColors(rgba, text, hsl = true) {
|
|
407
410
|
const root = await this.#queue(text);
|
|
408
411
|
/* NOT FOR BROWSER ONLY */
|
|
409
|
-
|
|
412
|
+
/* eslint-disable require-atomic-updates */
|
|
410
413
|
try {
|
|
411
|
-
colors
|
|
414
|
+
colors ??= new RegExp(String.raw `\b${Object.keys((await import('color-name')).default).join('|')}\b`, 'giu');
|
|
412
415
|
}
|
|
413
|
-
catch {
|
|
416
|
+
catch {
|
|
417
|
+
colors = false;
|
|
418
|
+
}
|
|
419
|
+
/* eslint-enable require-atomic-updates */
|
|
414
420
|
/* NOT FOR BROWSER ONLY END */
|
|
415
421
|
return root.querySelectorAll('attr-value,parameter-value,arg-default').reverse()
|
|
416
422
|
.flatMap(token => {
|
|
@@ -637,7 +643,7 @@ class LanguageService {
|
|
|
637
643
|
if (t === 'magic-word' && n !== 'invoke') {
|
|
638
644
|
return undefined;
|
|
639
645
|
}
|
|
640
|
-
const key = this.#text.slice(cur.getAbsoluteIndex(), root.indexFromPos(line, character)).trimStart(), [
|
|
646
|
+
const key = this.#text.slice(cur.getAbsoluteIndex(), root.indexFromPos(line, character)).trimStart(), [mod, func] = t === 'magic-word' ? transclusion.getModule() : [];
|
|
641
647
|
return key
|
|
642
648
|
? getCompletion(root.querySelectorAll('parameter').filter(token => {
|
|
643
649
|
if (token === parentNode
|
|
@@ -650,7 +656,7 @@ class LanguageService {
|
|
|
650
656
|
return true;
|
|
651
657
|
}
|
|
652
658
|
const [m, f] = token.parentNode.getModule();
|
|
653
|
-
return m ===
|
|
659
|
+
return m === mod && f === func;
|
|
654
660
|
}).map(({ name }) => name), 'Variable', key, position, type === 'parameter-value' ? '=' : '')
|
|
655
661
|
: undefined;
|
|
656
662
|
/* NOT FOR BROWSER ONLY */
|
|
@@ -893,7 +899,7 @@ class LanguageService {
|
|
|
893
899
|
*/
|
|
894
900
|
async provideLinks(text) {
|
|
895
901
|
this.config ??= index_1.default.getConfig();
|
|
896
|
-
const { articlePath, protocol } = this.config, absolute = articlePath?.includes('//'), protocolRegex =
|
|
902
|
+
const { articlePath, protocol } = this.config, absolute = articlePath?.includes('//'), protocolRegex = getLinkRegex(protocol);
|
|
897
903
|
return (await this.#queue(text))
|
|
898
904
|
.querySelectorAll(`magic-link,ext-link-url,free-ext-link,attr-value,image-parameter#link${absolute ? ',link-target,template-name,invoke-module,magic-word#filepath,magic-word#widget' : ''}`)
|
|
899
905
|
.reverse()
|
|
@@ -953,8 +959,8 @@ class LanguageService {
|
|
|
953
959
|
ns = name === 'filepath' ? 6 : 274;
|
|
954
960
|
// no default
|
|
955
961
|
}
|
|
956
|
-
const title = index_1.default
|
|
957
|
-
|
|
962
|
+
const title = index_1.default
|
|
963
|
+
.normalizeTitle(target, ns, false, this.config, { temporary: true });
|
|
958
964
|
if (!title.valid) {
|
|
959
965
|
return false;
|
|
960
966
|
}
|
|
@@ -1331,7 +1337,7 @@ class LanguageService {
|
|
|
1331
1337
|
this.config = index_1.default.getConfig(config);
|
|
1332
1338
|
}
|
|
1333
1339
|
catch {
|
|
1334
|
-
this.config = index_1.default.getConfig(await (0, config_1.default)(site, `${mt[0]}/w
|
|
1340
|
+
this.config = index_1.default.getConfig(await (0, config_1.default)(site, `${mt[0]}/w`, false, true));
|
|
1335
1341
|
}
|
|
1336
1342
|
Object.assign(this.config, { articlePath: `${mt[0]}/wiki/` });
|
|
1337
1343
|
}
|
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
|
*
|
|
@@ -18,21 +24,28 @@ export declare class Title {
|
|
|
18
24
|
get prefix(): string;
|
|
19
25
|
/** full title / 完整标题 */
|
|
20
26
|
get title(): string;
|
|
21
|
-
/**
|
|
27
|
+
/**
|
|
28
|
+
* file extension / 扩展名
|
|
29
|
+
* @since v1.1.0
|
|
30
|
+
*/
|
|
22
31
|
get extension(): string | undefined;
|
|
23
32
|
/**
|
|
24
33
|
* @see MediaWikiTitleCodec::splitTitleString
|
|
25
34
|
*
|
|
26
35
|
* @param title 标题(含或不含命名空间前缀)
|
|
27
36
|
* @param defaultNs 命名空间
|
|
28
|
-
* @param
|
|
29
|
-
* @param
|
|
37
|
+
* @param config
|
|
38
|
+
* @param opt 选项
|
|
39
|
+
* @param opt.temporary 是否是临时标题
|
|
40
|
+
* @param opt.decode 是否需要解码
|
|
41
|
+
* @param opt.selfLink 是否允许selfLink
|
|
30
42
|
*/
|
|
31
|
-
constructor(title: string, defaultNs: number, config: Config, temporary
|
|
43
|
+
constructor(title: string, defaultNs: number, config: Config, { temporary, decode, selfLink }?: TitleOptions);
|
|
32
44
|
/**
|
|
33
45
|
* Check if the title is a redirect
|
|
34
46
|
*
|
|
35
47
|
* 检测是否是重定向
|
|
48
|
+
* @since v1.12.2
|
|
36
49
|
*/
|
|
37
50
|
getRedirection(): [boolean, string];
|
|
38
51
|
/**
|
|
@@ -40,6 +53,7 @@ export declare class Title {
|
|
|
40
53
|
*
|
|
41
54
|
* 生成URL
|
|
42
55
|
* @param articlePath article path / 条目路径
|
|
56
|
+
* @since v1.10.0
|
|
43
57
|
*/
|
|
44
58
|
getUrl(articlePath?: string): string;
|
|
45
59
|
}
|
package/dist/lib/title.js
CHANGED
|
@@ -41,7 +41,10 @@ class Title {
|
|
|
41
41
|
get title() {
|
|
42
42
|
return this.getRedirection()[1];
|
|
43
43
|
}
|
|
44
|
-
/**
|
|
44
|
+
/**
|
|
45
|
+
* file extension / 扩展名
|
|
46
|
+
* @since v1.1.0
|
|
47
|
+
*/
|
|
45
48
|
get extension() {
|
|
46
49
|
const { main } = this, i = main.lastIndexOf('.');
|
|
47
50
|
return i === -1 ? undefined : main.slice(i + 1).toLowerCase();
|
|
@@ -51,10 +54,13 @@ class Title {
|
|
|
51
54
|
*
|
|
52
55
|
* @param title 标题(含或不含命名空间前缀)
|
|
53
56
|
* @param defaultNs 命名空间
|
|
54
|
-
* @param
|
|
55
|
-
* @param
|
|
57
|
+
* @param config
|
|
58
|
+
* @param opt 选项
|
|
59
|
+
* @param opt.temporary 是否是临时标题
|
|
60
|
+
* @param opt.decode 是否需要解码
|
|
61
|
+
* @param opt.selfLink 是否允许selfLink
|
|
56
62
|
*/
|
|
57
|
-
constructor(title, defaultNs, config, temporary, decode, selfLink) {
|
|
63
|
+
constructor(title, defaultNs, config, { temporary, decode, selfLink } = {}) {
|
|
58
64
|
const subpage = title.trim().startsWith('../');
|
|
59
65
|
if (decode && title.includes('%')) {
|
|
60
66
|
try {
|
|
@@ -116,6 +122,7 @@ class Title {
|
|
|
116
122
|
* Check if the title is a redirect
|
|
117
123
|
*
|
|
118
124
|
* 检测是否是重定向
|
|
125
|
+
* @since v1.12.2
|
|
119
126
|
*/
|
|
120
127
|
getRedirection() {
|
|
121
128
|
// eslint-disable-next-line @typescript-eslint/prefer-destructuring
|
|
@@ -133,6 +140,7 @@ class Title {
|
|
|
133
140
|
*
|
|
134
141
|
* 生成URL
|
|
135
142
|
* @param articlePath article path / 条目路径
|
|
143
|
+
* @since v1.10.0
|
|
136
144
|
*/
|
|
137
145
|
getUrl(articlePath) {
|
|
138
146
|
LSP: { // eslint-disable-line no-unused-labels
|
package/dist/parser/braces.js
CHANGED
|
@@ -1,16 +1,21 @@
|
|
|
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");
|
|
7
8
|
const arg_1 = require("../src/arg");
|
|
9
|
+
/* NOT FOR BROWSER ONLY */
|
|
10
|
+
const v8_1 = require("v8");
|
|
11
|
+
const MAXHEAP = (0, v8_1.getHeapStatistics)().total_available_size * 0.9, MAXITER = MAXHEAP / 2e5;
|
|
12
|
+
/* NOT FOR BROWSER ONLY END */
|
|
8
13
|
const closes = {
|
|
9
14
|
'=': String.raw `\n(?!(?:[^\S\n]|\0\d+[cn]\x7F)*\n)`,
|
|
10
15
|
'{': String.raw `\}{2,}|\|`,
|
|
11
16
|
'-': String.raw `\}-`,
|
|
12
17
|
'[': String.raw `\]\]`,
|
|
13
|
-
}, openBraces = String.raw `|\{{2,}`, marks = new Map([['!', '!'], ['!!', '+'], ['(!', '{'], ['!)', '}'], ['!-', '-'], ['=', '~'], ['server', 'm']]);
|
|
18
|
+
}, openBraces = String.raw `|\{{2,}`, marks = new Map([['!', '!'], ['!!', '+'], ['(!', '{'], ['!)', '}'], ['!-', '-'], ['=', '~'], ['server', 'm']]), getExecRegex = (0, common_1.getRegex)(s => new RegExp(s, 'gmu'));
|
|
14
19
|
/**
|
|
15
20
|
* 获取模板或魔术字对应的字符
|
|
16
21
|
* @param s 模板或魔术字名
|
|
@@ -33,7 +38,8 @@ const getSymbol = (s) => {
|
|
|
33
38
|
* @param wikitext
|
|
34
39
|
* @param config
|
|
35
40
|
* @param accum
|
|
36
|
-
* @throws
|
|
41
|
+
* @throws `RangeError` Maximum iteration exceeded
|
|
42
|
+
* @throws `TranscludeToken.constructor()`
|
|
37
43
|
*/
|
|
38
44
|
const parseBraces = (wikitext, config, accum) => {
|
|
39
45
|
const source = String.raw `${config.excludes?.includes('heading') ? '' : String.raw `^((?:\0\d+[cno]\x7F)*)={1,6}|`}\[\[|-\{(?!\{)`, { parserFunction: [, , , subst] } = config, stack = [], linkStack = [];
|
|
@@ -42,7 +48,17 @@ const parseBraces = (wikitext, config, accum) => {
|
|
|
42
48
|
* @param s 不含内链的字符串
|
|
43
49
|
*/
|
|
44
50
|
const restore = (s) => s.replace(/\0(\d+)\x7F/gu, (_, p1) => linkStack[p1]);
|
|
45
|
-
|
|
51
|
+
/**
|
|
52
|
+
* 填入模板内容
|
|
53
|
+
* @param text wikitext全文
|
|
54
|
+
* @param parts 模板参数
|
|
55
|
+
* @param lastIndex 匹配的起始位置
|
|
56
|
+
* @param index 匹配位置
|
|
57
|
+
*/
|
|
58
|
+
const push = (text, parts, lastIndex, index) => {
|
|
59
|
+
parts[parts.length - 1].push(restore(text.slice(lastIndex, index)));
|
|
60
|
+
};
|
|
61
|
+
wikitext = wikitext.replace(/\{\{([^\n{}[]*)\}\}(?!\})|\[\[[^\n[\]{]*\]\]|-\{[^\n{}[]*\}-/gu, (m, p1) => {
|
|
46
62
|
if (p1 !== undefined) {
|
|
47
63
|
try {
|
|
48
64
|
const { length } = accum, parts = p1.split('|');
|
|
@@ -65,23 +81,21 @@ const parseBraces = (wikitext, config, accum) => {
|
|
|
65
81
|
});
|
|
66
82
|
const lastBraces = wikitext.lastIndexOf('}}') - wikitext.length;
|
|
67
83
|
let moreBraces = lastBraces + wikitext.length !== -1;
|
|
68
|
-
let regex =
|
|
84
|
+
let regex = getExecRegex(source + (moreBraces ? openBraces : '')), mt = regex.exec(wikitext), iter = 0, lastIndex;
|
|
69
85
|
while (mt
|
|
70
86
|
|| lastIndex !== undefined && lastIndex <= wikitext.length
|
|
71
87
|
&& stack[stack.length - 1]?.[0]?.startsWith('=')) {
|
|
88
|
+
/* NOT FOR BROWSER ONLY */
|
|
89
|
+
if (iter++ > MAXITER && process.memoryUsage().heapUsed > MAXHEAP) {
|
|
90
|
+
throw new RangeError('Maximum iteration exceeded');
|
|
91
|
+
}
|
|
92
|
+
/* NOT FOR BROWSER ONLY END */
|
|
72
93
|
if (mt?.[1]) {
|
|
73
94
|
const [, { length }] = mt;
|
|
74
95
|
mt[0] = mt[0].slice(length);
|
|
75
96
|
mt.index += length;
|
|
76
97
|
}
|
|
77
98
|
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;
|
|
78
|
-
/**
|
|
79
|
-
* 填入模板内容
|
|
80
|
-
* @param text wikitext全文
|
|
81
|
-
*/
|
|
82
|
-
const push = (text) => {
|
|
83
|
-
parts[parts.length - 1].push(restore(text.slice(topPos, curIndex)));
|
|
84
|
-
};
|
|
85
99
|
if (syntax === ']]' || syntax === '}-') { // 情形1:闭合内链或转换
|
|
86
100
|
lastIndex = curIndex + 2;
|
|
87
101
|
}
|
|
@@ -102,7 +116,7 @@ const parseBraces = (wikitext, config, accum) => {
|
|
|
102
116
|
}
|
|
103
117
|
else if (syntax === '|' || innerEqual) { // 情形3:模板内部,含行首单个'='
|
|
104
118
|
lastIndex = curIndex + 1;
|
|
105
|
-
push(wikitext);
|
|
119
|
+
push(wikitext, parts, topPos, curIndex);
|
|
106
120
|
if (syntax === '|') {
|
|
107
121
|
parts.push([]);
|
|
108
122
|
}
|
|
@@ -113,7 +127,7 @@ const parseBraces = (wikitext, config, accum) => {
|
|
|
113
127
|
else if (syntax.startsWith('}}')) { // 情形4:闭合模板
|
|
114
128
|
const close = syntax.slice(0, Math.min(open.length, 3)), rest = open.length - close.length, { length } = accum;
|
|
115
129
|
lastIndex = curIndex + close.length; // 这不是最终的lastIndex
|
|
116
|
-
push(wikitext);
|
|
130
|
+
push(wikitext, parts, topPos, curIndex);
|
|
117
131
|
let skip = false, ch = 't';
|
|
118
132
|
if (close.length === 3) {
|
|
119
133
|
const argParts = parts.map(part => part.join('=')), str = argParts.length > 1 && (0, string_1.removeComment)(argParts[1]).trim();
|
|
@@ -167,9 +181,9 @@ const parseBraces = (wikitext, config, accum) => {
|
|
|
167
181
|
curTop = stack[stack.length - 1];
|
|
168
182
|
}
|
|
169
183
|
}
|
|
170
|
-
regex =
|
|
184
|
+
regex = getExecRegex(source
|
|
171
185
|
+ (moreBraces ? openBraces : '')
|
|
172
|
-
+ (curTop ? `|${closes[curTop[0][0]]}${curTop.findEqual ? '|=' : ''}` : '')
|
|
186
|
+
+ (curTop ? `|${closes[curTop[0][0]]}${curTop.findEqual ? '|=' : ''}` : ''));
|
|
173
187
|
regex.lastIndex = lastIndex;
|
|
174
188
|
mt = regex.exec(wikitext);
|
|
175
189
|
}
|
|
@@ -1,27 +1,16 @@
|
|
|
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");
|
|
7
8
|
const ext_1 = require("../src/tagPair/ext");
|
|
8
9
|
const comment_1 = require("../src/nowiki/comment");
|
|
9
|
-
const onlyincludeLeft = '<onlyinclude>', onlyincludeRight = '</onlyinclude>', { length } = onlyincludeLeft,
|
|
10
|
-
/**
|
|
11
|
-
* 获取正则表达式
|
|
12
|
-
* @param ext 扩展标签
|
|
13
|
-
* @param includeOnly 是否嵌入
|
|
14
|
-
*/
|
|
15
|
-
const getRegex = (ext, includeOnly) => {
|
|
16
|
-
const regex = includeOnly ? regexInclude : regexNoinclude;
|
|
17
|
-
if (regex.has(ext)) {
|
|
18
|
-
return regex.get(ext);
|
|
19
|
-
}
|
|
10
|
+
const onlyincludeLeft = '<onlyinclude>', onlyincludeRight = '</onlyinclude>', { length } = onlyincludeLeft, getRegex = [false, true].map(includeOnly => {
|
|
20
11
|
const noincludeRegex = includeOnly ? 'includeonly' : '(?:no|only)include', includeRegex = includeOnly ? 'noinclude' : 'includeonly';
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
return re;
|
|
24
|
-
};
|
|
12
|
+
return (0, common_1.getObjRegex)(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'));
|
|
13
|
+
});
|
|
25
14
|
/**
|
|
26
15
|
* 更新`<onlyinclude>`和`</onlyinclude>`的位置
|
|
27
16
|
* @param wikitext
|
|
@@ -67,7 +56,7 @@ const parseCommentAndExt = (wikitext, config, accum, includeOnly) => {
|
|
|
67
56
|
return str;
|
|
68
57
|
}
|
|
69
58
|
}
|
|
70
|
-
return wikitext.replace(getRegex(config.ext
|
|
59
|
+
return wikitext.replace(getRegex[includeOnly ? 1 : 0](config.ext), (substr, name, attr, inner, closing, include, includeAttr, includeInner, includeClosing) => {
|
|
71
60
|
const l = accum.length;
|
|
72
61
|
let ch = 'n';
|
|
73
62
|
if (name) {
|
package/dist/parser/links.js
CHANGED
|
@@ -50,7 +50,7 @@ const parseLinks = (wikitext, config, accum, tidy) => {
|
|
|
50
50
|
s += `[[${x}`;
|
|
51
51
|
continue;
|
|
52
52
|
}
|
|
53
|
-
const { ns, valid, } = index_1.default.normalizeTitle(link, 0, false, config, true, true, true, true);
|
|
53
|
+
const { ns, valid, } = index_1.default.normalizeTitle(link, 0, false, config, { halfParsed: true, temporary: true, decode: true, selfLink: true });
|
|
54
54
|
if (!valid) {
|
|
55
55
|
s += `[[${x}`;
|
|
56
56
|
continue;
|
package/dist/parser/redirect.js
CHANGED
|
@@ -16,9 +16,7 @@ const parseRedirect = (text, config, accum) => {
|
|
|
16
16
|
config.regexRedirect ??= new RegExp(String.raw `^(\s*)((?:${config.redirection.join('|')})\s*(?::\s*)?)\[\[([^\n|\]]+)(\|.*?)?\]\](\s*)`, 'iu');
|
|
17
17
|
const mt = config.regexRedirect.exec(text);
|
|
18
18
|
if (mt
|
|
19
|
-
&& index_1.default
|
|
20
|
-
.normalizeTitle(mt[3], 0, false, config, true, true, true)
|
|
21
|
-
.valid) {
|
|
19
|
+
&& index_1.default.normalizeTitle(mt[3], 0, false, config, { halfParsed: true, temporary: true, decode: true }).valid) {
|
|
22
20
|
text = `\0${accum.length}o\x7F${text.slice(mt[0].length)}`;
|
|
23
21
|
// @ts-expect-error abstract class
|
|
24
22
|
new redirect_1.RedirectToken(...mt.slice(1), config, accum);
|
package/dist/src/converter.js
CHANGED
|
@@ -22,7 +22,7 @@ class ConverterToken extends index_1.Token {
|
|
|
22
22
|
constructor(flags, rules, config, accum = []) {
|
|
23
23
|
super(undefined, config, accum);
|
|
24
24
|
// @ts-expect-error abstract class
|
|
25
|
-
this.
|
|
25
|
+
this.insertAt(new converterFlags_1.ConverterFlagsToken(flags, config, accum));
|
|
26
26
|
const [firstRule] = rules, hasColon = firstRule.includes(':'),
|
|
27
27
|
// @ts-expect-error abstract class
|
|
28
28
|
firstRuleToken = new converterRule_1.ConverterRuleToken(firstRule, hasColon, config, accum);
|
package/dist/src/gallery.js
CHANGED
|
@@ -44,7 +44,7 @@ class GalleryToken extends index_2.Token {
|
|
|
44
44
|
* @param file 文件名
|
|
45
45
|
*/
|
|
46
46
|
#checkFile(file) {
|
|
47
|
-
return this.normalizeTitle(file, 6, true, true, true).valid;
|
|
47
|
+
return this.normalizeTitle(file, 6, { halfParsed: true, temporary: true, decode: true }).valid;
|
|
48
48
|
}
|
|
49
49
|
/** @private */
|
|
50
50
|
toString(skip) {
|
package/dist/src/heading.js
CHANGED
|
@@ -35,7 +35,7 @@ class HeadingToken extends index_2.Token {
|
|
|
35
35
|
const token = new index_2.Token(input[0], config, accum);
|
|
36
36
|
token.type = 'heading-title';
|
|
37
37
|
token.setAttribute('stage', 2);
|
|
38
|
-
const trail = new syntax_1.SyntaxToken(input[1],
|
|
38
|
+
const trail = new syntax_1.SyntaxToken(input[1], 'heading-trail', config, accum);
|
|
39
39
|
this.append(token, trail);
|
|
40
40
|
}
|
|
41
41
|
/** 标题格式的等号 */
|
|
@@ -102,7 +102,7 @@ class HeadingToken extends index_2.Token {
|
|
|
102
102
|
left: rect.left + level,
|
|
103
103
|
}, 'format-leakage', index_1.default.msg('unbalanced $1 in a section header', 'bold apostrophes')), end = start + level + innerStr.length;
|
|
104
104
|
if (rootStr.slice(e.endIndex, end).trim()) {
|
|
105
|
-
e.suggestions = [{ desc: 'close', range: [end, end], text:
|
|
105
|
+
e.suggestions = [{ desc: 'close', range: [end, end], text: `'''` }];
|
|
106
106
|
}
|
|
107
107
|
else {
|
|
108
108
|
e.fix = { desc: 'remove', range: [e.startIndex, e.endIndex], text: '' };
|
|
@@ -112,7 +112,7 @@ class HeadingToken extends index_2.Token {
|
|
|
112
112
|
if (italicQuotes.length % 2) {
|
|
113
113
|
const e = (0, lint_1.generateForChild)(italicQuotes[italicQuotes.length - 1], { start: start + level }, 'format-leakage', index_1.default.msg('unbalanced $1 in a section header', 'italic apostrophes')), end = start + level + innerStr.length;
|
|
114
114
|
e.fix = rootStr.slice(e.endIndex, end).trim()
|
|
115
|
-
? { desc: 'close', range: [end, end], text:
|
|
115
|
+
? { desc: 'close', range: [end, end], text: `''` }
|
|
116
116
|
: { desc: 'remove', range: [e.startIndex, e.endIndex], text: '' };
|
|
117
117
|
errors.push(e);
|
|
118
118
|
}
|
|
@@ -4,10 +4,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.ImageParameterToken = exports.galleryParams = void 0;
|
|
7
|
+
const common_1 = require("@bhsd/common");
|
|
7
8
|
const string_1 = require("../util/string");
|
|
8
9
|
const lint_1 = require("../util/lint");
|
|
9
10
|
const index_1 = __importDefault(require("../index"));
|
|
10
11
|
const index_2 = require("./index");
|
|
12
|
+
const getUrlLikeRegex = (0, common_1.getRegex)(protocol => new RegExp(String.raw `^(?:${protocol}|//|\0\d+m\x7F)`, 'iu'));
|
|
13
|
+
const getUrlRegex = (0, common_1.getRegex)(protocol => new RegExp(String.raw `^(?:(?:${protocol}|//)${string_1.extUrlCharFirst}|\0\d+m\x7F)${string_1.extUrlChar}$`, 'iu'));
|
|
14
|
+
const getSyntaxRegex = (0, common_1.getRegex)(syntax => new RegExp(String.raw `^(\s*(?!\s))${syntax.replace('$1', '(.*)')}${syntax.endsWith('$1') ? '(?=$|\n)' : ''}(\s*)$`, 'u'));
|
|
11
15
|
exports.galleryParams = new Set(['alt', 'link', 'lang', 'page', 'caption']);
|
|
12
16
|
function validate(key, val, config, halfParsed, ext) {
|
|
13
17
|
val = val.trim();
|
|
@@ -19,15 +23,13 @@ function validate(key, val, config, halfParsed, ext) {
|
|
|
19
23
|
if (!value) {
|
|
20
24
|
return val;
|
|
21
25
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if (re1.test(value)) {
|
|
25
|
-
return re2.test(value) && val;
|
|
26
|
+
else if (getUrlLikeRegex(config.protocol).test(value)) {
|
|
27
|
+
return getUrlRegex(config.protocol).test(value) && val;
|
|
26
28
|
}
|
|
27
29
|
else if (value.startsWith('[[') && value.endsWith(']]')) {
|
|
28
30
|
value = value.slice(2, -2);
|
|
29
31
|
}
|
|
30
|
-
const title = index_1.default.normalizeTitle(value, 0, false, config,
|
|
32
|
+
const title = index_1.default.normalizeTitle(value, 0, false, config, { halfParsed, decode: true, selfLink: true });
|
|
31
33
|
return title.valid && title;
|
|
32
34
|
}
|
|
33
35
|
case 'lang':
|
|
@@ -59,10 +61,8 @@ class ImageParameterToken extends index_2.Token {
|
|
|
59
61
|
/** @param str 图片参数 */
|
|
60
62
|
constructor(str, extension, config, accum) {
|
|
61
63
|
let mt;
|
|
62
|
-
const regexes = Object.entries(config.img)
|
|
63
|
-
|
|
64
|
-
return [syntax, param, re];
|
|
65
|
-
}), param = regexes.find(([, key, regex]) => {
|
|
64
|
+
const regexes = Object.entries(config.img)
|
|
65
|
+
.map(([syntax, param]) => [syntax, param, getSyntaxRegex(syntax)]), param = regexes.find(([, key, regex]) => {
|
|
66
66
|
mt = regex.exec(str);
|
|
67
67
|
return mt
|
|
68
68
|
&& (mt.length !== 4
|
package/dist/src/imagemap.js
CHANGED
|
@@ -38,7 +38,7 @@ class ImagemapToken extends index_2.Token {
|
|
|
38
38
|
//
|
|
39
39
|
}
|
|
40
40
|
else if (first) {
|
|
41
|
-
const pipe = line.indexOf('|'), file = pipe === -1 ? line : line.slice(0, pipe), { valid, ns, } = this.normalizeTitle(file, 0, true, true);
|
|
41
|
+
const pipe = line.indexOf('|'), file = pipe === -1 ? line : line.slice(0, pipe), { valid, ns, } = this.normalizeTitle(file, 0, { halfParsed: true, temporary: true });
|
|
42
42
|
if (valid
|
|
43
43
|
&& ns === 6) {
|
|
44
44
|
// @ts-expect-error abstract class
|
|
@@ -59,7 +59,8 @@ class ImagemapToken extends index_2.Token {
|
|
|
59
59
|
const i = line.indexOf('['), substr = line.slice(i), mtIn = /^\[\[([^|]+)(?:\|([^\]]+))?\]\][\w\s]*$/u
|
|
60
60
|
.exec(substr);
|
|
61
61
|
if (mtIn) {
|
|
62
|
-
if (this.normalizeTitle(mtIn[1], 0, true, true,
|
|
62
|
+
if (this.normalizeTitle(mtIn[1], 0, { halfParsed: true, temporary: true, selfLink: true })
|
|
63
|
+
.valid) {
|
|
63
64
|
// @ts-expect-error abstract class
|
|
64
65
|
super.insertAt(new imagemapLink_1.ImagemapLinkToken(line.slice(0, i), mtIn.slice(1), substr.slice(substr.indexOf(']]') + 2), config, accum));
|
|
65
66
|
continue;
|
package/dist/src/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import Parser from '../index';
|
|
|
2
2
|
import { AstElement } from '../lib/element';
|
|
3
3
|
import { AstText } from '../lib/text';
|
|
4
4
|
import type { LintError, TokenTypes } from '../base';
|
|
5
|
-
import type { Title } from '../lib/title';
|
|
5
|
+
import type { Title, TitleOptions } from '../lib/title';
|
|
6
6
|
import type { AstNodes } from '../internal';
|
|
7
7
|
/**
|
|
8
8
|
* base class for all tokens
|
package/dist/src/index.js
CHANGED
|
@@ -49,6 +49,7 @@ exports.Token = void 0;
|
|
|
49
49
|
const string_1 = require("../util/string");
|
|
50
50
|
const constants_1 = require("../util/constants");
|
|
51
51
|
const lint_1 = require("../util/lint");
|
|
52
|
+
const debug_1 = require("../util/debug");
|
|
52
53
|
const index_1 = __importDefault(require("../index"));
|
|
53
54
|
const element_1 = require("../lib/element");
|
|
54
55
|
const text_1 = require("../lib/text");
|
|
@@ -168,7 +169,7 @@ class Token extends element_1.AstElement {
|
|
|
168
169
|
this.#stage = constants_1.MAX_STAGE;
|
|
169
170
|
const { length, firstChild } = this, str = firstChild?.toString();
|
|
170
171
|
if (length === 1 && firstChild.type === 'text' && str.includes('\0')) {
|
|
171
|
-
|
|
172
|
+
(0, debug_1.setChildNodes)(this, 0, 1, this.buildFromStr(str));
|
|
172
173
|
this.normalize();
|
|
173
174
|
if (this.type === 'root') {
|
|
174
175
|
for (const token of this.#accum) {
|
|
@@ -317,6 +318,8 @@ class Token extends element_1.AstElement {
|
|
|
317
318
|
return this.#accum;
|
|
318
319
|
case 'built':
|
|
319
320
|
return this.#built;
|
|
321
|
+
case 'stage':
|
|
322
|
+
return this.#stage;
|
|
320
323
|
default:
|
|
321
324
|
return super.getAttribute(key);
|
|
322
325
|
}
|
|
@@ -344,9 +347,8 @@ class Token extends element_1.AstElement {
|
|
|
344
347
|
return token;
|
|
345
348
|
}
|
|
346
349
|
/** @private */
|
|
347
|
-
normalizeTitle(title, defaultNs = 0,
|
|
348
|
-
return index_1.default
|
|
349
|
-
.normalizeTitle(title, defaultNs, this.#include, this.#config, temporary, halfParsed, decode, selfLink);
|
|
350
|
+
normalizeTitle(title, defaultNs = 0, opt) {
|
|
351
|
+
return index_1.default.normalizeTitle(title, defaultNs, this.#include, this.#config, opt);
|
|
350
352
|
}
|
|
351
353
|
/** @private */
|
|
352
354
|
lint(start = this.getAbsoluteIndex(), re) {
|
|
@@ -423,7 +425,7 @@ class Token extends element_1.AstElement {
|
|
|
423
425
|
});
|
|
424
426
|
/* NOT FOR BROWSER ONLY */
|
|
425
427
|
}
|
|
426
|
-
else if ((0, lsp_1.isAttr)(this, true)) {
|
|
428
|
+
else if (index_1.default.lintCSS && (0, lsp_1.isAttr)(this, true)) {
|
|
427
429
|
const root = this.getRootNode(), textDoc = new document_1.EmbeddedCSSDocument(root, this);
|
|
428
430
|
errors.push(...document_1.cssLSP.doValidation(textDoc, textDoc.styleSheet)
|
|
429
431
|
.filter(({ code }) => code !== 'css-ruleorselectorexpected')
|
package/dist/src/link/base.js
CHANGED
|
@@ -132,7 +132,7 @@ class LinkBaseToken extends index_2.Token {
|
|
|
132
132
|
}
|
|
133
133
|
/** @private */
|
|
134
134
|
getTitle(temporary, halfParsed) {
|
|
135
|
-
return this.normalizeTitle(this.firstChild.toString(true), 0,
|
|
135
|
+
return this.normalizeTitle(this.firstChild.toString(true), 0, { halfParsed, temporary, decode: true, selfLink: true });
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
138
|
exports.LinkBaseToken = LinkBaseToken;
|
package/dist/src/link/file.d.ts
CHANGED
|
@@ -13,6 +13,8 @@ export declare abstract class FileToken extends LinkBaseToken {
|
|
|
13
13
|
readonly childNodes: readonly [AtomToken, ...ImageParameterToken[]];
|
|
14
14
|
abstract get lastChild(): AtomToken | ImageParameterToken;
|
|
15
15
|
get type(): 'file' | 'gallery-image' | 'imagemap-image';
|
|
16
|
+
/** file extension / 扩展名 */
|
|
17
|
+
get extension(): string | undefined;
|
|
16
18
|
/**
|
|
17
19
|
* @param link 文件名
|
|
18
20
|
* @param text 图片参数
|
package/dist/src/link/file.js
CHANGED
|
@@ -4,7 +4,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.FileToken = void 0;
|
|
7
|
-
const string_1 = require("../../util/string");
|
|
8
7
|
const lint_1 = require("../../util/lint");
|
|
9
8
|
const rect_1 = require("../../lib/rect");
|
|
10
9
|
const index_1 = __importDefault(require("../../index"));
|
|
@@ -15,24 +14,21 @@ const frame = new Map([
|
|
|
15
14
|
['frameless', 'Frameless'],
|
|
16
15
|
['framed', 'Frame'],
|
|
17
16
|
['thumbnail', 'Thumb'],
|
|
18
|
-
]), horizAlign = new Set(['left', 'right', 'center', 'none']), vertAlign = new Set(['baseline', 'sub', 'super', 'top', 'text-top', 'middle', 'bottom', 'text-bottom']);
|
|
17
|
+
]), horizAlign = new Set(['left', 'right', 'center', 'none']), vertAlign = new Set(['baseline', 'sub', 'super', 'top', 'text-top', 'middle', 'bottom', 'text-bottom']), extensions = new Set(['tiff', 'tif', 'png', 'gif', 'jpg', 'jpeg', 'webp', 'xcf', 'pdf', 'svg', 'djvu']);
|
|
19
18
|
/**
|
|
20
19
|
* a more sophisticated string-explode function
|
|
21
|
-
* @param start start syntax of a nested AST node
|
|
22
|
-
* @param end end syntax of a nested AST node
|
|
23
|
-
* @param separator syntax for explosion
|
|
24
20
|
* @param str string to be exploded
|
|
25
21
|
*/
|
|
26
|
-
const explode = (
|
|
22
|
+
const explode = (str) => {
|
|
27
23
|
if (str === undefined) {
|
|
28
24
|
return [];
|
|
29
25
|
}
|
|
30
|
-
const regex =
|
|
26
|
+
const regex = /-\{|\}-|\|/gu, exploded = [];
|
|
31
27
|
let mt = regex.exec(str), depth = 0, lastIndex = 0;
|
|
32
28
|
while (mt) {
|
|
33
29
|
const { 0: match, index } = mt;
|
|
34
|
-
if (match !==
|
|
35
|
-
depth += match ===
|
|
30
|
+
if (match !== '|') {
|
|
31
|
+
depth += match === '-{' ? 1 : -1;
|
|
36
32
|
}
|
|
37
33
|
else if (depth === 0) {
|
|
38
34
|
exploded.push(str.slice(lastIndex, index));
|
|
@@ -53,6 +49,10 @@ class FileToken extends base_1.LinkBaseToken {
|
|
|
53
49
|
get type() {
|
|
54
50
|
return 'file';
|
|
55
51
|
}
|
|
52
|
+
/** file extension / 扩展名 */
|
|
53
|
+
get extension() {
|
|
54
|
+
return this.getAttribute('title').extension;
|
|
55
|
+
}
|
|
56
56
|
/**
|
|
57
57
|
* @param link 文件名
|
|
58
58
|
* @param text 图片参数
|
|
@@ -61,7 +61,7 @@ class FileToken extends base_1.LinkBaseToken {
|
|
|
61
61
|
constructor(link, text, config = index_1.default.getConfig(), accum = [], delimiter = '|') {
|
|
62
62
|
super(link, undefined, config, accum, delimiter);
|
|
63
63
|
const { extension } = this.getTitle(true, true);
|
|
64
|
-
this.append(...explode(
|
|
64
|
+
this.append(...explode(text).map(
|
|
65
65
|
// @ts-expect-error abstract class
|
|
66
66
|
(part) => new imageParameter_1.ImageParameterToken(part, extension, config, accum)));
|
|
67
67
|
}
|
|
@@ -92,12 +92,14 @@ class FileToken extends base_1.LinkBaseToken {
|
|
|
92
92
|
* 图片参数到语法错误的映射
|
|
93
93
|
* @param msg 消息键
|
|
94
94
|
* @param p1 替换$1
|
|
95
|
+
* @param severity 错误等级
|
|
95
96
|
*/
|
|
96
|
-
const generate = (msg, p1) => (arg) => {
|
|
97
|
-
const e = (0, lint_1.generateForChild)(arg, rect, 'no-duplicate', index_1.default.msg(`${msg} image $1 parameter`, p1));
|
|
97
|
+
const generate = (msg, p1, severity) => (arg) => {
|
|
98
|
+
const e = (0, lint_1.generateForChild)(arg, rect, 'no-duplicate', index_1.default.msg(`${msg} image $1 parameter`, p1), severity);
|
|
98
99
|
e.suggestions = [{ desc: 'remove', range: [e.startIndex - 1, e.endIndex], text: '' }];
|
|
99
100
|
return e;
|
|
100
101
|
};
|
|
102
|
+
const { extension } = this;
|
|
101
103
|
for (const key of keys) {
|
|
102
104
|
if (key === 'invalid' || key === 'width' && unscaled) {
|
|
103
105
|
continue;
|
|
@@ -110,7 +112,7 @@ class FileToken extends base_1.LinkBaseToken {
|
|
|
110
112
|
];
|
|
111
113
|
}
|
|
112
114
|
if (relevantArgs.length > 1) {
|
|
113
|
-
errors.push(...relevantArgs.map(generate('duplicated', key)));
|
|
115
|
+
errors.push(...relevantArgs.map(generate('duplicated', key, key === 'caption' && extension && !extensions.has(extension) ? 'warning' : 'error')));
|
|
114
116
|
}
|
|
115
117
|
}
|
|
116
118
|
if (frameKeys.length > 1) {
|
|
@@ -43,7 +43,7 @@ class GalleryImageToken extends file_1.FileToken {
|
|
|
43
43
|
/** @private */
|
|
44
44
|
getTitle(temporary) {
|
|
45
45
|
const imagemap = this.type === 'imagemap-image';
|
|
46
|
-
return this.normalizeTitle(this.firstChild.toString(), imagemap ? 0 : 6,
|
|
46
|
+
return this.normalizeTitle(this.firstChild.toString(), imagemap ? 0 : 6, { halfParsed: true, temporary, decode: !imagemap });
|
|
47
47
|
}
|
|
48
48
|
/** @private */
|
|
49
49
|
getAttribute(key) {
|
|
@@ -27,8 +27,7 @@ class RedirectTargetToken extends base_1.LinkBaseToken {
|
|
|
27
27
|
}
|
|
28
28
|
/** @private */
|
|
29
29
|
getTitle() {
|
|
30
|
-
return this
|
|
31
|
-
.normalizeTitle(this.firstChild.toString(), 0, false, true, true);
|
|
30
|
+
return this.normalizeTitle(this.firstChild.toString(), 0, { halfParsed: true, decode: true });
|
|
32
31
|
}
|
|
33
32
|
/** @private */
|
|
34
33
|
lint(start = this.getAbsoluteIndex()) {
|
package/dist/src/magicLink.js
CHANGED
|
@@ -95,7 +95,7 @@ class MagicLinkToken extends index_2.Token {
|
|
|
95
95
|
if (type === 'magic-link') {
|
|
96
96
|
if (link.startsWith('ISBN')) {
|
|
97
97
|
return this
|
|
98
|
-
.normalizeTitle(`BookSources/${link.slice(5)}`, -1, true)
|
|
98
|
+
.normalizeTitle(`BookSources/${link.slice(5)}`, -1, { temporary: true })
|
|
99
99
|
.getUrl(articlePath);
|
|
100
100
|
}
|
|
101
101
|
link = link.startsWith('RFC')
|
package/dist/src/nested.js
CHANGED
|
@@ -12,7 +12,10 @@ const index_1 = __importDefault(require("../index"));
|
|
|
12
12
|
const index_2 = require("./index");
|
|
13
13
|
const ext_1 = require("./tagPair/ext");
|
|
14
14
|
const noinclude_1 = require("./nowiki/noinclude");
|
|
15
|
-
const childTypes = new Set(['comment', 'include', 'arg', 'template', 'magic-word'])
|
|
15
|
+
const childTypes = new Set(['comment', 'include', 'arg', 'template', 'magic-word']), lintRegex = [false, true].map(article => {
|
|
16
|
+
const noinclude = article ? 'includeonly' : 'noinclude';
|
|
17
|
+
return new RegExp(String.raw `^(?:<${noinclude}(?:\s[^>]*)?/?>|</${noinclude}\s*>)$`, 'iu');
|
|
18
|
+
});
|
|
16
19
|
/**
|
|
17
20
|
* extension tag that has a nested structure
|
|
18
21
|
*
|
|
@@ -56,10 +59,7 @@ class NestedToken extends index_2.Token {
|
|
|
56
59
|
}
|
|
57
60
|
/** @private */
|
|
58
61
|
lint(start = this.getAbsoluteIndex(), re) {
|
|
59
|
-
const rect = new rect_1.BoundingRect(this, start),
|
|
60
|
-
const regex = typeof this.#regex === 'boolean'
|
|
61
|
-
? new RegExp(String.raw `^(?:<${noinclude}(?:\s[^>]*)?/?>|</${noinclude}\s*>)$`, 'iu')
|
|
62
|
-
: /^<!--[\s\S]*-->$/u;
|
|
62
|
+
const rect = new rect_1.BoundingRect(this, start), regex = typeof this.#regex === 'boolean' ? lintRegex[this.#regex ? 1 : 0] : /^<!--[\s\S]*-->$/u;
|
|
63
63
|
return [
|
|
64
64
|
...super.lint(start, re),
|
|
65
65
|
...this.childNodes.filter(child => {
|
package/dist/src/nowiki/index.js
CHANGED
|
@@ -4,9 +4,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.NowikiToken = void 0;
|
|
7
|
+
const common_1 = require("@bhsd/common");
|
|
7
8
|
const lint_1 = require("../../util/lint");
|
|
8
9
|
const index_1 = __importDefault(require("../../index"));
|
|
9
10
|
const base_1 = require("./base");
|
|
11
|
+
const getLintRegex = (0, common_1.getRegex)(name => new RegExp(String.raw `<\s*(?:/\s*)${name === 'nowiki' ? '' : '?'}(${name})\b`, 'giu'));
|
|
10
12
|
/**
|
|
11
13
|
* text-only token inside an extension tag
|
|
12
14
|
*
|
|
@@ -24,8 +26,7 @@ class NowikiToken extends base_1.NowikiBaseToken {
|
|
|
24
26
|
e.fix = { range: [start, e.endIndex], text: '', desc: 'empty' };
|
|
25
27
|
return [e];
|
|
26
28
|
}
|
|
27
|
-
|
|
28
|
-
return super.lint(start, re);
|
|
29
|
+
return super.lint(start, getLintRegex(name));
|
|
29
30
|
}
|
|
30
31
|
}
|
|
31
32
|
exports.NowikiToken = NowikiToken;
|
package/dist/src/redirect.js
CHANGED
|
@@ -76,8 +76,7 @@ let RedirectToken = (() => {
|
|
|
76
76
|
super(undefined, config, accum);
|
|
77
77
|
this.#pre = pre;
|
|
78
78
|
this.#post = post;
|
|
79
|
-
|
|
80
|
-
this.append(new syntax_1.SyntaxToken(syntax, pattern, 'redirect-syntax', config, accum, {}),
|
|
79
|
+
this.append(new syntax_1.SyntaxToken(syntax, 'redirect-syntax', config, accum),
|
|
81
80
|
// @ts-expect-error abstract class
|
|
82
81
|
new redirectTarget_1.RedirectTargetToken(link, text?.slice(1), config, accum));
|
|
83
82
|
}
|
package/dist/src/syntax.d.ts
CHANGED
|
@@ -9,7 +9,9 @@ declare type SyntaxTypes = 'heading-trail' | 'magic-word-name' | 'table-syntax'
|
|
|
9
9
|
export declare class SyntaxToken extends Token {
|
|
10
10
|
#private;
|
|
11
11
|
get type(): SyntaxTypes;
|
|
12
|
-
/**
|
|
13
|
-
|
|
12
|
+
/**
|
|
13
|
+
* @class
|
|
14
|
+
*/
|
|
15
|
+
constructor(wikitext: string | undefined, type: SyntaxTypes, config?: Config, accum?: Token[], acceptable?: Acceptable);
|
|
14
16
|
}
|
|
15
17
|
export {};
|
package/dist/src/syntax.js
CHANGED
|
@@ -12,8 +12,10 @@ class SyntaxToken extends index_1.Token {
|
|
|
12
12
|
get type() {
|
|
13
13
|
return this.#type;
|
|
14
14
|
}
|
|
15
|
-
/**
|
|
16
|
-
|
|
15
|
+
/**
|
|
16
|
+
* @class
|
|
17
|
+
*/
|
|
18
|
+
constructor(wikitext, type, config, accum, acceptable) {
|
|
17
19
|
super(wikitext, config, accum, acceptable);
|
|
18
20
|
this.#type = type;
|
|
19
21
|
}
|
package/dist/src/table/base.js
CHANGED
|
@@ -24,7 +24,7 @@ class TableBaseToken extends (0, attributesParent_1.attributesParent)(1)(index_2
|
|
|
24
24
|
*/
|
|
25
25
|
constructor(pattern, syntax, type, attr, config = index_1.default.getConfig(), accum = [], acceptable) {
|
|
26
26
|
super(undefined, config, accum, acceptable);
|
|
27
|
-
this.append(new syntax_1.SyntaxToken(syntax,
|
|
27
|
+
this.append(new syntax_1.SyntaxToken(syntax, 'table-syntax', config, accum),
|
|
28
28
|
// @ts-expect-error abstract class
|
|
29
29
|
new attributes_1.AttributesToken(attr, 'table-attrs', type, config, accum));
|
|
30
30
|
}
|
package/dist/src/table/index.js
CHANGED
|
@@ -10,7 +10,6 @@ const rect_1 = require("../../lib/rect");
|
|
|
10
10
|
const index_1 = __importDefault(require("../../index"));
|
|
11
11
|
const trBase_1 = require("./trBase");
|
|
12
12
|
const syntax_1 = require("../syntax");
|
|
13
|
-
const closingPattern = /^\n[^\S\n]*(?:\|\}|\{\{\s*!\s*\}\}\}|\{\{\s*!\)\s*\}\})$/u;
|
|
14
13
|
/**
|
|
15
14
|
* 生成一个指定长度的空数组
|
|
16
15
|
* @param n 数组长度
|
|
@@ -91,11 +90,9 @@ class TableToken extends trBase_1.TrBaseToken {
|
|
|
91
90
|
* @param halfParsed
|
|
92
91
|
*/
|
|
93
92
|
close(syntax = '\n|}', halfParsed) {
|
|
94
|
-
const config = this.getAttribute('config'), accum = this.getAttribute('accum'), inner =
|
|
95
|
-
? [syntax]
|
|
96
|
-
: index_1.default.parse(syntax, this.getAttribute('include'), 2, config).childNodes;
|
|
93
|
+
const config = this.getAttribute('config'), accum = this.getAttribute('accum'), inner = [syntax];
|
|
97
94
|
debug_1.Shadow.run(() => {
|
|
98
|
-
const token = new syntax_1.SyntaxToken(undefined,
|
|
95
|
+
const token = new syntax_1.SyntaxToken(undefined, 'table-syntax', config, accum);
|
|
99
96
|
super.insertAt(token);
|
|
100
97
|
});
|
|
101
98
|
this.lastChild.replaceChildren(...inner);
|
package/dist/src/table/trBase.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.TrBaseToken = void 0;
|
|
|
4
4
|
const lint_1 = require("../../util/lint");
|
|
5
5
|
const base_1 = require("./base");
|
|
6
6
|
const td_1 = require("./td");
|
|
7
|
+
const tableTags = new Set(['tr', 'td', 'th', 'caption']);
|
|
7
8
|
/**
|
|
8
9
|
* table row or table
|
|
9
10
|
*
|
|
@@ -19,7 +20,8 @@ class TrBaseToken extends base_1.TableBaseToken {
|
|
|
19
20
|
const first = inter.childNodes.find(child => child.text().trim()), tdPattern = /^\s*(?:!|\{\{\s*![!-]?\s*\}\})/u;
|
|
20
21
|
if (!first
|
|
21
22
|
|| tdPattern.test(first.toString())
|
|
22
|
-
|| first.is('arg') && tdPattern.test(first.default || '')
|
|
23
|
+
|| first.is('arg') && tdPattern.test(first.default || '')
|
|
24
|
+
|| first.is('html') && tableTags.has(first.name)) {
|
|
23
25
|
return errors;
|
|
24
26
|
}
|
|
25
27
|
else if (first.is('magic-word')) {
|
package/dist/src/transclude.js
CHANGED
|
@@ -66,7 +66,7 @@ class TranscludeToken extends index_1.Token {
|
|
|
66
66
|
if (fullWidth) {
|
|
67
67
|
this.#colon = ':';
|
|
68
68
|
}
|
|
69
|
-
const
|
|
69
|
+
const token = new syntax_1.SyntaxToken(magicWord, 'magic-word-name', config, accum);
|
|
70
70
|
super.insertAt(token);
|
|
71
71
|
if (arg !== false) {
|
|
72
72
|
parts.unshift([arg]);
|
|
@@ -85,7 +85,7 @@ class TranscludeToken extends index_1.Token {
|
|
|
85
85
|
}
|
|
86
86
|
if (this.type === 'template') {
|
|
87
87
|
const name = (0, string_1.removeComment)(title).trim();
|
|
88
|
-
if (!this.normalizeTitle(name, 10, true, true).valid) {
|
|
88
|
+
if (!this.normalizeTitle(name, 10, { halfParsed: true, temporary: true }).valid) {
|
|
89
89
|
accum.pop();
|
|
90
90
|
throw new SyntaxError('Invalid template name');
|
|
91
91
|
}
|
|
@@ -144,7 +144,7 @@ class TranscludeToken extends index_1.Token {
|
|
|
144
144
|
}
|
|
145
145
|
/** 获取模板或模块名 */
|
|
146
146
|
#getTitle() {
|
|
147
|
-
const isTemplate = this.type === 'template', title = this.normalizeTitle(this.childNodes[isTemplate ? 0 : 1].toString(true), isTemplate ? 10 : 828, true);
|
|
147
|
+
const isTemplate = this.type === 'template', title = this.normalizeTitle(this.childNodes[isTemplate ? 0 : 1].toString(true), isTemplate ? 10 : 828, { temporary: true });
|
|
148
148
|
return title;
|
|
149
149
|
}
|
|
150
150
|
/**
|
package/dist/util/debug.js
CHANGED
|
@@ -37,7 +37,14 @@ exports.isToken = isToken;
|
|
|
37
37
|
* @param inserted 插入的子节点
|
|
38
38
|
*/
|
|
39
39
|
const setChildNodes = (parent, position, deleteCount, inserted = []) => {
|
|
40
|
-
|
|
40
|
+
let nodes = parent.getChildNodes(), removed;
|
|
41
|
+
if (nodes.length === deleteCount) {
|
|
42
|
+
removed = nodes;
|
|
43
|
+
nodes = inserted;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
removed = nodes.splice(position, deleteCount, ...inserted);
|
|
47
|
+
}
|
|
41
48
|
for (let i = 0; i < inserted.length; i++) {
|
|
42
49
|
const node = inserted[i];
|
|
43
50
|
node.setAttribute('parentNode', parent);
|
|
@@ -46,6 +53,9 @@ const setChildNodes = (parent, position, deleteCount, inserted = []) => {
|
|
|
46
53
|
}
|
|
47
54
|
nodes[position - 1]?.setAttribute('nextSibling', nodes[position]);
|
|
48
55
|
nodes[position + inserted.length]?.setAttribute('previousSibling', nodes[position + inserted.length - 1]);
|
|
56
|
+
if (nodes === inserted) {
|
|
57
|
+
parent.setAttribute('childNodes', nodes);
|
|
58
|
+
}
|
|
49
59
|
return removed;
|
|
50
60
|
};
|
|
51
61
|
exports.setChildNodes = setChildNodes;
|
package/dist/util/string.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.noWrap = exports.decodeNumber = exports.decodeHtml = exports.text = exports.escapeRegExp = exports.removeComment = exports.tidy = exports.extUrlChar = exports.extUrlCharFirst = exports.zs = exports.rawurldecode = void 0;
|
|
3
|
+
exports.noWrap = exports.decodeNumber = exports.decodeHtml = exports.decodeHtmlBasic = exports.text = exports.escapeRegExp = exports.removeComment = exports.tidy = exports.extUrlChar = exports.extUrlCharFirst = exports.zs = exports.rawurldecode = void 0;
|
|
4
4
|
var common_1 = require("@bhsd/common");
|
|
5
5
|
Object.defineProperty(exports, "rawurldecode", { enumerable: true, get: function () { return common_1.rawurldecode; } });
|
|
6
6
|
exports.zs = String.raw ` \xA0\u1680\u2000-\u200A\u202F\u205F\u3000`;
|
|
@@ -27,9 +27,8 @@ exports.escapeRegExp = factory(/[\\{}()|.?*+^$[\]]/gu, String.raw `\$&`);
|
|
|
27
27
|
const text = (childNodes, separator = '') => childNodes.map(child => typeof child === 'string' ? child : child.text()).join(separator);
|
|
28
28
|
exports.text = text;
|
|
29
29
|
const names = { lt: '<', gt: '>', lbrack: '[', rbrack: ']', lbrace: '{', rbrace: '}', nbsp: ' ', amp: '&', quot: '"' };
|
|
30
|
-
/* istanbul ignore next */
|
|
31
30
|
/** decode HTML entities */
|
|
32
|
-
|
|
31
|
+
exports.decodeHtmlBasic = factory(/&(?:#(\d+|[Xx][\da-fA-F]+)|([lg]t|[LG]T|[lr]brac[ke]|nbsp|amp|AMP|quot|QUOT));/gu, (_, code, name) => code
|
|
33
32
|
? String.fromCodePoint(Number((/^x/iu.test(code) ? '0' : '') + code))
|
|
34
33
|
: names[name.toLowerCase()]);
|
|
35
34
|
/**
|
|
@@ -48,7 +47,7 @@ const decodeHtml = (str) => {
|
|
|
48
47
|
}
|
|
49
48
|
/* istanbul ignore next */
|
|
50
49
|
/* NOT FOR BROWSER ONLY END */
|
|
51
|
-
return decodeHtmlBasic(str);
|
|
50
|
+
return (0, exports.decodeHtmlBasic)(str);
|
|
52
51
|
};
|
|
53
52
|
exports.decodeHtml = decodeHtml;
|
|
54
53
|
/** decode numbered HTML entities */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wikilint",
|
|
3
|
-
"version": "2.18.
|
|
3
|
+
"version": "2.18.3",
|
|
4
4
|
"description": "A Node.js linter for MediaWiki markup",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mediawiki",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
]
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
|
-
"@bhsd/common": "^0.
|
|
68
|
+
"@bhsd/common": "^0.9.0",
|
|
69
69
|
"vscode-languageserver-types": "^3.17.5"
|
|
70
70
|
},
|
|
71
71
|
"optionalDependencies": {
|