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