wikiparser-node 1.39.1 → 1.41.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 +51 -5
- package/bundle/bundle-es8.min.js +30 -29
- package/bundle/bundle-lsp.min.js +28 -28
- package/bundle/bundle.min.js +16 -16
- package/config/.schema.json +5 -0
- package/config/default.json +11 -2
- package/config/enwiki.json +91 -89
- package/config/jawiki.json +168 -158
- package/config/llwiki.json +2 -1
- package/config/minimum.json +3 -81
- package/config/moegirl.json +2 -1
- package/config/zhwiki.json +128 -126
- package/data/signatures.json +1 -1
- package/dist/addon/attribute.js +1 -1
- package/dist/addon/table.js +1 -1
- package/dist/addon/transclude.js +3 -1
- package/dist/base.d.mts +11 -9
- package/dist/base.d.ts +11 -9
- package/dist/base.js +1 -0
- package/dist/base.mjs +1 -0
- package/dist/bin/config.js +11 -10
- package/dist/index.d.ts +5 -5
- package/dist/index.js +5 -1
- package/dist/lib/lintConfig.js +42 -23
- package/dist/lib/lsp.js +6 -12
- package/dist/lib/node.js +5 -2
- package/dist/lib/text.js +5 -2
- package/dist/lib/title.js +8 -4
- package/dist/mixin/elementLike.js +2 -2
- package/dist/parser/commentAndExt.js +2 -1
- package/dist/render/expand.js +3 -3
- package/dist/render/extension.js +15 -3
- package/dist/render/magicWords.js +13 -10
- package/dist/src/attribute.d.ts +4 -1
- package/dist/src/attribute.js +5 -4
- package/dist/src/attributes.js +29 -7
- package/dist/src/heading.js +8 -3
- package/dist/src/link/base.d.ts +1 -1
- package/dist/src/link/base.js +10 -6
- package/dist/src/link/file.js +2 -2
- package/dist/src/magicLink.js +20 -16
- package/dist/src/multiLine/gallery.d.ts +5 -3
- package/dist/src/multiLine/gallery.js +6 -4
- package/dist/src/nowiki/base.d.ts +1 -1
- package/dist/src/parameter.js +5 -2
- package/dist/src/table/tr.js +1 -1
- package/dist/src/tagPair/ext.js +12 -18
- package/dist/src/tagPair/index.d.ts +1 -1
- package/dist/src/transclude.d.ts +6 -1
- package/dist/src/transclude.js +27 -19
- package/dist/util/constants.js +2 -1
- package/dist/util/sharable.js +2 -0
- package/dist/util/sharable.mjs +3 -1
- package/extensions/dist/base.js +3 -2
- package/extensions/dist/env.js +34 -0
- package/i18n/en.json +1 -0
- package/i18n/zh-hans.json +1 -0
- package/i18n/zh-hant.json +1 -0
- package/package.json +20 -33
package/dist/index.js
CHANGED
|
@@ -190,7 +190,11 @@ const Parser = {
|
|
|
190
190
|
root.parseOnce(0, include).parseOnce();
|
|
191
191
|
const t = new title_1.Title(root.firstChild.toString(), defaultNs, config, opt);
|
|
192
192
|
root.build();
|
|
193
|
-
|
|
193
|
+
const keys = [
|
|
194
|
+
'main',
|
|
195
|
+
'fragment',
|
|
196
|
+
];
|
|
197
|
+
for (const key of keys) {
|
|
194
198
|
const str = t[key];
|
|
195
199
|
if (str?.includes('\0')) {
|
|
196
200
|
const s = root.buildFromStr(str, constants_1.BuildMethod.Text);
|
package/dist/lib/lintConfig.js
CHANGED
|
@@ -15,8 +15,8 @@ const dict = new Map([
|
|
|
15
15
|
['error', 'error'],
|
|
16
16
|
]);
|
|
17
17
|
const defaultLintRuleConfig = {
|
|
18
|
-
'arg-in-ext': 1,
|
|
19
|
-
'blank-alt': 1,
|
|
18
|
+
'arg-in-ext': [1],
|
|
19
|
+
'blank-alt': [1],
|
|
20
20
|
'bold-header': [
|
|
21
21
|
1,
|
|
22
22
|
{
|
|
@@ -50,7 +50,7 @@ const defaultLintRuleConfig = {
|
|
|
50
50
|
// value: 2,
|
|
51
51
|
},
|
|
52
52
|
],
|
|
53
|
-
'insecure-style': 2,
|
|
53
|
+
'insecure-style': [2],
|
|
54
54
|
'invalid-gallery': [
|
|
55
55
|
2,
|
|
56
56
|
{
|
|
@@ -75,14 +75,14 @@ const defaultLintRuleConfig = {
|
|
|
75
75
|
// name: 2,
|
|
76
76
|
},
|
|
77
77
|
],
|
|
78
|
-
'invalid-isbn': 2,
|
|
78
|
+
'invalid-isbn': [2],
|
|
79
79
|
'invalid-json': [
|
|
80
80
|
2,
|
|
81
81
|
{
|
|
82
82
|
duplicate: 1,
|
|
83
83
|
},
|
|
84
84
|
],
|
|
85
|
-
'invalid-url': 1,
|
|
85
|
+
'invalid-url': [1],
|
|
86
86
|
'lonely-apos': [
|
|
87
87
|
1,
|
|
88
88
|
{
|
|
@@ -113,7 +113,7 @@ const defaultLintRuleConfig = {
|
|
|
113
113
|
// ref: 2,
|
|
114
114
|
},
|
|
115
115
|
],
|
|
116
|
-
'no-arg': 1,
|
|
116
|
+
'no-arg': [1],
|
|
117
117
|
'no-duplicate': [
|
|
118
118
|
2,
|
|
119
119
|
{
|
|
@@ -147,8 +147,8 @@ const defaultLintRuleConfig = {
|
|
|
147
147
|
// references: 2,
|
|
148
148
|
},
|
|
149
149
|
],
|
|
150
|
-
'obsolete-attr': 1,
|
|
151
|
-
'obsolete-tag': 1,
|
|
150
|
+
'obsolete-attr': [1],
|
|
151
|
+
'obsolete-tag': [1],
|
|
152
152
|
'parsing-order': [
|
|
153
153
|
2,
|
|
154
154
|
{
|
|
@@ -166,6 +166,18 @@ const defaultLintRuleConfig = {
|
|
|
166
166
|
// td: 1,
|
|
167
167
|
},
|
|
168
168
|
],
|
|
169
|
+
'required-attr': [
|
|
170
|
+
2,
|
|
171
|
+
{
|
|
172
|
+
// indicator: 2,
|
|
173
|
+
// langconvert: 2,
|
|
174
|
+
// mapframe: 2,
|
|
175
|
+
// maplink: 2,
|
|
176
|
+
// phonos: 2,
|
|
177
|
+
// section: 2,
|
|
178
|
+
// templatestyles: 2,
|
|
179
|
+
},
|
|
180
|
+
],
|
|
169
181
|
'syntax-like': [
|
|
170
182
|
2,
|
|
171
183
|
{
|
|
@@ -173,7 +185,7 @@ const defaultLintRuleConfig = {
|
|
|
173
185
|
// redirect: 2,
|
|
174
186
|
},
|
|
175
187
|
],
|
|
176
|
-
'table-layout': 1,
|
|
188
|
+
'table-layout': [1],
|
|
177
189
|
'tag-like': [
|
|
178
190
|
2,
|
|
179
191
|
{
|
|
@@ -181,17 +193,17 @@ const defaultLintRuleConfig = {
|
|
|
181
193
|
invalid: 1,
|
|
182
194
|
},
|
|
183
195
|
],
|
|
184
|
-
'unbalanced-header': 2,
|
|
196
|
+
'unbalanced-header': [2],
|
|
185
197
|
'unclosed-comment': [
|
|
186
198
|
1,
|
|
187
199
|
{
|
|
188
200
|
// include: 1,
|
|
189
201
|
},
|
|
190
202
|
],
|
|
191
|
-
'unclosed-quote': 1,
|
|
192
|
-
'unclosed-table': 2,
|
|
193
|
-
unescaped: 2,
|
|
194
|
-
'unknown-page': 1,
|
|
203
|
+
'unclosed-quote': [1],
|
|
204
|
+
'unclosed-table': [2],
|
|
205
|
+
unescaped: [2],
|
|
206
|
+
'unknown-page': [1],
|
|
195
207
|
'unmatched-tag': [
|
|
196
208
|
1,
|
|
197
209
|
{
|
|
@@ -238,7 +250,7 @@ const defaultLintRuleConfig = {
|
|
|
238
250
|
warn: 1,
|
|
239
251
|
},
|
|
240
252
|
],
|
|
241
|
-
'invalid-math': 2,
|
|
253
|
+
'invalid-math': [2],
|
|
242
254
|
};
|
|
243
255
|
const defaultLintConfig = {
|
|
244
256
|
configurationComment: 'lint',
|
|
@@ -255,8 +267,9 @@ const validateSeverity = (severity) => dict.has(severity);
|
|
|
255
267
|
* 验证设置值是否符合规范
|
|
256
268
|
* @param value 设置值
|
|
257
269
|
*/
|
|
258
|
-
const validateConfigValue = (value) => validateSeverity(value)
|
|
259
|
-
|
|
270
|
+
const validateConfigValue = (value) => validateSeverity(value) || (Array.isArray(value)
|
|
271
|
+
? validateSeverity(value[0]) && (value.length === 1 || typeof value[1] === 'object')
|
|
272
|
+
: typeof value === 'object');
|
|
260
273
|
/**
|
|
261
274
|
* 设置语法检查规则
|
|
262
275
|
* @param obj 语法检查设置对象
|
|
@@ -273,7 +286,16 @@ const set = (obj, key, value) => {
|
|
|
273
286
|
return false;
|
|
274
287
|
}
|
|
275
288
|
if (validateConfigValue(value)) {
|
|
276
|
-
|
|
289
|
+
if (Array.isArray(value)) {
|
|
290
|
+
obj[key] = value;
|
|
291
|
+
}
|
|
292
|
+
else if (typeof value === 'object') {
|
|
293
|
+
const [base, options = {}] = defaultLintRuleConfig[key];
|
|
294
|
+
obj[key] = [base, { ...clone(options), ...value }];
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
obj[key] = [value];
|
|
298
|
+
}
|
|
277
299
|
return true;
|
|
278
300
|
}
|
|
279
301
|
/* c8 ignore next */
|
|
@@ -296,11 +318,8 @@ class LintRuleConfiguration {
|
|
|
296
318
|
}
|
|
297
319
|
/** @implements */
|
|
298
320
|
getSeverity(rule, key) {
|
|
299
|
-
const
|
|
300
|
-
|
|
301
|
-
return dict.get(value);
|
|
302
|
-
}
|
|
303
|
-
return key ? dict.get(value[1]?.[key]) ?? dict.get(value[0]) : dict.get(value[0]);
|
|
321
|
+
const [base, options] = this[rule], severity = dict.get(base);
|
|
322
|
+
return key ? dict.get(options?.[key]) ?? severity : severity;
|
|
304
323
|
}
|
|
305
324
|
}
|
|
306
325
|
/** 语法检查设置 */
|
package/dist/lib/lsp.js
CHANGED
|
@@ -856,21 +856,16 @@ class LanguageService {
|
|
|
856
856
|
end: { line: endLine, character: endCol },
|
|
857
857
|
},
|
|
858
858
|
severity: severity === 'error' ? 1 : 2,
|
|
859
|
-
source:
|
|
860
|
-
/* eslint-disable @stylistic/operator-linebreak */
|
|
861
|
-
sources[rule] ??
|
|
859
|
+
source: sources[rule] ??
|
|
862
860
|
'WikiLint',
|
|
863
861
|
code: code ??
|
|
864
|
-
/* eslint-enable @stylistic/operator-linebreak */
|
|
865
862
|
rule,
|
|
866
863
|
message,
|
|
867
864
|
data: [
|
|
868
865
|
...fix ? [getQuickFix(root, fix, true)] : [],
|
|
869
866
|
...suggestions ? suggestions.map(suggestion => getQuickFix(root, suggestion)) : [],
|
|
870
867
|
],
|
|
871
|
-
})),
|
|
872
|
-
/* eslint-disable @stylistic/operator-linebreak */
|
|
873
|
-
cssDiagnostics = stylelint ?
|
|
868
|
+
})), cssDiagnostics = stylelint ?
|
|
874
869
|
await (async () => {
|
|
875
870
|
NPM: {
|
|
876
871
|
const tokens = this.findStyleTokens();
|
|
@@ -929,7 +924,6 @@ class LanguageService {
|
|
|
929
924
|
return warning ? e : e.filter(({ severity }) => severity === 1);
|
|
930
925
|
})) :
|
|
931
926
|
[];
|
|
932
|
-
/* eslint-enable @stylistic/operator-linebreak */
|
|
933
927
|
/* NOT FOR BROWSER ONLY */
|
|
934
928
|
let lilypondDiagnostics = [];
|
|
935
929
|
if (this.lilypond) {
|
|
@@ -1013,7 +1007,7 @@ class LanguageService {
|
|
|
1013
1007
|
* @param text source Wikitext / 源代码
|
|
1014
1008
|
*/
|
|
1015
1009
|
async provideFoldingRanges(text) {
|
|
1016
|
-
const root = await this.#queue(text), { length } = root.getLines(), ranges = [], levels =
|
|
1010
|
+
const root = await this.#queue(text), { length } = root.getLines(), ranges = [], levels = Array.from({ length: 6 }), tokens = root.querySelectorAll('heading-title,table,template,magic-word');
|
|
1017
1011
|
for (const token of [...tokens].reverse()) { // 提高 getBoundingClientRect 的性能
|
|
1018
1012
|
token.getRelativeIndex();
|
|
1019
1013
|
}
|
|
@@ -1397,7 +1391,7 @@ class LanguageService {
|
|
|
1397
1391
|
if (!this.data) {
|
|
1398
1392
|
return undefined;
|
|
1399
1393
|
}
|
|
1400
|
-
const { line, character } = position, curLine = text.split(/\r?\n/u, line + 1)[line], { lastChild } = await this.#queueSignature(`${curLine.slice(0, character +
|
|
1394
|
+
const { line, character } = position, curLine = text.split(/\r?\n/u, line + 1)[line], { lastChild } = await this.#queueSignature(`${curLine.slice(0, character + (0, common_1.numLeadingSpaces)(curLine.slice(character), /[{}<]|$/u))}}}`);
|
|
1401
1395
|
if (!lastChild.is('magic-word') || lastChild.length === 1) {
|
|
1402
1396
|
return undefined;
|
|
1403
1397
|
}
|
|
@@ -1561,7 +1555,7 @@ class LanguageService {
|
|
|
1561
1555
|
* @param text source Wikitext / 源代码
|
|
1562
1556
|
*/
|
|
1563
1557
|
async provideDocumentSymbols(text) {
|
|
1564
|
-
const root = await this.#queue(text), lines = root.getLines(), { length } = lines, symbols = [], names = new Set(), sections =
|
|
1558
|
+
const root = await this.#queue(text), lines = root.getLines(), { length } = lines, symbols = [], names = new Set(), sections = Array.from({ length: 6 }), tokens = root.querySelectorAll('heading-title');
|
|
1565
1559
|
for (const token of tokens) {
|
|
1566
1560
|
const { top, height, left, width } = token.getBoundingClientRect(), { level } = token.parentNode;
|
|
1567
1561
|
for (let i = level - 1; i < 6; i++) {
|
|
@@ -1612,7 +1606,7 @@ class LanguageService {
|
|
|
1612
1606
|
catch {
|
|
1613
1607
|
this.config = await index_1.default.fetchConfig(site, `${host}/w`, user);
|
|
1614
1608
|
}
|
|
1615
|
-
|
|
1609
|
+
this.config.articlePath = `${host}/wiki/`;
|
|
1616
1610
|
}
|
|
1617
1611
|
/** @implements */
|
|
1618
1612
|
[Symbol.dispose]() {
|
package/dist/lib/node.js
CHANGED
|
@@ -200,7 +200,10 @@ let AstNode = (() => {
|
|
|
200
200
|
/** @private */
|
|
201
201
|
getChildNodes() {
|
|
202
202
|
const { childNodes } = this;
|
|
203
|
-
|
|
203
|
+
if (Object.isFrozen(childNodes)) {
|
|
204
|
+
return [...childNodes];
|
|
205
|
+
}
|
|
206
|
+
return childNodes;
|
|
204
207
|
}
|
|
205
208
|
/** @private */
|
|
206
209
|
getAttribute(key) {
|
|
@@ -636,7 +639,7 @@ let AstNode = (() => {
|
|
|
636
639
|
if (this.getRootNode() !== other.getRootNode()) {
|
|
637
640
|
throw new RangeError('Nodes to be compared are not in the same document!');
|
|
638
641
|
}
|
|
639
|
-
const aAncestors = [...this.getAncestors().
|
|
642
|
+
const aAncestors = [...this.getAncestors().toReversed(), this], bAncestors = [...other.getAncestors().toReversed(), other], depth = aAncestors.findIndex((ancestor, i) => bAncestors[i] !== ancestor), { childNodes } = aAncestors[depth - 1];
|
|
640
643
|
return childNodes.indexOf(aAncestors[depth]) - childNodes.indexOf(bAncestors[depth]);
|
|
641
644
|
}
|
|
642
645
|
/** 获取当前节点的相对位置 */
|
package/dist/lib/text.js
CHANGED
|
@@ -186,7 +186,10 @@ let AstText = (() => {
|
|
|
186
186
|
}
|
|
187
187
|
/** @private */
|
|
188
188
|
toString(skip) {
|
|
189
|
-
|
|
189
|
+
if (skip && !this.parentNode?.getAttribute('built')) {
|
|
190
|
+
return (0, string_1.removeComment)(this.data);
|
|
191
|
+
}
|
|
192
|
+
return this.data;
|
|
190
193
|
}
|
|
191
194
|
/** @private */
|
|
192
195
|
text() {
|
|
@@ -217,7 +220,7 @@ let AstText = (() => {
|
|
|
217
220
|
return [];
|
|
218
221
|
}
|
|
219
222
|
errorRegex.lastIndex = 0;
|
|
220
|
-
const errors = [], nextType = nextSibling?.type, nextName = nextSibling?.name, previousType = previousSibling?.type, root = this.getRootNode(), rootStr = root.toString(), { ext, html, variants } = root.getAttribute('config'), { top, left } = root.posFromIndex(start), { lintConfig } = index_1.default, tagLike = lintConfig.rules['tag-like'], specified =
|
|
223
|
+
const errors = [], nextType = nextSibling?.type, nextName = nextSibling?.name, previousType = previousSibling?.type, root = this.getRootNode(), rootStr = root.toString(), { ext, html, variants } = root.getAttribute('config'), { top, left } = root.posFromIndex(start), { lintConfig } = index_1.default, tagLike = lintConfig.rules['tag-like'], specified = tagLike[1]
|
|
221
224
|
? new Set(Object.keys(tagLike[1]).filter(tag => tag !== 'invalid' && tag !== 'disallowed'))
|
|
222
225
|
: new Set(), tags = new Set([
|
|
223
226
|
'onlyinclude',
|
package/dist/lib/title.js
CHANGED
|
@@ -136,7 +136,8 @@ class Title {
|
|
|
136
136
|
catch /* c8 ignore next */ { }
|
|
137
137
|
}
|
|
138
138
|
title = (0, string_1.decodeHtml)(title).replace(/[_ ]+/gu, ' ').trim();
|
|
139
|
-
if (subpage
|
|
139
|
+
if (subpage
|
|
140
|
+
|| page && trimmed.startsWith('/')) {
|
|
140
141
|
this.#ns = 0;
|
|
141
142
|
}
|
|
142
143
|
else {
|
|
@@ -206,7 +207,9 @@ class Title {
|
|
|
206
207
|
#getTitle(prefix, redirect = true) {
|
|
207
208
|
let title = (prefix + this.main).replace(/ /gu, '_');
|
|
208
209
|
if (title.startsWith('/')) {
|
|
209
|
-
title =
|
|
210
|
+
title =
|
|
211
|
+
(this.page ?? '') +
|
|
212
|
+
title.replace(/(.)\/$/u, '$1');
|
|
210
213
|
}
|
|
211
214
|
else if (title.startsWith('../') && this.page?.includes('/')) {
|
|
212
215
|
const [level, sub] = resolve(title), dirs = this.page.split('/');
|
|
@@ -237,7 +240,7 @@ class Title {
|
|
|
237
240
|
getRedirection() {
|
|
238
241
|
const { prefix,
|
|
239
242
|
/* NOT FOR BROWSER */
|
|
240
|
-
main, interwiki, } = this, pre = interwiki + (interwiki && ':') +
|
|
243
|
+
main, interwiki, } = this, pre = interwiki + (interwiki && ':') +
|
|
241
244
|
prefix, result = this.#getTitle(pre);
|
|
242
245
|
/* NOT FOR BROWSER */
|
|
243
246
|
if (result[0]) {
|
|
@@ -338,7 +341,8 @@ class Title {
|
|
|
338
341
|
autoConvert() {
|
|
339
342
|
const { conversionTable } = this;
|
|
340
343
|
if (conversionTable.size > 0) {
|
|
341
|
-
const regex = new RegExp([...conversionTable.keys()].
|
|
344
|
+
const regex = new RegExp([...conversionTable.keys()].toSorted((a, b) => b.localeCompare(a)).map(string_1.escapeRegExp)
|
|
345
|
+
.join('|'), 'gu');
|
|
342
346
|
this.main = this.main.replace(regex, p => conversionTable.get(p));
|
|
343
347
|
}
|
|
344
348
|
}
|
|
@@ -25,9 +25,9 @@ const elementLike = (constructor) => {
|
|
|
25
25
|
/* NOT FOR BROWSER END */
|
|
26
26
|
#getCondition(selector) {
|
|
27
27
|
return (0, selector_1.getCondition)(selector,
|
|
28
|
-
// eslint-disable-next-line unicorn/no-negated-condition
|
|
28
|
+
// eslint-disable-next-line unicorn/no-negated-condition
|
|
29
29
|
!('type' in this) ?
|
|
30
|
-
undefined :
|
|
30
|
+
undefined :
|
|
31
31
|
this);
|
|
32
32
|
}
|
|
33
33
|
getElementBy(condition) {
|
|
@@ -96,7 +96,8 @@ const parseCommentAndExt = (wikitext, config, accum, includeOnly) => {
|
|
|
96
96
|
ch = 'c';
|
|
97
97
|
const closed = substr.endsWith('-->');
|
|
98
98
|
// @ts-expect-error abstract class
|
|
99
|
-
new comment_1.CommentToken((0, string_1.restore)(substr, accum, 1)
|
|
99
|
+
new comment_1.CommentToken((0, string_1.restore)(substr, accum, 1)
|
|
100
|
+
.slice(4, closed ? -3 : undefined), closed, config, accum);
|
|
100
101
|
}
|
|
101
102
|
else if (include) {
|
|
102
103
|
// @ts-expect-error abstract class
|
package/dist/render/expand.js
CHANGED
|
@@ -99,7 +99,7 @@ const expand = (wikitext, page, callPage, config, include, context, now = index_
|
|
|
99
99
|
if (!/\0\d+g\x7F/u.test(data)) {
|
|
100
100
|
continue;
|
|
101
101
|
}
|
|
102
|
-
const expanded = data.
|
|
102
|
+
const expanded = data.replaceAll(/\0(\d+)g\x7F/gu, (_, i) => {
|
|
103
103
|
const target = accum[i];
|
|
104
104
|
if (target.type === 'onlyinclude') {
|
|
105
105
|
clean(accum, target);
|
|
@@ -107,7 +107,7 @@ const expand = (wikitext, page, callPage, config, include, context, now = index_
|
|
|
107
107
|
}
|
|
108
108
|
const { lastChild } = target;
|
|
109
109
|
clean(accum, lastChild);
|
|
110
|
-
return lastChild.firstChild.toString().
|
|
110
|
+
return lastChild.firstChild.toString().replaceAll(/\0(\d+)c\x7F[\n ]|\0(\d+)n\x7F|^\n|\n$/gu, (m, p1, p2) => {
|
|
111
111
|
if (p1 !== undefined) {
|
|
112
112
|
const { innerText } = accum[p1];
|
|
113
113
|
return /^T:[^_/\n<>~]+$/u.test(innerText) ? '' : m;
|
|
@@ -132,7 +132,7 @@ const expand = (wikitext, page, callPage, config, include, context, now = index_
|
|
|
132
132
|
if (!/\0\d+[tm!{}+~-]\x7F/u.test(data)) {
|
|
133
133
|
continue;
|
|
134
134
|
}
|
|
135
|
-
const expanded = data.
|
|
135
|
+
const expanded = data.replaceAll(/([^\x7F]?)\0(\d+)[tm!{}+~-]\x7F/gu, (m, prev, i) => {
|
|
136
136
|
const target = accum[i], { type, name, length, firstChild: f, childNodes } = target, isTemplate = type === 'template', args = childNodes.slice(1);
|
|
137
137
|
if (type === 'arg') {
|
|
138
138
|
const arg = (0, string_1.removeCommentLine)(f.toString()).trim();
|
package/dist/render/extension.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/* eslint @stylistic/operator-linebreak: [2, "before", {overrides: {"=": "after"}}] */
|
|
3
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
3
|
exports.renderExt = void 0;
|
|
5
4
|
const constants_1 = require("../util/constants");
|
|
@@ -12,12 +11,25 @@ const string_1 = require("../util/string");
|
|
|
12
11
|
const renderExt = (token, opt) => {
|
|
13
12
|
const { name, firstChild, lastChild } = token;
|
|
14
13
|
switch (name) {
|
|
14
|
+
case 'nowiki': {
|
|
15
|
+
const html = lastChild.toHtmlInternal();
|
|
16
|
+
return token.closest('ext-inner')?.name === 'poem' ? html : (0, string_1.newline)(html);
|
|
17
|
+
}
|
|
18
|
+
case 'pre': {
|
|
19
|
+
const html = lastChild.toHtmlInternal({
|
|
20
|
+
...opt,
|
|
21
|
+
nowrap: false,
|
|
22
|
+
});
|
|
23
|
+
return `<pre${firstChild.toHtmlInternal()}>${token.closest('ext-inner')?.name === 'poem' ? html : (0, string_1.newline)(html)}</pre>`;
|
|
24
|
+
}
|
|
25
|
+
case 'langconvert':
|
|
26
|
+
return lastChild.toHtmlInternal({ ...opt, nowrap: true });
|
|
15
27
|
case 'poem': {
|
|
16
28
|
const padding = firstChild.hasAttr('compact') ? '' : '\n';
|
|
17
29
|
firstChild.classList.add('poem');
|
|
18
30
|
return `<div${firstChild.toHtmlInternal()}>${padding}${lastChild.toHtmlInternal({ ...opt, nowrap: false })
|
|
19
|
-
.
|
|
20
|
-
.
|
|
31
|
+
.replaceAll(/(?<!^|<hr>)\n(?!$)/gu, '<br>\n')
|
|
32
|
+
.replaceAll(/^ +/gmu, p => ' '.repeat(p.length))
|
|
21
33
|
.trim()}${padding}</div>`;
|
|
22
34
|
}
|
|
23
35
|
case 'gallery': {
|
|
@@ -150,21 +150,24 @@ function urlFunction(config, args, local) {
|
|
|
150
150
|
title.ns = 6;
|
|
151
151
|
title.fragment = undefined;
|
|
152
152
|
}
|
|
153
|
-
const link = title.getUrl(
|
|
153
|
+
const { articlePath, server = '' } = config, path = articlePath && (/^\/(?!\/)/u.test(articlePath) ? server : '') + articlePath, link = title.getUrl(path), protocol = link.startsWith('//') ? 'https:' : '';
|
|
154
154
|
try {
|
|
155
155
|
const url = new URL(protocol + link);
|
|
156
|
-
url.search = query ? `?${query.
|
|
156
|
+
url.search = query ? `?${query.replaceAll(/\s/gu, '_')}` : '';
|
|
157
157
|
return local ? url : [url, protocol];
|
|
158
158
|
}
|
|
159
159
|
catch (e) {
|
|
160
160
|
if (local) {
|
|
161
161
|
title.fragment = undefined;
|
|
162
|
-
return title.getUrl(
|
|
162
|
+
return title.getUrl(path) + (query ? `?${query}` : '');
|
|
163
163
|
}
|
|
164
164
|
throw e;
|
|
165
165
|
}
|
|
166
166
|
}
|
|
167
|
-
const parseUrl = ({
|
|
167
|
+
const parseUrl = ({ server = '', articlePath = '' }) => {
|
|
168
|
+
if (/^\/(?!\/)/u.test(articlePath)) {
|
|
169
|
+
articlePath = server + articlePath;
|
|
170
|
+
}
|
|
168
171
|
let offset = 0;
|
|
169
172
|
if (articlePath.startsWith('//')) {
|
|
170
173
|
offset = 6;
|
|
@@ -197,8 +200,8 @@ const parseUrl = ({ testServer = '', articlePath = testServer }) => {
|
|
|
197
200
|
'3B': ';',
|
|
198
201
|
40: '@',
|
|
199
202
|
'7E': '~',
|
|
200
|
-
}, strip = (s) => s.
|
|
201
|
-
.
|
|
203
|
+
}, strip = (s) => s.replaceAll(/\0\d+.\x7F/gu, ''), wfUrlencode = (s) => encodeURIComponent(s.replaceAll(' ', '_'))
|
|
204
|
+
.replaceAll(/%(2[01489ACF]|3B|40|7E)/gu, (_, p) => dictUrl[p]), localurl = (config, args) => {
|
|
202
205
|
const url = urlFunction(config, args, true);
|
|
203
206
|
return typeof url === 'string' ? url : url.pathname + url.search;
|
|
204
207
|
}, fullurl = (config, args) => {
|
|
@@ -246,7 +249,7 @@ const parseUrl = ({ testServer = '', articlePath = testServer }) => {
|
|
|
246
249
|
if (!text) {
|
|
247
250
|
return '';
|
|
248
251
|
}
|
|
249
|
-
let output = `\n${text}`.
|
|
252
|
+
let output = `\n${text}`.replaceAll(/["&'=;_]|!!|__|:\/\/|~{3}|\n(?:[!#*:]|-{4})|(?:ISBN|PMID|RFC) /gu, m => dictHtml1[m]).slice(1);
|
|
250
253
|
output = output.charAt(0).replace(/[+_~-]/u, m => dictHtml2[m])
|
|
251
254
|
+ output.slice(1);
|
|
252
255
|
output = output.slice(0, -1)
|
|
@@ -334,7 +337,7 @@ const expandMagicWord = (name, args, page = '', config = index_1.default.getConf
|
|
|
334
337
|
case 'currentweek':
|
|
335
338
|
return currentWeek(now, new Date(Date.UTC(now.getUTCFullYear(), 0, 1)));
|
|
336
339
|
case 'currenttimestamp':
|
|
337
|
-
return now.toISOString().slice(0, 19).
|
|
340
|
+
return now.toISOString().slice(0, 19).replaceAll(/[-:T]/gu, '');
|
|
338
341
|
case 'localyear':
|
|
339
342
|
return localYear(now);
|
|
340
343
|
case 'localmonth':
|
|
@@ -552,10 +555,10 @@ const expandMagicWord = (name, args, page = '', config = index_1.default.getConf
|
|
|
552
555
|
case 'padright':
|
|
553
556
|
return pad(args, 'padEnd');
|
|
554
557
|
case 'anchorencode':
|
|
555
|
-
return anchorencode((0, html_1.getId)(strip(arg0).
|
|
558
|
+
return anchorencode((0, html_1.getId)(strip(arg0).replaceAll(/\[\[([^[]+?)\]\]/gu, (_, p) => {
|
|
556
559
|
const i = p.indexOf('|');
|
|
557
560
|
return i <= 0 || i === p.length - 1 ? p : p.slice(i + 1);
|
|
558
|
-
}))).
|
|
561
|
+
}))).replaceAll(/%(?=[\da-f]{2})/giu, '%25');
|
|
559
562
|
case 'special':
|
|
560
563
|
return special(target, config);
|
|
561
564
|
case 'speciale':
|
package/dist/src/attribute.d.ts
CHANGED
|
@@ -17,7 +17,10 @@ export type AttributeTypes = 'ext-attr' | 'html-attr' | 'table-attr';
|
|
|
17
17
|
export declare abstract class AttributeToken extends Token {
|
|
18
18
|
#private;
|
|
19
19
|
readonly name: string;
|
|
20
|
-
readonly childNodes: readonly [
|
|
20
|
+
readonly childNodes: readonly [
|
|
21
|
+
AtomToken,
|
|
22
|
+
Token
|
|
23
|
+
];
|
|
21
24
|
abstract get firstChild(): AtomToken;
|
|
22
25
|
abstract get lastChild(): Token;
|
|
23
26
|
abstract get parentNode(): AttributesToken | undefined;
|
package/dist/src/attribute.js
CHANGED
|
@@ -162,9 +162,10 @@ let AttributeToken = (() => {
|
|
|
162
162
|
valueToken.setAttribute('stage', 1);
|
|
163
163
|
}
|
|
164
164
|
else {
|
|
165
|
-
valueToken =
|
|
166
|
-
|
|
167
|
-
|
|
165
|
+
valueToken =
|
|
166
|
+
new atom_1.AtomToken(value, 'attr-value', config, accum, {
|
|
167
|
+
[`Stage-${exports.stages[type]}`]: ':',
|
|
168
|
+
});
|
|
168
169
|
}
|
|
169
170
|
super(undefined, config, accum);
|
|
170
171
|
this.#type = type;
|
|
@@ -278,7 +279,7 @@ let AttributeToken = (() => {
|
|
|
278
279
|
}
|
|
279
280
|
else if (typeof value === 'string' && ((/^xmlns:[\w:.-]+$/u.test(name) || urlAttrs.has(name)) && evil.test(value)
|
|
280
281
|
|| simple
|
|
281
|
-
&& (name === 'href' || tag === 'img' && name === 'src')
|
|
282
|
+
&& (name === 'href' || type === 'ext-attr' && tag === 'img' && name === 'src')
|
|
282
283
|
&& !new RegExp(String.raw `^(?:${this.getAttribute('config').protocol}|//)\S+$`, 'iu')
|
|
283
284
|
.test(value))) {
|
|
284
285
|
/* PRINT ONLY */
|
package/dist/src/attributes.js
CHANGED
|
@@ -73,6 +73,15 @@ const wordRegex = /* #__PURE__ */ (() => {
|
|
|
73
73
|
}
|
|
74
74
|
/* c8 ignore stop */
|
|
75
75
|
})();
|
|
76
|
+
const required = new Map([
|
|
77
|
+
['indicator', ['name']],
|
|
78
|
+
['langconvert', ['from', 'to']],
|
|
79
|
+
['mapframe', ['width', 'height']],
|
|
80
|
+
['maplink', ['width', 'height']],
|
|
81
|
+
['phonos', [['ipa', 'file', 'wikibase']]],
|
|
82
|
+
['section', [['begin', 'end']]],
|
|
83
|
+
['templatestyles', ['src']],
|
|
84
|
+
]);
|
|
76
85
|
/**
|
|
77
86
|
* attributes of extension and HTML tags
|
|
78
87
|
*
|
|
@@ -174,16 +183,15 @@ let AttributesToken = (() => {
|
|
|
174
183
|
let out = '', mt = regex.exec(attr), lastIndex = 0;
|
|
175
184
|
const insertDirty = /** 插入无效属性 */ () => {
|
|
176
185
|
if (out) {
|
|
177
|
-
super.insertAt(new atom_1.AtomToken(out, toDirty(type), config, accum, {
|
|
178
|
-
[`Stage-${stages[type]}`]: ':',
|
|
179
|
-
}));
|
|
186
|
+
super.insertAt(new atom_1.AtomToken(out, toDirty(type), config, accum, { [`Stage-${stages[type]}`]: ':' }));
|
|
180
187
|
out = '';
|
|
181
188
|
}
|
|
182
189
|
};
|
|
183
190
|
while (mt) {
|
|
184
191
|
const { index, 0: full, 1: key, 2: equal, 3: quoteStart, 4: quoted, 5: quoteEnd, 6: unquoted } = mt;
|
|
185
192
|
out += attr.slice(lastIndex, index);
|
|
186
|
-
if (/^(?:[\w:]|\0\d+t\x7F)(?:[\w:.-]|\0\d+t\x7F)*$/u
|
|
193
|
+
if (/^(?:[\w:]|\0\d+t\x7F)(?:[\w:.-]|\0\d+t\x7F)*$/u
|
|
194
|
+
.test((0, string_1.removeComment)(key).trim())) {
|
|
187
195
|
const value = quoted ?? unquoted, quotes = [quoteStart, quoteEnd],
|
|
188
196
|
// @ts-expect-error abstract class
|
|
189
197
|
token = new attribute_1.AttributeToken((0, exports.toAttributeType)(type), name, key, quotes, config, equal, value, accum);
|
|
@@ -255,7 +263,7 @@ let AttributesToken = (() => {
|
|
|
255
263
|
/** @private */
|
|
256
264
|
lint(start = this.getAbsoluteIndex(), re) {
|
|
257
265
|
LINT: {
|
|
258
|
-
const errors = super.lint(start, re), { parentNode, childNodes } = this, attrs = new Map(), duplicated = new Set(), rect = new rect_1.BoundingRect(this, start), rules = ['no-ignored', 'no-duplicate'], { lintConfig } = index_1.default, { computeEditInfo, fix } = lintConfig, s = ['closingTag', 'invalidAttributes', 'nonWordAttributes']
|
|
266
|
+
const errors = super.lint(start, re), { parentNode, childNodes, type, name: tag } = this, attrs = new Map(), duplicated = new Set(), rect = new rect_1.BoundingRect(this, start), rules = ['no-ignored', 'required-attr', 'no-duplicate'], { lintConfig } = index_1.default, { computeEditInfo, fix } = lintConfig, s = ['closingTag', 'invalidAttributes', 'nonWordAttributes']
|
|
259
267
|
.map(k => lintConfig.getSeverity(rules[0], k));
|
|
260
268
|
if (s[0] && this.#lint()) {
|
|
261
269
|
const e = (0, lint_1.generateForSelf)(this, rect, rules[0], 'attributes-of-closing-tag', s[0]);
|
|
@@ -290,7 +298,21 @@ let AttributesToken = (() => {
|
|
|
290
298
|
}
|
|
291
299
|
}
|
|
292
300
|
}
|
|
293
|
-
|
|
301
|
+
if (type === 'ext-attrs' && required.has(tag)) {
|
|
302
|
+
const severity = lintConfig.getSeverity(rules[1], tag);
|
|
303
|
+
if (severity) {
|
|
304
|
+
for (const key of required.get(tag)) {
|
|
305
|
+
const keys = typeof key === 'string' ? [key] : key, missing = keys.every(k => {
|
|
306
|
+
const value = this.getAttr(k);
|
|
307
|
+
return value === true || !value;
|
|
308
|
+
});
|
|
309
|
+
if (missing) {
|
|
310
|
+
errors.push((0, lint_1.generateForSelf)(this, rect, rules[1], index_1.default.msg('required-attribute', keys.join('/')), severity));
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
const severity = lintConfig.getSeverity(rules[2], 'attribute');
|
|
294
316
|
if (severity && duplicated.size > 0) {
|
|
295
317
|
for (const key of duplicated) {
|
|
296
318
|
const pairs = attrs.get(key).map(attr => {
|
|
@@ -298,7 +320,7 @@ let AttributesToken = (() => {
|
|
|
298
320
|
return [attr, value === true ? '' : value];
|
|
299
321
|
});
|
|
300
322
|
Array.prototype.push.apply(errors, pairs.map(([attr, value], i) => {
|
|
301
|
-
const e = (0, lint_1.generateForChild)(attr, rect, rules[
|
|
323
|
+
const e = (0, lint_1.generateForChild)(attr, rect, rules[2], index_1.default.msg('duplicate-attribute', key), severity);
|
|
302
324
|
if (computeEditInfo || fix) {
|
|
303
325
|
const remove = (0, lint_1.fixByRemove)(e);
|
|
304
326
|
if (!value || pairs.slice(0, i).some(([, v]) => v === value)) {
|
package/dist/src/heading.js
CHANGED
|
@@ -38,6 +38,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
38
38
|
};
|
|
39
39
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
40
|
exports.HeadingToken = void 0;
|
|
41
|
+
const common_1 = require("@bhsd/common");
|
|
41
42
|
const lint_1 = require("../util/lint");
|
|
42
43
|
const debug_1 = require("../util/debug");
|
|
43
44
|
const rect_1 = require("../lib/rect");
|
|
@@ -170,10 +171,14 @@ let HeadingToken = (() => {
|
|
|
170
171
|
//
|
|
171
172
|
}
|
|
172
173
|
else if (unbalancedStart) {
|
|
173
|
-
const
|
|
174
|
-
e.suggestions = [{ desc: `h${level}`, range: [e.startIndex, e.startIndex + extra
|
|
174
|
+
const extra = (0, common_1.numLeadingSpaces)(innerStr, /[^=]|$/u), newLevel = level + extra;
|
|
175
|
+
e.suggestions = [{ desc: `h${level}`, range: [e.startIndex, e.startIndex + extra], text: '' }];
|
|
175
176
|
if (newLevel < 7) {
|
|
176
|
-
e.suggestions.push({
|
|
177
|
+
e.suggestions.push({
|
|
178
|
+
desc: `h${newLevel}`,
|
|
179
|
+
range: [e.endIndex, e.endIndex],
|
|
180
|
+
text: '='.repeat(extra),
|
|
181
|
+
});
|
|
177
182
|
}
|
|
178
183
|
}
|
|
179
184
|
else {
|
package/dist/src/link/base.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ import type { Title } from '../../lib/title';
|
|
|
12
12
|
export declare abstract class LinkBaseToken extends Token {
|
|
13
13
|
#private;
|
|
14
14
|
readonly name: string;
|
|
15
|
-
abstract get type(): '
|
|
15
|
+
abstract get type(): 'gallery-image' | 'link' | 'category' | 'file' | 'redirect-target' | 'ext-inner' | 'imagemap-image';
|
|
16
16
|
readonly childNodes: readonly [AtomToken, ...Token[]];
|
|
17
17
|
abstract get firstChild(): AtomToken;
|
|
18
18
|
abstract get lastChild(): Token;
|