wikiparser-node 1.0.3 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/addon/table.js +89 -61
- package/dist/index.d.ts +1 -1
- package/dist/index.js +14 -9
- package/dist/lib/node.js +10 -9
- package/dist/lib/range.d.ts +2 -13
- package/dist/lib/range.js +148 -115
- package/dist/lib/ranges.d.ts +4 -6
- package/dist/lib/ranges.js +25 -28
- package/dist/lib/text.js +3 -2
- package/dist/lib/title.d.ts +13 -1
- package/dist/lib/title.js +53 -16
- package/dist/parser/commentAndExt.js +5 -1
- package/dist/parser/selector.js +1 -1
- package/dist/src/html.d.ts +7 -1
- package/dist/src/html.js +16 -15
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/magicLink.d.ts +1 -1
- package/dist/src/nowiki/doubleUnderscore.d.ts +1 -1
- package/dist/src/nowiki/hr.d.ts +1 -1
- package/dist/src/nowiki/list.js +2 -1
- package/dist/src/nowiki/listBase.d.ts +1 -1
- package/dist/src/nowiki/quote.d.ts +1 -1
- package/dist/src/syntax.d.ts +1 -1
- package/dist/src/table/base.d.ts +1 -1
- package/dist/src/table/index.js +15 -0
- package/dist/src/tagPair/ext.d.ts +1 -1
- package/dist/src/tagPair/index.js +2 -2
- package/dist/util/constants.js +2 -1
- package/dist/util/debug.js +2 -0
- package/dist/util/diff.js +2 -0
- package/dist/util/lint.js +2 -0
- package/dist/util/string.js +2 -0
- package/package.json +1 -1
package/dist/lib/range.js
CHANGED
|
@@ -19,7 +19,6 @@ class AstRange {
|
|
|
19
19
|
* @param start 是否未初始化起点
|
|
20
20
|
* @throws `Error` 未初始化
|
|
21
21
|
*/
|
|
22
|
-
// eslint-disable-next-line class-methods-use-this
|
|
23
22
|
#notInit(start) {
|
|
24
23
|
throw new Error(`请先指定${start ? '起始' : '终止'}位置!`);
|
|
25
24
|
}
|
|
@@ -57,72 +56,111 @@ class AstRange {
|
|
|
57
56
|
}
|
|
58
57
|
/** 起始和终止位置是否重合 */
|
|
59
58
|
get collapsed() {
|
|
60
|
-
return this.
|
|
59
|
+
return this.startContainer === this.endContainer && this.startOffset === this.endOffset;
|
|
61
60
|
}
|
|
62
61
|
/** 最近的公共祖先 */
|
|
63
62
|
get commonAncestorContainer() {
|
|
64
63
|
const { startContainer, endContainer } = this;
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
return startContainer.contains(endContainer) ? startContainer : startContainer.parentNode;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* 检查起点和终点的设置是否有效
|
|
68
|
+
* @throws `RangeError` 起点和终点不是兄弟节点
|
|
69
|
+
* @throws `RangeError` 起点位于终点之后
|
|
70
|
+
*/
|
|
71
|
+
#check() {
|
|
72
|
+
const { startContainer, startOffset, endContainer, endOffset } = this;
|
|
73
|
+
if (startContainer === endContainer) {
|
|
74
|
+
if (startOffset > endOffset) {
|
|
75
|
+
throw new RangeError('起点不能位于终点之后!');
|
|
76
|
+
}
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const { type: startType, parentNode: startParent } = startContainer, { type: endType, parentNode: endParent } = endContainer;
|
|
80
|
+
if (startType !== 'text') {
|
|
81
|
+
if (endType !== 'text' || startContainer !== endParent) {
|
|
82
|
+
throw new RangeError('起点和终点不是兄弟节点!');
|
|
83
|
+
}
|
|
84
|
+
else if (startOffset > endParent.childNodes.indexOf(endContainer)) {
|
|
85
|
+
throw new RangeError('起点不能位于终点之后!');
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
else if (endType === 'text') {
|
|
89
|
+
if (!startParent || startParent !== endParent) {
|
|
90
|
+
throw new RangeError('起点和终点不是兄弟节点!');
|
|
91
|
+
}
|
|
92
|
+
const { childNodes } = startParent;
|
|
93
|
+
if (childNodes.indexOf(startContainer) > childNodes.indexOf(endContainer)) {
|
|
94
|
+
throw new RangeError('起点不能位于终点之后!');
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
else if (startParent !== endContainer) {
|
|
98
|
+
throw new RangeError('起点和终点不是兄弟节点!');
|
|
99
|
+
}
|
|
100
|
+
else if (endOffset <= startParent.childNodes.indexOf(startContainer)) {
|
|
101
|
+
throw new RangeError('起点不能位于终点之后!');
|
|
68
102
|
}
|
|
69
|
-
return parentNode;
|
|
70
103
|
}
|
|
71
104
|
/**
|
|
72
105
|
* 设置起点
|
|
73
106
|
* @param startNode 起点容器
|
|
74
107
|
* @param startOffset 起点位置
|
|
75
|
-
* @throws `RangeError` 不在同一个文档
|
|
76
108
|
* @throws `RangeError` offset取值超出范围
|
|
77
109
|
*/
|
|
78
110
|
setStart(startNode, startOffset) {
|
|
79
|
-
const
|
|
80
|
-
if (
|
|
81
|
-
throw new RangeError('起点不在同一个文档中!');
|
|
82
|
-
}
|
|
83
|
-
else if (startOffset < 0 || startOffset > length) {
|
|
111
|
+
const { length } = startNode;
|
|
112
|
+
if (startOffset < 0 || startOffset > length) {
|
|
84
113
|
throw new RangeError(`offset取值范围应为 0 ~ ${length}`);
|
|
85
114
|
}
|
|
86
|
-
else if (root && getIndex(startNode, startOffset) > this.endIndex) {
|
|
87
|
-
throw new RangeError('起点不能位于终点之后!');
|
|
88
|
-
}
|
|
89
115
|
this.#startContainer = startNode;
|
|
90
116
|
this.#startOffset = startOffset;
|
|
117
|
+
if (this.#endContainer) {
|
|
118
|
+
try {
|
|
119
|
+
this.#check();
|
|
120
|
+
}
|
|
121
|
+
catch (e) {
|
|
122
|
+
this.#startContainer = undefined;
|
|
123
|
+
this.#startOffset = undefined;
|
|
124
|
+
throw e;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
91
127
|
}
|
|
92
128
|
/**
|
|
93
129
|
* 设置终点
|
|
94
130
|
* @param endNode 终点容器
|
|
95
131
|
* @param endOffset 终点位置
|
|
96
|
-
* @throws `RangeError` 不在同一个文档
|
|
97
132
|
* @throws `RangeError` offset取值超出范围
|
|
98
133
|
*/
|
|
99
134
|
setEnd(endNode, endOffset) {
|
|
100
|
-
const
|
|
101
|
-
if (
|
|
102
|
-
throw new RangeError('终点不在同一个文档中!');
|
|
103
|
-
}
|
|
104
|
-
else if (endOffset < 0 || endOffset > length) {
|
|
135
|
+
const { length } = endNode;
|
|
136
|
+
if (endOffset < 0 || endOffset > length) {
|
|
105
137
|
throw new RangeError(`offset取值范围应为 0 ~ ${length}`);
|
|
106
138
|
}
|
|
107
|
-
else if (root && getIndex(endNode, endOffset) < this.startIndex) {
|
|
108
|
-
throw new RangeError('终点不能位于起点之前!');
|
|
109
|
-
}
|
|
110
139
|
this.#endContainer = endNode;
|
|
111
140
|
this.#endOffset = endOffset;
|
|
141
|
+
if (this.#startContainer) {
|
|
142
|
+
try {
|
|
143
|
+
this.#check();
|
|
144
|
+
}
|
|
145
|
+
catch (e) {
|
|
146
|
+
this.#endContainer = undefined;
|
|
147
|
+
this.#endOffset = undefined;
|
|
148
|
+
throw e;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
112
151
|
}
|
|
113
152
|
/**
|
|
114
153
|
* 在节点后设置
|
|
115
154
|
* @param method 方法名
|
|
116
155
|
* @param referenceNode 节点
|
|
156
|
+
* @throws `RangeError` 参考节点没有父节点
|
|
117
157
|
*/
|
|
118
158
|
#setAfter(method, referenceNode) {
|
|
119
159
|
const { parentNode } = referenceNode;
|
|
120
|
-
if (parentNode) {
|
|
121
|
-
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
this[method](referenceNode, referenceNode.length);
|
|
160
|
+
if (!parentNode) {
|
|
161
|
+
throw new RangeError('参考节点没有父节点!');
|
|
125
162
|
}
|
|
163
|
+
this[method](parentNode, parentNode.childNodes.indexOf(referenceNode) + 1);
|
|
126
164
|
}
|
|
127
165
|
/**
|
|
128
166
|
* 在节点后设置起点
|
|
@@ -142,15 +180,14 @@ class AstRange {
|
|
|
142
180
|
* 在节点前设置
|
|
143
181
|
* @param method 方法名
|
|
144
182
|
* @param referenceNode 节点
|
|
183
|
+
* @throws `RangeError` 参考节点没有父节点
|
|
145
184
|
*/
|
|
146
185
|
#setBefore(method, referenceNode) {
|
|
147
186
|
const { parentNode } = referenceNode;
|
|
148
|
-
if (parentNode) {
|
|
149
|
-
|
|
150
|
-
}
|
|
151
|
-
else {
|
|
152
|
-
this[method](referenceNode, 0);
|
|
187
|
+
if (!parentNode) {
|
|
188
|
+
throw new RangeError('参考节点没有父节点!');
|
|
153
189
|
}
|
|
190
|
+
this[method](parentNode, parentNode.childNodes.indexOf(referenceNode));
|
|
154
191
|
}
|
|
155
192
|
/**
|
|
156
193
|
* 在节点前设置起点
|
|
@@ -179,19 +216,18 @@ class AstRange {
|
|
|
179
216
|
/**
|
|
180
217
|
* 设置Range包含整个节点
|
|
181
218
|
* @param referenceNode 节点
|
|
219
|
+
* @throws `RangeError` 参考节点没有父节点
|
|
182
220
|
*/
|
|
183
221
|
selectNode(referenceNode) {
|
|
184
222
|
const { parentNode } = referenceNode;
|
|
185
|
-
if (parentNode) {
|
|
186
|
-
|
|
187
|
-
this.#startContainer = parentNode;
|
|
188
|
-
this.#startOffset = i;
|
|
189
|
-
this.#endContainer = parentNode;
|
|
190
|
-
this.#endOffset = i + 1;
|
|
191
|
-
}
|
|
192
|
-
else {
|
|
193
|
-
this.selectNodeContents(referenceNode);
|
|
223
|
+
if (!parentNode) {
|
|
224
|
+
throw new RangeError('参考节点没有父节点!');
|
|
194
225
|
}
|
|
226
|
+
const i = parentNode.childNodes.indexOf(referenceNode);
|
|
227
|
+
this.#startContainer = parentNode;
|
|
228
|
+
this.#startOffset = i;
|
|
229
|
+
this.#endContainer = parentNode;
|
|
230
|
+
this.#endOffset = i + 1;
|
|
195
231
|
}
|
|
196
232
|
/**
|
|
197
233
|
* 使起始和终止位置重合
|
|
@@ -214,38 +250,24 @@ class AstRange {
|
|
|
214
250
|
* @throws `RangeError` 不在同一个文档
|
|
215
251
|
*/
|
|
216
252
|
comparePoint(referenceNode, offset) {
|
|
217
|
-
const { startContainer, startIndex, endIndex } = this;
|
|
253
|
+
const { startContainer, startIndex, endContainer, endIndex } = this;
|
|
218
254
|
if (startContainer.getRootNode() !== referenceNode.getRootNode()) {
|
|
219
255
|
throw new RangeError('待比较的端点不在同一个文档中!');
|
|
220
256
|
}
|
|
221
257
|
const index = getIndex(referenceNode, offset);
|
|
222
|
-
if (index < startIndex) {
|
|
258
|
+
if (index < startIndex || index === startIndex && !startContainer.contains(referenceNode)) {
|
|
223
259
|
return -1;
|
|
224
260
|
}
|
|
225
|
-
return index
|
|
261
|
+
return index < endIndex || index === endIndex && endContainer.contains(referenceNode) ? 0 : 1;
|
|
226
262
|
}
|
|
227
263
|
/**
|
|
228
264
|
* 端点是否在Range中
|
|
229
265
|
* @param referenceNode 端点容器
|
|
230
266
|
* @param offset 端点位置
|
|
231
|
-
* @throws `RangeError` 不在同一个文档
|
|
232
267
|
*/
|
|
233
268
|
isPointInRange(referenceNode, offset) {
|
|
234
269
|
return this.comparePoint(referenceNode, offset) === 0;
|
|
235
270
|
}
|
|
236
|
-
/**
|
|
237
|
-
* 是否与节点相交
|
|
238
|
-
* @param referenceNode 节点
|
|
239
|
-
* @throws `RangeError` 不在同一个文档
|
|
240
|
-
*/
|
|
241
|
-
intersectsNode(referenceNode) {
|
|
242
|
-
const { startContainer, startIndex, endIndex } = this;
|
|
243
|
-
if (startContainer.getRootNode() !== referenceNode.getRootNode()) {
|
|
244
|
-
throw new RangeError('待比较的端点不在同一个文档中!');
|
|
245
|
-
}
|
|
246
|
-
const index = referenceNode.getAbsoluteIndex();
|
|
247
|
-
return index < endIndex && index + String(referenceNode).length > startIndex;
|
|
248
|
-
}
|
|
249
271
|
/** 复制AstRange对象 */
|
|
250
272
|
cloneRange() {
|
|
251
273
|
const range = new AstRange();
|
|
@@ -255,38 +277,26 @@ class AstRange {
|
|
|
255
277
|
}
|
|
256
278
|
/** 删除Range中的内容 */
|
|
257
279
|
deleteContents() {
|
|
258
|
-
const { startContainer,
|
|
259
|
-
let {
|
|
260
|
-
|
|
261
|
-
(
|
|
262
|
-
|
|
263
|
-
endContainer.deleteData(0, endOffset);
|
|
264
|
-
}
|
|
265
|
-
else {
|
|
266
|
-
for (let i = endOffset - 1; i >= 0; i--) {
|
|
267
|
-
endContainer.removeAt(i);
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
endOffset = parentNode.childNodes.indexOf(endContainer);
|
|
271
|
-
endContainer = parentNode;
|
|
280
|
+
const { startContainer, endContainer, commonAncestorContainer } = this, { childNodes } = commonAncestorContainer;
|
|
281
|
+
let { startOffset, endOffset } = this;
|
|
282
|
+
if (commonAncestorContainer.type === 'text') {
|
|
283
|
+
commonAncestorContainer.deleteData(startOffset, endOffset);
|
|
284
|
+
return;
|
|
272
285
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
endContainer.removeAt(i);
|
|
277
|
-
}
|
|
278
|
-
endContainer = childNodes[j];
|
|
279
|
-
endOffset = endContainer.length;
|
|
286
|
+
else if (startContainer.type === 'text') {
|
|
287
|
+
startContainer.deleteData(startOffset, Infinity);
|
|
288
|
+
startOffset = childNodes.indexOf(startContainer) + 1;
|
|
280
289
|
}
|
|
281
290
|
if (endContainer.type === 'text') {
|
|
282
|
-
endContainer.deleteData(
|
|
291
|
+
endContainer.deleteData(0, endOffset);
|
|
292
|
+
endOffset = childNodes.indexOf(endContainer);
|
|
283
293
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
endContainer.removeAt(i);
|
|
287
|
-
}
|
|
294
|
+
for (let i = endOffset - 1; i >= startOffset; i--) {
|
|
295
|
+
commonAncestorContainer.removeAt(i);
|
|
288
296
|
}
|
|
289
|
-
this.#
|
|
297
|
+
this.#startContainer = commonAncestorContainer;
|
|
298
|
+
this.#startOffset = startOffset;
|
|
299
|
+
this.#endContainer = commonAncestorContainer;
|
|
290
300
|
this.#endOffset = startOffset;
|
|
291
301
|
}
|
|
292
302
|
/** 获取行列位置和大小 */
|
|
@@ -299,50 +309,73 @@ class AstRange {
|
|
|
299
309
|
* @param newNode 插入的节点
|
|
300
310
|
*/
|
|
301
311
|
insertNode(newNode) {
|
|
302
|
-
const { startContainer, startOffset } = this;
|
|
312
|
+
const { startContainer, startOffset } = this, endContainer = this.#endContainer;
|
|
303
313
|
if (startContainer.type === 'text') {
|
|
304
|
-
|
|
305
|
-
|
|
314
|
+
if (startOffset) {
|
|
315
|
+
startContainer.splitText(startOffset);
|
|
316
|
+
this.#startContainer = startContainer.nextSibling;
|
|
317
|
+
this.#startOffset = 0;
|
|
318
|
+
startContainer.after(newNode);
|
|
319
|
+
if (endContainer === startContainer) {
|
|
320
|
+
this.#endContainer = this.#startContainer;
|
|
321
|
+
this.#endOffset -= startOffset;
|
|
322
|
+
}
|
|
323
|
+
else if (endContainer && endContainer.type !== 'text') {
|
|
324
|
+
this.#endOffset += 2;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
else {
|
|
328
|
+
startContainer.before(newNode);
|
|
329
|
+
if (endContainer && endContainer.type !== 'text') {
|
|
330
|
+
this.#endOffset++;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
306
333
|
}
|
|
307
334
|
else {
|
|
308
335
|
startContainer.insertAt(newNode, startOffset);
|
|
336
|
+
this.#startOffset++;
|
|
337
|
+
if (endContainer === startContainer) {
|
|
338
|
+
this.#endOffset++;
|
|
339
|
+
}
|
|
309
340
|
}
|
|
310
341
|
}
|
|
311
342
|
/** @private */
|
|
312
343
|
toString() {
|
|
313
|
-
|
|
344
|
+
const { startContainer, startIndex, endIndex } = this;
|
|
345
|
+
return String(startContainer.getRootNode()).slice(startIndex, endIndex);
|
|
314
346
|
}
|
|
315
|
-
/**
|
|
316
|
-
* 在满足条件时获取范围内的全部节点
|
|
317
|
-
* @throws `Error` 不是某个节点的连续子节点
|
|
318
|
-
*/
|
|
347
|
+
/** 获取范围内的全部节点 */
|
|
319
348
|
extractContents() {
|
|
320
|
-
|
|
321
|
-
return [];
|
|
322
|
-
}
|
|
323
|
-
const { startContainer, endContainer, commonAncestorContainer } = this;
|
|
324
|
-
let { startOffset, endOffset } = this;
|
|
349
|
+
const { startContainer, startOffset, endContainer, endOffset, commonAncestorContainer } = this, { childNodes } = commonAncestorContainer;
|
|
325
350
|
if (commonAncestorContainer.type === 'text') {
|
|
351
|
+
if (startOffset === endOffset) {
|
|
352
|
+
return [];
|
|
353
|
+
}
|
|
326
354
|
commonAncestorContainer.splitText(endOffset);
|
|
327
355
|
commonAncestorContainer.splitText(startOffset);
|
|
328
|
-
|
|
356
|
+
const { nextSibling } = commonAncestorContainer;
|
|
357
|
+
this.#startContainer = nextSibling;
|
|
358
|
+
this.#startOffset = 0;
|
|
359
|
+
this.#endContainer = nextSibling;
|
|
360
|
+
this.#endOffset -= startOffset;
|
|
361
|
+
return [nextSibling];
|
|
329
362
|
}
|
|
330
|
-
else if (
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
if (endContainer.type === 'text' && endContainer.parentNode === commonAncestorContainer) {
|
|
337
|
-
endContainer.splitText(endOffset);
|
|
338
|
-
endOffset = commonAncestorContainer.childNodes.indexOf(endContainer);
|
|
363
|
+
else if (endContainer.type === 'text') {
|
|
364
|
+
if (endOffset && endOffset < endContainer.length) {
|
|
365
|
+
endContainer.splitText(endOffset);
|
|
366
|
+
}
|
|
367
|
+
this.#endContainer = commonAncestorContainer;
|
|
368
|
+
this.#endOffset = childNodes.indexOf(endContainer) + (endOffset && 1);
|
|
339
369
|
}
|
|
340
|
-
if (startContainer.type === 'text'
|
|
341
|
-
startContainer.
|
|
342
|
-
|
|
343
|
-
|
|
370
|
+
if (startContainer.type === 'text') {
|
|
371
|
+
if (startOffset && startOffset < startContainer.length) {
|
|
372
|
+
startContainer.splitText(startOffset);
|
|
373
|
+
this.#endOffset++;
|
|
374
|
+
}
|
|
375
|
+
this.#startContainer = commonAncestorContainer;
|
|
376
|
+
this.#startOffset = childNodes.indexOf(startContainer) + (startOffset && 1);
|
|
344
377
|
}
|
|
345
|
-
return commonAncestorContainer.childNodes.slice(startOffset, endOffset);
|
|
378
|
+
return commonAncestorContainer.childNodes.slice(this.#startOffset, this.#endOffset);
|
|
346
379
|
}
|
|
347
380
|
/** 在满足条件时拷贝范围内的全部节点 */
|
|
348
381
|
cloneContents() {
|
package/dist/lib/ranges.d.ts
CHANGED
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
/** 模拟Python的Range对象。除`step`至少为`1`外,允许负数、小数或`end < start`的情形。 */
|
|
2
2
|
export declare class Range {
|
|
3
|
-
|
|
4
|
-
end: number;
|
|
5
|
-
step: number;
|
|
3
|
+
#private;
|
|
6
4
|
/**
|
|
7
5
|
* @param s 表达式
|
|
8
6
|
* @throws `RangeError` 起点、终点和步长均应为整数
|
|
9
7
|
* @throws `RangeError` n的系数不能为0
|
|
10
8
|
* @throws `RangeError` 应使用CSS选择器或Python切片的格式
|
|
11
9
|
*/
|
|
12
|
-
constructor(str: string
|
|
10
|
+
constructor(str: string);
|
|
13
11
|
/**
|
|
14
12
|
* 将Range转换为针对特定数组的下标集
|
|
15
|
-
* @param arr
|
|
13
|
+
* @param arr 参考数组`[0, 1, 2, ...]`
|
|
16
14
|
*/
|
|
17
|
-
applyTo(arr: number
|
|
15
|
+
applyTo(arr: number[]): number[];
|
|
18
16
|
}
|
|
19
17
|
/** @extends {Array<number|Range>} */
|
|
20
18
|
export declare class Ranges extends Array<number | Range> {
|
package/dist/lib/ranges.js
CHANGED
|
@@ -4,6 +4,9 @@ exports.Ranges = exports.Range = void 0;
|
|
|
4
4
|
const constants_1 = require("../util/constants");
|
|
5
5
|
/** 模拟Python的Range对象。除`step`至少为`1`外,允许负数、小数或`end < start`的情形。 */
|
|
6
6
|
class Range {
|
|
7
|
+
#start;
|
|
8
|
+
#end;
|
|
9
|
+
#step;
|
|
7
10
|
/**
|
|
8
11
|
* @param s 表达式
|
|
9
12
|
* @throws `RangeError` 起点、终点和步长均应为整数
|
|
@@ -11,10 +14,6 @@ class Range {
|
|
|
11
14
|
* @throws `RangeError` 应使用CSS选择器或Python切片的格式
|
|
12
15
|
*/
|
|
13
16
|
constructor(str) {
|
|
14
|
-
if (str instanceof Range) {
|
|
15
|
-
Object.assign(this, str);
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
17
|
str = str.trim();
|
|
19
18
|
if (str === 'odd') {
|
|
20
19
|
Object.assign(this, { start: 1, end: Infinity, step: 2 });
|
|
@@ -24,17 +23,17 @@ class Range {
|
|
|
24
23
|
}
|
|
25
24
|
else if (str.includes(':')) {
|
|
26
25
|
const [start, end, step = '1'] = str.split(':', 3);
|
|
27
|
-
this
|
|
28
|
-
this
|
|
29
|
-
this
|
|
30
|
-
if (!Number.isInteger(this
|
|
31
|
-
throw new RangeError(`起点 ${this
|
|
26
|
+
this.#start = Number(start);
|
|
27
|
+
this.#end = Number(end || Infinity);
|
|
28
|
+
this.#step = Math.max(Number(step), 1);
|
|
29
|
+
if (!Number.isInteger(this.#start)) {
|
|
30
|
+
throw new RangeError(`起点 ${this.#start} 应为整数!`);
|
|
32
31
|
}
|
|
33
|
-
else if (this
|
|
34
|
-
throw new RangeError(`终点 ${this
|
|
32
|
+
else if (this.#end !== Infinity && !Number.isInteger(this.#end)) {
|
|
33
|
+
throw new RangeError(`终点 ${this.#end} 应为整数!`);
|
|
35
34
|
}
|
|
36
|
-
else if (!Number.isInteger(this
|
|
37
|
-
throw new RangeError(`步长 ${this
|
|
35
|
+
else if (!Number.isInteger(this.#step)) {
|
|
36
|
+
throw new RangeError(`步长 ${this.#step} 应为整数!`);
|
|
38
37
|
}
|
|
39
38
|
}
|
|
40
39
|
else {
|
|
@@ -42,21 +41,21 @@ class Range {
|
|
|
42
41
|
.exec(str);
|
|
43
42
|
if (mt) {
|
|
44
43
|
const [, sgnA = '+', a = 1, sgnB = '+'] = mt, b = Number(mt[4] ?? 0);
|
|
45
|
-
this
|
|
46
|
-
if (this
|
|
44
|
+
this.#step = Number(a);
|
|
45
|
+
if (this.#step === 0) {
|
|
47
46
|
throw new RangeError(`参数 ${str} 中 "n" 的系数不允许为 0!`);
|
|
48
47
|
}
|
|
49
48
|
else if (sgnA === '+') {
|
|
50
|
-
this
|
|
51
|
-
this
|
|
49
|
+
this.#start = sgnB === '+' || b === 0 ? b : this.#step - 1 - (b - 1) % this.#step;
|
|
50
|
+
this.#end = Infinity;
|
|
52
51
|
}
|
|
53
52
|
else if (sgnB === '-') {
|
|
54
|
-
this
|
|
55
|
-
this
|
|
53
|
+
this.#start = 0;
|
|
54
|
+
this.#end = b > 0 ? 0 : this.#step;
|
|
56
55
|
}
|
|
57
56
|
else {
|
|
58
|
-
this
|
|
59
|
-
this
|
|
57
|
+
this.#start = b % this.#step;
|
|
58
|
+
this.#end = this.#step + b;
|
|
60
59
|
}
|
|
61
60
|
}
|
|
62
61
|
else {
|
|
@@ -66,12 +65,10 @@ class Range {
|
|
|
66
65
|
}
|
|
67
66
|
/**
|
|
68
67
|
* 将Range转换为针对特定数组的下标集
|
|
69
|
-
* @param arr
|
|
68
|
+
* @param arr 参考数组`[0, 1, 2, ...]`
|
|
70
69
|
*/
|
|
71
70
|
applyTo(arr) {
|
|
72
|
-
return
|
|
73
|
-
.slice(this.start, this.end)
|
|
74
|
-
.filter((_, j) => j % this.step === 0);
|
|
71
|
+
return arr.slice(this.#start, this.#end).filter((_, j) => j % this.#step === 0);
|
|
75
72
|
}
|
|
76
73
|
}
|
|
77
74
|
exports.Range = Range;
|
|
@@ -85,7 +82,7 @@ class Ranges extends Array {
|
|
|
85
82
|
}
|
|
86
83
|
for (const ele of Array.isArray(a) ? a : [a]) {
|
|
87
84
|
if (ele instanceof Range) {
|
|
88
|
-
this.push(
|
|
85
|
+
this.push(ele);
|
|
89
86
|
continue;
|
|
90
87
|
}
|
|
91
88
|
const number = Number(ele);
|
|
@@ -105,13 +102,13 @@ class Ranges extends Array {
|
|
|
105
102
|
* @param arr 参考数组
|
|
106
103
|
*/
|
|
107
104
|
applyTo(arr) {
|
|
108
|
-
const length = typeof arr === 'number' ? arr : arr.length;
|
|
105
|
+
const length = typeof arr === 'number' ? arr : arr.length, a = new Array(length).fill(undefined).map((_, i) => i);
|
|
109
106
|
return [
|
|
110
107
|
...new Set([...this].flatMap(ele => {
|
|
111
108
|
if (typeof ele === 'number') {
|
|
112
109
|
return ele < 0 ? ele + length : ele;
|
|
113
110
|
}
|
|
114
|
-
return ele.applyTo(
|
|
111
|
+
return ele.applyTo(a);
|
|
115
112
|
})),
|
|
116
113
|
].filter(i => i >= 0 && i < length).sort();
|
|
117
114
|
}
|
package/dist/lib/text.js
CHANGED
|
@@ -96,8 +96,9 @@ class AstText extends node_1.AstNode {
|
|
|
96
96
|
return errors
|
|
97
97
|
.map(({ 0: error, 1: prefix, 2: tag, index }) => {
|
|
98
98
|
if (prefix) {
|
|
99
|
-
|
|
100
|
-
|
|
99
|
+
const { length } = prefix;
|
|
100
|
+
index += length;
|
|
101
|
+
error = error.slice(length);
|
|
101
102
|
}
|
|
102
103
|
const startIndex = start + index, lines = data.slice(0, index).split('\n'), startLine = lines.length + top - 1, line = lines.at(-1), startCol = lines.length === 1 ? left + line.length : line.length, { 0: char, length } = error, endIndex = startIndex + length, end = char === '}' || char === ']' ? endIndex + 1 : startIndex + 49, rootStr = String(root), nextChar = rootStr[endIndex], previousChar = rootStr[startIndex - 1], severity = length > 1 && (char !== '<' || /[\s/>]/u.test(nextChar ?? ''))
|
|
103
104
|
|| char === '{' && (nextChar === char || previousChar === '-')
|
package/dist/lib/title.d.ts
CHANGED
|
@@ -5,7 +5,6 @@ export declare class Title {
|
|
|
5
5
|
valid: boolean;
|
|
6
6
|
ns: number;
|
|
7
7
|
fragment: string | undefined;
|
|
8
|
-
encoded: boolean;
|
|
9
8
|
interwiki: string;
|
|
10
9
|
/** 不含命名空间的标题主体部分 */
|
|
11
10
|
get main(): string;
|
|
@@ -14,6 +13,9 @@ export declare class Title {
|
|
|
14
13
|
get prefix(): string;
|
|
15
14
|
/** 完整标题 */
|
|
16
15
|
get title(): string;
|
|
16
|
+
/** 扩展名 */
|
|
17
|
+
get extension(): string | undefined;
|
|
18
|
+
set extension(extension: string | undefined);
|
|
17
19
|
/**
|
|
18
20
|
* @param title 标题(含或不含命名空间前缀)
|
|
19
21
|
* @param defaultNs 命名空间
|
|
@@ -23,4 +25,14 @@ export declare class Title {
|
|
|
23
25
|
constructor(title: string, defaultNs?: number, config?: Parser.Config, decode?: boolean, selfLink?: boolean);
|
|
24
26
|
/** 执行单向转换 */
|
|
25
27
|
autoConvert(): void;
|
|
28
|
+
/** 转换为主页面 */
|
|
29
|
+
toSubjectPage(): void;
|
|
30
|
+
/** 转换为讨论页面 */
|
|
31
|
+
toTalkPage(): void;
|
|
32
|
+
/** 是否是讨论页 */
|
|
33
|
+
isTalkPage(): boolean;
|
|
34
|
+
/** 转换为上一级页面 */
|
|
35
|
+
toBasePage(): void;
|
|
36
|
+
/** 转换为根页面 */
|
|
37
|
+
toRootPage(): void;
|
|
26
38
|
}
|