wikiparser-node 1.3.6 → 1.3.7
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/dist/index.js +2 -2
- package/dist/lib/element.js +14 -9
- package/dist/lib/node.js +6 -12
- package/dist/lib/text.js +27 -19
- package/dist/lib/title.js +5 -5
- package/dist/mixin/attributesParent.js +1 -1
- package/dist/mixin/singleLine.js +2 -2
- package/dist/parser/braces.js +5 -5
- package/dist/parser/commentAndExt.js +6 -3
- package/dist/parser/converter.js +4 -4
- package/dist/parser/magicLinks.js +4 -4
- package/dist/parser/quotes.js +1 -1
- package/dist/parser/selector.js +3 -2
- package/dist/parser/table.js +1 -1
- package/dist/src/attribute.js +9 -3
- package/dist/src/attributes.js +6 -7
- package/dist/src/converterRule.js +3 -3
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +5 -13
- package/dist/src/link/base.js +1 -1
- package/dist/src/link/file.js +2 -1
- package/dist/src/link/index.js +1 -0
- package/dist/src/magicLink.js +6 -5
- package/dist/src/nested.js +2 -2
- package/dist/src/nowiki/quote.js +1 -1
- package/dist/src/parameter.js +1 -1
- package/dist/src/table/base.d.ts +4 -0
- package/dist/src/table/base.js +1 -1
- package/dist/src/table/index.js +2 -1
- package/dist/src/table/td.js +7 -4
- package/dist/src/table/trBase.js +4 -2
- package/dist/src/tagPair/ext.d.ts +1 -1
- package/dist/src/tagPair/ext.js +1 -3
- package/dist/src/transclude.js +5 -3
- package/dist/util/constants.js +6 -1
- package/dist/util/string.js +2 -2
- package/package.json +7 -5
- package/dist/bin/toc.js +0 -18
package/dist/index.js
CHANGED
|
@@ -64,7 +64,7 @@ const Parser = {
|
|
|
64
64
|
debug_1.Shadow.run(() => {
|
|
65
65
|
for (const key of ['main', 'fragment']) {
|
|
66
66
|
if (titleObj[key]?.includes('\0')) {
|
|
67
|
-
titleObj[key] = token.buildFromStr(titleObj[key],
|
|
67
|
+
titleObj[key] = token.buildFromStr(titleObj[key], constants_1.BuildMethod.Text);
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
});
|
|
@@ -163,7 +163,7 @@ const Parser = {
|
|
|
163
163
|
/** @implements */
|
|
164
164
|
isInterwiki(title, { interwiki } = Parser.getConfig()) {
|
|
165
165
|
return new RegExp(`^(${interwiki.join('|')})\\s*:`, 'diu')
|
|
166
|
-
.exec(title.
|
|
166
|
+
.exec(title.replace(/_/gu, ' ').replace(/^\s*:?\s*/u, ''));
|
|
167
167
|
},
|
|
168
168
|
/** @implements */
|
|
169
169
|
reparse(date) {
|
package/dist/lib/element.js
CHANGED
|
@@ -51,7 +51,7 @@ class AstElement extends node_1.AstNode {
|
|
|
51
51
|
}
|
|
52
52
|
/** 末位非文本子节点 */
|
|
53
53
|
get lastElementChild() {
|
|
54
|
-
return this.children.
|
|
54
|
+
return this.children[this.childElementCount - 1];
|
|
55
55
|
}
|
|
56
56
|
/** 非文本子节点总数 */
|
|
57
57
|
get childElementCount() {
|
|
@@ -93,7 +93,11 @@ class AstElement extends node_1.AstNode {
|
|
|
93
93
|
/** 内部宽度 */
|
|
94
94
|
get clientWidth() {
|
|
95
95
|
const { innerText } = this;
|
|
96
|
-
|
|
96
|
+
if (typeof innerText === 'string') {
|
|
97
|
+
const lines = innerText.split('\n');
|
|
98
|
+
return lines[lines.length - 1].length;
|
|
99
|
+
}
|
|
100
|
+
return undefined;
|
|
97
101
|
}
|
|
98
102
|
constructor() {
|
|
99
103
|
super();
|
|
@@ -200,7 +204,8 @@ class AstElement extends node_1.AstNode {
|
|
|
200
204
|
*/
|
|
201
205
|
setText(str, i = 0) {
|
|
202
206
|
this.verifyChild(i);
|
|
203
|
-
|
|
207
|
+
i += i < 0 ? this.length : 0;
|
|
208
|
+
const oldText = this.childNodes[i], { type, constructor: { name } } = oldText;
|
|
204
209
|
if (type === 'text') {
|
|
205
210
|
const { data } = oldText;
|
|
206
211
|
oldText.replaceData(str);
|
|
@@ -234,11 +239,6 @@ class AstElement extends node_1.AstNode {
|
|
|
234
239
|
print(opt = {}) {
|
|
235
240
|
return String(this) ? `<span class="wpb-${opt.class ?? this.type}">${(0, string_1.print)(this.childNodes, opt)}</span>` : '';
|
|
236
241
|
}
|
|
237
|
-
/* NOT FOR BROWSER */
|
|
238
|
-
/** @private */
|
|
239
|
-
matchesTypes(types) {
|
|
240
|
-
return types.has(this.type);
|
|
241
|
-
}
|
|
242
242
|
/**
|
|
243
243
|
* 保存为JSON
|
|
244
244
|
* @param file 文件名
|
|
@@ -253,6 +253,11 @@ class AstElement extends node_1.AstNode {
|
|
|
253
253
|
}
|
|
254
254
|
return json;
|
|
255
255
|
}
|
|
256
|
+
/* NOT FOR BROWSER */
|
|
257
|
+
/** @private */
|
|
258
|
+
matchesTypes(types) {
|
|
259
|
+
return types.has(this.type);
|
|
260
|
+
}
|
|
256
261
|
/** 销毁 */
|
|
257
262
|
destroy() {
|
|
258
263
|
this.parentNode?.destroy();
|
|
@@ -432,7 +437,7 @@ class AstElement extends node_1.AstNode {
|
|
|
432
437
|
const condition = [...copy], step = condition.pop();
|
|
433
438
|
if (this.#matches(step)) {
|
|
434
439
|
const { parentNode, previousElementSibling } = this;
|
|
435
|
-
switch (condition.
|
|
440
|
+
switch (condition[condition.length - 1]?.relation) {
|
|
436
441
|
case undefined:
|
|
437
442
|
return true;
|
|
438
443
|
case '>':
|
package/dist/lib/node.js
CHANGED
|
@@ -29,7 +29,7 @@ class AstNode {
|
|
|
29
29
|
}
|
|
30
30
|
/** 末位子节点 */
|
|
31
31
|
get lastChild() {
|
|
32
|
-
return this.childNodes.
|
|
32
|
+
return this.childNodes[this.childNodes.length - 1];
|
|
33
33
|
}
|
|
34
34
|
/** 父节点 */
|
|
35
35
|
get parentNode() {
|
|
@@ -118,7 +118,7 @@ class AstNode {
|
|
|
118
118
|
if (key === 'parentNode') {
|
|
119
119
|
this.#parentNode = value;
|
|
120
120
|
}
|
|
121
|
-
else if (Object.
|
|
121
|
+
else if (Object.prototype.hasOwnProperty.call(this, key)) {
|
|
122
122
|
const descriptor = Object.getOwnPropertyDescriptor(this, key);
|
|
123
123
|
if (this.#optional.has(key)) {
|
|
124
124
|
descriptor.enumerable = Boolean(value);
|
|
@@ -148,21 +148,15 @@ class AstNode {
|
|
|
148
148
|
posFromIndex(index) {
|
|
149
149
|
const str = String(this);
|
|
150
150
|
if (index >= -str.length && index <= str.length) {
|
|
151
|
-
const lines = str.slice(0, index).split('\n');
|
|
152
|
-
return {
|
|
153
|
-
top: lines.length - 1,
|
|
154
|
-
left: lines.at(-1).length,
|
|
155
|
-
};
|
|
151
|
+
const lines = str.slice(0, index).split('\n'), top = lines.length - 1;
|
|
152
|
+
return { top, left: lines[top].length };
|
|
156
153
|
}
|
|
157
154
|
return undefined;
|
|
158
155
|
}
|
|
159
156
|
/** 获取行数和最后一行的列数 */
|
|
160
157
|
#getDimension() {
|
|
161
|
-
const lines = String(this).split('\n');
|
|
162
|
-
return {
|
|
163
|
-
height: lines.length,
|
|
164
|
-
width: lines.at(-1).length,
|
|
165
|
-
};
|
|
158
|
+
const lines = String(this).split('\n'), height = lines.length;
|
|
159
|
+
return { height, width: lines[height - 1].length };
|
|
166
160
|
}
|
|
167
161
|
/** @private */
|
|
168
162
|
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
|
package/dist/lib/text.js
CHANGED
|
@@ -5,7 +5,7 @@ const constants_1 = require("../util/constants");
|
|
|
5
5
|
const debug_1 = require("../util/debug");
|
|
6
6
|
const Parser = require("../index");
|
|
7
7
|
const node_1 = require("./node");
|
|
8
|
-
const errorSyntax = /<\s*\/?([a-z]\w*)|\{+|\}+|\[{2,}|\[(?![^[]*\])|(
|
|
8
|
+
const errorSyntax = /<\s*\/?([a-z]\w*)|\{+|\}+|\[{2,}|\[(?![^[]*\])|((?:^|\])[^[]*?)\]+|https?[:/]\/+/giu, errorSyntaxUrl = /<\s*\/?([a-z]\w*)|\{+|\}+|\[{2,}|\[(?![^[]*\])|((?:^|\])[^[]*?)\]+/giu, disallowedTags = [
|
|
9
9
|
'html',
|
|
10
10
|
'base',
|
|
11
11
|
'head',
|
|
@@ -71,7 +71,10 @@ class AstText extends node_1.AstNode {
|
|
|
71
71
|
constructor(text) {
|
|
72
72
|
super();
|
|
73
73
|
Object.defineProperties(this, {
|
|
74
|
-
data: {
|
|
74
|
+
data: {
|
|
75
|
+
value: text,
|
|
76
|
+
writable: false,
|
|
77
|
+
},
|
|
75
78
|
childNodes: { enumerable: false, configurable: false },
|
|
76
79
|
type: { enumerable: false, writable: false, configurable: false },
|
|
77
80
|
});
|
|
@@ -109,17 +112,19 @@ class AstText extends node_1.AstNode {
|
|
|
109
112
|
else {
|
|
110
113
|
errorRegex = errorSyntax;
|
|
111
114
|
}
|
|
112
|
-
const errors = [
|
|
113
|
-
if (
|
|
115
|
+
const errors = [], { ext, html } = this.getRootNode().getAttribute('config');
|
|
116
|
+
if (data.search(errorRegex) !== -1) {
|
|
117
|
+
errorRegex.lastIndex = 0;
|
|
114
118
|
const root = this.getRootNode(), { top, left } = root.posFromIndex(start), tags = new Set(['onlyinclude', 'noinclude', 'includeonly', ext, html, disallowedTags].flat(2));
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
119
|
+
for (let mt = errorRegex.exec(data); mt; mt = errorRegex.exec(data)) {
|
|
120
|
+
const [, tag, prefix] = mt;
|
|
121
|
+
let { 0: error, index } = mt;
|
|
122
|
+
if (prefix && prefix !== ']') {
|
|
118
123
|
const { length } = prefix;
|
|
119
124
|
index += length;
|
|
120
125
|
error = error.slice(length);
|
|
121
126
|
}
|
|
122
|
-
const startIndex = start + index, lines = data.slice(0, index).split('\n'), startLine = lines.length + top - 1, line = lines.
|
|
127
|
+
const startIndex = start + index, lines = data.slice(0, index).split('\n'), startLine = lines.length + top - 1, line = lines[lines.length - 1], startCol = lines.length === 1 ? left + line.length : line.length, { 0: char, length } = error, endIndex = startIndex + length, rootStr = String(root), nextChar = rootStr[endIndex], previousChar = rootStr[startIndex - 1], severity = length > 1 && (char !== '<' || /[\s/>]/u.test(nextChar ?? ''))
|
|
123
128
|
|| char === '{' && (nextChar === char || previousChar === '-')
|
|
124
129
|
|| char === '}' && (previousChar === char || nextChar === '-')
|
|
125
130
|
|| char === '[' && (nextChar === char
|
|
@@ -129,17 +134,20 @@ class AstText extends node_1.AstNode {
|
|
|
129
134
|
|| !data.slice(0, index).trim() && previousType === 'free-ext-link')
|
|
130
135
|
? 'error'
|
|
131
136
|
: 'warning';
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
137
|
+
if (char !== '<' || tags.has(tag.toLowerCase())) {
|
|
138
|
+
errors.push({
|
|
139
|
+
message: Parser.msg('lonely "$1"', char === 'h' ? error : char),
|
|
140
|
+
severity,
|
|
141
|
+
startIndex,
|
|
142
|
+
endIndex,
|
|
143
|
+
startLine,
|
|
144
|
+
endLine: startLine,
|
|
145
|
+
startCol,
|
|
146
|
+
endCol: startCol + length,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return errors;
|
|
143
151
|
}
|
|
144
152
|
return [];
|
|
145
153
|
}
|
package/dist/lib/title.js
CHANGED
|
@@ -24,7 +24,7 @@ class Title {
|
|
|
24
24
|
return this.#main;
|
|
25
25
|
}
|
|
26
26
|
set main(title) {
|
|
27
|
-
title = title.
|
|
27
|
+
title = title.replace(/_/gu, ' ').trim();
|
|
28
28
|
this.#main = title && `${title[0].toUpperCase()}${title.slice(1)}`;
|
|
29
29
|
}
|
|
30
30
|
/** 命名空间前缀 */
|
|
@@ -35,13 +35,13 @@ class Title {
|
|
|
35
35
|
/** 完整标题 */
|
|
36
36
|
get title() {
|
|
37
37
|
const prefix = `${this.interwiki}${this.interwiki && ':'}${this.prefix}`;
|
|
38
|
-
let title = `${prefix}${this.main}`.
|
|
38
|
+
let title = `${prefix}${this.main}`.replace(/ /gu, '_');
|
|
39
39
|
const redirected = this.redirects.get(title);
|
|
40
40
|
if (redirected) {
|
|
41
41
|
return redirected;
|
|
42
42
|
}
|
|
43
43
|
this.autoConvert();
|
|
44
|
-
title = `${prefix}${this.main}`.
|
|
44
|
+
title = `${prefix}${this.main}`.replace(/ /gu, '_');
|
|
45
45
|
return this.redirects.get(title) ?? title;
|
|
46
46
|
}
|
|
47
47
|
/** 扩展名 */
|
|
@@ -77,7 +77,7 @@ class Title {
|
|
|
77
77
|
}
|
|
78
78
|
catch { }
|
|
79
79
|
}
|
|
80
|
-
title = title.
|
|
80
|
+
title = title.replace(/_/gu, ' ').trim();
|
|
81
81
|
let ns = defaultNs;
|
|
82
82
|
if (title.startsWith(':')) {
|
|
83
83
|
ns = 0;
|
|
@@ -108,7 +108,7 @@ class Title {
|
|
|
108
108
|
}
|
|
109
109
|
else if (fragment.includes('.')) {
|
|
110
110
|
try {
|
|
111
|
-
fragment = decodeURIComponent(fragment.
|
|
111
|
+
fragment = decodeURIComponent(fragment.replace(/\./gu, '%'));
|
|
112
112
|
}
|
|
113
113
|
catch { }
|
|
114
114
|
}
|
|
@@ -12,7 +12,7 @@ const attributesParent = (constructor, i = 0) => {
|
|
|
12
12
|
class AttributesParent extends constructor {
|
|
13
13
|
/** AttributesToken子节点 */
|
|
14
14
|
get #attributesChild() {
|
|
15
|
-
return this.childNodes
|
|
15
|
+
return this.childNodes[i];
|
|
16
16
|
}
|
|
17
17
|
/** getAttrs()方法的getter写法 */
|
|
18
18
|
get attributes() {
|
package/dist/mixin/singleLine.js
CHANGED
|
@@ -11,11 +11,11 @@ const singleLine = (constructor) => {
|
|
|
11
11
|
class SingleLineToken extends constructor {
|
|
12
12
|
/** @private */
|
|
13
13
|
toString(omit) {
|
|
14
|
-
return super.toString(omit).
|
|
14
|
+
return super.toString(omit).replace(/\n/gu, ' ');
|
|
15
15
|
}
|
|
16
16
|
/** @override */
|
|
17
17
|
text() {
|
|
18
|
-
return super.text().
|
|
18
|
+
return super.text().replace(/\n/gu, ' ');
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
Object.defineProperty(SingleLineToken, 'name', { value: `SingleLine${constructor.name}` });
|
package/dist/parser/braces.js
CHANGED
|
@@ -18,7 +18,7 @@ const parseBraces = (wikitext, config = Parser.getConfig(), accum = []) => {
|
|
|
18
18
|
const source = `${config.excludes?.includes('heading') ? '' : '^(\0\\d+c\x7F)*={1,6}|'}\\[\\[|\\{{2,}|-\\{(?!\\{)`, { parserFunction: [, , , subst] } = config, stack = [], closes = { '=': '\n', '{': '\\}{2,}|\\|', '-': '\\}-', '[': '\\]\\]' }, marks = new Map([['!', '!'], ['!!', '+'], ['(!', '{'], ['!)', '}'], ['!-', '-'], ['=', '~']]);
|
|
19
19
|
let regex = new RegExp(source, 'gmu'), mt = regex.exec(wikitext), moreBraces = wikitext.includes('}}'), lastIndex;
|
|
20
20
|
while (mt
|
|
21
|
-
|| lastIndex !== undefined && lastIndex <= wikitext.length && stack.
|
|
21
|
+
|| lastIndex !== undefined && lastIndex <= wikitext.length && stack[stack.length - 1]?.[0]?.startsWith('=')) {
|
|
22
22
|
if (mt?.[1]) {
|
|
23
23
|
const [, { length }] = mt;
|
|
24
24
|
mt[0] = mt[0].slice(length);
|
|
@@ -30,14 +30,14 @@ const parseBraces = (wikitext, config = Parser.getConfig(), accum = []) => {
|
|
|
30
30
|
* @param text wikitext全文
|
|
31
31
|
*/
|
|
32
32
|
const push = (text) => {
|
|
33
|
-
parts.
|
|
33
|
+
parts[parts.length - 1].push(text.slice(topPos, curIndex));
|
|
34
34
|
};
|
|
35
35
|
if (syntax === ']]' || syntax === '}-') { // 情形1:闭合内链或转换
|
|
36
36
|
lastIndex = curIndex + 2;
|
|
37
37
|
}
|
|
38
38
|
else if (syntax === '\n') { // 情形2:闭合标题或文末
|
|
39
39
|
lastIndex = curIndex + 1;
|
|
40
|
-
const { pos, findEqual } = stack.
|
|
40
|
+
const { pos, findEqual } = stack[stack.length - 1] ?? {};
|
|
41
41
|
if (pos === undefined || findEqual || (0, string_1.removeComment)(wikitext.slice(pos, index)) !== '') {
|
|
42
42
|
const rmt = /^(={1,6})(.+)\1((?:\s|\0\d+c\x7F)*)$/u
|
|
43
43
|
.exec(wikitext.slice(index, curIndex));
|
|
@@ -113,10 +113,10 @@ const parseBraces = (wikitext, config = Parser.getConfig(), accum = []) => {
|
|
|
113
113
|
stack.push(...'0' in top ? [top] : [], mt);
|
|
114
114
|
}
|
|
115
115
|
moreBraces &&= wikitext.slice(lastIndex).includes('}}');
|
|
116
|
-
let curTop = stack.
|
|
116
|
+
let curTop = stack[stack.length - 1];
|
|
117
117
|
if (!moreBraces && curTop?.[0]?.startsWith('{')) {
|
|
118
118
|
stack.pop();
|
|
119
|
-
curTop = stack.
|
|
119
|
+
curTop = stack[stack.length - 1];
|
|
120
120
|
}
|
|
121
121
|
regex = new RegExp(source + (curTop ? `|${closes[curTop[0][0]]}${curTop.findEqual ? '|=' : ''}` : ''), 'gmu');
|
|
122
122
|
regex.lastIndex = lastIndex;
|
|
@@ -50,9 +50,12 @@ const parseCommentAndExt = (wikitext, config = Parser.getConfig(), accum = [], i
|
|
|
50
50
|
return str;
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
|
-
const ext = config.ext.join('|'), noincludeRegex = includeOnly ? 'includeonly' : '(?:no|only)include', includeRegex = includeOnly ? 'noinclude' : 'includeonly', regex = new RegExp('<!--.*?(?:-->|$)
|
|
54
|
-
+
|
|
55
|
-
+
|
|
53
|
+
const ext = config.ext.join('|'), noincludeRegex = includeOnly ? 'includeonly' : '(?:no|only)include', includeRegex = includeOnly ? 'noinclude' : 'includeonly', regex = new RegExp('<!--.*?(?:-->|$)' // comment
|
|
54
|
+
+ '|'
|
|
55
|
+
+ `<${noincludeRegex}(?:\\s[^>]*?)?>|</${noincludeRegex}\\s*>` // <noinclude>
|
|
56
|
+
+ '|'
|
|
57
|
+
+ `<(${ext})(\\s[^>]*?)?(?:/>|>(.*?)</(\\1\\s*)>)` // 扩展标签
|
|
58
|
+
+ '|'
|
|
56
59
|
+ `<(${includeRegex})(\\s[^>]*?)?(?:/>|>(.*?)(?:</(${includeRegex}\\s*)>|$))`, // <includeonly>
|
|
57
60
|
'gisu');
|
|
58
61
|
return wikitext.replace(regex, (substr, name, attr, inner, closing, include, includeAttr, includeInner, includeClosing) => {
|
package/dist/parser/converter.js
CHANGED
|
@@ -16,10 +16,10 @@ const parseConverter = (text, config = Parser.getConfig(), accum = []) => {
|
|
|
16
16
|
while (mt) {
|
|
17
17
|
const { 0: syntax, index } = mt;
|
|
18
18
|
if (syntax === '}-') {
|
|
19
|
-
const top = stack.pop(), { length } = accum, str = text.slice(top.index + 2, index), i = str.indexOf('|'), [flags, raw] = i === -1 ? [[], str] : [str.slice(0, i).split(';'), str.slice(i + 1)],
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
const top = stack.pop(), { length } = accum, str = text.slice(top.index + 2, index), i = str.indexOf('|'), [flags, raw] = i === -1 ? [[], str] : [str.slice(0, i).split(';'), str.slice(i + 1)], temp = raw.replace(/(&[#a-z\d]+);/giu, '$1\x01'), variants = `(?:${config.variants.join('|')})`, rules = temp.split(new RegExp(`;(?=\\s*(?:${`(?:${variants}|[^;]*?=>\\s*${variants})\\s*:`
|
|
20
|
+
+ '|'
|
|
21
|
+
+ '(?:\0\\d+c\x7f(?:\\s|\0\\d+c\x7f)*)?$' // 末尾的空白
|
|
22
|
+
}))`, 'u')).map(rule => rule.replace(/\x01/gu, ';'));
|
|
23
23
|
new converter_1.ConverterToken(flags, rules, config, accum);
|
|
24
24
|
text = `${text.slice(0, top.index)}\0${length}v\x7F${text.slice(index + 2)}`;
|
|
25
25
|
if (stack.length === 0) {
|
|
@@ -12,9 +12,9 @@ const magicLink_1 = require("../src/magicLink");
|
|
|
12
12
|
* @param accum
|
|
13
13
|
*/
|
|
14
14
|
const parseMagicLinks = (wikitext, config = Parser.getConfig(), accum = []) => {
|
|
15
|
-
const regex = new RegExp(`(
|
|
16
|
-
return wikitext.replace(regex, (m, p1) => {
|
|
17
|
-
let trail = '', url = m;
|
|
15
|
+
const regex = new RegExp(`(^|[^\\p{L}\\d_])(?:${config.protocol})(${string_1.extUrlCharFirst}${string_1.extUrlChar})`, 'giu');
|
|
16
|
+
return wikitext.replace(regex, (m, lead, p1) => {
|
|
17
|
+
let trail = '', url = lead ? m.slice(1) : m;
|
|
18
18
|
const m2 = /&(?:lt|gt|nbsp|#x0*(?:3[ce]|a0)|#0*(?:6[02]|160));/iu.exec(url);
|
|
19
19
|
if (m2) {
|
|
20
20
|
trail = url.slice(m2.index);
|
|
@@ -33,7 +33,7 @@ const parseMagicLinks = (wikitext, config = Parser.getConfig(), accum = []) => {
|
|
|
33
33
|
return m;
|
|
34
34
|
}
|
|
35
35
|
new magicLink_1.MagicLinkToken(url, false, config, accum);
|
|
36
|
-
return
|
|
36
|
+
return `${lead}\0${accum.length - 1}w\x7F${trail}`;
|
|
37
37
|
});
|
|
38
38
|
};
|
|
39
39
|
exports.parseMagicLinks = parseMagicLinks;
|
package/dist/parser/quotes.js
CHANGED
package/dist/parser/selector.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.parseSelector = void 0;
|
|
4
4
|
const constants_1 = require("../util/constants");
|
|
5
|
+
const string_1 = require("../util/string");
|
|
5
6
|
const Parser = require("../index");
|
|
6
7
|
const simplePseudos = new Set([
|
|
7
8
|
'root',
|
|
@@ -53,7 +54,7 @@ const pseudoRegex = new RegExp(`:(${complexPseudos.join('|')})$`, 'u'), regularR
|
|
|
53
54
|
*/
|
|
54
55
|
const sanitize = (selector) => {
|
|
55
56
|
for (const [c, escaped] of specialChars) {
|
|
56
|
-
selector = selector.
|
|
57
|
+
selector = selector.replace(new RegExp((0, string_1.escapeRegExp)(`\\${c}`), 'gu'), escaped);
|
|
57
58
|
}
|
|
58
59
|
return selector;
|
|
59
60
|
};
|
|
@@ -63,7 +64,7 @@ const sanitize = (selector) => {
|
|
|
63
64
|
*/
|
|
64
65
|
const desanitize = (selector) => {
|
|
65
66
|
for (const [c, escaped] of specialChars) {
|
|
66
|
-
selector = selector.
|
|
67
|
+
selector = selector.replace(new RegExp(escaped, 'gu'), c);
|
|
67
68
|
}
|
|
68
69
|
return selector.trim();
|
|
69
70
|
};
|
package/dist/parser/table.js
CHANGED
|
@@ -81,7 +81,7 @@ const parseTable = ({ firstChild: { data }, type, name }, config = Parser.getCon
|
|
|
81
81
|
top = stack.pop();
|
|
82
82
|
}
|
|
83
83
|
top.close(`\n${spaces}${closing}`, true);
|
|
84
|
-
push(attr, stack.
|
|
84
|
+
push(attr, stack[stack.length - 1]);
|
|
85
85
|
}
|
|
86
86
|
else if (row) {
|
|
87
87
|
top = pop();
|
package/dist/src/attribute.js
CHANGED
|
@@ -146,7 +146,13 @@ const commonHtmlAttrs = new Set([
|
|
|
146
146
|
]),
|
|
147
147
|
tabs: new Set(['plain', 'class', 'container', 'id', 'title', 'style']),
|
|
148
148
|
combobox: new Set(['placeholder', 'value', 'id', 'class', 'text', 'dropdown', 'style']),
|
|
149
|
-
}, insecureStyle = new RegExp(
|
|
149
|
+
}, insecureStyle = new RegExp('expression'
|
|
150
|
+
+ '|'
|
|
151
|
+
+ '(?:filter|accelerator|-o-link(?:-source)?|-o-replace)\\s*:'
|
|
152
|
+
+ '|'
|
|
153
|
+
+ '(?:url|image(?:-set)?)\\s*\\('
|
|
154
|
+
+ '|'
|
|
155
|
+
+ 'attr\\s*\\([^)]+[\\s,]url', 'u');
|
|
150
156
|
/**
|
|
151
157
|
* 扩展和HTML标签属性
|
|
152
158
|
* @classdesc `{childNodes: [AtomToken, Token|AtomToken]}`
|
|
@@ -239,7 +245,7 @@ class AttributeToken extends (0, fixed_1.fixed)(index_1.Token) {
|
|
|
239
245
|
/** @private */
|
|
240
246
|
afterBuild() {
|
|
241
247
|
if (this.#equal.includes('\0')) {
|
|
242
|
-
this.#equal = this.buildFromStr(this.#equal,
|
|
248
|
+
this.#equal = this.buildFromStr(this.#equal, constants_1.BuildMethod.String);
|
|
243
249
|
}
|
|
244
250
|
if (this.parentNode) {
|
|
245
251
|
this.setAttribute('tag', this.parentNode.name);
|
|
@@ -303,7 +309,7 @@ class AttributeToken extends (0, fixed_1.fixed)(index_1.Token) {
|
|
|
303
309
|
if (this.#quotes[1]) {
|
|
304
310
|
return value;
|
|
305
311
|
}
|
|
306
|
-
return this.#quotes[0] ?
|
|
312
|
+
return value[this.#quotes[0] ? 'trimEnd' : 'trim']();
|
|
307
313
|
}
|
|
308
314
|
return this.type === 'ext-attr' || '';
|
|
309
315
|
}
|
package/dist/src/attributes.js
CHANGED
|
@@ -81,12 +81,11 @@ class AttributesToken extends index_1.Token {
|
|
|
81
81
|
this.setAttribute('name', name);
|
|
82
82
|
if (attr) {
|
|
83
83
|
const regex = new RegExp('([^\\s/](?:(?!\0\\d+~\x7F)[^\\s/=])*)' // 属性名
|
|
84
|
-
+ '(
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
+ ')?', 'gsu');
|
|
84
|
+
+ `(?:${'((?:\\s|\0\\d+c\x7F)*' // `=`前的空白字符
|
|
85
|
+
+ '(?:=|\0\\d+~\x7F)' // `=`
|
|
86
|
+
+ '(?:\\s|\0\\d+c\x7F)*)' // `=`后的空白字符
|
|
87
|
+
+ `(?:(["'])(.*?)(\\3|$)|(\\S*))` // 属性值
|
|
88
|
+
})?`, 'gsu');
|
|
90
89
|
let out = '', mt = regex.exec(attr), lastIndex = 0;
|
|
91
90
|
const insertDirty = /** 插入无效属性 */ () => {
|
|
92
91
|
if (out) {
|
|
@@ -134,7 +133,7 @@ class AttributesToken extends index_1.Token {
|
|
|
134
133
|
*/
|
|
135
134
|
getAttrToken(key) {
|
|
136
135
|
const tokens = this.getAttrTokens(key);
|
|
137
|
-
return tokens.
|
|
136
|
+
return tokens[tokens.length - 1];
|
|
138
137
|
}
|
|
139
138
|
/**
|
|
140
139
|
* 获取指定属性
|
|
@@ -15,7 +15,7 @@ class ConverterRuleToken extends index_1.Token {
|
|
|
15
15
|
/* NOT FOR BROWSER */
|
|
16
16
|
/** 语言变体 */
|
|
17
17
|
get variant() {
|
|
18
|
-
return this.childNodes.
|
|
18
|
+
return this.childNodes[this.length - 2]?.text().trim() ?? '';
|
|
19
19
|
}
|
|
20
20
|
set variant(variant) {
|
|
21
21
|
this.setVariant(variant);
|
|
@@ -122,7 +122,7 @@ class ConverterRuleToken extends index_1.Token {
|
|
|
122
122
|
afterBuild() {
|
|
123
123
|
const /** @implements */ converterRuleListener = (e, data) => {
|
|
124
124
|
const { prevTarget } = e;
|
|
125
|
-
if (this.length > 1 && this.childNodes.
|
|
125
|
+
if (this.length > 1 && this.childNodes[this.length - 2] === prevTarget) {
|
|
126
126
|
const { variant } = this;
|
|
127
127
|
if (!this.getAttribute('config').variants.includes(variant)) {
|
|
128
128
|
(0, debug_1.undo)(e, data);
|
|
@@ -171,7 +171,7 @@ class ConverterRuleToken extends index_1.Token {
|
|
|
171
171
|
super.insertAt(debug_1.Shadow.run(() => new atom_1.AtomToken(variant, 'converter-rule-variant', config)), 0);
|
|
172
172
|
}
|
|
173
173
|
else {
|
|
174
|
-
this.childNodes.
|
|
174
|
+
this.childNodes[this.length - 2].setText(variant);
|
|
175
175
|
}
|
|
176
176
|
}
|
|
177
177
|
/**
|
package/dist/src/index.d.ts
CHANGED
package/dist/src/index.js
CHANGED
|
@@ -151,15 +151,15 @@ class Token extends element_1.AstElement {
|
|
|
151
151
|
if (i % 2 === 0) {
|
|
152
152
|
return new text_1.AstText(s);
|
|
153
153
|
}
|
|
154
|
-
else if (Number.isNaN(Number(s.
|
|
154
|
+
else if (Number.isNaN(Number(s.slice(-1)))) {
|
|
155
155
|
return this.#accum[Number(s.slice(0, -1))];
|
|
156
156
|
}
|
|
157
157
|
throw new Error(`解析错误!未正确标记的 Token:${s}`);
|
|
158
158
|
});
|
|
159
|
-
if (type ===
|
|
159
|
+
if (type === constants_1.BuildMethod.String) {
|
|
160
160
|
return nodes.map(String).join('');
|
|
161
161
|
}
|
|
162
|
-
else if (type ===
|
|
162
|
+
else if (type === constants_1.BuildMethod.Text) {
|
|
163
163
|
return (0, string_1.text)(nodes);
|
|
164
164
|
}
|
|
165
165
|
return nodes;
|
|
@@ -303,15 +303,7 @@ class Token extends element_1.AstElement {
|
|
|
303
303
|
return this.#include;
|
|
304
304
|
}
|
|
305
305
|
const root = this.getRootNode();
|
|
306
|
-
|
|
307
|
-
return root.getAttribute('include');
|
|
308
|
-
}
|
|
309
|
-
const includeToken = root.getElementByTypes('include');
|
|
310
|
-
if (includeToken) {
|
|
311
|
-
return (includeToken.name === 'noinclude');
|
|
312
|
-
}
|
|
313
|
-
const noincludeToken = root.getElementByTypes('noinclude');
|
|
314
|
-
return (Boolean(noincludeToken) && !/^<\/?noinclude(?:\s[^>]*)?\/?>$/iu.test(String(noincludeToken)));
|
|
306
|
+
return (root !== this && root.getAttribute('include'));
|
|
315
307
|
}
|
|
316
308
|
case 'stage':
|
|
317
309
|
return this.#stage;
|
|
@@ -458,7 +450,7 @@ class Token extends element_1.AstElement {
|
|
|
458
450
|
createComment(data = '') {
|
|
459
451
|
const { CommentToken } = require('./nowiki/comment');
|
|
460
452
|
const config = this.getAttribute('config');
|
|
461
|
-
return debug_1.Shadow.run(() => new CommentToken(data.
|
|
453
|
+
return debug_1.Shadow.run(() => new CommentToken(data.replace(/-->/gu, '-->'), true, config));
|
|
462
454
|
}
|
|
463
455
|
/**
|
|
464
456
|
* 创建标签
|
package/dist/src/link/base.js
CHANGED
|
@@ -61,7 +61,7 @@ class LinkBaseToken extends index_1.Token {
|
|
|
61
61
|
this.#title = this.getTitle();
|
|
62
62
|
this.setAttribute('name', this.#title.title);
|
|
63
63
|
if (this.#delimiter.includes('\0')) {
|
|
64
|
-
this.#delimiter = this.buildFromStr(this.#delimiter,
|
|
64
|
+
this.#delimiter = this.buildFromStr(this.#delimiter, constants_1.BuildMethod.String);
|
|
65
65
|
}
|
|
66
66
|
const /** @implements */ linkListener = (e, data) => {
|
|
67
67
|
const { prevTarget } = e;
|
package/dist/src/link/file.js
CHANGED
package/dist/src/link/index.js
CHANGED
|
@@ -110,6 +110,7 @@ class LinkToken extends base_1.LinkBaseToken {
|
|
|
110
110
|
this.setLinkText(m2[1].trim());
|
|
111
111
|
return;
|
|
112
112
|
}
|
|
113
|
+
// eslint-disable-next-line es-x/no-regexp-lookbehind-assertions
|
|
113
114
|
const m3 = /^:?(?:[ \w\x80-\xFF-]+:)?(.+?)(?:(?<!\()\(.+\))?(?:, |,|، )./u
|
|
114
115
|
.exec(linkText);
|
|
115
116
|
if (m3) {
|
package/dist/src/magicLink.js
CHANGED
|
@@ -63,9 +63,10 @@ class MagicLinkToken extends (0, syntax_1.syntax)(index_1.Token) {
|
|
|
63
63
|
}
|
|
64
64
|
rect ??= { start, ...this.getRootNode().posFromIndex(start) };
|
|
65
65
|
const refError = (0, lint_1.generateForChild)(child, rect, '', 'warning');
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
regexGlobal.lastIndex = 0;
|
|
67
|
+
for (let mt = regexGlobal.exec(data); mt; mt = regexGlobal.exec(data)) {
|
|
68
|
+
const { index, 0: s } = mt, lines = data.slice(0, index).split('\n'), { length: top } = lines, { length: left } = lines[lines.length - 1], startIndex = refError.startIndex + index, startLine = refError.startLine + top - 1, startCol = top === 1 ? refError.startCol + left : left;
|
|
69
|
+
errors.push({
|
|
69
70
|
...refError,
|
|
70
71
|
message: Parser.msg('$1 in URL', s.startsWith('|') ? '"|"' : Parser.msg('full-width punctuation')),
|
|
71
72
|
startIndex,
|
|
@@ -74,8 +75,8 @@ class MagicLinkToken extends (0, syntax_1.syntax)(index_1.Token) {
|
|
|
74
75
|
endLine: startLine,
|
|
75
76
|
startCol,
|
|
76
77
|
endCol: startCol + s.length,
|
|
77
|
-
};
|
|
78
|
-
}
|
|
78
|
+
});
|
|
79
|
+
}
|
|
79
80
|
}
|
|
80
81
|
return errors;
|
|
81
82
|
}
|
package/dist/src/nested.js
CHANGED
|
@@ -33,9 +33,9 @@ class NestedToken extends index_1.Token {
|
|
|
33
33
|
new comment_1.CommentToken(comment.slice(4, closed ? -3 : undefined), closed, config, accum);
|
|
34
34
|
}
|
|
35
35
|
return str;
|
|
36
|
-
})?.replace(/(
|
|
36
|
+
})?.replace(/(^|\0\d+[ce]\x7F)([^\0]+)(?=$|\0\d+[ce]\x7F)/gu, (_, lead, substr) => {
|
|
37
37
|
new noinclude_1.NoincludeToken(substr, config, accum);
|
|
38
|
-
return
|
|
38
|
+
return `${lead}\0${accum.length}c\x7F`;
|
|
39
39
|
});
|
|
40
40
|
super(wikitext, config, accum, {
|
|
41
41
|
NoincludeToken: ':', ExtToken: ':',
|
package/dist/src/nowiki/quote.js
CHANGED
|
@@ -16,7 +16,7 @@ class QuoteToken extends (0, syntax_1.syntax)(base_1.NowikiBaseToken, /^(?:'{5}|
|
|
|
16
16
|
let refError;
|
|
17
17
|
if (previousSibling?.type === 'text' && previousSibling.data.endsWith(`'`)) {
|
|
18
18
|
refError = (0, lint_1.generateForSelf)(this, { start }, message);
|
|
19
|
-
const { startIndex: endIndex, startLine: endLine, startCol: endCol } = refError, [{ length }] = /(
|
|
19
|
+
const { startIndex: endIndex, startLine: endLine, startCol: endCol } = refError, [, { length }] = /(?:^|[^'])('+)$/u.exec(previousSibling.data), startIndex = start - length;
|
|
20
20
|
errors.push({
|
|
21
21
|
...refError,
|
|
22
22
|
startIndex,
|
package/dist/src/parameter.js
CHANGED
|
@@ -13,7 +13,7 @@ const index_1 = require("./index");
|
|
|
13
13
|
* @param name 预定的参数名
|
|
14
14
|
*/
|
|
15
15
|
const getName = (name) => name.toString(new Set(['comment', 'noinclude', 'include']))
|
|
16
|
-
.replace(/^[ \t\n\0\v]+|(
|
|
16
|
+
.replace(/^[ \t\n\0\v]+|([^ \t\n\0\v])[ \t\n\0\v]+$/gu, '$1');
|
|
17
17
|
/**
|
|
18
18
|
* 模板或魔术字参数
|
|
19
19
|
* @classdesc `{childNodes: [Token, Token]}`
|
package/dist/src/table/base.d.ts
CHANGED
|
@@ -6,6 +6,10 @@ declare const TableBaseToken_base: (abstract new (...args: any[]) => {
|
|
|
6
6
|
readonly childNodes: Parser.AstNodes[];
|
|
7
7
|
readonly "__#7@#attributesChild": Parser.AttributesToken;
|
|
8
8
|
attributes: Record<string, string | true>;
|
|
9
|
+
/**
|
|
10
|
+
* 表格行,含开头的换行,不含结尾的换行
|
|
11
|
+
* @classdesc `{childNodes: [SyntaxToken, AttributesToken, ...Token]}`
|
|
12
|
+
*/
|
|
9
13
|
className: string;
|
|
10
14
|
classList: Set<string>;
|
|
11
15
|
id: string;
|
package/dist/src/table/base.js
CHANGED
|
@@ -15,7 +15,7 @@ const attributes_1 = require("../attributes");
|
|
|
15
15
|
*/
|
|
16
16
|
const escapeTable = (syntax) => {
|
|
17
17
|
const wikitext = syntax.childNodes.map(child => child.type === 'text'
|
|
18
|
-
? child.data.
|
|
18
|
+
? child.data.replace(/\|/gu, '{{!}}')
|
|
19
19
|
: String(child)).join(''), { childNodes } = Parser.parse(wikitext, syntax.getAttribute('include'), 2, syntax.getAttribute('config'));
|
|
20
20
|
syntax.replaceChildren(...childNodes);
|
|
21
21
|
};
|
package/dist/src/table/index.js
CHANGED
|
@@ -69,7 +69,8 @@ class TableToken extends trBase_1.TrBaseToken {
|
|
|
69
69
|
* @throws `SyntaxError` 表格的闭合部分非法
|
|
70
70
|
*/
|
|
71
71
|
insertAt(token, i = this.length) {
|
|
72
|
-
|
|
72
|
+
i += i < 0 ? this.length : 0;
|
|
73
|
+
const previous = this.childNodes[i - 1];
|
|
73
74
|
if (typeof token !== 'string' && token.type === 'td' && previous?.type === 'tr') {
|
|
74
75
|
Parser.warn('改为将单元格插入当前行。');
|
|
75
76
|
return previous.insertAt(token);
|
package/dist/src/table/td.js
CHANGED
|
@@ -67,7 +67,7 @@ class TdToken extends (0, fixed_1.fixed)(base_1.TableBaseToken) {
|
|
|
67
67
|
}
|
|
68
68
|
/** 表格语法信息 */
|
|
69
69
|
#getSyntax() {
|
|
70
|
-
const syntax = this.firstChild.text(), esc = syntax.includes('{{'), char = syntax.
|
|
70
|
+
const syntax = this.firstChild.text(), esc = syntax.includes('{{'), char = syntax.slice(-1);
|
|
71
71
|
let subtype = 'td';
|
|
72
72
|
if (char === '!') {
|
|
73
73
|
subtype = 'th';
|
|
@@ -96,7 +96,7 @@ class TdToken extends (0, fixed_1.fixed)(base_1.TableBaseToken) {
|
|
|
96
96
|
/** @private */
|
|
97
97
|
afterBuild() {
|
|
98
98
|
if (this.#innerSyntax.includes('\0')) {
|
|
99
|
-
this.#innerSyntax = this.buildFromStr(this.#innerSyntax,
|
|
99
|
+
this.#innerSyntax = this.buildFromStr(this.#innerSyntax, constants_1.BuildMethod.String);
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
/** @private */
|
|
@@ -126,8 +126,11 @@ class TdToken extends (0, fixed_1.fixed)(base_1.TableBaseToken) {
|
|
|
126
126
|
const errors = super.lint(start);
|
|
127
127
|
start += this.getRelativeIndex(this.length - 1);
|
|
128
128
|
for (const child of this.lastChild.childNodes) {
|
|
129
|
-
if (child.type === 'text'
|
|
130
|
-
|
|
129
|
+
if (child.type === 'text') {
|
|
130
|
+
const { data } = child;
|
|
131
|
+
if (data.includes('|')) {
|
|
132
|
+
errors.push((0, lint_1.generateForChild)(child, { start }, 'additional "|" in a table cell', data.includes('||') ? 'error' : 'warning'));
|
|
133
|
+
}
|
|
131
134
|
}
|
|
132
135
|
}
|
|
133
136
|
return errors;
|
package/dist/src/table/trBase.js
CHANGED
|
@@ -67,7 +67,8 @@ class TrBaseToken extends base_1.TableBaseToken {
|
|
|
67
67
|
* @param i 移除位置
|
|
68
68
|
*/
|
|
69
69
|
removeAt(i) {
|
|
70
|
-
|
|
70
|
+
i += i < 0 ? this.length : 0;
|
|
71
|
+
const child = this.childNodes[i];
|
|
71
72
|
if (child instanceof td_1.TdToken && child.isIndependent()) {
|
|
72
73
|
const { nextSibling } = child;
|
|
73
74
|
if (nextSibling?.type === 'td') {
|
|
@@ -90,7 +91,8 @@ class TrBaseToken extends base_1.TableBaseToken {
|
|
|
90
91
|
this.typeError('insertAt', 'TrToken', 'TdToken');
|
|
91
92
|
}
|
|
92
93
|
}
|
|
93
|
-
|
|
94
|
+
i += i < 0 ? this.length : 0;
|
|
95
|
+
const child = this.childNodes[i];
|
|
94
96
|
if (token instanceof td_1.TdToken && token.isIndependent() && child instanceof td_1.TdToken) {
|
|
95
97
|
child.independence();
|
|
96
98
|
}
|
|
@@ -9,7 +9,7 @@ declare const ExtToken_base: (abstract new (...args: any[]) => {
|
|
|
9
9
|
attributes: Record<string, string | true>;
|
|
10
10
|
className: string;
|
|
11
11
|
classList: Set<string>;
|
|
12
|
-
id: string;
|
|
12
|
+
id: string; /** @override */
|
|
13
13
|
hasAttr(key: string): boolean;
|
|
14
14
|
getAttr(key: string): string | true | undefined;
|
|
15
15
|
getAttrNames(): Set<string>;
|
package/dist/src/tagPair/ext.js
CHANGED
|
@@ -39,9 +39,7 @@ class ExtToken extends (0, attributesParent_1.attributesParent)(index_2.TagPairT
|
|
|
39
39
|
* @param closed 是否封闭
|
|
40
40
|
*/
|
|
41
41
|
constructor(name, attr, inner, closed, config = Parser.getConfig(), accum = []) {
|
|
42
|
-
const lcName = name.toLowerCase(), attrToken = new attributes_1.AttributesToken(!attr || attr.trimStart() !== attr
|
|
43
|
-
? attr
|
|
44
|
-
: ` ${attr}`, 'ext-attrs', lcName, config, accum), newConfig = { ...config, ext: del(config.ext, lcName), excludes: [...config.excludes ?? []] };
|
|
42
|
+
const lcName = name.toLowerCase(), attrToken = new attributes_1.AttributesToken(!attr || attr.trimStart() !== attr ? attr : ` ${attr}`, 'ext-attrs', lcName, config, accum), newConfig = { ...config, ext: del(config.ext, lcName), excludes: [...config.excludes ?? []] };
|
|
45
43
|
let innerToken;
|
|
46
44
|
switch (lcName) {
|
|
47
45
|
case 'tab':
|
package/dist/src/transclude.js
CHANGED
|
@@ -146,7 +146,7 @@ class TranscludeToken extends index_1.Token {
|
|
|
146
146
|
/** @private */
|
|
147
147
|
afterBuild() {
|
|
148
148
|
if (this.modifier.includes('\0')) {
|
|
149
|
-
this.setAttribute('modifier', this.buildFromStr(this.modifier,
|
|
149
|
+
this.setAttribute('modifier', this.buildFromStr(this.modifier, constants_1.BuildMethod.String));
|
|
150
150
|
}
|
|
151
151
|
if (this.isTemplate()) {
|
|
152
152
|
const isTemplate = this.type === 'template';
|
|
@@ -304,7 +304,7 @@ class TranscludeToken extends index_1.Token {
|
|
|
304
304
|
* @param copy 是否返回一个备份
|
|
305
305
|
*/
|
|
306
306
|
getArgs(key, exact = false, copy = true) {
|
|
307
|
-
const keyStr = String(key).replace(/^[ \t\n\0\v]+|(
|
|
307
|
+
const keyStr = String(key).replace(/^[ \t\n\0\v]+|([^ \t\n\0\v])[ \t\n\0\v]+$/gu, '$1');
|
|
308
308
|
let args;
|
|
309
309
|
if (this.#args.has(keyStr)) {
|
|
310
310
|
args = this.#args.get(keyStr);
|
|
@@ -441,7 +441,8 @@ class TranscludeToken extends index_1.Token {
|
|
|
441
441
|
* @param exact 是否匹配匿名性
|
|
442
442
|
*/
|
|
443
443
|
getArg(key, exact = false) {
|
|
444
|
-
|
|
444
|
+
const args = [...this.getArgs(key, exact, false)].sort((a, b) => a.compareDocumentPosition(b));
|
|
445
|
+
return args[args.length - 1];
|
|
445
446
|
}
|
|
446
447
|
/**
|
|
447
448
|
* 移除指定参数
|
|
@@ -639,6 +640,7 @@ class TranscludeToken extends index_1.Token {
|
|
|
639
640
|
}
|
|
640
641
|
else if (aggressive && (anonCount ? /\D\d+$/u : /(?:^|\D)\d+$/u).test(key)) {
|
|
641
642
|
let last;
|
|
643
|
+
// eslint-disable-next-line es-x/no-regexp-lookbehind-assertions
|
|
642
644
|
const str = key.slice(0, -/(?<!\d)\d+$/u.exec(key)[0].length), regex = new RegExp(`^${(0, string_1.escapeRegExp)(str)}\\d+$`, 'u'), series = this.getAllArgs().filter(({ name }) => regex.test(name)), ordered = series.every(({ name }, i) => {
|
|
643
645
|
const j = Number(name.slice(str.length)), cmp = j <= i + 1 && (i === 0 || j >= last || name === key);
|
|
644
646
|
last = j;
|
package/dist/util/constants.js
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.promises = exports.typeAliases = exports.aliases = exports.parsers = exports.mixins = exports.classes = exports.MAX_STAGE = void 0;
|
|
3
|
+
exports.promises = exports.typeAliases = exports.aliases = exports.parsers = exports.mixins = exports.classes = exports.BuildMethod = exports.MAX_STAGE = void 0;
|
|
4
4
|
exports.MAX_STAGE = 11;
|
|
5
|
+
var BuildMethod;
|
|
6
|
+
(function (BuildMethod) {
|
|
7
|
+
BuildMethod[BuildMethod["String"] = 0] = "String";
|
|
8
|
+
BuildMethod[BuildMethod["Text"] = 1] = "Text";
|
|
9
|
+
})(BuildMethod || (exports.BuildMethod = BuildMethod = {}));
|
|
5
10
|
/* NOT FOR BROWSER */
|
|
6
11
|
exports.classes = {};
|
|
7
12
|
exports.mixins = {};
|
package/dist/util/string.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.normalizeSpace = exports.print = exports.noWrap = exports.decodeHtml = exports.text = exports.escapeRegExp = exports.removeComment = exports.extUrlChar = exports.extUrlCharFirst = void 0;
|
|
4
|
-
exports.extUrlCharFirst = '(?:\\[[\\da-f:.]+\\]|[^[\\]<>"
|
|
5
|
-
exports.extUrlChar = '(?:[^[\\]<>"
|
|
4
|
+
exports.extUrlCharFirst = '(?:\\[[\\da-f:.]+\\]|[^[\\]<>"\0-\x1F\x7F\\p{Zs}\uFFFD])';
|
|
5
|
+
exports.extUrlChar = '(?:[^[\\]<>"\0-\x1F\x7F\\p{Zs}\uFFFD]|\0\\d+[c!~]\x7F)*';
|
|
6
6
|
/**
|
|
7
7
|
* 生成正则替换函数
|
|
8
8
|
* @param regex 正则表达式
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wikiparser-node",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.7",
|
|
4
4
|
"description": "A Node.js parser for MediaWiki markup with AST",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mediawiki",
|
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
"/printed/README",
|
|
19
19
|
"/config/",
|
|
20
20
|
"/i18n/",
|
|
21
|
-
"/dist/"
|
|
21
|
+
"/dist/",
|
|
22
|
+
"!/dist/[bt]*/"
|
|
22
23
|
],
|
|
23
24
|
"main": "./dist/index.js",
|
|
24
25
|
"repository": {
|
|
@@ -27,15 +28,15 @@
|
|
|
27
28
|
},
|
|
28
29
|
"scripts": {
|
|
29
30
|
"toc": "node ./dist/bin/toc.js",
|
|
30
|
-
"prepublishOnly": "npm run build
|
|
31
|
-
"build": "rm -rf dist/; tsc
|
|
31
|
+
"prepublishOnly": "npm run build && rm dist/internal.js dist/base.js dist/[mpu]*/*.d.ts",
|
|
32
|
+
"build": "rm -rf dist/; tsc && grep -rl --include='*.d.ts' '@private' dist/ | xargs gsed -i '/@private/,+1d'",
|
|
32
33
|
"diff": "git diff --ignore-all-space --color-moved",
|
|
33
34
|
"lint:ts": "tsc --noEmit && eslint --cache .",
|
|
34
35
|
"lint:json": "ajv -s config/.schema.json -d 'config/*.json' --strict=true --strict-required=false",
|
|
35
36
|
"lint": "npm run lint:ts && npm run lint:json",
|
|
36
37
|
"test": "node dist/test/test.js",
|
|
37
38
|
"test:real": "node dist/test/real.js",
|
|
38
|
-
"test:single": "node dist/test/single.js
|
|
39
|
+
"test:single": "node dist/test/single.js && node --prof dist/test/single.js && node --prof-process isolate-0x*-v8.log > test/processed.txt && rm isolate-0x*-v8.log"
|
|
39
40
|
},
|
|
40
41
|
"devDependencies": {
|
|
41
42
|
"@cypress/request": "^3.0.1",
|
|
@@ -46,6 +47,7 @@
|
|
|
46
47
|
"@typescript-eslint/parser": "^6.12.0",
|
|
47
48
|
"ajv-cli": "^5.0.0",
|
|
48
49
|
"eslint": "^8.56.0",
|
|
50
|
+
"eslint-plugin-es-x": "^7.3.0",
|
|
49
51
|
"eslint-plugin-eslint-comments": "^3.2.0",
|
|
50
52
|
"eslint-plugin-jsdoc": "^47.0.2",
|
|
51
53
|
"eslint-plugin-json-es": "^1.5.7",
|
package/dist/bin/toc.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const fs = require("fs");
|
|
4
|
-
const path = require("path");
|
|
5
|
-
const { argv: [, , filename] } = process;
|
|
6
|
-
if (!filename) {
|
|
7
|
-
throw new RangeError('请指定文档文件!');
|
|
8
|
-
}
|
|
9
|
-
const fullpath = path.join(__dirname, '..', '..', 'wiki', `${filename}.md`), isEnglish = filename.endsWith('-(EN)');
|
|
10
|
-
if (!fs.existsSync(fullpath)) {
|
|
11
|
-
throw new RangeError(`文档 ${filename}.md 不存在!`);
|
|
12
|
-
}
|
|
13
|
-
const content = fs.readFileSync(fullpath, 'utf8');
|
|
14
|
-
if (/^- \[[^\]]+\]\(#[^)]+\)$/mu.test(content)) {
|
|
15
|
-
throw new Error(`文档 ${filename}.md 中已包含目录!`);
|
|
16
|
-
}
|
|
17
|
-
const toc = content.split('\n').filter(line => line.startsWith('#')).map(line => line.replace(/^(#+)\s+(\S.*)$/u, (_, { length }, title) => `${'\t'.repeat(length - 1)}- [${title}](#${title.toLowerCase().replaceAll(' ', '-').replaceAll('.', '')})`)).join('\n');
|
|
18
|
-
fs.writeFileSync(fullpath, `<details>\n\t<summary>${isEnglish ? 'Table of Contents' : '目录'}</summary>\n\n${toc}\n\n</details>\n\n# Other Languages\n\n- [${isEnglish ? '简体中文' : 'English'}](./${isEnglish ? filename.slice(0, -5) : `${filename}-%28EN%29`})\n\n${content}`);
|