wikiparser-node 0.11.0 → 1.0.0-beta.1

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 (252) hide show
  1. package/config/.schema.json +26 -0
  2. package/dist/index.d.ts +61 -113
  3. package/dist/index.js +314 -0
  4. package/dist/lib/element.d.ts +122 -108
  5. package/dist/lib/element.js +656 -0
  6. package/dist/lib/node.d.ts +115 -221
  7. package/dist/lib/node.js +473 -0
  8. package/dist/lib/ranges.d.ts +27 -26
  9. package/dist/lib/ranges.js +130 -0
  10. package/dist/lib/text.d.ts +36 -28
  11. package/dist/lib/text.js +215 -0
  12. package/dist/lib/title.d.ts +26 -12
  13. package/dist/lib/title.js +108 -0
  14. package/dist/mixin/attributesParent.js +90 -0
  15. package/dist/mixin/fixed.js +29 -0
  16. package/dist/mixin/hidden.js +19 -0
  17. package/dist/mixin/singleLine.js +23 -0
  18. package/dist/mixin/sol.js +41 -0
  19. package/dist/parser/brackets.js +118 -0
  20. package/dist/parser/commentAndExt.js +48 -0
  21. package/dist/parser/converter.js +31 -0
  22. package/dist/parser/externalLinks.js +22 -0
  23. package/dist/parser/hrAndDoubleUnderscore.js +35 -0
  24. package/dist/parser/html.js +29 -0
  25. package/dist/parser/links.js +86 -0
  26. package/dist/parser/list.js +51 -0
  27. package/dist/parser/magicLinks.js +32 -0
  28. package/dist/parser/quotes.js +57 -0
  29. package/dist/parser/selector.js +158 -0
  30. package/dist/parser/table.js +108 -0
  31. package/dist/src/arg.d.ts +47 -23
  32. package/dist/src/arg.js +196 -0
  33. package/dist/src/atom.d.ts +12 -0
  34. package/dist/src/atom.js +22 -0
  35. package/dist/src/attribute.d.ts +74 -33
  36. package/dist/src/attribute.js +433 -0
  37. package/dist/src/attributes.d.ts +61 -55
  38. package/dist/src/attributes.js +371 -0
  39. package/dist/src/converter.d.ts +45 -71
  40. package/dist/src/converter.js +135 -0
  41. package/dist/src/converterFlags.d.ts +64 -39
  42. package/dist/src/converterFlags.js +235 -0
  43. package/dist/src/converterRule.d.ts +49 -27
  44. package/dist/src/converterRule.js +255 -0
  45. package/dist/src/extLink.d.ts +41 -38
  46. package/dist/src/extLink.js +154 -0
  47. package/dist/src/gallery.d.ts +59 -18
  48. package/dist/src/gallery.js +132 -0
  49. package/dist/src/heading.d.ts +60 -22
  50. package/dist/src/heading.js +135 -0
  51. package/dist/src/hidden.d.ts +20 -0
  52. package/dist/src/hidden.js +24 -0
  53. package/dist/src/html.d.ts +83 -29
  54. package/dist/src/html.js +242 -0
  55. package/dist/src/imageParameter.d.ts +59 -40
  56. package/dist/src/imageParameter.js +251 -0
  57. package/dist/src/imagemap.d.ts +65 -21
  58. package/dist/src/imagemap.js +169 -0
  59. package/dist/src/imagemapLink.d.ts +46 -14
  60. package/dist/src/imagemapLink.js +38 -0
  61. package/dist/src/index.d.ts +71 -105
  62. package/dist/src/index.js +826 -0
  63. package/dist/src/link/base.d.ts +71 -0
  64. package/dist/src/link/base.js +225 -0
  65. package/dist/src/link/category.d.ts +10 -11
  66. package/dist/src/link/category.js +26 -0
  67. package/dist/src/link/file.d.ts +61 -39
  68. package/dist/src/link/file.js +242 -0
  69. package/dist/src/link/galleryImage.d.ts +34 -12
  70. package/dist/src/link/galleryImage.js +98 -0
  71. package/dist/src/link/index.d.ts +25 -63
  72. package/dist/src/link/index.js +136 -0
  73. package/dist/src/magicLink.d.ts +22 -15
  74. package/dist/src/magicLink.js +126 -0
  75. package/dist/src/nested.d.ts +47 -0
  76. package/dist/src/nested.js +84 -0
  77. package/dist/src/nowiki/base.d.ts +39 -0
  78. package/dist/src/nowiki/base.js +29 -0
  79. package/dist/src/nowiki/comment.d.ts +31 -20
  80. package/dist/src/nowiki/comment.js +61 -0
  81. package/dist/src/nowiki/dd.d.ts +17 -11
  82. package/dist/src/nowiki/dd.js +50 -0
  83. package/dist/src/nowiki/doubleUnderscore.d.ts +28 -13
  84. package/dist/src/nowiki/doubleUnderscore.js +45 -0
  85. package/dist/src/nowiki/hr.d.ts +28 -10
  86. package/dist/src/nowiki/hr.js +33 -0
  87. package/dist/src/nowiki/index.d.ts +17 -23
  88. package/dist/src/nowiki/index.js +21 -0
  89. package/dist/src/nowiki/list.d.ts +15 -7
  90. package/dist/src/nowiki/list.js +11 -0
  91. package/dist/src/nowiki/noinclude.d.ts +20 -7
  92. package/dist/src/nowiki/noinclude.js +22 -0
  93. package/dist/src/nowiki/quote.d.ts +25 -10
  94. package/dist/src/nowiki/quote.js +55 -0
  95. package/dist/src/onlyinclude.d.ts +28 -12
  96. package/dist/src/onlyinclude.js +64 -0
  97. package/dist/src/paramTag/index.d.ts +40 -17
  98. package/dist/src/paramTag/index.js +76 -0
  99. package/dist/src/paramTag/inputbox.d.ts +8 -7
  100. package/dist/src/paramTag/inputbox.js +19 -0
  101. package/dist/src/parameter.d.ts +62 -41
  102. package/dist/src/parameter.js +201 -0
  103. package/dist/src/pre.d.ts +32 -0
  104. package/dist/src/pre.js +39 -0
  105. package/dist/src/syntax.d.ts +17 -14
  106. package/dist/src/syntax.js +65 -0
  107. package/dist/src/table/base.d.ts +55 -0
  108. package/dist/src/table/base.js +77 -0
  109. package/dist/src/table/index.d.ts +123 -156
  110. package/dist/src/table/index.js +811 -0
  111. package/dist/src/table/td.d.ts +90 -67
  112. package/dist/src/table/td.js +276 -0
  113. package/dist/src/table/tr.d.ts +30 -85
  114. package/dist/src/table/tr.js +48 -0
  115. package/dist/src/table/trBase.d.ts +72 -0
  116. package/dist/src/table/trBase.js +153 -0
  117. package/dist/src/tagPair/ext.d.ts +47 -11
  118. package/dist/src/tagPair/ext.js +127 -0
  119. package/dist/src/tagPair/include.d.ts +32 -13
  120. package/dist/src/tagPair/include.js +40 -0
  121. package/dist/src/tagPair/index.d.ts +44 -29
  122. package/dist/src/tagPair/index.js +111 -0
  123. package/dist/src/transclude.d.ts +88 -85
  124. package/dist/src/transclude.js +739 -0
  125. package/dist/util/base.js +26 -0
  126. package/dist/util/debug.js +52 -0
  127. package/dist/util/diff.js +69 -0
  128. package/dist/util/lint.js +38 -0
  129. package/dist/util/string.js +103 -0
  130. package/errors/README +1 -0
  131. package/i18n/zh-hans.json +1 -0
  132. package/i18n/zh-hant.json +1 -0
  133. package/package.json +21 -24
  134. package/printed/README +1 -0
  135. package/dist/mixin/attributeParent.d.ts +0 -9
  136. package/dist/mixin/fixedToken.d.ts +0 -8
  137. package/dist/mixin/hidden.d.ts +0 -8
  138. package/dist/mixin/singleLine.d.ts +0 -8
  139. package/dist/mixin/sol.d.ts +0 -8
  140. package/dist/parser/brackets.d.ts +0 -12
  141. package/dist/parser/commentAndExt.d.ts +0 -8
  142. package/dist/parser/converter.d.ts +0 -7
  143. package/dist/parser/externalLinks.d.ts +0 -7
  144. package/dist/parser/hrAndDoubleUnderscore.d.ts +0 -11
  145. package/dist/parser/html.d.ts +0 -7
  146. package/dist/parser/links.d.ts +0 -7
  147. package/dist/parser/list.d.ts +0 -7
  148. package/dist/parser/magicLinks.d.ts +0 -7
  149. package/dist/parser/quotes.d.ts +0 -7
  150. package/dist/parser/selector.d.ts +0 -12
  151. package/dist/parser/table.d.ts +0 -11
  152. package/dist/src/atom/hidden.d.ts +0 -5
  153. package/dist/src/atom/index.d.ts +0 -15
  154. package/dist/src/charinsert.d.ts +0 -32
  155. package/dist/src/hasNowiki/index.d.ts +0 -14
  156. package/dist/src/hasNowiki/pre.d.ts +0 -13
  157. package/dist/src/nested/choose.d.ts +0 -13
  158. package/dist/src/nested/combobox.d.ts +0 -13
  159. package/dist/src/nested/index.d.ts +0 -18
  160. package/dist/src/nested/references.d.ts +0 -13
  161. package/dist/tool/index.d.ts +0 -420
  162. package/dist/util/base.d.ts +0 -10
  163. package/dist/util/debug.d.ts +0 -20
  164. package/dist/util/diff.d.ts +0 -8
  165. package/dist/util/lint.d.ts +0 -28
  166. package/dist/util/string.d.ts +0 -55
  167. package/index.js +0 -333
  168. package/lib/element.js +0 -618
  169. package/lib/node.js +0 -730
  170. package/lib/ranges.js +0 -130
  171. package/lib/text.js +0 -265
  172. package/lib/title.js +0 -83
  173. package/mixin/attributeParent.js +0 -117
  174. package/mixin/fixedToken.js +0 -40
  175. package/mixin/hidden.js +0 -21
  176. package/mixin/singleLine.js +0 -31
  177. package/mixin/sol.js +0 -54
  178. package/parser/brackets.js +0 -128
  179. package/parser/commentAndExt.js +0 -62
  180. package/parser/converter.js +0 -46
  181. package/parser/externalLinks.js +0 -33
  182. package/parser/hrAndDoubleUnderscore.js +0 -49
  183. package/parser/html.js +0 -42
  184. package/parser/links.js +0 -94
  185. package/parser/list.js +0 -59
  186. package/parser/magicLinks.js +0 -41
  187. package/parser/quotes.js +0 -64
  188. package/parser/selector.js +0 -180
  189. package/parser/table.js +0 -114
  190. package/src/arg.js +0 -207
  191. package/src/atom/hidden.js +0 -13
  192. package/src/atom/index.js +0 -43
  193. package/src/attribute.js +0 -472
  194. package/src/attributes.js +0 -453
  195. package/src/charinsert.js +0 -97
  196. package/src/converter.js +0 -176
  197. package/src/converterFlags.js +0 -284
  198. package/src/converterRule.js +0 -256
  199. package/src/extLink.js +0 -180
  200. package/src/gallery.js +0 -149
  201. package/src/hasNowiki/index.js +0 -44
  202. package/src/hasNowiki/pre.js +0 -40
  203. package/src/heading.js +0 -134
  204. package/src/html.js +0 -254
  205. package/src/imageParameter.js +0 -303
  206. package/src/imagemap.js +0 -199
  207. package/src/imagemapLink.js +0 -41
  208. package/src/index.js +0 -938
  209. package/src/link/category.js +0 -44
  210. package/src/link/file.js +0 -287
  211. package/src/link/galleryImage.js +0 -120
  212. package/src/link/index.js +0 -388
  213. package/src/magicLink.js +0 -151
  214. package/src/nested/choose.js +0 -24
  215. package/src/nested/combobox.js +0 -23
  216. package/src/nested/index.js +0 -96
  217. package/src/nested/references.js +0 -23
  218. package/src/nowiki/comment.js +0 -71
  219. package/src/nowiki/dd.js +0 -59
  220. package/src/nowiki/doubleUnderscore.js +0 -56
  221. package/src/nowiki/hr.js +0 -41
  222. package/src/nowiki/index.js +0 -56
  223. package/src/nowiki/list.js +0 -16
  224. package/src/nowiki/noinclude.js +0 -28
  225. package/src/nowiki/quote.js +0 -69
  226. package/src/onlyinclude.js +0 -64
  227. package/src/paramTag/index.js +0 -89
  228. package/src/paramTag/inputbox.js +0 -35
  229. package/src/parameter.js +0 -239
  230. package/src/syntax.js +0 -91
  231. package/src/table/index.js +0 -985
  232. package/src/table/td.js +0 -343
  233. package/src/table/tr.js +0 -319
  234. package/src/tagPair/ext.js +0 -146
  235. package/src/tagPair/include.js +0 -50
  236. package/src/tagPair/index.js +0 -131
  237. package/src/transclude.js +0 -843
  238. package/tool/index.js +0 -1209
  239. package/typings/api.d.ts +0 -9
  240. package/typings/array.d.ts +0 -29
  241. package/typings/event.d.ts +0 -22
  242. package/typings/index.d.ts +0 -118
  243. package/typings/node.d.ts +0 -35
  244. package/typings/parser.d.ts +0 -12
  245. package/typings/table.d.ts +0 -10
  246. package/typings/token.d.ts +0 -31
  247. package/typings/tool.d.ts +0 -6
  248. package/util/base.js +0 -17
  249. package/util/debug.js +0 -73
  250. package/util/diff.js +0 -76
  251. package/util/lint.js +0 -57
  252. package/util/string.js +0 -126
