wikiparser-node 1.18.2 → 1.18.4

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 (76) hide show
  1. package/README.md +6 -1
  2. package/bundle/bundle-es7.min.js +29 -28
  3. package/bundle/bundle-lsp.min.js +31 -30
  4. package/bundle/bundle.min.js +30 -29
  5. package/config/minimum.json +7 -0
  6. package/dist/addon/token.js +37 -28
  7. package/dist/addon/transclude.js +1 -3
  8. package/dist/base.d.mts +4 -0
  9. package/dist/base.d.ts +4 -0
  10. package/dist/base.js +1 -0
  11. package/dist/base.mjs +2 -1
  12. package/dist/bin/config.js +3 -2
  13. package/dist/index.d.ts +14 -1
  14. package/dist/index.js +72 -72
  15. package/dist/lib/element.d.ts +6 -0
  16. package/dist/lib/element.js +543 -466
  17. package/dist/lib/lsp.d.ts +1 -0
  18. package/dist/lib/lsp.js +20 -15
  19. package/dist/lib/redirectMap.d.ts +7 -0
  20. package/dist/lib/redirectMap.js +31 -0
  21. package/dist/lib/text.d.ts +2 -2
  22. package/dist/lib/text.js +385 -325
  23. package/dist/lib/title.d.ts +23 -4
  24. package/dist/lib/title.js +17 -5
  25. package/dist/mixin/noEscape.d.ts +4 -0
  26. package/dist/mixin/noEscape.js +22 -0
  27. package/dist/mixin/readOnly.d.ts +4 -0
  28. package/dist/mixin/readOnly.js +26 -0
  29. package/dist/parser/braces.js +79 -37
  30. package/dist/parser/commentAndExt.js +5 -16
  31. package/dist/parser/links.js +1 -1
  32. package/dist/parser/quotes.js +1 -1
  33. package/dist/parser/redirect.js +1 -3
  34. package/dist/src/arg.js +253 -202
  35. package/dist/src/attribute.d.ts +0 -5
  36. package/dist/src/attribute.js +4 -8
  37. package/dist/src/converter.js +213 -162
  38. package/dist/src/gallery.js +1 -2
  39. package/dist/src/heading.js +5 -6
  40. package/dist/src/imageParameter.js +16 -16
  41. package/dist/src/imagemap.js +3 -2
  42. package/dist/src/index.d.ts +1 -1
  43. package/dist/src/index.js +722 -694
  44. package/dist/src/link/base.js +292 -241
  45. package/dist/src/link/file.js +13 -17
  46. package/dist/src/link/galleryImage.js +1 -1
  47. package/dist/src/link/redirectTarget.js +1 -2
  48. package/dist/src/magicLink.d.ts +0 -6
  49. package/dist/src/magicLink.js +5 -15
  50. package/dist/src/nested.js +7 -7
  51. package/dist/src/nowiki/base.js +2 -1
  52. package/dist/src/nowiki/index.js +4 -3
  53. package/dist/src/onlyinclude.js +95 -44
  54. package/dist/src/parameter.d.ts +0 -6
  55. package/dist/src/parameter.js +1 -13
  56. package/dist/src/redirect.js +6 -6
  57. package/dist/src/syntax.d.ts +4 -1
  58. package/dist/src/syntax.js +4 -1
  59. package/dist/src/table/base.d.ts +0 -5
  60. package/dist/src/table/base.js +2 -9
  61. package/dist/src/table/index.d.ts +1 -0
  62. package/dist/src/table/index.js +7 -4
  63. package/dist/src/table/td.d.ts +1 -0
  64. package/dist/src/table/td.js +2 -3
  65. package/dist/src/table/trBase.js +31 -14
  66. package/dist/src/tagPair/index.js +2 -1
  67. package/dist/src/transclude.js +713 -657
  68. package/dist/util/debug.js +10 -3
  69. package/dist/util/diff.js +1 -1
  70. package/dist/util/string.js +4 -5
  71. package/extensions/dist/base.js +8 -6
  72. package/extensions/dist/lint.js +1 -1
  73. package/extensions/es7/base.js +8 -6
  74. package/extensions/es7/lint.js +1 -1
  75. package/extensions/ui.css +1 -1
  76. package/package.json +3 -3
@@ -1,4 +1,38 @@
1
1
  "use strict";
2
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
3
+ var useValue = arguments.length > 2;
4
+ for (var i = 0; i < initializers.length; i++) {
5
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
6
+ }
7
+ return useValue ? value : void 0;
8
+ };
9
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
10
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
11
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
12
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
13
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
14
+ var _, done = false;
15
+ for (var i = decorators.length - 1; i >= 0; i--) {
16
+ var context = {};
17
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
18
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
19
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
20
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
21
+ if (kind === "accessor") {
22
+ if (result === void 0) continue;
23
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
24
+ if (_ = accept(result.get)) descriptor.get = _;
25
+ if (_ = accept(result.set)) descriptor.set = _;
26
+ if (_ = accept(result.init)) initializers.unshift(_);
27
+ }
28
+ else if (_ = accept(result)) {
29
+ if (kind === "field") initializers.unshift(_);
30
+ else descriptor[key] = _;
31
+ }
32
+ }
33
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
34
+ done = true;
35
+ };
2
36
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
37
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
38
  };
@@ -12,509 +46,552 @@ const node_1 = require("./node");
12
46
  const fs_1 = __importDefault(require("fs"));
