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.
- package/config/.schema.json +26 -0
- package/dist/index.d.ts +61 -113
- package/dist/index.js +314 -0
- package/dist/lib/element.d.ts +122 -108
- package/dist/lib/element.js +656 -0
- package/dist/lib/node.d.ts +115 -221
- package/dist/lib/node.js +473 -0
- package/dist/lib/ranges.d.ts +27 -26
- package/dist/lib/ranges.js +130 -0
- package/dist/lib/text.d.ts +36 -28
- package/dist/lib/text.js +215 -0
- package/dist/lib/title.d.ts +26 -12
- package/dist/lib/title.js +108 -0
- package/dist/mixin/attributesParent.js +90 -0
- package/dist/mixin/fixed.js +29 -0
- package/dist/mixin/hidden.js +19 -0
- package/dist/mixin/singleLine.js +23 -0
- package/dist/mixin/sol.js +41 -0
- package/dist/parser/brackets.js +118 -0
- package/dist/parser/commentAndExt.js +48 -0
- package/dist/parser/converter.js +31 -0
- package/dist/parser/externalLinks.js +22 -0
- package/dist/parser/hrAndDoubleUnderscore.js +35 -0
- package/dist/parser/html.js +29 -0
- package/dist/parser/links.js +86 -0
- package/dist/parser/list.js +51 -0
- package/dist/parser/magicLinks.js +32 -0
- package/dist/parser/quotes.js +57 -0
- package/dist/parser/selector.js +158 -0
- package/dist/parser/table.js +108 -0
- package/dist/src/arg.d.ts +47 -23
- package/dist/src/arg.js +196 -0
- package/dist/src/atom.d.ts +12 -0
- package/dist/src/atom.js +22 -0
- package/dist/src/attribute.d.ts +74 -33
- package/dist/src/attribute.js +433 -0
- package/dist/src/attributes.d.ts +61 -55
- package/dist/src/attributes.js +371 -0
- package/dist/src/converter.d.ts +45 -71
- package/dist/src/converter.js +135 -0
- package/dist/src/converterFlags.d.ts +64 -39
- package/dist/src/converterFlags.js +235 -0
- package/dist/src/converterRule.d.ts +49 -27
- package/dist/src/converterRule.js +255 -0
- package/dist/src/extLink.d.ts +41 -38
- package/dist/src/extLink.js +154 -0
- package/dist/src/gallery.d.ts +59 -18
- package/dist/src/gallery.js +132 -0
- package/dist/src/heading.d.ts +60 -22
- package/dist/src/heading.js +135 -0
- package/dist/src/hidden.d.ts +20 -0
- package/dist/src/hidden.js +24 -0
- package/dist/src/html.d.ts +83 -29
- package/dist/src/html.js +242 -0
- package/dist/src/imageParameter.d.ts +59 -40
- package/dist/src/imageParameter.js +251 -0
- package/dist/src/imagemap.d.ts +65 -21
- package/dist/src/imagemap.js +169 -0
- package/dist/src/imagemapLink.d.ts +46 -14
- package/dist/src/imagemapLink.js +38 -0
- package/dist/src/index.d.ts +71 -105
- package/dist/src/index.js +826 -0
- package/dist/src/link/base.d.ts +71 -0
- package/dist/src/link/base.js +225 -0
- package/dist/src/link/category.d.ts +10 -11
- package/dist/src/link/category.js +26 -0
- package/dist/src/link/file.d.ts +61 -39
- package/dist/src/link/file.js +242 -0
- package/dist/src/link/galleryImage.d.ts +34 -12
- package/dist/src/link/galleryImage.js +98 -0
- package/dist/src/link/index.d.ts +25 -63
- package/dist/src/link/index.js +136 -0
- package/dist/src/magicLink.d.ts +22 -15
- package/dist/src/magicLink.js +126 -0
- package/dist/src/nested.d.ts +47 -0
- package/dist/src/nested.js +84 -0
- package/dist/src/nowiki/base.d.ts +39 -0
- package/dist/src/nowiki/base.js +29 -0
- package/dist/src/nowiki/comment.d.ts +31 -20
- package/dist/src/nowiki/comment.js +61 -0
- package/dist/src/nowiki/dd.d.ts +17 -11
- package/dist/src/nowiki/dd.js +50 -0
- package/dist/src/nowiki/doubleUnderscore.d.ts +28 -13
- package/dist/src/nowiki/doubleUnderscore.js +45 -0
- package/dist/src/nowiki/hr.d.ts +28 -10
- package/dist/src/nowiki/hr.js +33 -0
- package/dist/src/nowiki/index.d.ts +17 -23
- package/dist/src/nowiki/index.js +21 -0
- package/dist/src/nowiki/list.d.ts +15 -7
- package/dist/src/nowiki/list.js +11 -0
- package/dist/src/nowiki/noinclude.d.ts +20 -7
- package/dist/src/nowiki/noinclude.js +22 -0
- package/dist/src/nowiki/quote.d.ts +25 -10
- package/dist/src/nowiki/quote.js +55 -0
- package/dist/src/onlyinclude.d.ts +28 -12
- package/dist/src/onlyinclude.js +64 -0
- package/dist/src/paramTag/index.d.ts +40 -17
- package/dist/src/paramTag/index.js +76 -0
- package/dist/src/paramTag/inputbox.d.ts +8 -7
- package/dist/src/paramTag/inputbox.js +19 -0
- package/dist/src/parameter.d.ts +62 -41
- package/dist/src/parameter.js +201 -0
- package/dist/src/pre.d.ts +32 -0
- package/dist/src/pre.js +39 -0
- package/dist/src/syntax.d.ts +17 -14
- package/dist/src/syntax.js +65 -0
- package/dist/src/table/base.d.ts +55 -0
- package/dist/src/table/base.js +77 -0
- package/dist/src/table/index.d.ts +123 -156
- package/dist/src/table/index.js +811 -0
- package/dist/src/table/td.d.ts +90 -67
- package/dist/src/table/td.js +276 -0
- package/dist/src/table/tr.d.ts +30 -85
- package/dist/src/table/tr.js +48 -0
- package/dist/src/table/trBase.d.ts +72 -0
- package/dist/src/table/trBase.js +153 -0
- package/dist/src/tagPair/ext.d.ts +47 -11
- package/dist/src/tagPair/ext.js +127 -0
- package/dist/src/tagPair/include.d.ts +32 -13
- package/dist/src/tagPair/include.js +40 -0
- package/dist/src/tagPair/index.d.ts +44 -29
- package/dist/src/tagPair/index.js +111 -0
- package/dist/src/transclude.d.ts +88 -85
- package/dist/src/transclude.js +739 -0
- package/dist/util/base.js +26 -0
- package/dist/util/debug.js +52 -0
- package/dist/util/diff.js +69 -0
- package/dist/util/lint.js +38 -0
- package/dist/util/string.js +103 -0
- package/errors/README +1 -0
- package/i18n/zh-hans.json +1 -0
- package/i18n/zh-hant.json +1 -0
- package/package.json +21 -24
- package/printed/README +1 -0
- package/dist/mixin/attributeParent.d.ts +0 -9
- package/dist/mixin/fixedToken.d.ts +0 -8
- package/dist/mixin/hidden.d.ts +0 -8
- package/dist/mixin/singleLine.d.ts +0 -8
- package/dist/mixin/sol.d.ts +0 -8
- package/dist/parser/brackets.d.ts +0 -12
- package/dist/parser/commentAndExt.d.ts +0 -8
- package/dist/parser/converter.d.ts +0 -7
- package/dist/parser/externalLinks.d.ts +0 -7
- package/dist/parser/hrAndDoubleUnderscore.d.ts +0 -11
- package/dist/parser/html.d.ts +0 -7
- package/dist/parser/links.d.ts +0 -7
- package/dist/parser/list.d.ts +0 -7
- package/dist/parser/magicLinks.d.ts +0 -7
- package/dist/parser/quotes.d.ts +0 -7
- package/dist/parser/selector.d.ts +0 -12
- package/dist/parser/table.d.ts +0 -11
- package/dist/src/atom/hidden.d.ts +0 -5
- package/dist/src/atom/index.d.ts +0 -15
- package/dist/src/charinsert.d.ts +0 -32
- package/dist/src/hasNowiki/index.d.ts +0 -14
- package/dist/src/hasNowiki/pre.d.ts +0 -13
- package/dist/src/nested/choose.d.ts +0 -13
- package/dist/src/nested/combobox.d.ts +0 -13
- package/dist/src/nested/index.d.ts +0 -18
- package/dist/src/nested/references.d.ts +0 -13
- package/dist/tool/index.d.ts +0 -420
- package/dist/util/base.d.ts +0 -10
- package/dist/util/debug.d.ts +0 -20
- package/dist/util/diff.d.ts +0 -8
- package/dist/util/lint.d.ts +0 -28
- package/dist/util/string.d.ts +0 -55
- package/index.js +0 -333
- package/lib/element.js +0 -618
- package/lib/node.js +0 -730
- package/lib/ranges.js +0 -130
- package/lib/text.js +0 -265
- package/lib/title.js +0 -83
- package/mixin/attributeParent.js +0 -117
- package/mixin/fixedToken.js +0 -40
- package/mixin/hidden.js +0 -21
- package/mixin/singleLine.js +0 -31
- package/mixin/sol.js +0 -54
- package/parser/brackets.js +0 -128
- package/parser/commentAndExt.js +0 -62
- package/parser/converter.js +0 -46
- package/parser/externalLinks.js +0 -33
- package/parser/hrAndDoubleUnderscore.js +0 -49
- package/parser/html.js +0 -42
- package/parser/links.js +0 -94
- package/parser/list.js +0 -59
- package/parser/magicLinks.js +0 -41
- package/parser/quotes.js +0 -64
- package/parser/selector.js +0 -180
- package/parser/table.js +0 -114
- package/src/arg.js +0 -207
- package/src/atom/hidden.js +0 -13
- package/src/atom/index.js +0 -43
- package/src/attribute.js +0 -472
- package/src/attributes.js +0 -453
- package/src/charinsert.js +0 -97
- package/src/converter.js +0 -176
- package/src/converterFlags.js +0 -284
- package/src/converterRule.js +0 -256
- package/src/extLink.js +0 -180
- package/src/gallery.js +0 -149
- package/src/hasNowiki/index.js +0 -44
- package/src/hasNowiki/pre.js +0 -40
- package/src/heading.js +0 -134
- package/src/html.js +0 -254
- package/src/imageParameter.js +0 -303
- package/src/imagemap.js +0 -199
- package/src/imagemapLink.js +0 -41
- package/src/index.js +0 -938
- package/src/link/category.js +0 -44
- package/src/link/file.js +0 -287
- package/src/link/galleryImage.js +0 -120
- package/src/link/index.js +0 -388
- package/src/magicLink.js +0 -151
- package/src/nested/choose.js +0 -24
- package/src/nested/combobox.js +0 -23
- package/src/nested/index.js +0 -96
- package/src/nested/references.js +0 -23
- package/src/nowiki/comment.js +0 -71
- package/src/nowiki/dd.js +0 -59
- package/src/nowiki/doubleUnderscore.js +0 -56
- package/src/nowiki/hr.js +0 -41
- package/src/nowiki/index.js +0 -56
- package/src/nowiki/list.js +0 -16
- package/src/nowiki/noinclude.js +0 -28
- package/src/nowiki/quote.js +0 -69
- package/src/onlyinclude.js +0 -64
- package/src/paramTag/index.js +0 -89
- package/src/paramTag/inputbox.js +0 -35
- package/src/parameter.js +0 -239
- package/src/syntax.js +0 -91
- package/src/table/index.js +0 -985
- package/src/table/td.js +0 -343
- package/src/table/tr.js +0 -319
- package/src/tagPair/ext.js +0 -146
- package/src/tagPair/include.js +0 -50
- package/src/tagPair/index.js +0 -131
- package/src/transclude.js +0 -843
- package/tool/index.js +0 -1209
- package/typings/api.d.ts +0 -9
- package/typings/array.d.ts +0 -29
- package/typings/event.d.ts +0 -22
- package/typings/index.d.ts +0 -118
- package/typings/node.d.ts +0 -35
- package/typings/parser.d.ts +0 -12
- package/typings/table.d.ts +0 -10
- package/typings/token.d.ts +0 -31
- package/typings/tool.d.ts +0 -6
- package/util/base.js +0 -17
- package/util/debug.js +0 -73
- package/util/diff.js +0 -76
- package/util/lint.js +0 -57
- package/util/string.js +0 -126
package/dist/lib/node.js
ADDED
|
@@ -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;
|
package/dist/lib/ranges.d.ts
CHANGED
|
@@ -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
|
|
7
|
+
* @param s 表达式
|
|
23
8
|
* @throws `RangeError` 起点、终点和步长均应为整数
|
|
24
9
|
* @throws `RangeError` n的系数不能为0
|
|
25
10
|
* @throws `RangeError` 应使用CSS选择器或Python切片的格式
|
|
26
11
|
*/
|
|
27
|
-
constructor(
|
|
28
|
-
start: number;
|
|
29
|
-
end: number;
|
|
30
|
-
step: number;
|
|
12
|
+
constructor(s: string | Range);
|
|
31
13
|
/**
|
|
32
14
|
* 将Range转换为针对特定数组的下标集
|
|
33
|
-
* @param
|
|
34
|
-
* @complexity `n`
|
|
15
|
+
* @param arr 参考数组
|
|
35
16
|
*/
|
|
36
|
-
applyTo(arr: 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;
|