@@ -0,0 +1,473 @@
1
+ "use strict";
2
+ const debug_1 = require("../util/debug");
3
+ const assert = require("assert/strict");
4
+ const EventEmitter = require("events");
5
+ const Parser = require("../index");
6
+ /** 类似Node */
7
+ class AstNode {
8
+ /** @browser */
9
+ type;
10
+ /** @browser */
11
+ childNodes = [];
12
+ /** @browser */
13
+ #parentNode;
14
+ #optional = new Set();
15
+ #events = new EventEmitter();
16
+ /**
17
+ * 首位子节点
18
+ * @browser
19
+ */
20
+ get firstChild() {
21
+ return this.childNodes[0];
22
+ }
23
+ /**
24
+ * 末位子节点
25
+ * @browser
26
+ */
27
+ get lastChild() {
28
+ return this.childNodes.at(-1);
29
+ }
30
+ /**
31
+ * 父节点
32
+ * @browser
33
+ */
34
+ get parentNode() {
35
+ return this.#parentNode;
36
+ }
37
+ /**
38
+ * 后一个兄弟节点
39
+ * @browser
40
+ */
41
+ get nextSibling() {
42
+ const childNodes = this.#parentNode?.childNodes;
43
+ return childNodes && childNodes[childNodes.indexOf(this) + 1];
44
+ }
45
+ /**
46
+ * 前一个兄弟节点
47
+ * @browser
48
+ */
49
+ get previousSibling() {
50
+ const childNodes = this.#parentNode?.childNodes;
51
+ return childNodes && childNodes[childNodes.indexOf(this) - 1];
52
+ }
53
+ /**
54
+ * 行数
55
+ * @browser
56
+ */
57
+ get offsetHeight() {
58
+ return this.#getDimension().height;
59
+ }
60
+ /**
61
+ * 最后一行的列数
62
+ * @browser
63
+ */
64
+ get offsetWidth() {
65
+ return this.#getDimension().width;
66
+ }
67
+ /** 后一个非文本兄弟节点 */
68
+ get nextElementSibling() {
69
+ const childNodes = this.#parentNode?.childNodes, i = childNodes?.indexOf(this);
70
+ return childNodes?.slice(i + 1)?.find(({ type }) => type !== 'text');
71
+ }
72
+ /** 前一个非文本兄弟节点 */
73
+ get previousElementSibling() {
74
+ const childNodes = this.#parentNode?.childNodes, i = childNodes?.indexOf(this);
75
+ return childNodes?.slice(0, i)?.findLast(({ type }) => type !== 'text');
76
+ }
77
+ /** 是否具有根节点 */
78
+ get isConnected() {
79
+ return this.getRootNode().type === 'root';
80
+ }
81
+ /** 不是自身的根节点 */
82
+ get ownerDocument() {
83
+ const root = this.getRootNode();
84
+ return root.type === 'root' && root !== this ? root : undefined;
85
+ }
86
+ /** 后方是否还有其他节点(不含后代) */
87
+ get eof() {
88
+ if (this.type === 'root') {
89
+ return true;
90
+ }
91
+ let { nextSibling } = this;
92
+ while (nextSibling?.type === 'text' && String(nextSibling).trim() === '') {
93
+ ({ nextSibling } = nextSibling);
94
+ }
95
+ return nextSibling === undefined && this.parentNode?.eof;
96
+ }
97
+ /** 相对于父容器的行号 */
98
+ get offsetTop() {
99
+ return this.#getPosition().top;
100
+ }
101
+ /** 相对于父容器的列号 */
102
+ get offsetLeft() {
103
+ return this.#getPosition().left;
104
+ }
105
+ /** 位置、大小和padding */
106
+ get style() {
107
+ return { ...this.#getPosition(), ...this.#getDimension(), padding: this.getPadding() };
108
+ }
109
+ /** @private */
110
+ get fixed() {
111
+ return 'fixed' in this.constructor;
112
+ }
113
+ constructor() {
114
+ Object.defineProperty(this, 'childNodes', { writable: false });
115
+ Object.freeze(this.childNodes);
116
+ }
117
+ /** @private */
118
+ hasAttribute(key) {
119
+ return typeof key === 'string' ? key in this : this.typeError('hasAttribute', 'String');
120
+ }
121
+ /** @private */
122
+ getAttribute(key) {
123
+ if (key === 'optional') {
124
+ return new Set(this.#optional);
125
+ }
126
+ return this.hasAttribute(key)
127
+ ? String(this[key])
128
+ : undefined;
129
+ }
130
+ /** @private */
131
+ setAttribute(key, value) {
132
+ if (key === 'parentNode') {
133
+ this.#parentNode = value;
134
+ }
135
+ else if (Object.hasOwn(this, key)) {
136
+ const descriptor = Object.getOwnPropertyDescriptor(this, key);
137
+ if (this.#optional.has(key)) {
138
+ descriptor.enumerable = Boolean(value);
139
+ }
140
+ const oldValue = this[key], frozen = oldValue !== null && typeof oldValue === 'object' && Object.isFrozen(oldValue);
141
+ Object.defineProperty(this, key, { ...descriptor, value });
142
+ if (frozen && typeof value === 'object') {
143
+ Object.freeze(value);
144
+ }
145
+ }
146
+ else {
147
+ this[key] = value;
148
+ }
149
+ return this;
150
+ }
151
+ /**
152
+ * 获取根节点
153
+ * @browser
154
+ */
155
+ getRootNode() {
156
+ let { parentNode } = this;
157
+ while (parentNode?.parentNode) {
158
+ ({ parentNode } = parentNode);
159
+ }
160
+ return parentNode ?? this;
161
+ }
162
+ /**
163
+ * 将字符位置转换为行列号
164
+ * @browser
165
+ * @param index 字符位置
166
+ */
167
+ posFromIndex(index) {
168
+ if (!Number.isInteger(index)) {
169
+ this.typeError('posFromIndex', 'Number');
170
+ }
171
+ const str = String(this);
172
+ if (index >= -str.length && index <= str.length) {
173
+ const lines = str.slice(0, index).split('\n');
174
+ return { top: lines.length - 1, left: lines.at(-1).length };
175
+ }
176
+ return undefined;
177
+ }
178
+ /**
179
+ * 获取行数和最后一行的列数
180
+ * @browser
181
+ */
182
+ #getDimension() {
183
+ const lines = String(this).split('\n');
184
+ return { height: lines.length, width: lines.at(-1).length };
185
+ }
186
+ /** @private */
187
+ getPadding() {
188
+ return 0;
189
+ }
190
+ /** @private */
191
+ getGaps(i) {
192
+ return 0;
193
+ }
194
+ /**
195
+ * 获取当前节点的相对字符位置,或其第`j`个子节点的相对字符位置
196
+ * @browser
197
+ * @param j 子节点序号
198
+ */
199
+ getRelativeIndex(j) {
200
+ let childNodes;
201
+ /**
202
+ * 获取子节点相对于父节点的字符位置,使用前需要先给`childNodes`赋值
203
+ * @param end 子节点序号
204
+ * @param parent 父节点
205
+ */
206
+ const getIndex = (end, parent) => childNodes.slice(0, end).reduce((acc, cur, i) => acc + String(cur).length + parent.getGaps(i), 0)
207
+ + parent.getPadding();
208
+ if (j === undefined) {
209
+ const { parentNode } = this;
210
+ if (parentNode) {
211
+ ({ childNodes } = parentNode);
212
+ return getIndex(childNodes.indexOf(this), parentNode);
213
+ }
214
+ return 0;
215
+ }
216
+ this.verifyChild(j, 1);
217
+ ({ childNodes } = this);
218
+ return getIndex(j, this);
219
+ }
220
+ /**
221
+ * 获取当前节点的绝对位置
222
+ * @browser
223
+ */
224
+ getAbsoluteIndex() {
225
+ const { parentNode } = this;
226
+ return parentNode ? parentNode.getAbsoluteIndex() + this.getRelativeIndex() : 0;
227
+ }
228
+ /** @private */
229
+ typeError(method, ...types) {
230
+ return (0, debug_1.typeError)(this.constructor, method, ...types);
231
+ }
232
+ /** @private */
233
+ seal(key) {
234
+ this.#optional.add(key);
235
+ Object.defineProperty(this, key, { writable: false, enumerable: Boolean(this[key]), configurable: true });
236
+ }
237
+ /**
238
+ * 是否是全同节点
239
+ * @param node 待比较的节点
240
+ * @throws `assert.AssertionError`
241
+ */
242
+ isEqualNode(node) {
243
+ try {
244
+ assert.deepStrictEqual(this, node);
245
+ }
246
+ catch (e) {
247
+ if (e instanceof assert.AssertionError) {
248
+ return false;
249
+ }
250
+ throw e;
251
+ }
252
+ return true;
253
+ }
254
+ /**
255
+ * 在当前节点前后插入兄弟节点
256
+ * @param nodes 插入节点
257
+ * @param offset 插入的相对位置
258
+ * @throws `Error` 不存在父节点
259
+ */
260
+ #insertAdjacent(nodes, offset) {
261
+ const { parentNode } = this;
262
+ if (!parentNode) {
263
+ throw new Error('不存在父节点!');
264
+ }
265
+ const i = parentNode.childNodes.indexOf(this) + offset;
266
+ for (let j = 0; j < nodes.length; j++) {
267
+ parentNode.insertAt(nodes[j], i + j);
268
+ }
269
+ }
270
+ /**
271
+ * 在后方批量插入兄弟节点
272
+ * @param nodes 插入节点
273
+ */
274
+ after(...nodes) {
275
+ this.#insertAdjacent(nodes, 1);
276
+ }
277
+ /**
278
+ * 在前方批量插入兄弟节点
279
+ * @param nodes 插入节点
280
+ */
281
+ before(...nodes) {
282
+ this.#insertAdjacent(nodes, 0);
283
+ }
284
+ /**
285
+ * 移除当前节点
286
+ * @throws `Error` 不存在父节点
287
+ */
288
+ remove() {
289
+ const { parentNode } = this;
290
+ if (!parentNode) {
291
+ throw new Error('不存在父节点!');
292
+ }
293
+ parentNode.removeChild(this);
294
+ }
295
+ /**
296
+ * 将当前节点批量替换为新的节点
297
+ * @param nodes 插入节点
298
+ */
299
+ replaceWith(...nodes) {
300
+ this.after(...nodes);
301
+ this.remove();
302
+ }
303
+ /**
304
+ * 是自身或后代节点
305
+ * @param node 待检测节点
306
+ */
307
+ contains(node) {
308
+ return node instanceof AstNode
309
+ ? node === this || this.childNodes.some(child => child.contains(node))
310
+ : this.typeError('contains', 'AstNode');
311
+ }
312
+ /** @private */
313
+ verifyChild(i, addition = 0) {
314
+ if (!Number.isInteger(i)) {
315
+ this.typeError('verifyChild', 'Number');
316
+ }
317
+ const { childNodes: { length } } = this;
318
+ if (i < -length || i >= length + addition) {
319
+ throw new RangeError(`不存在第 ${i} 个子节点!`);
320
+ }
321
+ }
322
+ /**
323
+ * 添加事件监听
324
+ * @param types 事件类型
325
+ * @param listener 监听函数
326
+ * @param options 选项
327
+ * @param options.once 仅执行一次
328
+ */
329
+ addEventListener(types, listener, options) {
330
+ if (Array.isArray(types)) {
331
+ for (const type of types) {
332
+ this.addEventListener(type, listener, options);
333
+ }
334
+ }
335
+ else if (typeof types === 'string' && typeof listener === 'function') {
336
+ this.#events[options?.once ? 'once' : 'on'](types, listener);
337
+ }
338
+ else {
339
+ this.typeError('addEventListener', 'String', 'Function');
340
+ }
341
+ }
342
+ /**
343
+ * 移除事件监听
344
+ * @param types 事件类型
345
+ * @param listener 监听函数
346
+ */
347
+ removeEventListener(types, listener) {
348
+ if (Array.isArray(types)) {
349
+ for (const type of types) {
350
+ this.removeEventListener(type, listener);
351
+ }
352
+ }
353
+ else if (typeof types === 'string' && typeof listener === 'function') {
354
+ this.#events.off(types, listener);
355
+ }
356
+ else {
357
+ this.typeError('removeEventListener', 'String', 'Function');
358
+ }
359
+ }
360
+ /**
361
+ * 移除事件的所有监听
362
+ * @param types 事件类型
363
+ */
364
+ removeAllEventListeners(types) {
365
+ if (Array.isArray(types)) {
366
+ for (const type of types) {
367
+ this.removeAllEventListeners(type);
368
+ }
369
+ }
370
+ else if (types === undefined || typeof types === 'string') {
371
+ this.#events.removeAllListeners(types);
372
+ }
373
+ else {
374
+ this.typeError('removeAllEventListeners', 'String');
375
+ }
376
+ }
377
+ /**
378
+ * 列举事件监听
379
+ * @param type 事件类型
380
+ */
381
+ listEventListeners(type) {
382
+ return typeof type === 'string' ? this.#events.listeners(type) : this.typeError('listEventListeners', 'String');
383
+ }
384
+ /**
385
+ * 触发事件
386
+ * @param e 事件对象
387
+ * @param data 事件数据
388
+ */
389
+ dispatchEvent(e, data) {
390
+ if (!(e instanceof Event)) {
391
+ this.typeError('dispatchEvent', 'Event');
392
+ }
393
+ else if (!e.target) { // 初始化
394
+ Object.defineProperty(e, 'target', { value: this, enumerable: true });
395
+ /** 终止冒泡 */
396
+ e.stopPropagation = function () {
397
+ Object.defineProperty(this, 'bubbles', { value: false });
398
+ };
399
+ }
400
+ Object.defineProperties(e, {
401
+ prevTarget: { value: e.currentTarget, enumerable: true, configurable: true },
402
+ currentTarget: { value: this, enumerable: true, configurable: true },
403
+ });
404
+ this.#events.emit(e.type, e, data);
405
+ if (e.bubbles && this.parentNode) {
406
+ this.parentNode.dispatchEvent(e, data);
407
+ }
408
+ }
409
+ /** 获取所有祖先节点 */
410
+ getAncestors() {
411
+ const ancestors = [];
412
+ let { parentNode } = this;
413
+ while (parentNode) {
414
+ ancestors.push(parentNode);
415
+ ({ parentNode } = parentNode);
416
+ }
417
+ return ancestors;
418
+ }
419
+ /**
420
+ * 比较和另一个节点的相对位置
421
+ * @param other 待比较的节点
422
+ * @throws `Error` 不在同一个语法树
423
+ */
424
+ compareDocumentPosition(other) {
425
+ if (!(other instanceof AstNode)) {
426
+ this.typeError('compareDocumentPosition', 'AstNode');
427
+ }
428
+ else if (this === other) {
429
+ return 0;
430
+ }
431
+ else if (this.contains(other)) {
432
+ return -1;
433
+ }
434
+ else if (other.contains(this)) {
435
+ return 1;
436
+ }
437
+ else if (this.getRootNode() !== other.getRootNode()) {
438
+ throw new Error('不在同一个语法树!');
439
+ }
440
+ const aAncestors = [...this.getAncestors().reverse(), this], bAncestors = [...other.getAncestors().reverse(), other], depth = aAncestors.findIndex((ancestor, i) => bAncestors[i] !== ancestor), commonAncestor = aAncestors[depth - 1], { childNodes } = commonAncestor;
441
+ return childNodes.indexOf(aAncestors[depth])
442
+ - childNodes.indexOf(bAncestors[depth]);
443
+ }
444
+ /**
445
+ * 将行列号转换为字符位置
446
+ * @param top 行号
447
+ * @param left 列号
448
+ */
449
+ indexFromPos(top, left) {
450
+ if (!Number.isInteger(top) || !Number.isInteger(left)) {
451
+ this.typeError('indexFromPos', 'Number');
452
+ }
453
+ const lines = String(this).split('\n');
454
+ return top >= 0 && left >= 0 && lines.length >= top + 1 && lines[top].length >= left
455
+ ? lines.slice(0, top).reduce((acc, curLine) => acc + curLine.length + 1, 0) + left
456
+ : undefined;
457
+ }
458
+ /**
459
+ * 获取当前节点的相对位置,或其第`j`个子节点的相对位置
460
+ * @param j 子节点序号
461
+ */
462
+ #getPosition(j) {
463
+ return j === undefined
464
+ ? this.parentNode?.posFromIndex(this.getRelativeIndex()) ?? { top: 0, left: 0 }
465
+ : this.posFromIndex(this.getRelativeIndex(j));
466
+ }
467
+ /** 获取当前节点的行列位置和大小 */
468
+ getBoundingClientRect() {
469
+ return { ...this.#getDimension(), ...this.getRootNode().posFromIndex(this.getAbsoluteIndex()) };
470
+ }
471
+ }
472
+ Parser.classes['AstNode'] = __filename;
473
+ module.exports = AstNode;
@@ -1,37 +1,38 @@
1
- export = Ranges;
2
- /** @extends {Array<number|Range>} */
3
- declare class Ranges extends Array<number | Range> {
4
- /**
5
- * 检查某个下标是否符合表达式
6
- * @param {string} str 表达式
7
- * @param {number} i 待检查的下标
8
- */
9
- static nth(str: string, i: number): boolean;
10
- /** @param {number|string|Range|(number|string|Range)[]} arr 表达式数组 */
11
- constructor(arr: number | string | Range | (number | string | Range)[]);
12
- /**
13
- * 将Ranges转换为针对特定Array的下标集
14
- * @param {number|*[]} arr 参考数组
15
- * @complexity `n`
16
- */
17
- applyTo(arr: number | any[]): number[];
18
- }
19
1
  /** 模拟Python的Range对象。除`step`至少为`1`外,允许负数、小数或`end < start`的情形。 */
