wikiparser-node 0.7.1-b → 0.8.0-m

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.
Files changed (78) hide show
  1. package/config/default.json +832 -0
  2. package/config/llwiki.json +630 -0
  3. package/config/minimum.json +142 -0
  4. package/config/moegirl.json +728 -0
  5. package/config/zhwiki.json +1269 -0
  6. package/index.js +79 -0
  7. package/lib/element.js +137 -0
  8. package/lib/node.js +226 -0
  9. package/lib/text.js +123 -0
  10. package/lib/title.js +60 -0
  11. package/mixin/hidden.js +18 -0
  12. package/package.json +9 -11
  13. package/parser/brackets.js +119 -0
  14. package/parser/commentAndExt.js +61 -0
  15. package/parser/converter.js +45 -0
  16. package/parser/externalLinks.js +32 -0
  17. package/parser/hrAndDoubleUnderscore.js +37 -0
  18. package/parser/html.js +41 -0
  19. package/parser/links.js +93 -0
  20. package/parser/list.js +58 -0
  21. package/parser/magicLinks.js +40 -0
  22. package/parser/quotes.js +63 -0
  23. package/parser/table.js +113 -0
  24. package/src/arg.js +89 -0
  25. package/src/atom/hidden.js +11 -0
  26. package/src/atom/index.js +26 -0
  27. package/src/attribute.js +277 -0
  28. package/src/attributes.js +150 -0
  29. package/src/converter.js +70 -0
  30. package/src/converterFlags.js +97 -0
  31. package/src/converterRule.js +75 -0
  32. package/src/extLink.js +60 -0
  33. package/src/gallery.js +101 -0
  34. package/src/hasNowiki/index.js +32 -0
  35. package/src/hasNowiki/pre.js +28 -0
  36. package/src/heading.js +83 -0
  37. package/src/html.js +133 -0
  38. package/src/imageParameter.js +106 -0
  39. package/src/imagemap.js +140 -0
  40. package/src/imagemapLink.js +29 -0
  41. package/src/index.js +407 -0
  42. package/src/link/category.js +13 -0
  43. package/src/link/file.js +125 -0
  44. package/src/link/galleryImage.js +62 -0
  45. package/src/link/index.js +125 -0
  46. package/src/magicLink.js +68 -0
  47. package/src/nested/choose.js +23 -0
  48. package/src/nested/combobox.js +22 -0
  49. package/src/nested/index.js +69 -0
  50. package/src/nested/references.js +22 -0
  51. package/src/nowiki/comment.js +47 -0
  52. package/src/nowiki/dd.js +13 -0
  53. package/src/nowiki/doubleUnderscore.js +26 -0
  54. package/src/nowiki/hr.js +22 -0
  55. package/src/nowiki/index.js +34 -0
  56. package/src/nowiki/list.js +13 -0
  57. package/src/nowiki/noinclude.js +14 -0
  58. package/src/nowiki/quote.js +55 -0
  59. package/src/onlyinclude.js +39 -0
  60. package/src/paramTag/index.js +66 -0
  61. package/src/paramTag/inputbox.js +32 -0
  62. package/src/parameter.js +97 -0
  63. package/src/syntax.js +23 -0
  64. package/src/table/index.js +46 -0
  65. package/src/table/td.js +119 -0
  66. package/src/table/tr.js +74 -0
  67. package/src/tagPair/ext.js +121 -0
  68. package/src/tagPair/include.js +26 -0
  69. package/src/tagPair/index.js +77 -0
  70. package/src/transclude.js +323 -0
  71. package/util/base.js +17 -0
  72. package/util/diff.js +76 -0
  73. package/util/lint.js +54 -0
  74. package/util/string.js +60 -0
  75. package/bundle/bundle.min.js +0 -40
  76. package/extensions/editor.css +0 -60
  77. package/extensions/editor.js +0 -324
  78. package/extensions/ui.css +0 -119
