wikiparser-node 0.3.1 → 0.5.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.
Files changed (80) hide show
  1. package/README.md +1 -1
  2. package/config/default.json +13 -17
  3. package/config/llwiki.json +11 -79
  4. package/config/moegirl.json +7 -1
  5. package/config/zhwiki.json +1269 -0
  6. package/index.js +130 -97
  7. package/lib/element.js +410 -518
  8. package/lib/node.js +493 -115
  9. package/lib/ranges.js +27 -19
  10. package/lib/text.js +175 -0
  11. package/lib/title.js +14 -6
  12. package/mixin/attributeParent.js +70 -24
  13. package/mixin/fixedToken.js +18 -10
  14. package/mixin/hidden.js +6 -4
  15. package/mixin/sol.js +39 -12
  16. package/package.json +17 -4
  17. package/parser/brackets.js +18 -18
  18. package/parser/commentAndExt.js +16 -14
  19. package/parser/converter.js +14 -13
  20. package/parser/externalLinks.js +12 -11
  21. package/parser/hrAndDoubleUnderscore.js +24 -14
  22. package/parser/html.js +8 -7
  23. package/parser/links.js +13 -13
  24. package/parser/list.js +12 -11
  25. package/parser/magicLinks.js +11 -10
  26. package/parser/quotes.js +6 -5
  27. package/parser/selector.js +175 -0
  28. package/parser/table.js +31 -24
  29. package/src/arg.js +91 -43
  30. package/src/atom/hidden.js +5 -2
  31. package/src/atom/index.js +17 -9
  32. package/src/attribute.js +210 -101
  33. package/src/converter.js +78 -43
  34. package/src/converterFlags.js +104 -45
  35. package/src/converterRule.js +136 -78
  36. package/src/extLink.js +81 -27
  37. package/src/gallery.js +63 -20
  38. package/src/heading.js +58 -20
  39. package/src/html.js +138 -48
  40. package/src/imageParameter.js +93 -58
  41. package/src/index.js +314 -186
  42. package/src/link/category.js +22 -54
  43. package/src/link/file.js +83 -32
  44. package/src/link/galleryImage.js +21 -7
  45. package/src/link/index.js +170 -81
  46. package/src/magicLink.js +64 -14
  47. package/src/nowiki/comment.js +36 -10
  48. package/src/nowiki/dd.js +37 -22
  49. package/src/nowiki/doubleUnderscore.js +21 -7
  50. package/src/nowiki/hr.js +11 -7
  51. package/src/nowiki/index.js +16 -9
  52. package/src/nowiki/list.js +2 -2
  53. package/src/nowiki/noinclude.js +8 -4
  54. package/src/nowiki/quote.js +38 -7
  55. package/src/onlyinclude.js +24 -7
  56. package/src/parameter.js +102 -62
  57. package/src/syntax.js +23 -20
  58. package/src/table/index.js +282 -174
  59. package/src/table/td.js +112 -61
  60. package/src/table/tr.js +135 -74
  61. package/src/tagPair/ext.js +30 -23
  62. package/src/tagPair/include.js +26 -11
  63. package/src/tagPair/index.js +72 -29
  64. package/src/transclude.js +235 -127
  65. package/tool/index.js +42 -32
  66. package/util/debug.js +21 -18
  67. package/util/diff.js +76 -0
  68. package/util/lint.js +40 -0
  69. package/util/string.js +56 -26
  70. package/.eslintrc.json +0 -319
  71. package/errors/README +0 -1
  72. package/jsconfig.json +0 -7
  73. package/printed/README +0 -1
  74. package/typings/element.d.ts +0 -28
  75. package/typings/index.d.ts +0 -52
  76. package/typings/node.d.ts +0 -23
  77. package/typings/parser.d.ts +0 -9
  78. package/typings/table.d.ts +0 -14
  79. package/typings/token.d.ts +0 -22
  80. package/typings/tool.d.ts +0 -10
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
- const /** @type {Parser} */ Parser = require('../..'),
4
- LinkToken = require('.'),
5
- Token = require('..');
3
+ const Title = require('../../lib/title'),
4
+ Parser = require('../..'),
5
+ LinkToken = require('.');
6
6
 