20
2
  declare class Range {
3
+ start: number;
4
+ end: number;
5
+ step: number;
21
6
  /**
22
- * @param {string|Range} str 表达式
7
+ * @param s 表达式
23
8
  * @throws `RangeError` 起点、终点和步长均应为整数
24
9
  * @throws `RangeError` n的系数不能为0
25
10
  * @throws `RangeError` 应使用CSS选择器或Python切片的格式
26
11
  */
27
- constructor(str: string | Range);
28
- start: number;
29
- end: number;
30
- step: number;
12
+ constructor(s: string | Range);
31
13
  /**
32
14
  * 将Range转换为针对特定数组的下标集
33
- * @param {number|*[]} arr 参考数组
34
- * @complexity `n`
15
+ * @param arr 参考数组
35
16
  */
36
- applyTo(arr: number | any[]): number[];
17
+ applyTo(arr: number | unknown[]): number[];
37
18
  }
19
+ /** @extends {Array<number|Range>} */
20
+ declare class Ranges extends Array<number | Range> {
21
+ /** @param a 表达式数组 */
22
+ constructor(a?: number | string | Range | (number | string | Range)[]);
23
+ /**
24
+ * 将Ranges转换为针对特定Array的下标集
25
+ * @param arr 参考数组
26
+ */
27
+ applyTo(arr: number | unknown[]): number[];
28
+ /**
29
+ * 检查某个下标是否符合表达式
30
+ * @param str 表达式
31
+ * @param i 待检查的下标
32
+ */
33
+ static nth(this: void, str: string, i: number): boolean;
34
+ }
35
+ declare namespace Ranges {
36
+ export { Range };
37
+ }
38
+ export = Ranges;
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ const Parser = require("../index");
3
+ /** 模拟Python的Range对象。除`step`至少为`1`外,允许负数、小数或`end < start`的情形。 */
4
+ class Range {
5
+ start;
6
+ end;
7
+ step;
8
+ /**
9
+ * @param s 表达式
10
+ * @throws `RangeError` 起点、终点和步长均应为整数
11
+ * @throws `RangeError` n的系数不能为0
12
+ * @throws `RangeError` 应使用CSS选择器或Python切片的格式
13
+ */
14
+ constructor(s) {
15
+ if (s instanceof Range) {
16
+ Object.assign(this, s);
17
+ return;
18
+ }
19
+ const str = s.trim();
20
+ if (str === 'odd') {
21
+ Object.assign(this, { start: 1, end: Infinity, step: 2 });
22
+ }
23
+ else if (str === 'even') {
24
+ Object.assign(this, { start: 0, end: Infinity, step: 2 });
25
+ }
26
+ else if (str.includes(':')) {
27
+ const [start, end, step = '1'] = str.split(':', 3);
28
+ this.start = Number(start);
29
+ this.end = Number(end || Infinity);
30
+ this.step = Math.max(Number(step), 1);
31
+ if (!Number.isInteger(this.start)) {
32
+ throw new RangeError(`起点 ${this.start} 应为整数!`);
33
+ }
34
+ else if (this.end !== Infinity && !Number.isInteger(this.end)) {
35
+ throw new RangeError(`终点 ${this.end} 应为整数!`);
36
+ }
37
+ else if (!Number.isInteger(this.step)) {
38
+ throw new RangeError(`步长 ${this.step} 应为整数!`);
39
+ }
40
+ }
41
+ else {
42
+ const mt = /^([+-])?(\d+)?n(?:([+-])(\d+))?$/u
43
+ .exec(str);
44
+ if (mt) {
45
+ const [, sgnA = '+', a = 1, sgnB = '+'] = mt, b = Number(mt[4] ?? 0);
46
+ this.step = Number(a);
47
+ if (this.step === 0) {
48
+ throw new RangeError(`参数 ${str} 中 "n" 的系数不允许为 0!`);
49
+ }
50
+ else if (sgnA === '+') {
51
+ this.start = sgnB === '+' || b === 0 ? b : this.step - 1 - (b - 1) % this.step;
52
+ this.end = Infinity;
53
+ }
54
+ else if (sgnB === '-') {
55
+ this.start = 0;
56
+ this.end = b > 0 ? 0 : this.step;
57
+ }
58
+ else {
59
+ this.start = b % this.step;
60
+ this.end = this.step + b;
61
+ }
62
+ }
63
+ else {
64
+ throw new RangeError(`参数 ${str} 应写作CSS选择器的 "an+b" 形式或Python切片!`);
65
+ }
66
+ }
67
+ }
68
+ /**
69
+ * 将Range转换为针对特定数组的下标集
70
+ * @param arr 参考数组
71
+ */
72
+ applyTo(arr) {
73
+ return new Array(typeof arr === 'number' ? arr : arr.length).fill(undefined).map((_, i) => i)
74
+ .slice(this.start, this.end)
75
+ .filter((_, j) => j % this.step === 0);
76
+ }
77
+ }
78
+ /** @extends {Array<number|Range>} */
79
+ class Ranges extends Array {
80
+ /** @param a 表达式数组 */
81
+ constructor(a) {
82
+ super();
83
+ if (a === undefined) {
84
+ return;
85
+ }
86
+ const arr = Array.isArray(a) ? a : [a];
87
+ for (const ele of arr) {
88
+ if (ele instanceof Range) {
89
+ this.push(new Range(ele));
90
+ continue;
91
+ }
92
+ const number = Number(ele);
93
+ if (Number.isInteger(number)) {
94
+ this.push(number);
95
+ }
96
+ else if (typeof ele === 'string' && Number.isNaN(number)) {
97
+ try {
98
+ const range = new Range(ele);
99
+ this.push(range);
100
+ }
101
+ catch { }
102
+ }
103
+ }
104
+ }
105
+ /**
106
+ * 将Ranges转换为针对特定Array的下标集
107
+ * @param arr 参考数组
108
+ */
109
+ applyTo(arr) {
110
+ const length = typeof arr === 'number' ? arr : arr.length;
111
+ return [
112
+ ...new Set([...this].flatMap(ele => {
113
+ if (typeof ele === 'number') {
114
+ return ele < 0 ? ele + length : ele;
115
+ }
116
+ return ele.applyTo(length);
117
+ })),
118
+ ].filter(i => i >= 0 && i < length).sort();
119
+ }
120
+ /**
121
+ * 检查某个下标是否符合表达式
122
+ * @param str 表达式
123
+ * @param i 待检查的下标
124
+ */
125
+ static nth(str, i) {
126
+ return new Ranges(str.split(',')).applyTo(i + 1).includes(i);
127
+ }
128
+ }
129
+ Parser.classes['Ranges'] = __filename;
130
+ module.exports = Ranges;