package/index.js ADDED
@@ -0,0 +1,79 @@
1
+ 'use strict';
2
+
3
+ const /** @type {Parser} */ Parser = {
4
+ config: undefined,
5
+ minConfig: require('./config/minimum'),
6
+
7
+ MAX_STAGE: 11,
8
+
9
+ getConfig(path) {
10
+ if (path) {
11
+ this.config = require(path);
12
+ }
13
+ return {...this.minConfig, ...this.config, excludes: []};
14
+ },
15
+
16
+ normalizeTitle(
17
+ title,
18
+ defaultNs = 0,
19
+ include = false,
20
+ config = Parser.getConfig(),
21
+ halfParsed = false,
22
+ decode = false,
23
+ selfLink = false,
24
+ ) {
25
+ let /** @type {Token} */ token;
26
+ if (!halfParsed) {
27
+ const Token = require('./src');
28
+ token = this.run(() => {
29
+ const newToken = new Token(String(title), config),
30
+ parseOnce = newToken.getAttribute('parseOnce');
31
+ parseOnce(0, include);
32
+ return parseOnce();
33
+ });
34
+ title = token.firstChild;
35
+ }
36
+ const Title = require('./lib/title');
37
+ const titleObj = new Title(String(title), defaultNs, config, decode, selfLink);
38
+ return titleObj;
39
+ },
40
+
41
+ parse(wikitext, include, maxStage = Parser.MAX_STAGE, config = Parser.getConfig()) {
42
+ if (typeof wikitext !== 'string') {
43
+ throw new TypeError('待解析的内容应为 String!');
44
+ }
45
+ const Token = require('./src');
46
+ let /** @type {Token} */ token;
47
+ this.run(() => {
48
+ token = new Token(wikitext, config);
49
+ try {
50
+ token.parse(maxStage, include);
51
+ } catch {}
52
+ });
53
+ return token;
54
+ },
55
+
56
+ run(callback) {
57
+ return callback();
58
+ },
59
+
60
+ isInterwiki(title, {interwiki} = Parser.getConfig()) {
61
+ title = String(title);
62
+ return new RegExp(`^(${interwiki.join('|')})\\s*:`, 'iu')
63
+ .exec(title.replaceAll('_', ' ').replace(/^\s*:?\s*/u, ''));
64
+ },
65
+ };
66
+
67
+ const /** @type {PropertyDescriptorMap} */ def = {},
68
+ immutable = new Set(['MAX_STAGE', 'minConfig']),
69
+ enumerable = new Set(['config', 'normalizeTitle', 'parse', 'isInterwiki']);
70
+ for (const key in Parser) {
71
+ if (immutable.has(key)) {
72
+ def[key] = {enumerable: false, writable: false};
73
+ } else if (!enumerable.has(key)) {
74
+ def[key] = {enumerable: false};
75
+ }
76
+ }
77
+ Object.defineProperties(Parser, def);
78
+
79
+ module.exports = Parser;
package/lib/element.js ADDED
@@ -0,0 +1,137 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs'),
4
+ path = require('path'),
5
+ AstNode = require('./node'),
6
+ AstText = require('./text');
7
+
8
+ /** 类似HTMLElement */
9
+ class AstElement extends AstNode {
10
+ /** @type {string} */ name;
11
+
12
+ /** 子节点总数 */
13
+ get length() {
14
+ return this.childNodes.length;
15
+ }
16
+
17
+ /**
18
+ * 最近的祖先节点
19
+ * @param {string} selector
20
+ */
21
+ closest(selector) {
22
+ const types = new Set(selector.split(',').map(type => type.trim()));
23
+ let {parentNode} = this;
24
+ while (parentNode) {
25
+ if (types.has(parentNode.type)) {
26
+ return parentNode;
27
+ }
28
+ ({parentNode} = parentNode);
29
+ }
30
+ return undefined;
31
+ }
32
+
33
+ /**
34
+ * 在末尾批量插入子节点
35
+ * @param {...this} elements 插入节点
36
+ * @complexity `n`
37
+ */
38
+ append(...elements) {
39
+ for (const element of elements) {
40
+ this.insertAt(element);
41
+ }
42
+ }
43
+
44
+ /**
45
+ * 批量替换子节点
46
+ * @param {...this} elements 新的子节点
47
+ * @complexity `n`
48
+ */
49
+ replaceChildren(...elements) {
50
+ this.childNodes.length = 0;
51
+ this.append(...elements);
52
+ }
53
+
54
+ /**
55
+ * 修改文本子节点
56
+ * @param {string} str 新文本
57
+ * @param {number} i 子节点位置
58
+ */
59
+ setText(str, i = 0) {
60
+ const /** @type {AstText} */ oldText = this.childNodes[i],
61
+ {type, data} = oldText;
62
+ if (type === 'text') {
63
+ oldText.replaceData(str);
64
+ return data;
65
+ }
66
+ return undefined;
67
+ }
68
+
69
+ /**
70
+ * 还原为wikitext
71
+ * @param {string} separator 子节点间的连接符
72
+ * @returns {string}
73
+ */
74
+ toString(selector, separator = '') {
75
+ return this.childNodes.map(child => child.toString()).join(separator);
76
+ }
77
+
78
+ static lintIgnoredExt = new Set([
79
+ 'nowiki',
80
+ 'pre',
81
+ 'charinsert',
82
+ 'score',
83
+ 'syntaxhighlight',
84
+ 'source',
85
+ 'math',
86
+ 'chem',
87
+ 'ce',
88
+ 'graph',
89
+ 'mapframe',
90
+ 'maplink',
91
+ 'quiz',
92
+ 'templatedata',
93
+ 'timeline',
94
+ ]);
95
+
96
+ /**
97
+ * Linter
98
+ * @param {number} start 起始位置
99
+ */
100
+ lint(start = 0) {
101
+ const SyntaxToken = require('../src/syntax');
102
+ if (this instanceof SyntaxToken || this.constructor.hidden
103
+ || this.type === 'ext-inner' && AstElement.lintIgnoredExt.has(this.name)
104
+ ) {
105
+ return [];
106
+ }
107
+ const /** @type {LintError[]} */ errors = [];
108
+ for (let i = 0, cur = start + this.getPadding(); i < this.length; i++) {
109
+ const child = this.childNodes[i];
110
+ errors.push(...child.lint(cur));
111
+ cur += String(child).length + this.getGaps(i);
112
+ }
113
+ return errors;
114
+ }
115
+
116
+ /**
117
+ * 保存为JSON
118
+ * @param {string} file 文件名
119
+ * @returns {Record<string, *>}
120
+ */
121
+ json(file) {
122
+ const {childNodes, ...prop} = this,
123
+ json = {
124
+ ...prop,
125
+ childNodes: childNodes.map(child => child.type === 'text' ? String(child) : child.json()),
126
+ };
127
+ if (typeof file === 'string') {
128
+ fs.writeFileSync(
129
+ path.join(__dirname.slice(0, -4), 'printed', `${file}${file.endsWith('.json') ? '' : '.json'}`),
130
+ JSON.stringify(json, null, 2),
131
+ );
132
+ }
133
+ return json;
134
+ }
135
+ }
136
+
137
+ module.exports = AstElement;
package/lib/node.js ADDED
@@ -0,0 +1,226 @@
1
+ 'use strict';
2
+
3
+ const {text} = require('../util/string');
4
+
5
+ /** 类似Node */
6
+ class AstNode {
7
+ /** @type {string} */ type;
8
+ /** @type {this[]} */ childNodes = [];
9
+ /** @type {this} */ #parentNode;
10
+
11
+ /** 首位子节点 */
12
+ get firstChild() {
13
+ return this.childNodes[0];
14
+ }
15
+
16
+ /** 末位子节点 */
17
+ get lastChild() {
18
+ return this.childNodes.at(-1);
19
+ }
20
+
21
+ /** 父节点 */
22
+ get parentNode() {
23
+ return this.#parentNode;
24
+ }
25
+
26
+ /**
27
+ * 后一个兄弟节点
28
+ * @complexity `n`
29
+ */
30
+ get nextSibling() {
31
+ const childNodes = this.#parentNode?.childNodes;
32
+ return childNodes && childNodes[childNodes.indexOf(this) + 1];
33
+ }
34
+
35
+ /**
36
+ * 前一个兄弟节点
37
+ * @complexity `n`
38
+ */
39
+ get previousSibling() {
40
+ const childNodes = this.#parentNode?.childNodes;
41
+ return childNodes && childNodes[childNodes.indexOf(this) - 1];
42
+ }
43
+
44
+ /**
45
+ * 是否具有某属性
46
+ * @param {PropertyKey} key 属性键
47
+ */
48
+ hasAttribute(key) {
49
+ const type = typeof key;
50
+ return type === 'string' || type === 'number' || type === 'symbol'
51
+ ? key in this
52
+ : false;
53
+ }
54
+
55
+ /**
56
+ * 获取属性值。除非用于私有属性,否则总是返回字符串。
57
+ * @template {string} T
58
+ * @param {T} key 属性键
59
+ * @returns {TokenAttribute<T>}
60
+ */
61
+ getAttribute(key) {
62
+ return this.hasAttribute(key) ? String(this[key]) : undefined;
63
+ }
64
+
65
+ /**
66
+ * 设置属性
67
+ * @template {string} T
68
+ * @param {T} key 属性键
69
+ * @param {TokenAttribute<T>} value 属性值
70
+ */
71
+ setAttribute(key, value) {
72
+ if (key === 'parentNode') {
73
+ this.#parentNode = value;
74
+ } else {
75
+ this[key] = value;
76
+ }
77
+ return this;
78
+ }
79
+
80
+ /**
81
+ * 可见部分
82
+ * @param {string} separator 子节点间的连接符
83
+ * @returns {string}
84
+ * @complexity `n`
85
+ */
86
+ text(separator = '') {
87
+ return text(this.childNodes, separator);
88
+ }
89
+
90
+ /**
91
+ * 移除子节点
92
+ * @param {number} i 移除位置
93
+ */
94
+ removeAt(i) {
95
+ const {childNodes} = this,
96
+ [node] = childNodes.splice(i, 1);
97
+ return node;
98
+ }
99
+
100
+ /**
101
+ * 插入子节点
102
+ * @template {this} T
103
+ * @param {T} node 待插入的子节点
104
+ * @param {number} i 插入位置
105
+ * @complexity `n`
106
+ */
107
+ insertAt(node, i = this.childNodes.length) {
108
+ const {childNodes} = this,
109
+ j = -1;
110
+ if (j === -1) {
111
+ node.setAttribute('parentNode', this);
112
+ }
113
+ childNodes.splice(i, 0, node);
114
+ return node;
115
+ }
116
+
117
+ /**
118
+ * 合并相邻的文本子节点
119
+ * @complexity `n`
120
+ */
121
+ normalize() {
122
+ const AstText = require('./text');
123
+ const /** @type {{childNodes: AstText[]}} */ {childNodes} = this;
124
+ for (let i = childNodes.length - 1; i >= 0; i--) {
125
+ const {type, data} = childNodes[i];
126
+ if (this.getGaps(i - 1)) {
127
+ //
128
+ } else if (data === '') {
129
+ childNodes.splice(i, 1);
130
+ } else if (type === 'text' && childNodes[i - 1]?.type === 'text') {
131
+ childNodes[i - 1].setAttribute('data', childNodes[i - 1].data + data);
132
+ childNodes.splice(i, 1);
133
+ }
134
+ }
135
+ }
136
+
137
+ /** 获取根节点 */
138
+ getRootNode() {
139
+ let {parentNode} = this;
140
+ while (parentNode?.parentNode) {
141
+ ({parentNode} = parentNode);
142
+ }
143
+ return parentNode ?? this;
144
+ }
145
+
146
+ /**
147
+ * 将字符位置转换为行列号
148
+ * @param {number} index 字符位置
149
+ * @complexity `n`
150
+ */
151
+ posFromIndex(index) {
152
+ const str = String(this);
153
+ if (index >= -str.length && index <= str.length) {
154
+ const lines = str.slice(0, index).split('\n');
155
+ return {top: lines.length - 1, left: lines.at(-1).length};
156
+ }
157
+ return undefined;
158
+ }
159
+
160
+ /**
161
+ * 获取行数和最后一行的列数
162
+ * @complexity `n`
163
+ */
164
+ #getDimension() {
165
+ const lines = String(this).split('\n');
166
+ return {height: lines.length, width: lines.at(-1).length};
167
+ }
168
+
169
+ /** 第一个子节点前的间距 */
170
+ getPadding() {
171
+ return 0;
172
+ }
173
+
174
+ /** 子节点间距 */
175
+ getGaps() {
176
+ return 0;
177
+ }
178
+
179
+ /**
180
+ * 获取当前节点的相对字符位置,或其第`j`个子节点的相对字符位置
181
+ * @param {number|undefined} j 子节点序号
182
+ * @complexity `n`
183
+ */
184
+ getRelativeIndex(j) {
185
+ let /** @type {this[]} */ childNodes;
186
+
187
+ /**
188
+ * 获取子节点相对于父节点的字符位置,使用前需要先给`childNodes`赋值
189
+ * @param {number} end 子节点序号
190
+ * @param {this} parent 父节点
191
+ * @returns {number}
192
+ */
193
+ const getIndex = (end, parent) => childNodes.slice(0, end).reduce(
194
+ (acc, cur, i) => acc + String(cur).length + parent.getGaps(i),
195
+ 0,
196
+ ) + parent.getPadding();
197
+ if (j === undefined) {
198
+ const {parentNode} = this;
199
+ if (parentNode) {
200
+ ({childNodes} = parentNode);
201
+ return getIndex(childNodes.indexOf(this), parentNode);
202
+ }
203
+ return 0;
204
+ }
205
+ ({childNodes} = this);
206
+ return getIndex(j, this);
207
+ }
208
+
209
+ /**
210
+ * 行数
211
+ * @complexity `n`
212
+ */
213
+ get offsetHeight() {
214
+ return this.#getDimension().height;
215
+ }
216
+
217
+ /**
218
+ * 最后一行的列数
219
+ * @complexity `n`
220
+ */
221
+ get offsetWidth() {
222
+ return this.#getDimension().width;
223
+ }
224
+ }
225
+
226
+ module.exports = AstNode;
package/lib/text.js ADDED
@@ -0,0 +1,123 @@
1
+ 'use strict';
2
+
3
+ const Parser = require('..'),
4
+ AstNode = require('./node'),
5
+ AstElement = require('./element');
6
+
7
+ const errorSyntax = /https?:|\{+|\}+|\[{2,}|\[(?![^[]*\])|((?:^|\])[^[]*?)\]+|<\s*\/?([a-z]\w*)(?=[\s/>])/giu,
8
+ errorSyntaxUrl = /\{+|\}+|\[{2,}|\[(?![^[]*\])|((?:^|\])[^[]*?)\]+|<\s*\/?([a-z]\w*)(?=[\s/>])/giu;
9
+
10
+ /** 文本节点 */
11
+ class AstText extends AstNode {
12
+ #config;
13
+ type = 'text';
14
+ /** @type {string} */ data;
15
+
16
+ /** @param {string} text 包含文本 */
17
+ constructor(text = '', config = Parser.getConfig()) {
18
+ super();
19
+ this.#config = config;
20
+ this.data = text;
21
+ }
22
+
23
+ /** 输出字符串 */
24
+ toString() {
25
+ return this.data;
26
+ }
27
+
28
+ /** @override */
29
+ text() {
30
+ return this.data;
31
+ }
32
+
33
+ /**
34
+ * Linter
35
+ * @this {AstText & {parentNode: AstElement}}
36
+ * @param {number} start 起始位置
37
+ * @returns {LintError[]}
38
+ */
39
+ lint(start = 0) {
40
+ const {data, parentNode} = this,
41
+ type = parentNode?.type,
42
+ name = parentNode?.name,
43
+ urlAttr = ['itemtype', 'src', 'srcset'].includes(parentNode?.parentNode?.name),
44
+ errorRegex
45
+ = type === 'free-ext-link' || type === 'ext-link-url' || type === 'image-parameter' && name === 'link'
46
+ ? errorSyntaxUrl
47
+ : errorSyntax,
48
+ errors = [];
49
+ if (data.search(errorRegex) !== -1) {
50
+ errorRegex.lastIndex = 0;
51
+ const root = this.getRootNode(),
52
+ {top, left} = root.posFromIndex(start),
53
+ allowedTags = new Set([this.#config.ext, this.#config.html].flat(2));
54
+ for (let mt = errorRegex.exec(data); mt; mt = errorRegex.exec(data)) {
55
+ const [, prefix, tag] = mt;
56
+ let {0: error, index} = mt;
57
+ if (prefix) {
58
+ index += prefix.length;
59
+ error = error.slice(prefix.length);
60
+ }
61
+ const startIndex = start + index,
62
+ lines = data.slice(0, index).split('\n'),
63
+ startLine = lines.length + top - 1,
64
+ line = lines.at(-1),
65
+ startCol = lines.length > 1 ? line.length : left + line.length,
66
+ {0: char, length} = error,
67
+ endIndex = startIndex + length,
68
+ end = char === '}' || char === ']' ? endIndex : startIndex + (char === 'h' ? 49 : 50);
69
+ let severity = length > 1 ? 'error' : 'warning';
70
+ if (char === 'h') {
71
+ switch (type) {
72
+ case 'ext-link-text':
73
+ severity = 'warning';
74
+ break;
75
+ case 'attr-value':
76
+ if (urlAttr) {
77
+ continue;
78
+ }
79
+ break;
80
+ case 'ext-inner':
81
+ if (name === 'sm2' || name === 'flashmp3') {
82
+ continue;
83
+ }
84
+ // no default
85
+ }
86
+ } else if (char === '<' && !allowedTags.has(tag.toLowerCase())) {
87
+ continue;
88
+ }
89
+ errors.push({
90
+ message: `孤立的"${char === 'h' ? error : char}"`,
91
+ severity,
92
+ startIndex,
93
+ endIndex,
94
+ startLine,
95
+ endLine: startLine,
96
+ startCol,
97
+ endCol: startCol + length,
98
+ excerpt: String(root).slice(Math.max(0, end - 50), end),
99
+ });
100
+ }
101
+ }
102
+ return errors;
103
+ }
104
+
105
+ /**
106
+ * 修改内容
107
+ * @param {string} text 新内容
108
+ */
109
+ #setData(text) {
110
+ text = String(text);
111
+ this.setAttribute('data', text);
112
+ }
113
+
114
+ /**
115
+ * 替换字符串
116
+ * @param {string} text 替换的字符串
117
+ */
118
+ replaceData(text = '') {
119
+ this.#setData(text);
120
+ }
121
+ }
122
+
123
+ module.exports = AstText;
package/lib/title.js ADDED
@@ -0,0 +1,60 @@
1
+ 'use strict';
2
+
3
+ const Parser = require('..');
4
+
5
+ /** MediaWiki页面标题对象 */
6
+ class Title {
7
+ valid = true;
8
+ ns = 0;
9
+ fragment = '';
10
+ encoded = false;
11
+ interwiki = '';
12
+
13
+ /**
14
+ * @param {string} title 标题(含或不含命名空间前缀)
15
+ * @param {number} defaultNs 命名空间
16
+ * @param {boolean} decode 是否需要解码
17
+ * @param {boolean} selfLink 是否允许selfLink
18
+ */
19
+ constructor(title, defaultNs = 0, config = Parser.getConfig(), decode = false, selfLink = false) {
20
+ const {namespaces, nsid} = config;
21
+ let namespace = namespaces[defaultNs];
22
+ if (decode && title.includes('%')) {
23
+ try {
24
+ const encoded = /%(?!5[bd]|7[b-d])[\da-f]{2}/iu.test(title);
25
+ title = decodeURIComponent(title);
26
+ this.encoded = encoded;
27
+ } catch {}
28
+ }
29
+ title = title.replaceAll('_', ' ').trim();
30
+ if (title[0] === ':') {
31
+ namespace = '';
32
+ title = title.slice(1).trim();
33
+ }
34
+ const iw = defaultNs ? undefined : Parser.isInterwiki(title, config);
35
+ if (iw) {
36
+ this.interwiki = iw[1].toLowerCase();
37
+ title = title.slice(iw[0].length);
38
+ }
39
+ const m = title.split(':');
40
+ if (m.length > 1) {
41
+ const id = namespaces[nsid[m[0].trim().toLowerCase()]];
42
+ if (id !== undefined) {
43
+ namespace = id;
44
+ title = m.slice(1).join(':').trim();
45
+ }
46
+ }
47
+ this.ns = nsid[namespace.toLowerCase()];
48
+ const i = title.indexOf('#');
49
+ let fragment = '';
50
+ if (i !== -1) {
51
+ fragment = title.slice(i + 1).trimEnd();
52
+ title = title.slice(0, i).trim();
53
+ }
54
+ this.valid = Boolean(title || selfLink && fragment || this.interwiki)
55
+ && !/\0\d+[eh!+-]\x7F|[<>[\]{}|]|%[\da-f]{2}/iu.test(title);
56
+ this.fragment = fragment;
57
+ }
58
+ }
59
+
60
+ module.exports = Title;
@@ -0,0 +1,18 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * 解析后不可见的类
5
+ * @template T
6
+ * @param {T} Constructor 基类
7
+ * @returns {T}
8
+ */
9
+ const hidden = Constructor => class extends Constructor {
10
+ static hidden = true;
11
+
12
+ /** 没有可见部分 */
13
+ text() { // eslint-disable-line class-methods-use-this
14
+ return '';
15
+ }
16
+ };
17
+
18
+ module.exports = hidden;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wikiparser-node",
3
- "version": "0.7.1-b",
3
+ "version": "0.8.0-m",
4
4
  "description": "A Node.js parser for MediaWiki markup with AST",
5
5
  "keywords": [
6
6
  "mediawiki",
@@ -14,29 +14,27 @@
14
14
  "license": "GPL-3.0",
15
15
  "author": "Bhsd",
16
16
  "files": [
17
- "/bundle/bundle.min.js",
18
- "/extensions/",
19
- "!/extensions/gh-page.*",
20
- "!/extensions/.eslintrc.json"
17
+ "/index.js",
18
+ "/parser/",
19
+ "/util/",
20
+ "/lib/",
21
+ "/src/",
22
+ "/config/",
23
+ "/mixin/"
21
24
  ],
22
- "browser": "/bundle/bundle.min.js",
23
25
  "repository": {
24
26
  "type": "git",
25
27
  "url": "git+https://github.com/bhsd-harry/wikiparser-node.git"
26
28
  },
27
29
  "scripts": {
28
- "test": "rm bundle/*.js; webpack && eslint .",
30
+ "test": "eslint .",
29
31
  "real": "node test/real.js",
30
32
  "single": "node test/single.js"
31
33
  },
32
34
  "devDependencies": {
33
35
  "@types/node": "^17.0.23",
34
- "webpack-cli": "^4.10.0",
35
- "webpack": "^5.73.0",
36
- "esbuild-loader": "^2.20.0",
37
36
  "eslint": "^8.30.0",
38
37
  "eslint-plugin-n": "^15.6.0",
39
- "eslint-plugin-es-x": "^5.4.0",
40
38
  "eslint-plugin-regexp": "^1.11.0",
41
39
  "eslint-plugin-unicorn": "^45.0.2",
42
40
  "eslint-plugin-jsdoc": "^1.0.0",