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/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.startIndex === this.endIndex;
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
- let parentNode = startContainer;
66
- while (!parentNode.contains(endContainer)) {
67
- ({ parentNode } = parentNode);
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 root = this.#endContainer?.getRootNode(), { length } = startNode;
80
- if (root && root !== startNode.getRootNode()) {
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 root = this.#startContainer?.getRootNode(), { length } = endNode;
101
- if (root && root !== endNode.getRootNode()) {
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
- this[method](parentNode, parentNode.childNodes.indexOf(referenceNode) + 1);
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
- this[method](parentNode, parentNode.childNodes.indexOf(referenceNode));
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
- const i = parentNode.childNodes.indexOf(referenceNode);
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 > endIndex ? 1 : 0;
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, startOffset } = this;
259
- let { endContainer, endOffset } = this, parentNode;
260
- while (!endContainer.contains(startContainer)) {
261
- ({ parentNode } = endContainer);
262
- if (endContainer.type === 'text') {
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
- while (endContainer !== startContainer) {
274
- const { childNodes } = endContainer, j = childNodes.findIndex(child => child.contains(startContainer));
275
- for (let i = endOffset - 1; i > j; i--) {
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(startOffset, endOffset);
291
+ endContainer.deleteData(0, endOffset);
292
+ endOffset = childNodes.indexOf(endContainer);
283
293
  }
284
- else {
285
- for (let i = endOffset - 1; i >= startOffset; i--) {
286
- endContainer.removeAt(i);
287
- }
294
+ for (let i = endOffset - 1; i >= startOffset; i--) {
295
+ commonAncestorContainer.removeAt(i);
288
296
  }
289
- this.#endContainer = endContainer;
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
- startContainer.splitText(startOffset);
305
- startContainer.after(newNode);
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
- return String(this.startContainer.getRootNode()).slice(this.startIndex, this.endIndex);
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
- if (this.collapsed) {
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
- return [commonAncestorContainer.nextSibling];
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 (startContainer !== commonAncestorContainer
331
- && (startContainer.type !== 'text' || startContainer.parentNode !== commonAncestorContainer)
332
- || endContainer !== commonAncestorContainer
333
- && (endContainer.type !== 'text' || endContainer.parentNode !== commonAncestorContainer)) {
334
- throw new Error('extractContents 方法只能用于获取某个节点的连续子节点!');
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' && startContainer.parentNode === commonAncestorContainer) {
341
- startContainer.splitText(startOffset);
342
- startOffset = commonAncestorContainer.childNodes.indexOf(startContainer) + 1;
343
- endOffset++;
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() {
@@ -1,20 +1,18 @@
1
1
  /** 模拟Python的Range对象。除`step`至少为`1`外,允许负数、小数或`end < start`的情形。 */
2
2
  export declare class Range {
3
- start: number;
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 | Range);
10
+ constructor(str: string);
13
11
  /**
14
12
  * 将Range转换为针对特定数组的下标集
15
- * @param arr 参考数组
13
+ * @param arr 参考数组`[0, 1, 2, ...]`
16
14
  */
17
- applyTo(arr: number | unknown[]): number[];
15
+ applyTo(arr: number[]): number[];
18
16
  }
19
17
  /** @extends {Array<number|Range>} */
20
18
  export declare class Ranges extends Array<number | Range> {
@@ -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.start = Number(start);
28
- this.end = Number(end || Infinity);
29
- this.step = Math.max(Number(step), 1);
30
- if (!Number.isInteger(this.start)) {
31
- throw new RangeError(`起点 ${this.start} 应为整数!`);
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.end !== Infinity && !Number.isInteger(this.end)) {
34
- throw new RangeError(`终点 ${this.end} 应为整数!`);
32
+ else if (this.#end !== Infinity && !Number.isInteger(this.#end)) {
33
+ throw new RangeError(`终点 ${this.#end} 应为整数!`);
35
34
  }
36
- else if (!Number.isInteger(this.step)) {
37
- throw new RangeError(`步长 ${this.step} 应为整数!`);
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.step = Number(a);
46
- if (this.step === 0) {
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.start = sgnB === '+' || b === 0 ? b : this.step - 1 - (b - 1) % this.step;
51
- this.end = Infinity;
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.start = 0;
55
- this.end = b > 0 ? 0 : this.step;
53
+ this.#start = 0;
54
+ this.#end = b > 0 ? 0 : this.#step;
56
55
  }
57
56
  else {
58
- this.start = b % this.step;
59
- this.end = this.step + b;
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 new Array(typeof arr === 'number' ? arr : arr.length).fill(undefined).map((_, i) => i)
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(new Range(ele));
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(length);
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
- index += prefix.length;
100
- error = error.slice(prefix.length);
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 === '-')
@@ -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
  }