7
7
  /**
8
8
  * 分类
@@ -10,72 +10,40 @@ const /** @type {Parser} */ Parser = require('../..'),
10
10
  */
11
11
  class CategoryToken extends LinkToken {
12
12
  type = 'category';
13
- sortkey = '';
14
13
 
15
14
  setLangLink = undefined;
16
15
  setFragment = undefined;
17
16
  asSelfLink = undefined;
18
17
  pipeTrick = undefined;
19
18
 
20
- /**
21
- * @param {string} link
22
- * @param {string|undefined} text
23
- * @param {Title} title
24
- * @param {accum} accum
25
- */
26
- constructor(link, text, title, config = Parser.getConfig(), accum = []) {
27
- super(link, text, title, config, accum);
28
- this.seal(['sortkey', 'setFragment', 'asSelfLink', 'pipeTrick']);
29
- }
30
-
31
- afterBuild() {
32
- super.afterBuild();
33
- this.#updateSortkey();
34
- const that = this;
35
- const /** @type {AstListener} */ categoryListener = ({prevTarget}) => {
36
- if (prevTarget?.type === 'link-text') {
37
- that.#updateSortkey();
38
- }
39
- };
40
- this.addEventListener(['remove', 'insert', 'replace', 'text'], categoryListener);
41
- return this;
42
- }
43
-
44
- #updateSortkey() {
45
- this.setAttribute('sortkey', this.children[1]?.text()
46
- ?.replace(/&#(\d+);/g, /** @param {string} p1 */ (_, p1) => String.fromCharCode(Number(p1)))
47
- ?.replace(/&#x([\da-f]+);/gi, /** @param {string} p1 */ (_, p1) => String.fromCharCode(parseInt(p1, 16)))
48
- ?.replaceAll('\n', '') ?? '',
19
+ /** 分类排序关键字 */
20
+ get sortkey() {
21
+ return this.childNodes[1]?.text()?.replaceAll(
22
+ /&#(\d+|x[\da-f]+);|\n/gu,
23
+ /** @param {string} p */
24
+ (_, p) => p ? String.fromCodePoint(p[0] === 'x' ? parseInt(p.slice(1), 16) : Number(p)) : '',
49
25
  );
50
26
  }
51
27
 
52
- /** @param {number} i */
53
- removeAt(i) {
54
- if (i === 1) {
55
- this.setAttribute('sortkey', '');
56
- }
57
- return super.removeAt(i);
28
+ set sortkey(text) {
29
+ this.setSortkey(text);
58
30
  }
59
31
 
60
32
  /**
61
- * @template {string|Token} T
62
- * @param {T} token
63
- * @param {number} i
33
+ * @param {string} link 分类名
34
+ * @param {string|undefined} text 排序关键字
35
+ * @param {Title} title 分类页面标题对象
36
+ * @param {accum} accum
64
37
  */
65
- insertAt(token, i) {
66
- super.insertAt(token, i);
67
- if (i === 1 && !Parser.running) {
68
- this.#updateSortkey();
69
- }
70
- return token;
71
- }
72
-
73
- /** @returns {string} */
74
- text() {
75
- return `[[${this.firstElementChild.text()}]]`;
38
+ constructor(link, text, title, config = Parser.getConfig(), accum = []) {
39
+ super(link, text, title, config, accum);
40
+ this.seal(['setFragment', 'asSelfLink', 'pipeTrick'], true);
76
41
  }
77
42
 
78
- /** @param {string} text */
43
+ /**
44
+ * 设置排序关键字
45
+ * @param {string} text 排序关键字
46
+ */
79
47
  setSortkey(text) {
80
48
  this.setLinkText(text);
81
49
  }
package/src/link/file.js CHANGED
@@ -1,8 +1,10 @@
1
1
  'use strict';
2
2
 
3
- const {explode, noWrap} = require('../../util/string'),
3
+ const Title = require('../../lib/title'),
4
+ {explode, noWrap} = require('../../util/string'),
4
5
  {externalUse} = require('../../util/debug'),
5
- /** @type {Parser} */ Parser = require('../..'),
6
+ {generateForChild} = require('../../util/lint'),
7
+ Parser = require('../..'),
6
8
  LinkToken = require('.'),
7
9
  ImageParameterToken = require('../imageParameter');
8
10
 
@@ -21,18 +23,25 @@ class FileToken extends LinkToken {
21
23
  setLinkText = undefined;
22
24
  pipeTrick = undefined;
23
25
 
26
+ /** 图片链接 */
24
27
  get link() {
25
28
  return this.getArg('link')?.link;
26
29
  }
30
+
27
31
  set link(value) {
28
32
  this.setValue('link', value);
29
33
  }
34
+
35
+ /** 图片大小 */
30
36
  get size() {
31
37
  return this.getArg('width')?.size;
32
38
  }
39
+
40
+ /** 图片宽度 */
33
41
  get width() {
34
42
  return this.size?.width;
35
43
  }
44
+
36
45
  set width(width) {
37
46
  const arg = this.getArg('width');
38
47
  if (arg) {
@@ -41,9 +50,12 @@ class FileToken extends LinkToken {
41
50
  this.setValue('width', width);
42
51
  }
43
52
  }
53
+
54
+ /** 图片高度 */
44
55
  get height() {
45
56
  return this.size?.height;
46
57
  }
58
+
47
59
  set height(height) {
48
60
  const arg = this.getArg('width');
49
61
  if (arg) {
@@ -54,9 +66,9 @@ class FileToken extends LinkToken {
54
66
  }
55
67
 
56
68
  /**
57
- * @param {string} link
58
- * @param {string|undefined} text
59
- * @param {Title} title
69
+ * @param {string} link 文件名
70
+ * @param {string|undefined} text 图片参数
71
+ * @param {Title} title 文件标题对象
60
72
  * @param {accum} accum
61
73
  * @complexity `n`
62
74
  */
@@ -64,11 +76,32 @@ class FileToken extends LinkToken {
64
76
  super(link, undefined, title, config, accum);
65
77
  this.setAttribute('acceptable', {AtomToken: 0, ImageParameterToken: '1:'});
66
78
  this.append(...explode('-{', '}-', '|', text).map(part => new ImageParameterToken(part, config, accum)));
67
- this.seal(['setLangLink', 'setFragment', 'asSelfLink', 'setLinkText', 'pipeTrick']);
79
+ this.seal(['setLangLink', 'setFragment', 'asSelfLink', 'setLinkText', 'pipeTrick'], true);
80
+ }
81
+
82
+ /**
83
+ * @override
84
+ * @param {number} start 起始位置
85
+ */
86
+ lint(start = 0) {
87
+ const errors = super.lint(start),
88
+ frameArgs = this.getFrameArgs(),
89
+ captions = this.getArgs('caption');
90
+ if (frameArgs.length > 1 || captions.size > 1) {
91
+ const rect = this.getRootNode().posFromIndex(start);
92
+ if (frameArgs.length > 1) {
93
+ errors.push(...frameArgs.map(arg => generateForChild(arg, rect, '重复或冲突的图片框架参数')));
94
+ }
95
+ if (captions.size > 1) {
96
+ errors.push(...[...captions].map(arg => generateForChild(arg, rect, '重复的图片说明')));
97
+ }
98
+ }
99
+ return errors;
68
100
  }
69
101
 
70
102
  /**
71
- * @param {number} i
103
+ * @override
104
+ * @param {number} i 移除位置
72
105
  * @complexity `n`
73
106
  */
74
107
  removeAt(i) {
@@ -82,7 +115,9 @@ class FileToken extends LinkToken {
82
115
  }
83
116
 
84
117
  /**
85
- * @param {ImageParameterToken} token
118
+ * @override
119
+ * @param {ImageParameterToken} token 待插入的子节点
120
+ * @param {number} i 插入位置
86
121
  * @complexity `n`
87
122
  */
88
123
  insertAt(token, i = this.childNodes.length) {
@@ -93,12 +128,18 @@ class FileToken extends LinkToken {
93
128
  return super.insertAt(token, i);
94
129
  }
95
130
 
96
- /** @returns {ImageParameterToken[]} */
131
+ /**
132
+ * 获取所有图片参数节点
133
+ * @returns {ImageParameterToken[]}
134
+ */
97
135
  getAllArgs() {
98
136
  return this.childNodes.slice(1);
99
137
  }
100
138
 
101
- /** @complexity `n` */
139
+ /**
140
+ * 获取图片框架属性参数节点
141
+ * @complexity `n`
142
+ */
102
143
  getFrameArgs() {
103
144
  const args = this.getAllArgs()
104
145
  .filter(({name}) => ['manualthumb', 'frameless', 'framed', 'thumbnail'].includes(name));
@@ -109,15 +150,16 @@ class FileToken extends LinkToken {
109
150
  }
110
151
 
111
152
  /**
112
- * @param {string} key
153
+ * 获取指定图片参数
154
+ * @param {string} key 参数名
155
+ * @param {boolean} copy 是否返回备份
113
156
  * @complexity `n`
114
157
  */
115
158
  getArgs(key, copy = true) {
116
159
  if (typeof key !== 'string') {
117
160
  this.typeError('getArgs', 'String');
118
- } else if (!copy && !Parser.debugging && externalUse('getArgs')) {
119
- this.debugOnly('getArgs');
120
161
  }
162
+ copy ||= !Parser.debugging && externalUse('getArgs');
121
163
  let args = this.#args[key];
122
164
  if (!args) {
123
165
  args = new Set(this.getAllArgs().filter(({name}) => key === name));
@@ -127,7 +169,8 @@ class FileToken extends LinkToken {
127
169
  }
128
170
 
129
171
  /**
130
- * @param {string} key
172
+ * 是否具有指定图片参数
173
+ * @param {string} key 参数名
131
174
  * @complexity `n`
132
175
  */
133
176
  hasArg(key) {
@@ -135,15 +178,17 @@ class FileToken extends LinkToken {
135
178
  }
136
179
 
137
180
  /**
138
- * @param {string} key
181
+ * 获取生效的指定图片参数
182
+ * @param {string} key 参数名
139
183
  * @complexity `n`
140
184
  */
141
185
  getArg(key) {
142
- return [...this.getArgs(key, false)].sort((a, b) => a.comparePosition(b)).at(-1);
186
+ return [...this.getArgs(key, false)].sort((a, b) => a.compareDocumentPosition(b)).at(-1);
143
187
  }
144
188
 
145
189
  /**
146
- * @param {string} key
190
+ * 移除指定图片参数
191
+ * @param {string} key 参数名
147
192
  * @complexity `n`
148
193
  */
149
194
  removeArg(key) {
@@ -152,10 +197,13 @@ class FileToken extends LinkToken {
152
197
  }
153
198
  }
154
199
 
155
- /** @complexity `n` */
200
+ /**
201
+ * 获取图片参数名
202
+ * @complexity `n`
203
+ */
156
204
  getKeys() {
157
205
  const args = this.getAllArgs();
158
- if (this.#keys.size === 0 && args.length) {
206
+ if (this.#keys.size === 0 && args.length > 0) {
159
207
  for (const {name} of args) {
160
208
  this.#keys.add(name);
161
209
  }
@@ -164,7 +212,8 @@ class FileToken extends LinkToken {
164
212
  }
165
213
 
166
214
  /**
167
- * @param {string} key
215
+ * 获取指定的图片参数值
216
+ * @param {string} key 参数名
168
217
  * @complexity `n`
169
218
  */
170
219
  getValues(key) {
@@ -172,22 +221,25 @@ class FileToken extends LinkToken {
172
221
  }
173
222
 
174
223
  /**
224
+ * 获取生效的指定图片参数值
175
225
  * @template {string|undefined} T
176
- * @param {T} key
226
+ * @param {T} key 参数名
177
227
  * @returns {T extends undefined ? Object<string, string> : string|true}
178
228
  * @complexity `n`
179
229
  */
180
230
  getValue(key) {
181
- if (key !== undefined) {
182
- return this.getArg(key)?.getValue();
183
- }
184
- return Object.fromEntries(this.getKeys().map(k => [k, this.getValue(k)]));
231
+ return key === undefined
232
+ ? Object.fromEntries(this.getKeys().map(k => [k, this.getValue(k)]))
233
+ : this.getArg(key)?.getValue();
185
234
  }
186
235
 
187
236
  /**
188
- * @param {string} key
189
- * @param {string|boolean} value
237
+ * 设置图片参数
238
+ * @param {string} key 参数名
239
+ * @param {string|boolean} value 参数值
190
240
  * @complexity `n`
241
+ * @throws `RangeError` 未定义的图片参数
242
+ * @throws `SyntaxError` 非法的参数
191
243
  */
192
244
  setValue(key, value) {
193
245
  if (typeof key !== 'string') {
@@ -220,13 +272,12 @@ class FileToken extends LinkToken {
220
272
  }
221
273
  const wikitext = `[[File:F|${syntax ? syntax.replace('$1', value) : value}]]`,
222
274
  root = Parser.parse(wikitext, this.getAttribute('include'), 6, config),
223
- {childNodes: {length}, firstElementChild} = root;
224
- if (length !== 1 || !firstElementChild?.matches('file#File:F')
225
- || firstElementChild.childNodes.length !== 2 || firstElementChild.lastElementChild.name !== key
226
- ) {
275
+ {childNodes: {length}, firstChild: file} = root,
276
+ {name, type, childNodes: {length: fileLength}, lastChild: imageParameter} = file;
277
+ if (length !== 1 || type !== 'file' || name !== 'File:F' || fileLength !== 2 || imageParameter.name !== key) {
227
278
  throw new SyntaxError(`非法的 ${key} 参数:${noWrap(value)}`);
228
279
  }
229
- this.appendChild(firstElementChild.lastChild);
280
+ this.appendChild(imageParameter);
230
281
  }
231
282
  }
232
283
 
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
- const /** @type {Parser} */ Parser = require('../..'),
3
+ const Title = require('../../lib/title'),
4
+ Parser = require('../..'),
4
5
  Token = require('..'),
5
6
  FileToken = require('./file');
6
7
 
@@ -16,9 +17,9 @@ class GalleryImageToken extends FileToken {
16
17
  height = undefined;
17
18
 
18
19
  /**
19
- * @param {string} link
20
- * @param {string|undefined} text
21
- * @param {Title} title
20
+ * @param {string} link 图片文件名
21
+ * @param {string|undefined} text 图片参数
22
+ * @param {Title} title 图片文件标题对象
22
23
  * @param {accum} accum
23
24
  */
24
25
  constructor(link, text, title, config = Parser.getConfig(), accum = []) {
@@ -26,21 +27,34 @@ class GalleryImageToken extends FileToken {
26
27
  if (text !== undefined) {
27
28
  token = new Token(text, config, true, accum);
28
29
  token.type = 'temp';
29
- token.setAttribute('stage', 1);
30
30
  for (let n = 1; n < Parser.MAX_STAGE; n++) {
31
- token.parseOnce();
31
+ token.getAttribute('parseOnce')();
32
32
  }
33
33
  accum.splice(accum.indexOf(token), 1);
34
34
  }
35
35
  const newConfig = structuredClone(config);
36
36
  newConfig.img = Object.fromEntries(Object.entries(config.img).filter(([, param]) => param !== 'width'));
37
37
  super(link, token?.toString(), title, newConfig, accum);
38
- this.seal(['size', 'width', 'height']);
38
+ this.seal(['size', 'width', 'height'], true);
39
39
  }
40
40
 
41
+ /** @override */
41
42
  getPadding() {
42
43
  return 0;
43
44
  }
45
+
46
+ /**
47
+ * @override
48
+ * @param {string} selector
49
+ */
50
+ toString(selector) {
51
+ return super.toString(selector).replaceAll('\n', ' ');
52
+ }
53
+
54
+ /** @override */
55
+ text() {
56
+ return super.text().replaceAll('\n', ' ');
57
+ }
44
58
  }
45
59
 
46
60
  Parser.classes.GalleryImageToken = __filename;