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
package/lib/node.js DELETED
@@ -1,730 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * @template T
5
- * @typedef {import('../typings/node').TokenAttribute<T>} TokenAttribute
6
- */
7
- /** @typedef {import('../typings/event').AstListener} AstListener */
8
-
9
- const {text} = require('../util/string'),
10
- {typeError} = require('../util/debug'),
11
- assert = require('assert/strict'),
12
- EventEmitter = require('events'),
13
- Parser = require('..');
14
-
15
- /** 类似Node */
16
- class AstNode {
17
- /** @type {string} */ type;
18
- /** @type {this[]} */ childNodes = [];
19
- /** @type {this} */ #parentNode;
20
- /** @type {Set<string>} */ #optional = new Set();
21
- #events = new EventEmitter();
22
-
23
- /**
24
- * 检查在某个位置增删子节点是否合法
25
- * @param {number} i 增删位置
26
- * @param {number} addition 将会插入的子节点个数
27
- * @throws `RangeError` 指定位置不存在子节点
28
- */
29
- #verifyChild = (i, addition = 0) => {
30
- if (!Number.isInteger(i)) {
31
- this.typeError('verifyChild', 'Number');
32
- }
33
- const {childNodes: {length}} = this;
34
- if (i < -length || i >= length + addition) {
35
- throw new RangeError(`不存在第 ${i} 个子节点!`);
36
- }
37
- };
38
-
39
- /** 首位子节点 */
40
- get firstChild() {
41
- return this.childNodes[0];
42
- }
43
-
44
- /** 末位子节点 */
45
- get lastChild() {
46
- return this.childNodes.at(-1);
47
- }
48
-
49
- /** 父节点 */
50
- get parentNode() {
51
- return this.#parentNode;
52
- }
53
-
54
- /**
55
- * 后一个兄弟节点
56
- * @complexity `n`
57
- */
58
- get nextSibling() {
59
- const childNodes = this.#parentNode?.childNodes;
60
- return childNodes && childNodes[childNodes.indexOf(this) + 1];
61
- }
62
-
63
- /**
64
- * 前一个兄弟节点
65
- * @complexity `n`
66
- */
67
- get previousSibling() {
68
- const childNodes = this.#parentNode?.childNodes;
69
- return childNodes && childNodes[childNodes.indexOf(this) - 1];
70
- }
71
-
72
- /**
73
- * 后一个非文本兄弟节点
74
- * @complexity `n`
75
- * @returns {this}
76
- */
77
- get nextElementSibling() {
78
- const childNodes = this.#parentNode?.childNodes,
79
- i = childNodes?.indexOf(this);
80
- return childNodes?.slice(i + 1)?.find(({type}) => type !== 'text');
81
- }
82
-
83
- /**
84
- * 前一个非文本兄弟节点
85
- * @complexity `n`
86
- * @returns {this}
87
- */
88
- get previousElementSibling() {
89
- const childNodes = this.#parentNode?.childNodes,
90
- i = childNodes?.indexOf(this);
91
- return childNodes?.slice(0, i)?.findLast(({type}) => type !== 'text');
92
- }
93
-
94
- /** 是否具有根节点 */
95
- get isConnected() {
96
- return this.getRootNode().type === 'root';
97
- }
98
-
99
- /** 不是自身的根节点 */
100
- get ownerDocument() {
101
- const root = this.getRootNode();
102
- return root.type === 'root' && root !== this ? root : undefined;
103
- }
104
-
105
- /**
106
- * 后方是否还有其他节点(不含后代)
107
- * @returns {boolean}
108
- * @complexity `n`
109
- */
110
- get eof() {
111
- if (this.type === 'root') {
112
- return true;
113
- }
114
- let {nextSibling} = this;
115
- while (nextSibling?.type === 'text' && String(nextSibling).trim() === '') {
116
- ({nextSibling} = nextSibling);
117
- }
118
- return nextSibling === undefined && this.parentNode?.eof;
119
- }
120
-
121
- constructor() {
122
- Object.defineProperty(this, 'childNodes', {writable: false});
123
- Object.freeze(this.childNodes);
124
- }
125
-
126
- /**
127
- * 标记仅用于代码调试的方法
128
- * @param {string} method
129
- * @throws `Error`
130
- */
131
- debugOnly(method = 'debugOnly') {
132
- throw new Error(`${this.constructor.name}.${method} 方法仅用于代码调试!`);
133
- }
134
-
135
- /**
136
- * 抛出`TypeError`
137
- * @param {string} method
138
- * @param {...string} types 可接受的参数类型
139
- */
140
- typeError(method, ...types) {
141
- return typeError(this.constructor, method, ...types);
142
- }
143
-
144
- /**
145
- * 冻结部分属性
146
- * @param {string|string[]} keys 属性键
147
- * @param {boolean} permanent 是否永久
148
- */
149
- seal(keys, permanent) {
150
- if (!Parser.running && !Parser.debugging) {
151
- this.debugOnly('seal');
152
- }
153
- keys = Array.isArray(keys) ? keys : [keys];
154
- if (!permanent) {
155
- for (const key of keys) {
156
- this.#optional.add(key);
157
- }
158
- }
159
- for (const key of keys) {
160
- Object.defineProperty(this, key, {
161
- writable: false, enumerable: !permanent && Boolean(this[key]), configurable: !permanent,
162
- });
163
- }
164
- }
165
-
166
- /**
167
- * 是否是全同节点
168
- * @param {this} node 待比较的节点
169
- * @throws `assert.AssertionError`
170
- */
171
- isEqualNode(node) {
172
- try {
173
- assert.deepStrictEqual(this, node);
174
- } catch (e) {
175
- if (e instanceof assert.AssertionError) {
176
- return false;
177
- }
178
- throw e;
179
- }
180
- return true;
181
- }
182
-
183
- /**
184
- * 是否具有某属性
185
- * @param {PropertyKey} key 属性键
186
- */
187
- hasAttribute(key) {
188
- const type = typeof key;
189
- return type === 'string' || type === 'number' || type === 'symbol'
190
- ? key in this
191
- : this.typeError('hasAttribute', 'String', 'Number', 'Symbol');
192
- }
193
-
194
- /**
195
- * 获取属性值。除非用于私有属性,否则总是返回字符串。
196
- * @template {string} T
197
- * @param {T} key 属性键
198
- * @returns {TokenAttribute<T>}
199
- */
200
- getAttribute(key) {
201
- if (key === 'optional') {
202
- return new Set(this.#optional);
203
- } else if (key === 'verifyChild') {
204
- return this.#verifyChild;
205
- }
206
- return this.hasAttribute(key) ? String(this[key]) : undefined;
207
- }
208
-
209
- /**
210
- * 设置属性
211
- * @template {string} T
212
- * @param {T} key 属性键
213
- * @param {TokenAttribute<T>} value 属性值
214
- */
215
- setAttribute(key, value) {
216
- if (key === 'parentNode') {
217
- this.#parentNode = value;
218
- } else if (Object.hasOwn(this, key)) {
219
- const descriptor = Object.getOwnPropertyDescriptor(this, key);
220
- if (this.#optional.has(key)) {
221
- descriptor.enumerable = Boolean(value);
222
- }
223
- const oldValue = this[key],
224
- frozen = oldValue !== null && typeof oldValue === 'object' && Object.isFrozen(oldValue);
225
- Object.defineProperty(this, key, {...descriptor, value});
226
- if (frozen && value !== null && typeof value === 'object') {
227
- Object.freeze(value);
228
- }
229
- } else {
230
- this[key] = value;
231
- }
232
- return this;
233
- }
234
-
235
- /**
236
- * 可见部分
237
- * @param {string} separator 子节点间的连接符
238
- * @returns {string}
239
- * @complexity `n`
240
- */
241
- text(separator = '') {
242
- return text(this.childNodes, separator);
243
- }
244
-
245
- /**
246
- * 移除子节点
247
- * @param {number} i 移除位置
248
- */
249
- removeAt(i) {
250
- this.getAttribute('verifyChild')(i);
251
- const childNodes = [...this.childNodes],
252
- e = new Event('remove', {bubbles: true}),
253
- [node] = childNodes.splice(i, 1);
254
- node.setAttribute('parentNode');
255
- this.setAttribute('childNodes', childNodes);
256
- this.dispatchEvent(e, {position: i, removed: node});
257
- return node;
258
- }
259
-
260
- /**
261
- * 插入子节点
262
- * @template {this} T
263
- * @param {T} node 待插入的子节点
264
- * @param {number} i 插入位置
265
- * @complexity `n`
266
- * @throws `RangeError` 不能插入祖先节点
267
- */
268
- insertAt(node, i = this.childNodes.length) {
269
- if (!(node instanceof AstNode)) {
270
- this.typeError('insertAt', 'String', 'AstNode');
271
- } else if (node.contains(this)) {
272
- Parser.error('不能插入祖先节点!', node);
273
- throw new RangeError('不能插入祖先节点!');
274
- }
275
- this.getAttribute('verifyChild')(i, 1);
276
- const childNodes = [...this.childNodes],
277
- e = new Event('insert', {bubbles: true}),
278
- j = Parser.running ? -1 : childNodes.indexOf(node);
279
- if (j === -1) {
280
- node.parentNode?.removeChild(node);
281
- node.setAttribute('parentNode', this);
282
- } else {
283
- childNodes.splice(j, 1);
284
- }
285
- childNodes.splice(i, 0, node);
286
- this.setAttribute('childNodes', childNodes);
287
- this.dispatchEvent(e, {position: i < 0 ? i + this.childNodes.length - 1 : i, inserted: node});
288
- return node;
289
- }
290
-
291
- /**
292
- * 获取子节点的位置
293
- * @param {this} node 子节点
294
- * @complexity `n`
295
- * @throws `RangeError` 找不到子节点
296
- */
297
- #getChildIndex(node) {
298
- const i = this.childNodes.indexOf(node);
299
- if (i === -1) {
300
- Parser.error('找不到子节点!', node);
301
- throw new RangeError('找不到子节点!');
302
- }
303
- return i;
304
- }
305
-
306
- /**
307
- * 移除子节点
308
- * @template {this} T
309
- * @param {T} node 子节点
310
- * @complexity `n`
311
- */
312
- removeChild(node) {
313
- this.removeAt(this.#getChildIndex(node));
314
- return node;
315
- }
316
-
317
- /**
318
- * 在末尾插入子节点
319
- * @template {this} T
320
- * @param {T} node 插入节点
321
- * @complexity `n`
322
- */
323
- appendChild(node) {
324
- return this.insertAt(node);
325
- }
326
-
327
- /**
328
- * 在指定位置前插入子节点
329
- * @template {this} T
330
- * @param {T} child 插入节点
331
- * @param {this} reference 指定位置处的子节点
332
- * @complexity `n`
333
- */
334
- insertBefore(child, reference) {
335
- return reference === undefined ? this.insertAt(child) : this.insertAt(child, this.#getChildIndex(reference));
336
- }
337
-
338
- /**
339
- * 替换子节点
340
- * @template {this} T
341
- * @param {this} newChild 新子节点
342
- * @param {T} oldChild 原子节点
343
- * @complexity `n`
344
- */
345
- replaceChild(newChild, oldChild) {
346
- const i = this.#getChildIndex(oldChild);
347
- this.removeAt(i);
348
- this.insertAt(newChild, i);
349
- return oldChild;
350
- }
351
-
352
- /**
353
- * 在当前节点前后插入兄弟节点
354
- * @param {this[]} nodes 插入节点
355
- * @param {number} offset 插入的相对位置
356
- * @complexity `n`
357
- * @throws `Error` 不存在父节点
358
- */
359
- #insertAdjacent(nodes, offset) {
360
- const {parentNode} = this;
361
- if (!parentNode) {
362
- throw new Error('不存在父节点!');
363
- }
364
- const i = parentNode.childNodes.indexOf(this) + offset;
365
- for (let j = 0; j < nodes.length; j++) {
366
- parentNode.insertAt(nodes[j], i + j);
367
- }
368
- }
369
-
370
- /**
371
- * 在后方批量插入兄弟节点
372
- * @param {...this} nodes 插入节点
373
- * @complexity `n`
374
- */
375
- after(...nodes) {
376
- this.#insertAdjacent(nodes, 1);
377
- }
378
-
379
- /**
380
- * 在前方批量插入兄弟节点
381
- * @param {...this} nodes 插入节点
382
- * @complexity `n`
383
- */
384
- before(...nodes) {
385
- this.#insertAdjacent(nodes, 0);
386
- }
387
-
388
- /**
389
- * 移除当前节点
390
- * @complexity `n`
391
- * @throws `Error` 不存在父节点
392
- */
393
- remove() {
394
- const {parentNode} = this;
395
- if (!parentNode) {
396
- throw new Error('不存在父节点!');
397
- }
398
- parentNode.removeChild(this);
399
- }
400
-
401
- /**
402
- * 将当前节点批量替换为新的节点
403
- * @param {...this} nodes 插入节点
404
- * @complexity `n`
405
- */
406
- replaceWith(...nodes) {
407
- this.after(...nodes);
408
- this.remove();
409
- }
410
-
411
- /**
412
- * 是自身或后代节点
413
- * @param {this} node 待检测节点
414
- * @returns {boolean}
415
- * @complexity `n`
416
- */
417
- contains(node) {
418
- return node instanceof AstNode
419
- ? node === this || this.childNodes.some(child => child.contains(node))
420
- : this.typeError('contains', 'AstNode');
421
- }
422
-
423
- /**
424
- * 添加事件监听
425
- * @param {string|string[]} types 事件类型
426
- * @param {AstListener} listener 监听函数
427
- * @param {{once: boolean}} options 选项
428
- */
429
- addEventListener(types, listener, options) {
430
- if (Array.isArray(types)) {
431
- for (const type of types) {
432
- this.addEventListener(type, listener, options);
433
- }
434
- } else if (typeof types === 'string' && typeof listener === 'function') {
435
- this.#events[options?.once ? 'once' : 'on'](types, listener);
436
- } else {
437
- this.typeError('addEventListener', 'String', 'Function');
438
- }
439
- }
440
-
441
- /**
442
- * 移除事件监听
443
- * @param {string|string[]} types 事件类型
444
- * @param {AstListener} listener 监听函数
445
- */
446
- removeEventListener(types, listener) {
447
- if (Array.isArray(types)) {
448
- for (const type of types) {
449
- this.removeEventListener(type, listener);
450
- }
451
- } else if (typeof types === 'string' && typeof listener === 'function') {
452
- this.#events.off(types, listener);
453
- } else {
454
- this.typeError('removeEventListener', 'String', 'Function');
455
- }
456
- }
457
-
458
- /**
459
- * 移除事件的所有监听
460
- * @param {string|string[]} types 事件类型
461
- */
462
- removeAllEventListeners(types) {
463
- if (Array.isArray(types)) {
464
- for (const type of types) {
465
- this.removeAllEventListeners(type);
466
- }
467
- } else if (types === undefined || typeof types === 'string') {
468
- this.#events.removeAllListeners(types);
469
- } else {
470
- this.typeError('removeAllEventListeners', 'String');
471
- }
472
- }
473
-
474
- /**
475
- * 列举事件监听
476
- * @param {string} type 事件类型
477
- * @returns {AstListener[]}
478
- */
479
- listEventListeners(type) {
480
- return typeof type === 'string' ? this.#events.listeners(type) : this.typeError('listEventListeners', 'String');
481
- }
482
-
483
- /**
484
- * 触发事件
485
- * @param {import('../typings/event').AstEvent} e 事件对象
486
- * @param {*} data 事件数据
487
- */
488
- dispatchEvent(e, data) {
489
- if (!(e instanceof Event)) {
490
- this.typeError('dispatchEvent', 'Event');
491
- } else if (!e.target) { // 初始化
492
- Object.defineProperty(e, 'target', {value: this, enumerable: true});
493
-
494
- /** 终止冒泡 */
495
- e.stopPropagation = function() {
496
- Object.defineProperty(this, 'bubbles', {value: false});
497
- };
498
- }
499
- Object.defineProperties(e, { // 每次bubble更新
500
- prevTarget: {value: e.currentTarget, enumerable: true, configurable: true},
501
- currentTarget: {value: this, enumerable: true, configurable: true},
502
- });
503
- this.#events.emit(e.type, e, data);
504
- if (e.bubbles && this.parentNode) {
505
- this.parentNode.dispatchEvent(e, data);
506
- }
507
- }
508
-
509
- /** 获取所有祖先节点 */
510
- getAncestors() {
511
- const /** @type {this[]} */ ancestors = [];
512
- let {parentNode} = this;
513
- while (parentNode) {
514
- ancestors.push(parentNode);
515
- ({parentNode} = parentNode);
516
- }
517
- return ancestors;
518
- }
519
-
520
- /**
521
- * 比较和另一个节点的相对位置
522
- * @param {this} other 待比较的节点
523
- * @complexity `n`
524
- * @throws `Error` 不在同一个语法树
525
- */
526
- compareDocumentPosition(other) {
527
- if (!(other instanceof AstNode)) {
528
- this.typeError('compareDocumentPosition', 'AstNode');
529
- } else if (this === other) {
530
- return 0;
531
- } else if (this.contains(other)) {
532
- return -1;
533
- } else if (other.contains(this)) {
534
- return 1;
535
- } else if (this.getRootNode() !== other.getRootNode()) {
536
- throw new Error('不在同一个语法树!');
537
- }
538
- const aAncestors = [...this.getAncestors().reverse(), this],
539
- bAncestors = [...other.getAncestors().reverse(), other],
540
- depth = aAncestors.findIndex((ancestor, i) => bAncestors[i] !== ancestor),
541
- commonAncestor = aAncestors[depth - 1],
542
- {childNodes} = commonAncestor;
543
- return childNodes.indexOf(aAncestors[depth]) - childNodes.indexOf(bAncestors[depth]);
544
- }
545
-
546
- /**
547
- * 合并相邻的文本子节点
548
- * @complexity `n`
549
- */
550
- normalize() {
551
- const AstText = require('./text');
552
- const /** @type {AstText[]} */ childNodes = [...this.childNodes];
553
- for (let i = childNodes.length - 1; i >= 0; i--) {
554
- const {type, data} = childNodes[i];
555
- if (this.getGaps(i - 1)) {
556
- //
557
- } else if (data === '') {
558
- childNodes.splice(i, 1);
559
- } else if (type === 'text' && childNodes[i - 1]?.type === 'text') {
560
- childNodes[i - 1].setAttribute('data', childNodes[i - 1].data + data);
561
- childNodes.splice(i, 1);
562
- }
563
- }
564
- this.setAttribute('childNodes', childNodes);
565
- }
566
-
567
- /** 获取根节点 */
568
- getRootNode() {
569
- let {parentNode} = this;
570
- while (parentNode?.parentNode) {
571
- ({parentNode} = parentNode);
572
- }
573
- return parentNode ?? this;
574
- }
575
-
576
- /**
577
- * 将字符位置转换为行列号
578
- * @param {number} index 字符位置
579
- * @complexity `n`
580
- */
581
- posFromIndex(index) {
582
- if (!Number.isInteger(index)) {
583
- this.typeError('posFromIndex', 'Number');
584
- }
585
- const str = String(this);
586
- if (index >= -str.length && index <= str.length) {
587
- const lines = str.slice(0, index).split('\n');
588
- return {top: lines.length - 1, left: lines.at(-1).length};
589
- }
590
- return undefined;
591
- }
592
-
593
- /**
594
- * 将行列号转换为字符位置
595
- * @param {number} top 行号
596
- * @param {number} left 列号
597
- * @complexity `n`
598
- */
599
- indexFromPos(top, left) {
600
- if (!Number.isInteger(top) || !Number.isInteger(left)) {
601
- this.typeError('indexFromPos', 'Number');
602
- }
603
- const lines = String(this).split('\n');
604
- return top >= 0 && left >= 0 && lines.length >= top + 1 && lines[top].length >= left
605
- ? lines.slice(0, top).reduce((acc, curLine) => acc + curLine.length + 1, 0) + left
606
- : undefined;
607
- }
608
-
609
- /**
610
- * 获取行数和最后一行的列数
611
- * @complexity `n`
612
- */
613
- #getDimension() {
614
- const lines = String(this).split('\n');
615
- return {height: lines.length, width: lines.at(-1).length};
616
- }
617
-
618
- /** 第一个子节点前的间距 */
619
- getPadding() {
620
- return 0;
621
- }
622
-
623
- /** 子节点间距 */
624
- getGaps() {
625
- return 0;
626
- }
627
-
628
- /**
629
- * 获取当前节点的相对字符位置,或其第`j`个子节点的相对字符位置
630
- * @param {number|undefined} j 子节点序号
631
- * @complexity `n`
632
- */
633
- getRelativeIndex(j) {
634
- let /** @type {this[]} */ childNodes;
635
-
636
- /**
637
- * 获取子节点相对于父节点的字符位置,使用前需要先给`childNodes`赋值
638
- * @param {number} end 子节点序号
639
- * @param {this} parent 父节点
640
- * @returns {number}
641
- */
642
- const getIndex = (end, parent) => childNodes.slice(0, end).reduce(
643
- (acc, cur, i) => acc + String(cur).length + parent.getGaps(i),
644
- 0,
645
- ) + parent.getPadding();
646
- if (j === undefined) {
647
- const {parentNode} = this;
648
- if (parentNode) {
649
- ({childNodes} = parentNode);
650
- return getIndex(childNodes.indexOf(this), parentNode);
651
- }
652
- return 0;
653
- }
654
- this.getAttribute('verifyChild')(j, 1);
655
- ({childNodes} = this);
656
- return getIndex(j, this);
657
- }
658
-
659
- /**
660
- * 获取当前节点的绝对位置
661
- * @returns {number}
662
- * @complexity `n`
663
- */
664
- getAbsoluteIndex() {
665
- const {parentNode} = this;
666
- return parentNode ? parentNode.getAbsoluteIndex() + this.getRelativeIndex() : 0;
667
- }
668
-
669
- /**
670
- * 获取当前节点的相对位置,或其第`j`个子节点的相对位置
671
- * @param {number|undefined} j 子节点序号
672
- * @complexity `n`
673
- */
674
- #getPosition(j) {
675
- return j === undefined
676
- ? this.parentNode?.posFromIndex(this.getRelativeIndex()) ?? {top: 0, left: 0}
677
- : this.posFromIndex(this.getRelativeIndex(j));
678
- }
679
-
680
- /**
681
- * 获取当前节点的行列位置和大小
682
- * @complexity `n`
683
- */
684
- getBoundingClientRect() {
685
- return {...this.#getDimension(), ...this.getRootNode().posFromIndex(this.getAbsoluteIndex())};
686
- }
687
-
688
- /**
689
- * 行数
690
- * @complexity `n`
691
- */
692
- get offsetHeight() {
693
- return this.#getDimension().height;
694
- }
695
-
696
- /**
697
- * 最后一行的列数
698
- * @complexity `n`
699
- */
700
- get offsetWidth() {
701
- return this.#getDimension().width;
702
- }
703
-
704
- /**
705
- * 相对于父容器的行号
706
- * @complexity `n`
707
- */
708
- get offsetTop() {
709
- return this.#getPosition().top;
710
- }
711
-
712
- /**
713
- * 相对于父容器的列号
714
- * @complexity `n`
715
- */
716
- get offsetLeft() {
717
- return this.#getPosition().left;
718
- }
719
-
720
- /**
721
- * 位置、大小和padding
722
- * @complexity `n`
723
- */
724
- get style() {
725
- return {...this.#getPosition(), ...this.#getDimension(), padding: this.getPadding()};
726
- }
727
- }
728
-
729
- Parser.classes.AstNode = __filename;
730
- module.exports = AstNode;