13
47
  const path_1 = __importDefault(require("path"));
14
48
  const constants_1 = require("../util/constants");
49
+ const html_1 = require("../util/html");
50
+ const readOnly_1 = require("../mixin/readOnly");
15
51
  /**
16
52
  * HTMLElement-like
17
53
  *
18
54
  * 类似HTMLElement
19
55
  */
20
- class AstElement extends node_1.AstNode {
21
- /** number of child nodes / 子节点总数 */
22
- get length() {
23
- return this.childNodes.length;
24
- }
25
- /* NOT FOR BROWSER */
26
- set length(n) {
27
- if (n >= 0 && n < this.length) {
28
- for (let i = this.length - 1; i >= n; i--) {
29
- this.removeAt(i);
56
+ let AstElement = (() => {
57
+ let _classSuper = node_1.AstNode;
58
+ let _instanceExtraInitializers = [];
59
+ let _removeAt_decorators;
60
+ let _insertAt_decorators;
61
+ return class AstElement extends _classSuper {
62
+ static {
63
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
64
+ _removeAt_decorators = [(0, readOnly_1.readOnly)()];
65
+ _insertAt_decorators = [(0, readOnly_1.readOnly)()];
66
+ __esDecorate(this, null, _removeAt_decorators, { kind: "method", name: "removeAt", static: false, private: false, access: { has: obj => "removeAt" in obj, get: obj => obj.removeAt }, metadata: _metadata }, null, _instanceExtraInitializers);
67
+ __esDecorate(this, null, _insertAt_decorators, { kind: "method", name: "insertAt", static: false, private: false, access: { has: obj => "insertAt" in obj, get: obj => obj.insertAt }, metadata: _metadata }, null, _instanceExtraInitializers);
68
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
69
+ }
70
+ /** number of child nodes / 子节点总数 */
71
+ get length() {
72
+ return this.childNodes.length;
73
+ }
74
+ /* NOT FOR BROWSER */
75
+ set length(n) {
76
+ if (n >= 0 && n < this.length) {
77
+ for (let i = this.length - 1; i >= n; i--) {
78
+ this.removeAt(i);
79
+ }
30
80
  }
31
81
  }
32
- }
33
- /** all child elements / 全部非文本子节点 */
34
- get children() {
35
- return this.childNodes.filter((child) => child.type !== 'text');
36
- }
37
- /** first child element / 首位非文本子节点 */
38
- get firstElementChild() {
39
- return this.childNodes.find((child) => child.type !== 'text');
40
- }
41
- /** last child element / 末位非文本子节点 */
42
- get lastElementChild() {
43
- return this.childNodes.findLast((child) => child.type !== 'text');
44
- }
45
- /** number of child elements / 非文本子节点总数 */
46
- get childElementCount() {
47
- return this.children.length;
48
- }
49
- /** parent node / 父节点 */
50
- get parentElement() {
51
- return this.parentNode;
52
- }
53
- /** visible text / 可见部分 */
54
- get outerText() {
55
- return this.text();
56
- }
57
- /** invisible / 不可见 */
58
- get hidden() {
59
- return this.text() === '';
60
- }
61
- /** height of the inner / 内部高度 */
62
- get clientHeight() {
63
- return this.innerText?.split('\n').length;
64
- }
65
- /** width of the inner / 内部宽度 */
66
- get clientWidth() {
67
- return this.innerText?.split('\n').pop().length;
68
- }
69
- /** all images, including gallery images / 所有图片,包括图库 */
70
- get images() {
71
- return this.querySelectorAll('file,gallery-image,imagemap-image');
72
- }
73
- /** all internal, external and free external links / 所有内链、外链和自由外链 */
74
- get links() {
75
- return this.querySelectorAll('link,redirect-target,ext-link,free-ext-link,magic-link,image-parameter#link').filter(({ parentNode }) => parentNode?.type !== 'image-parameter' || parentNode.name !== 'link');
76
- }
77
- /** all templates and modules / 所有模板和模块 */
78
- get embeds() {
79
- return this.querySelectorAll('template,magic-word#invoke');
80
- }
81
- constructor() {
82
- super();
83
- this.seal('name');
84
- }
85
- /* NOT FOR BROWSER END */
86
- /** @private */
87
- text(separator) {
88
- return (0, string_1.text)(this.childNodes, separator);
89
- }
90
- /**
91
- * Merge adjacent text child nodes
92
- *
93
- * 合并相邻的文本子节点
94
- */
95
- normalize() {
96
- const childNodes = this.getChildNodes();
82
+ /** all child elements / 全部非文本子节点 */
83
+ get children() {
84
+ return this.childNodes.filter((child) => child.type !== 'text');
85
+ }
86
+ /** first child element / 首位非文本子节点 */
87
+ get firstElementChild() {
88
+ return this.childNodes.find((child) => child.type !== 'text');
89
+ }
90
+ /** last child element / 末位非文本子节点 */
91
+ get lastElementChild() {
92
+ return this.childNodes.findLast((child) => child.type !== 'text');
93
+ }
94
+ /** number of child elements / 非文本子节点总数 */
95
+ get childElementCount() {
96
+ return this.children.length;
97
+ }
98
+ /** parent node / 父节点 */
99
+ get parentElement() {
100
+ return this.parentNode;
101
+ }
102
+ /** visible text / 可见部分 */
103
+ get outerText() {
104
+ return this.text();
105
+ }
106
+ /** invisible / 不可见 */
107
+ get hidden() {
108
+ return this.text() === '';
109
+ }
110
+ /** height of the inner / 内部高度 */
111
+ get clientHeight() {
112
+ return this.innerText?.split('\n').length;
113
+ }
114
+ /** width of the inner / 内部宽度 */
115
+ get clientWidth() {
116
+ return this.innerText?.split('\n').pop().length;
117
+ }
118
+ /** all images, including gallery images / 所有图片,包括图库 */
119
+ get images() {
120
+ return this.querySelectorAll('file,gallery-image,imagemap-image');
121
+ }
122
+ /** all internal, external and free external links / 所有内链、外链和自由外链 */
123
+ get links() {
124
+ return this.querySelectorAll('link,redirect-target,ext-link,free-ext-link,magic-link,image-parameter#link').filter(({ parentNode }) => parentNode?.type !== 'image-parameter' || parentNode.name !== 'link');
125
+ }
126
+ /** all templates and modules / 所有模板和模块 */
127
+ get embeds() {
128
+ return this.querySelectorAll('template,magic-word#invoke');
129
+ }
130
+ constructor() {
131
+ super();
132
+ __runInitializers(this, _instanceExtraInitializers);
133
+ this.seal('name');
134
+ }
135
+ /* NOT FOR BROWSER END */
136
+ /** @private */
137
+ text(separator) {
138
+ return (0, string_1.text)(this.childNodes, separator);
139
+ }
97
140
  /**
141
+ * Merge adjacent text child nodes
142
+ *
143
+ * 合并相邻的文本子节点
144
+ */
145
+ normalize() {
146
+ const childNodes = this.getChildNodes();
147
+ /**
148
+ * 移除子节点
149
+ * @param i 移除位置
150
+ */
151
+ const remove = (i) => {
152
+ /* NOT FOR BROWSER */
153
+ childNodes[i].setAttribute('parentNode', undefined);
154
+ /* NOT FOR BROWSER END */
155
+ childNodes.splice(i, 1);
156
+ childNodes[i - 1]?.setAttribute('nextSibling', childNodes[i]);
157
+ childNodes[i]?.setAttribute('previousSibling', childNodes[i - 1]);
158
+ };
159
+ for (let i = childNodes.length - 1; i >= 0; i--) {
160
+ const { type, data } = childNodes[i];
161
+ if (type !== 'text' || childNodes.length === 1 || this.getGaps(i - (i && 1))) {
162
+ //
163
+ }
164
+ else if (data === '') {
165
+ remove(i);
166
+ /* NOT FOR BROWSER */
167
+ }
168
+ else {
169
+ const prev = childNodes[i - 1];
170
+ if (prev?.type === 'text') {
171
+ prev.setAttribute('data', prev.data + data);
172
+ remove(i);
173
+ }
174
+ /* NOT FOR BROWSER END */
175
+ }
176
+ }
177
+ this.setAttribute('childNodes', childNodes);
178
+ }
179
+ /**
180
+ * Remove a child node
181
+ *
98
182
  * 移除子节点
99
- * @param i 移除位置
183
+ * @param i position of the child node / 移除位置
100
184
  */
101
- const remove = (i) => {
185
+ removeAt(i) {
102
186
  /* NOT FOR BROWSER */
103
- childNodes[i].setAttribute('parentNode', undefined);
187
+ this.verifyChild(i);
104
188
  /* NOT FOR BROWSER END */
105
- childNodes.splice(i, 1);
106
- childNodes[i - 1]?.setAttribute('nextSibling', childNodes[i]);
107
- childNodes[i]?.setAttribute('previousSibling', childNodes[i - 1]);
108
- };
109
- for (let i = childNodes.length - 1; i >= 0; i--) {
110
- const { type, data } = childNodes[i];
111
- if (type !== 'text' || childNodes.length === 1 || this.getGaps(i - (i && 1))) {
112
- //
189
+ return (0, debug_1.setChildNodes)(this, i, 1)[0];
190
+ }
191
+ /**
192
+ * Insert a child node
193
+ *
194
+ * 插入子节点
195
+ * @param node node to be inserted / 待插入的子节点
196
+ * @param i position to be inserted at / 插入位置
197
+ * @throws `RangeError` 不能插入祖先或子节点
198
+ */
199
+ insertAt(node, i = this.length) {
200
+ /* NOT FOR BROWSER */
201
+ /* istanbul ignore next */
202
+ if (node.contains(this)) {
203
+ throw new RangeError('Cannot insert an ancestor node!');
113
204
  }
114
- else if (data === '') {
115
- remove(i);
116
- /* NOT FOR BROWSER */
205
+ else if (node.parentNode === this) {
206
+ throw new RangeError('Cannot insert its own child node!');
117
207
  }
118
- else {
119
- const prev = childNodes[i - 1];
120
- if (prev?.type === 'text') {
121
- prev.setAttribute('data', prev.data + data);
122
- remove(i);
208
+ this.verifyChild(i, 1);
209
+ node.parentNode?.removeChild(node);
210
+ /* NOT FOR BROWSER END */
211
+ (0, debug_1.setChildNodes)(this, i, 0, [node]);
212
+ return node;
213
+ }
214
+ /**
215
+ * Get the closest ancestor node that matches the selector
216
+ *
217
+ * 最近的符合选择器的祖先节点
218
+ * @param selector 选择器
219
+ */
220
+ closest(selector) {
221
+ const condition = (0, selector_1.getCondition)(selector, this);
222
+ let { parentNode } = this;
223
+ while (parentNode) {
224
+ if (condition(parentNode)) {
225
+ return parentNode;
123
226
  }
124
- /* NOT FOR BROWSER END */
227
+ ({ parentNode } = parentNode);
125
228
  }
229
+ return undefined;
126
230
  }
127
- this.setAttribute('childNodes', childNodes);
128
- }
129
- /**
130
- * Remove a child node
131
- *
132
- * 移除子节点
133
- * @param i position of the child node / 移除位置
134
- */
135
- removeAt(i) {
136
- /* NOT FOR BROWSER */
137
- this.verifyChild(i);
138
- /* NOT FOR BROWSER END */
139
- return (0, debug_1.setChildNodes)(this, i, 1)[0];
140
- }
141
- /**
142
- * Insert a child node
143
- *
144
- * 插入子节点
145
- * @param node node to be inserted / 待插入的子节点
146
- * @param i position to be inserted at / 插入位置
147
- * @throws `RangeError` 不能插入祖先或子节点
148
- */
149
- insertAt(node, i = this.length) {
150
- /* NOT FOR BROWSER */
151
- /* istanbul ignore next */
152
- if (node.contains(this)) {
153
- throw new RangeError('Cannot insert an ancestor node!');
231
+ /**
232
+ * 符合条件的第一个后代节点
233
+ * @param condition 条件
234
+ */
235
+ #getElementBy(condition) {
236
+ for (const child of this.childNodes) {
237
+ if (child.type === 'text') {
238
+ continue;
239
+ }
240
+ else if (condition(child)) {
241
+ return child;
242
+ }
243
+ const descendant = child.#getElementBy(condition);
244
+ if (descendant) {
245
+ return descendant;
246
+ }
247
+ }
248
+ return undefined;
154
249
  }
155
- else if (node.parentNode === this) {
156
- throw new RangeError('Cannot insert its own child node!');
250
+ /**
251
+ * Get the first descendant that matches the selector
252
+ *
253
+ * 符合选择器的第一个后代节点
254
+ * @param selector 选择器
255
+ */
256
+ querySelector(selector) {
257
+ const condition = (0, selector_1.getCondition)(selector, this);
258
+ return this.#getElementBy(condition);
157
259
  }
158
- this.verifyChild(i, 1);
159
- node.parentNode?.removeChild(node);
160
- /* NOT FOR BROWSER END */
161
- (0, debug_1.setChildNodes)(this, i, 0, [node]);
162
- return node;
163
- }
164
- /**
165
- * Get the closest ancestor node that matches the selector
166
- *
167
- * 最近的符合选择器的祖先节点
168
- * @param selector 选择器
169
- */
170
- closest(selector) {
171
- const condition = (0, selector_1.getCondition)(selector, this);
172
- let { parentNode } = this;
173
- while (parentNode) {
174
- if (condition(parentNode)) {
175
- return parentNode;
260
+ /**
261
+ * 符合条件的所有后代节点
262
+ * @param condition 条件
263
+ */
264
+ #getElementsBy(condition) {
265
+ const descendants = [];
266
+ for (const child of this.childNodes) {
267
+ if (child.type === 'text') {
268
+ continue;
269
+ }
270
+ else if (condition(child)) {
271
+ descendants.push(child);
272
+ }
273
+ descendants.push(...child.#getElementsBy(condition));
176
274
  }
177
- ({ parentNode } = parentNode);
275
+ return descendants;
178
276
  }
179
- return undefined;
180
- }
181
- /**
182
- * 符合条件的第一个后代节点
183
- * @param condition 条件
184
- */
185
- #getElementBy(condition) {
186
- for (const child of this.childNodes) {
187
- if (child.type === 'text') {
188
- continue;
277
+ /**
278
+ * Get all descendants that match the selector
279
+ *
280
+ * 符合选择器的所有后代节点
281
+ * @param selector 选择器
282
+ */
283
+ querySelectorAll(selector) {
284
+ const condition = (0, selector_1.getCondition)(selector, this);
285
+ return this.#getElementsBy(condition);
286
+ }
287
+ /**
288
+ * Insert a batch of child nodes at the end
289
+ *
290
+ * 在末尾批量插入子节点
291
+ * @param elements nodes to be inserted / 插入节点
292
+ */
293
+ append(...elements) {
294
+ for (const element of elements) {
295
+ this.insertAt(element);
296
+ }
297
+ }
298
+ /**
299
+ * Replace all child nodes
300
+ *
301
+ * 批量替换子节点
302
+ * @param elements nodes to be inserted / 新的子节点
303
+ */
304
+ replaceChildren(...elements) {
305
+ for (let i = this.length - 1; i >= 0; i--) {
306
+ this.removeAt(i);
189
307
  }
190
- else if (condition(child)) {
191
- return child;
308
+ this.append(...elements);
309
+ }
310
+ /**
311
+ * Modify the text child node
312
+ *
313
+ * 修改文本子节点
314
+ * @param str new text / 新文本
315
+ * @param i position of the text child node / 子节点位置
316
+ * @throws `RangeError` 对应位置的子节点不是文本节点
317
+ */
318
+ setText(str, i = 0) {
319
+ i += i < 0 ? this.length : 0;
320
+ /* NOT FOR BROWSER */
321
+ this.verifyChild(i);
322
+ /* NOT FOR BROWSER END */
323
+ const oldText = this.childNodes[i];
324
+ if (oldText.type === 'text') { // eslint-disable-line @typescript-eslint/no-unnecessary-condition
325
+ const { data } = oldText;
326
+ oldText.replaceData(str);
327
+ return data;
192
328
  }
193
- const descendant = child.#getElementBy(condition);
194
- if (descendant) {
195
- return descendant;
329
+ /* NOT FOR BROWSER */
330
+ /* istanbul ignore next */
331
+ throw new RangeError(`The child node at position ${i} is ${oldText.constructor.name}!`);
332
+ }
333
+ /** @private */
334
+ toString(skip, separator = '') {
335
+ return this.childNodes.map(child => child.toString(skip)).join(separator);
336
+ }
337
+ /**
338
+ * Get the caret position from the character index
339
+ *
340
+ * 找到给定位置
341
+ * @param index character index / 位置
342
+ */
343
+ caretPositionFromIndex(index) {
344
+ LSP: { // eslint-disable-line no-unused-labels
345
+ if (index === undefined) {
346
+ return undefined;
347
+ }
348
+ const { length } = this.toString();
349
+ if (index > length || index < -length) {
350
+ return undefined;
351
+ }
352
+ index += index < 0 ? length : 0;
353
+ let self = this, acc = 0, start = 0;
354
+ while (self.type !== 'text') {
355
+ const { childNodes } = self;
356
+ acc += self.getAttribute('padding');
357
+ for (let i = 0; acc <= index && i < childNodes.length; i++) {
358
+ const cur = childNodes[i], { nextSibling } = cur, str = cur.toString(), l = str.length;
359
+ cur.setAttribute('aIndex', acc);
360
+ acc += l;
361
+ // 优先选择靠前的非文本兄弟节点,但永不进入假节点
362
+ if (acc > index
363
+ || acc === index && l > 0 && (!nextSibling
364
+ || nextSibling.type === 'text'
365
+ || cur.type !== 'text' && (str.trim() || !nextSibling.toString().trim()))) {
366
+ self = cur;
367
+ acc -= l;
368
+ start = acc;
369
+ break;
370
+ }
371
+ acc += self.getGaps(i);
372
+ }
373
+ if (self.childNodes === childNodes) {
374
+ return { offsetNode: self, offset: index - start };
375
+ }
376
+ }
377
+ return { offsetNode: self, offset: index - start };
196
378
  }
197
379
  }
198
- return undefined;
199
- }
200
- /**
201
- * Get the first descendant that matches the selector
202
- *
203
- * 符合选择器的第一个后代节点
204
- * @param selector 选择器
205
- */
206
- querySelector(selector) {
207
- const condition = (0, selector_1.getCondition)(selector, this);
208
- return this.#getElementBy(condition);
209
- }
210
- /**
211
- * 符合条件的所有后代节点
212
- * @param condition 条件
213
- */
214
- #getElementsBy(condition) {
215
- const descendants = [];
216
- for (const child of this.childNodes) {
217
- if (child.type === 'text') {
218
- continue;
380
+ /**
381
+ * Get the closest ancestor element from the character index
382
+ *
383
+ * 找到给定位置所在的最内层非文本节点
384
+ * @param index character index / 位置
385
+ */
386
+ elementFromIndex(index) {
387
+ LSP: { // eslint-disable-line no-unused-labels
388
+ const node = this.caretPositionFromIndex(index)?.offsetNode;
389
+ return node?.type === 'text' ? node.parentNode : node;
219
390
  }
220
- else if (condition(child)) {
221
- descendants.push(child);
391
+ }
392
+ /**
393
+ * Get the closest ancestor element from the position
394
+ *
395
+ * 找到给定位置所在的最内层非文本节点
396
+ * @param x column number / 列数
397
+ * @param y line number / 行数
398
+ */
399
+ elementFromPoint(x, y) {
400
+ // eslint-disable-next-line no-unused-labels
401
+ LSP: return this.elementFromIndex(this.indexFromPos(y, x));
402
+ }
403
+ /** @private */
404
+ lint(start = this.getAbsoluteIndex(), re) {
405
+ const errors = [];
406
+ for (let i = 0, cur = start + this.getAttribute('padding'); i < this.length; i++) {
407
+ const child = this.childNodes[i];
408
+ child.setAttribute('aIndex', cur);
409
+ errors.push(...child.lint(cur, re));
410
+ cur += child.toString().length + this.getGaps(i);
222
411
  }
223
- descendants.push(...child.#getElementsBy(condition));
412
+ return errors;
224
413
  }
225
- return descendants;
226
- }
227
- /**
228
- * Get all descendants that match the selector
229
- *
230
- * 符合选择器的所有后代节点
231
- * @param selector 选择器
232
- */
233
- querySelectorAll(selector) {
234
- const condition = (0, selector_1.getCondition)(selector, this);
235
- return this.#getElementsBy(condition);
236
- }
237
- /**
238
- * Insert a batch of child nodes at the end
239
- *
240
- * 在末尾批量插入子节点
241
- * @param elements nodes to be inserted / 插入节点
242
- */
243
- append(...elements) {
244
- for (const element of elements) {
245
- this.insertAt(element);
414
+ /** @private */
415
+ print(opt = {}) {
416
+ const cl = opt.class;
417
+ return this.toString()
418
+ ? (cl === '' ? '' : `<span class="wpb-${cl ?? this.type}">`)
419
+ + (0, string_1.print)(this.childNodes, opt)
420
+ + (cl === '' ? '' : '</span>')
421
+ : '';
246
422
  }
247
- }
248
- /**
249
- * Replace all child nodes
250
- *
251
- * 批量替换子节点
252
- * @param elements nodes to be inserted / 新的子节点
253
- */
254
- replaceChildren(...elements) {
255
- for (let i = this.length - 1; i >= 0; i--) {
256
- this.removeAt(i);
257
- }
258
- this.append(...elements);
259
- }
260
- /**
261
- * Modify the text child node
262
- *
263
- * 修改文本子节点
264
- * @param str new text / 新文本
265
- * @param i position of the text child node / 子节点位置
266
- * @throws `RangeError` 对应位置的子节点不是文本节点
267
- */
268
- setText(str, i = 0) {
269
- i += i < 0 ? this.length : 0;
270
- /* NOT FOR BROWSER */
271
- this.verifyChild(i);
272
- /* NOT FOR BROWSER END */
273
- const oldText = this.childNodes[i];
274
- if (oldText.type === 'text') { // eslint-disable-line @typescript-eslint/no-unnecessary-condition
275
- const { data } = oldText;
276
- oldText.replaceData(str);
277
- return data;
423
+ /**
424
+ * Save in JSON format
425
+ *
426
+ * 保存为JSON
427
+ * @param file file name / 文件名
428
+ * @param start
429
+ */
430
+ json(file, start = this.getAbsoluteIndex()) {
431
+ const json = {
432
+ ...this, // eslint-disable-line @typescript-eslint/no-misused-spread
433
+ type: this.type,
434
+ range: [start, start + this.toString().length],
435
+ childNodes: [],
436
+ };
437
+ for (let i = 0, cur = start + this.getAttribute('padding'); i < this.length; i++) {
438
+ const child = this.childNodes[i], { length } = child.toString();
439
+ child.setAttribute('aIndex', cur);
440
+ json.childNodes.push(child.type === 'text'
441
+ ? { data: child.data, range: [cur, cur + length] }
442
+ : child.json(undefined, cur));
443
+ cur += length + this.getGaps(i);
444
+ }
445
+ /* NOT FOR BROWSER */
446
+ /* istanbul ignore if */
447
+ if (typeof file === 'string') {
448
+ fs_1.default.writeFileSync(path_1.default.join(__dirname, '..', '..', 'printed', file + (file.endsWith('.json') ? '' : '.json')), JSON.stringify(json, null, 2));
449
+ }
450
+ /* NOT FOR BROWSER END */
451
+ return json;
278
452
  }
279
453
  /* NOT FOR BROWSER */
280
- /* istanbul ignore next */
281
- throw new RangeError(`The child node at position ${i} is ${oldText.constructor.name}!`);
282
- }
283
- /** @private */
284
- toString(skip, separator = '') {
285
- return this.childNodes.map(child => child.toString(skip)).join(separator);
286
- }
287
- /**
288
- * Get the caret position from the character index
289
- *
290
- * 找到给定位置
291
- * @param index character index / 位置
292
- */
293
- caretPositionFromIndex(index) {
294
- LSP: { // eslint-disable-line no-unused-labels
295
- if (index === undefined) {
296
- return undefined;
297
- }
298
- const { length } = this.toString();
299
- if (index > length || index < -length) {
300
- return undefined;
454
+ /**
455
+ * Check if the current element matches the selector
456
+ *
457
+ * 检查是否符合选择器
458
+ * @param selector 选择器
459
+ */
460
+ matches(selector) {
461
+ return selector === undefined || (0, selector_1.getCondition)(selector, this)(this);
462
+ }
463
+ /**
464
+ * Get all descendants of the types
465
+ *
466
+ * 类型选择器
467
+ * @param types token types / 节点类型
468
+ */
469
+ getElementByTypes(types) {
470
+ const typeSet = new Set(types.split(',').map(str => str.trim()));
471
+ return this.#getElementBy((({ type }) => typeSet.has(type)));
472
+ }
473
+ /**
474
+ * Get the first descendant with the id
475
+ *
476
+ * id选择器
477
+ * @param id id名
478
+ */
479
+ getElementById(id) {
480
+ return this.#getElementBy((token => 'id' in token && token.id === id));
481
+ }
482
+ /**
483
+ * Get all descendants with the class
484
+ *
485
+ * 类选择器
486
+ * @param className class name / 类名之一
487
+ */
488
+ getElementsByClassName(className) {
489
+ return this.#getElementsBy((token => 'classList' in token && token.classList.has(className)));
490
+ }
491
+ /**
492
+ * Get all descendants with the tag name
493
+ *
494
+ * 标签名选择器
495
+ * @param tag tag name / 标签名
496
+ */
497
+ getElementsByTagName(tag) {
498
+ return this.#getElementsBy((({ type, name }) => name === tag && (type === 'html' || type === 'ext')));
499
+ }
500
+ /**
501
+ * Insert a batch of child nodes at the start
502
+ *
503
+ * 在开头批量插入子节点
504
+ * @param elements nodes to be inserted / 插入节点
505
+ */
506
+ prepend(...elements) {
507
+ for (let i = 0; i < elements.length; i++) {
508
+ this.insertAt(elements[i], i);
301
509
  }
302
- index += index < 0 ? length : 0;
303
- let self = this, acc = 0, start = 0;
304
- while (self.type !== 'text') {
305
- const { childNodes } = self;
306
- acc += self.getAttribute('padding');
307
- for (let i = 0; acc <= index && i < childNodes.length; i++) {
308
- const cur = childNodes[i], { nextSibling } = cur, str = cur.toString(), l = str.length;
309
- cur.setAttribute('aIndex', acc);
310
- acc += l;
311
- // 优先选择靠前的非文本兄弟节点,但永不进入假节点
312
- if (acc > index
313
- || acc === index && l > 0 && (!nextSibling
314
- || nextSibling.type === 'text'
315
- || cur.type !== 'text' && (str.trim() || !nextSibling.toString().trim()))) {
316
- self = cur;
317
- acc -= l;
318
- start = acc;
319
- break;
320
- }
321
- acc += self.getGaps(i);
322
- }
323
- if (self.childNodes === childNodes) {
324
- return { offsetNode: self, offset: index - start };
325
- }
510
+ }
511
+ /**
512
+ * 获取子节点的位置
513
+ * @param node 子节点
514
+ * @throws `RangeError` 找不到子节点
515
+ */
516
+ #getChildIndex(node) {
517
+ const i = this.childNodes.indexOf(node);
518
+ /* istanbul ignore if */
519
+ if (i === -1) {
520
+ throw new RangeError('Not a child node!');
326
521
  }
327
- return { offsetNode: self, offset: index - start };
522
+ return i;
328
523
  }
329
- }
330
- /**
331
- * Get the closest ancestor element from the character index
332
- *
333
- * 找到给定位置所在的最内层非文本节点
334
- * @param index character index / 位置
335
- */
336
- elementFromIndex(index) {
337
- LSP: { // eslint-disable-line no-unused-labels
338
- const node = this.caretPositionFromIndex(index)?.offsetNode;
339
- return node?.type === 'text' ? node.parentNode : node;
524
+ /**
525
+ * Remove a child node
526
+ *
527
+ * 移除子节点
528
+ * @param node child node to be removed / 子节点
529
+ */
530
+ removeChild(node) {
531
+ return this.removeAt(this.#getChildIndex(node));
340
532
  }
341
- }
342
- /**
343
- * Get the closest ancestor element from the position
344
- *
345
- * 找到给定位置所在的最内层非文本节点
346
- * @param x column number / 列数
347
- * @param y line number / 行数
348
- */
349
- elementFromPoint(x, y) {
350
- // eslint-disable-next-line no-unused-labels
351
- LSP: return this.elementFromIndex(this.indexFromPos(y, x));
352
- }
353
- /** @private */
354
- lint(start = this.getAbsoluteIndex(), re) {
355
- const errors = [];
356
- for (let i = 0, cur = start + this.getAttribute('padding'); i < this.length; i++) {
357
- const child = this.childNodes[i];
358
- child.setAttribute('aIndex', cur);
359
- errors.push(...child.lint(cur, re));
360
- cur += child.toString().length + this.getGaps(i);
361
- }
362
- return errors;
363
- }
364
- /** @private */
365
- print(opt = {}) {
366
- const cl = opt.class;
367
- return this.toString()
368
- ? (cl === '' ? '' : `<span class="wpb-${cl ?? this.type}">`)
369
- + (0, string_1.print)(this.childNodes, opt)
370
- + (cl === '' ? '' : '</span>')
371
- : '';
372
- }
373
- /**
374
- * Save in JSON format
375
- *
376
- * 保存为JSON
377
- * @param file file name / 文件名
378
- * @param start
379
- */
380
- json(file, start = this.getAbsoluteIndex()) {
381
- const json = {
382
- ...this, // eslint-disable-line @typescript-eslint/no-misused-spread
383
- type: this.type,
384
- range: [start, start + this.toString().length],
385
- childNodes: [],
386
- };
387
- for (let i = 0, cur = start + this.getAttribute('padding'); i < this.length; i++) {
388
- const child = this.childNodes[i], { length } = child.toString();
389
- child.setAttribute('aIndex', cur);
390
- json.childNodes.push(child.type === 'text'
391
- ? { data: child.data, range: [cur, cur + length] }
392
- : child.json(undefined, cur));
393
- cur += length + this.getGaps(i);
533
+ insertBefore(child, reference) {
534
+ return reference === undefined
535
+ ? this.insertAt(child)
536
+ : this.insertAt(child, this.#getChildIndex(reference));
394
537
  }
395
- /* NOT FOR BROWSER */
396
- /* istanbul ignore if */
397
- if (typeof file === 'string') {
398
- fs_1.default.writeFileSync(path_1.default.join(__dirname, '..', '..', 'printed', file + (file.endsWith('.json') ? '' : '.json')), JSON.stringify(json, null, 2));
538
+ /**
539
+ * Get the caret position from the point
540
+ *
541
+ * 找到给定位置
542
+ * @param x column number / 列数
543
+ * @param y line number / 行数
544
+ */
545
+ caretPositionFromPoint(x, y) {
546
+ return this.caretPositionFromIndex(this.indexFromPos(y, x));
399
547
  }
400
- /* NOT FOR BROWSER END */
401
- return json;
402
- }
403
- /* NOT FOR BROWSER */
404
- /**
405
- * Check if the current element matches the selector
406
- *
407
- * 检查是否符合选择器
408
- * @param selector 选择器
409
- */
410
- matches(selector) {
411
- return selector === undefined || (0, selector_1.getCondition)(selector, this)(this);
412
- }
413
- /**
414
- * Get all descendants of the types
415
- *
416
- * 类型选择器
417
- * @param types token types / 节点类型
418
- */
419
- getElementByTypes(types) {
420
- const typeSet = new Set(types.split(',').map(str => str.trim()));
421
- return this.#getElementBy((({ type }) => typeSet.has(type)));
422
- }
423
- /**
424
- * Get the first descendant with the id
425
- *
426
- * id选择器
427
- * @param id id名
428
- */
429
- getElementById(id) {
430
- return this.#getElementBy((token => 'id' in token && token.id === id));
431
- }
432
- /**
433
- * Get all descendants with the class
434
- *
435
- * 类选择器
436
- * @param className class name / 类名之一
437
- */
438
- getElementsByClassName(className) {
439
- return this.#getElementsBy((token => 'classList' in token && token.classList.has(className)));
440
- }
441
- /**
442
- * Get all descendants with the tag name
443
- *
444
- * 标签名选择器
445
- * @param tag tag name / 标签名
446
- */
447
- getElementsByTagName(tag) {
448
- return this.#getElementsBy((({ type, name }) => name === tag && (type === 'html' || type === 'ext')));
449
- }
450
- /**
451
- * Insert a batch of child nodes at the start
452
- *
453
- * 在开头批量插入子节点
454
- * @param elements nodes to be inserted / 插入节点
455
- */
456
- prepend(...elements) {
457
- for (let i = 0; i < elements.length; i++) {
458
- this.insertAt(elements[i], i);
548
+ /**
549
+ * Get all ancestor elements from the character index
550
+ *
551
+ * 找到给定位置所在的所有节点
552
+ * @param index character index / 位置
553
+ */
554
+ elementsFromIndex(index) {
555
+ const offsetNode = this.elementFromIndex(index);
556
+ return offsetNode ? [...offsetNode.getAncestors().reverse(), offsetNode] : [];
459
557
  }
460
- }
461
- /**
462
- * 获取子节点的位置
463
- * @param node 子节点
464
- * @throws `RangeError` 找不到子节点
465
- */
466
- #getChildIndex(node) {
467
- const i = this.childNodes.indexOf(node);
468
- /* istanbul ignore if */
469
- if (i === -1) {
470
- throw new RangeError('Not a child node!');
471
- }
472
- return i;
473
- }
474
- /**
475
- * Remove a child node
476
- *
477
- * 移除子节点
478
- * @param node child node to be removed / 子节点
479
- */
480
- removeChild(node) {
481
- return this.removeAt(this.#getChildIndex(node));
482
- }
483
- insertBefore(child, reference) {
484
- return reference === undefined
485
- ? this.insertAt(child)
486
- : this.insertAt(child, this.#getChildIndex(reference));
487
- }
488
- /**
489
- * Get the caret position from the point
490
- *
491
- * 找到给定位置
492
- * @param x column number / 列数
493
- * @param y line number / 行数
494
- */
495
- caretPositionFromPoint(x, y) {
496
- return this.caretPositionFromIndex(this.indexFromPos(y, x));
497
- }
498
- /**
499
- * Get all ancestor elements from the character index
500
- *
501
- * 找到给定位置所在的所有节点
502
- * @param index character index / 位置
503
- */
504
- elementsFromIndex(index) {
505
- const offsetNode = this.elementFromIndex(index);
506
- return offsetNode ? [...offsetNode.getAncestors().reverse(), offsetNode] : [];
507
- }
508
- /**
509
- * Get all ancestor elements from the position
510
- *
511
- * 找到给定位置所在的所有节点
512
- * @param x column number / 列数
513
- * @param y line number / 行数
514
- */
515
- elementsFromPoint(x, y) {
516
- return this.elementsFromIndex(this.indexFromPos(y, x));
517
- }
518
- }
558
+ /**
559
+ * Get all ancestor elements from the position
560
+ *
561
+ * 找到给定位置所在的所有节点
562
+ * @param x column number / 列数
563
+ * @param y line number / 行数
564
+ */
565
+ elementsFromPoint(x, y) {
566
+ return this.elementsFromIndex(this.indexFromPos(y, x));
567
+ }
568
+ /**
569
+ * Escape `=` and `|`
570
+ *
571
+ * 转义 `=` 和 `|`
572
+ */
573
+ escape() {
574
+ for (const child of this.childNodes) {
575
+ child.escape();
576
+ }
577
+ }
578
+ /** @private */
579
+ toHtmlInternal(opt) {
580
+ for (const child of this.childNodes) {
581
+ if (child.type === 'text') {
582
+ child.removeBlankLines();
583
+ }
584
+ }
585
+ for (let i = 0; i < this.length; i++) {
586
+ const child = this.childNodes[i];
587
+ if (child.is('list') || child.is('dd')) {
588
+ child.getRange();
589
+ }
590
+ }
591
+ this.normalize();
592
+ return (0, html_1.html)(this.childNodes, '', opt);
593
+ }
594
+ };
595
+ })();
519
596
  exports.AstElement = AstElement;
520
597
  constants_1.classes['AstElement'] = __filename;