wikiparser-node 1.6.1 → 1.6.2

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 (45) hide show
  1. package/dist/addon/table.js +37 -37
  2. package/dist/base.d.ts +0 -3
  3. package/dist/index.d.ts +1 -0
  4. package/dist/index.js +12 -14
  5. package/dist/lib/element.d.ts +5 -5
  6. package/dist/lib/element.js +25 -22
  7. package/dist/lib/range.js +1 -1
  8. package/dist/lib/ranges.d.ts +3 -1
  9. package/dist/lib/ranges.js +34 -29
  10. package/dist/lib/text.js +2 -2
  11. package/dist/lib/title.d.ts +8 -6
  12. package/dist/lib/title.js +62 -43
  13. package/dist/parser/braces.js +1 -2
  14. package/dist/parser/commentAndExt.js +1 -2
  15. package/dist/parser/converter.js +1 -2
  16. package/dist/parser/externalLinks.js +18 -5
  17. package/dist/parser/hrAndDoubleUnderscore.js +1 -2
  18. package/dist/parser/html.js +7 -8
  19. package/dist/parser/links.js +6 -4
  20. package/dist/parser/list.js +1 -2
  21. package/dist/parser/magicLinks.js +3 -4
  22. package/dist/parser/quotes.js +1 -2
  23. package/dist/parser/selector.js +51 -23
  24. package/dist/parser/table.js +6 -7
  25. package/dist/src/attribute.js +1 -1
  26. package/dist/src/extLink.js +5 -2
  27. package/dist/src/imageParameter.js +2 -2
  28. package/dist/src/imagemap.js +1 -1
  29. package/dist/src/index.js +3 -4
  30. package/dist/src/link/base.js +1 -1
  31. package/dist/src/link/galleryImage.js +2 -1
  32. package/dist/src/magicLink.js +1 -1
  33. package/dist/src/nowiki/quote.js +1 -1
  34. package/dist/src/paramTag/inputbox.js +2 -2
  35. package/dist/src/parameter.js +1 -1
  36. package/dist/src/table/base.js +1 -1
  37. package/dist/src/table/index.js +7 -5
  38. package/dist/src/table/td.js +3 -2
  39. package/dist/src/table/trBase.js +1 -1
  40. package/dist/src/transclude.js +8 -8
  41. package/dist/util/constants.js +1 -2
  42. package/dist/util/debug.js +2 -9
  43. package/dist/util/diff.js +2 -2
  44. package/dist/util/string.js +8 -2
  45. package/package.json +2 -1
@@ -4,9 +4,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
4
4
  const assert = require("assert/strict");
5
5
  const debug_1 = require("../util/debug");
6
6
  const constants_1 = require("../util/constants");
7
- const src_1 = require("../src");
7
+ const index_1 = require("../src/index");
8
8
  const tr_1 = require("../src/table/tr");
9
- const table_1 = require("../src/table");
9
+ const index_2 = require("../src/table/index");
10
10
  const td_1 = require("../src/table/td");
11
11
  const trBase_1 = require("../src/table/trBase");
12
12
  /**
@@ -29,11 +29,11 @@ const cmpCoords = (coords1, coords2) => {
29
29
  * @param i 单元格序号
30
30
  * @param oneCol 是否仅有一列
31
31
  */
32
- const isStartCol = (rowLayout, i, oneCol = false) => {
32
+ const isStartCol = (rowLayout, i, oneCol) => {
33
33
  const coords = rowLayout[i];
34
34
  return rowLayout[i - 1] !== coords && (!oneCol || rowLayout[i + 1] !== coords);
35
35
  };
36
- function occupied(layout, i, oneRow = false, cells) {
36
+ function occupied(layout, i, oneRow, cells) {
37
37
  const rowLayout = layout[i];
38
38
  if (rowLayout) {
39
39
  return rowLayout.map(({ row, column }, j) => row === i && (!oneRow || cells[column]?.rowspan === 1) ? j : undefined).filter((j) => j !== undefined);
@@ -46,7 +46,7 @@ function occupied(layout, i, oneRow = false, cells) {
46
46
  * @param attr 属性
47
47
  * @param multi 是否对所有单元格设置,或是仅对行首单元格设置
48
48
  */
49
- const format = (cells, attr = {}, multi = false) => {
49
+ const format = (cells, attr = {}, multi) => {
50
50
  for (const [token, start] of cells) {
51
51
  if (multi || start) {
52
52
  if (typeof attr === 'string') {
@@ -76,18 +76,18 @@ const fill = (y, rowToken, layout, maxCol, token) => {
76
76
  }
77
77
  });
78
78
  };
79
- table_1.TableToken.prototype.printLayout =
79
+ index_2.TableToken.prototype.printLayout =
80
80
  /** @implements */
81
81
  function () {
82
82
  this.getLayout().print();
83
83
  };
84
- table_1.TableToken.prototype.toRenderedCoords =
84
+ index_2.TableToken.prototype.toRenderedCoords =
85
85
  /** @implements */
86
86
  function ({ row, column }) {
87
87
  const rowLayout = this.getLayout({ row, column })[row], x = rowLayout?.findIndex(coords => cmpCoords(coords, { row, column }) === 0);
88
88
  return rowLayout && (x === -1 ? undefined : { y: row, x: x });
89
89
  };
90
- table_1.TableToken.prototype.toRawCoords =
90
+ index_2.TableToken.prototype.toRawCoords =
91
91
  /** @implements */
92
92
  function ({ x, y }) {
93
93
  const rowLayout = this.getLayout({ x, y })[y], coords = rowLayout?.[x];
@@ -101,35 +101,35 @@ table_1.TableToken.prototype.toRawCoords =
101
101
  }
102
102
  return { row: 0, column: 0, start: true };
103
103
  };
104
- table_1.TableToken.prototype.getFullRow =
104
+ index_2.TableToken.prototype.getFullRow =
105
105
  /** @implements */
106
106
  function (y) {
107
107
  const rows = this.getAllRows();
108
108
  return new Map(this.getLayout({ y })[y]?.map(({ row, column }) => [rows[row].getNthCol(column), row === y]));
109
109
  };
110
- table_1.TableToken.prototype.getFullCol =
110
+ index_2.TableToken.prototype.getFullCol =
111
111
  /** @implements */
112
112
  function (x) {
113
113
  const layout = this.getLayout(), colLayout = layout.map(row => row[x]).filter(Boolean), rows = this.getAllRows();
114
114
  return new Map(colLayout.map(coords => [rows[coords.row].getNthCol(coords.column), layout[coords.row][x - 1] !== coords]));
115
115
  };
116
- table_1.TableToken.prototype.formatTableRow =
116
+ index_2.TableToken.prototype.formatTableRow =
117
117
  /** @implements */
118
- function (y, attr = {}, multiRow = false) {
118
+ function (y, attr = {}, multiRow) {
119
119
  format(this.getFullRow(y), attr, multiRow);
120
120
  };
121
- table_1.TableToken.prototype.formatTableCol =
121
+ index_2.TableToken.prototype.formatTableCol =
122
122
  /** @implements */
123
- function (x, attr = {}, multiCol = false) {
123
+ function (x, attr = {}, multiCol) {
124
124
  format(this.getFullCol(x), attr, multiCol);
125
125
  };
126
- table_1.TableToken.prototype.fillTableRow =
126
+ index_2.TableToken.prototype.fillTableRow =
127
127
  /** @implements */
128
128
  function (y, inner, subtype = 'td', attr = {}) {
129
129
  const rowToken = this.getNthRow(y), layout = this.getLayout({ y }), maxCol = Math.max(...layout.map(({ length }) => length)), token = (0, td_1.createTd)(inner, subtype, attr, this.getAttribute('include'), this.getAttribute('config'));
130
130
  fill(y, rowToken, layout, maxCol, token);
131
131
  };
132
- table_1.TableToken.prototype.fillTable =
132
+ index_2.TableToken.prototype.fillTable =
133
133
  /** @implements */
134
134
  function (inner, subtype = 'td', attr = {}) {
135
135
  const rowTokens = this.getAllRows(), layout = this.getLayout(), maxCol = Math.max(...layout.map(({ length }) => length)), token = (0, td_1.createTd)(inner, subtype, attr, this.getAttribute('include'), this.getAttribute('config'));
@@ -137,7 +137,7 @@ table_1.TableToken.prototype.fillTable =
137
137
  fill(y, rowTokens[y], layout, maxCol, token);
138
138
  }
139
139
  };
140
- table_1.TableToken.prototype.insertTableCell =
140
+ index_2.TableToken.prototype.insertTableCell =
141
141
  /** @implements */
142
142
  function (inner, coords, subtype = 'td', attr = {}) {
143
143
  let rawCoords;
@@ -156,11 +156,11 @@ table_1.TableToken.prototype.insertTableCell =
156
156
  ? trBase_1.TrBaseToken.prototype.insertTableCell.call(this, inner, rawCoords, subtype, attr)
157
157
  : rowToken.insertTableCell(inner, rawCoords, subtype, attr);
158
158
  };
159
- table_1.TableToken.prototype.prependTableRow =
159
+ index_2.TableToken.prototype.prependTableRow =
160
160
  /** @implements */
161
161
  function () {
162
162
  // @ts-expect-error abstract class
163
- const row = debug_1.Shadow.run(() => new tr_1.TrToken('\n|-', undefined, this.getAttribute('config'))), { childNodes } = this, [, , plain] = childNodes, start = plain?.constructor === src_1.Token ? 3 : 2, tdChildren = childNodes.slice(start), index = tdChildren.findIndex(({ type }) => type !== 'td');
163
+ const row = debug_1.Shadow.run(() => new tr_1.TrToken('\n|-', undefined, this.getAttribute('config'))), { childNodes } = this, [, , plain] = childNodes, start = plain?.constructor === index_1.Token ? 3 : 2, tdChildren = childNodes.slice(start), index = tdChildren.findIndex(({ type }) => type !== 'td');
164
164
  this.insertAt(row, index === -1 ? -1 : index + start);
165
165
  debug_1.Shadow.run(() => {
166
166
  for (const cell of tdChildren.slice(0, index === -1 ? undefined : index)) {
@@ -171,7 +171,7 @@ table_1.TableToken.prototype.prependTableRow =
171
171
  });
172
172
  return row;
173
173
  };
174
- table_1.TableToken.prototype.insertTableRow =
174
+ index_2.TableToken.prototype.insertTableRow =
175
175
  /** @implements */
176
176
  function (y, attr = {}, inner, subtype = 'td', innerAttr = {}) {
177
177
  let reference = this.getNthRow(y, false, true);
@@ -201,7 +201,7 @@ table_1.TableToken.prototype.insertTableRow =
201
201
  }
202
202
  return token;
203
203
  };
204
- table_1.TableToken.prototype.insertTableCol =
204
+ index_2.TableToken.prototype.insertTableCol =
205
205
  /** @implements */
206
206
  function (x, inner, subtype = 'td', attr = {}) {
207
207
  const layout = this.getLayout(), rowLength = layout.map(({ length }) => length), minCol = Math.min(...rowLength);
@@ -223,7 +223,7 @@ table_1.TableToken.prototype.insertTableCol =
223
223
  }
224
224
  }
225
225
  };
226
- table_1.TableToken.prototype.removeTableRow =
226
+ index_2.TableToken.prototype.removeTableRow =
227
227
  /** @implements */
228
228
  function (y) {
229
229
  const rows = this.getAllRows(), layout = this.getLayout(), rowLayout = layout[y], set = new WeakSet();
@@ -253,7 +253,7 @@ table_1.TableToken.prototype.removeTableRow =
253
253
  rowToken.remove();
254
254
  return rowToken;
255
255
  };
256
- table_1.TableToken.prototype.removeTableCol =
256
+ index_2.TableToken.prototype.removeTableCol =
257
257
  /** @implements */
258
258
  function (x) {
259
259
  for (const [token, start] of this.getFullCol(x)) {
@@ -269,7 +269,7 @@ table_1.TableToken.prototype.removeTableCol =
269
269
  }
270
270
  }
271
271
  };
272
- table_1.TableToken.prototype.mergeCells =
272
+ index_2.TableToken.prototype.mergeCells =
273
273
  /** @implements */
274
274
  function (xlim, ylim) {
275
275
  const layout = this.getLayout(), maxCol = Math.max(...layout.map(({ length }) => length)), [xmin, xmax] = xlim.map(x => x < 0 ? x + maxCol : x).sort(), [ymin, ymax] = ylim.map(y => y < 0 ? y + layout.length : y).sort(), set = new Set(layout.slice(ymin, ymax).flatMap(rowLayout => rowLayout.slice(xmin, xmax)));
@@ -286,7 +286,7 @@ table_1.TableToken.prototype.mergeCells =
286
286
  }
287
287
  return cornerCell;
288
288
  };
289
- table_1.TableToken.prototype.split =
289
+ index_2.TableToken.prototype.split =
290
290
  /** @implements */
291
291
  function (coords, dirs) {
292
292
  const cell = this.getNthCell(coords), attr = cell.getAttrs(), { subtype } = cell;
@@ -327,22 +327,22 @@ table_1.TableToken.prototype.split =
327
327
  }
328
328
  }
329
329
  };
330
- table_1.TableToken.prototype.splitIntoRows =
330
+ index_2.TableToken.prototype.splitIntoRows =
331
331
  /** @implements */
332
332
  function (coords) {
333
333
  this.split(coords, new Set(['rowspan']));
334
334
  };
335
- table_1.TableToken.prototype.splitIntoCols =
335
+ index_2.TableToken.prototype.splitIntoCols =
336
336
  /** @implements */
337
337
  function (coords) {
338
338
  this.split(coords, new Set(['colspan']));
339
339
  };
340
- table_1.TableToken.prototype.splitIntoCells =
340
+ index_2.TableToken.prototype.splitIntoCells =
341
341
  /** @implements */
342
342
  function (coords) {
343
343
  this.split(coords, new Set(['rowspan', 'colspan']));
344
344
  };
345
- table_1.TableToken.prototype.replicateTableRow =
345
+ index_2.TableToken.prototype.replicateTableRow =
346
346
  /** @implements */
347
347
  function (row) {
348
348
  let rowToken = this.getNthRow(row);
@@ -360,7 +360,7 @@ table_1.TableToken.prototype.replicateTableRow =
360
360
  }
361
361
  return replicated;
362
362
  };
363
- table_1.TableToken.prototype.replicateTableCol =
363
+ index_2.TableToken.prototype.replicateTableCol =
364
364
  /** @implements */
365
365
  function (x) {
366
366
  const replicated = [];
@@ -377,7 +377,7 @@ table_1.TableToken.prototype.replicateTableCol =
377
377
  }
378
378
  return replicated;
379
379
  };
380
- table_1.TableToken.prototype.moveTableRowBefore =
380
+ index_2.TableToken.prototype.moveTableRowBefore =
381
381
  /** @implements */
382
382
  function (y, before) {
383
383
  const layout = this.getLayout();
@@ -403,7 +403,7 @@ table_1.TableToken.prototype.moveTableRowBefore =
403
403
  this.insertBefore(rowToken, beforeToken);
404
404
  return rowToken;
405
405
  };
406
- table_1.TableToken.prototype.moveTableRowAfter =
406
+ index_2.TableToken.prototype.moveTableRowAfter =
407
407
  /** @implements */
408
408
  function (y, after) {
409
409
  const layout = this.getLayout(), afterToken = this.getNthRow(after), cells = afterToken.childNodes.filter(child => child.type === 'td' && child.subtype !== 'caption');
@@ -429,7 +429,7 @@ table_1.TableToken.prototype.moveTableRowAfter =
429
429
  }
430
430
  }
431
431
  if (afterToken === this) {
432
- const index = this.childNodes.slice(2).findIndex(table_1.isRowEnd);
432
+ const index = this.childNodes.slice(2).findIndex(index_2.isRowEnd);
433
433
  this.insertAt(rowToken, index + 2);
434
434
  }
435
435
  else {
@@ -437,7 +437,7 @@ table_1.TableToken.prototype.moveTableRowAfter =
437
437
  }
438
438
  return rowToken;
439
439
  };
440
- table_1.TableToken.prototype.moveCol =
440
+ index_2.TableToken.prototype.moveCol =
441
441
  /** @implements */
442
442
  function (x, reference, after = false) {
443
443
  const layout = this.getLayout();
@@ -467,17 +467,17 @@ table_1.TableToken.prototype.moveCol =
467
467
  }
468
468
  if (start) {
469
469
  const col = rowLayout.slice(reference + Number(after)).find(({ row }) => row === i)?.column;
470
- rowToken.insertBefore(token, col === undefined ? rowToken.childNodes.slice(2).find(table_1.isRowEnd) : rowToken.getNthCol(col));
470
+ rowToken.insertBefore(token, col === undefined ? rowToken.childNodes.slice(2).find(index_2.isRowEnd) : rowToken.getNthCol(col));
471
471
  }
472
472
  }
473
473
  }
474
474
  };
475
- table_1.TableToken.prototype.moveTableColBefore =
475
+ index_2.TableToken.prototype.moveTableColBefore =
476
476
  /** @implements */
477
477
  function (x, before) {
478
478
  this.moveCol(x, before);
479
479
  };
480
- table_1.TableToken.prototype.moveTableColAfter =
480
+ index_2.TableToken.prototype.moveTableColAfter =
481
481
  /** @implements */
482
482
  function (x, after) {
483
483
  this.moveCol(x, after, true);
package/dist/base.d.ts CHANGED
@@ -59,9 +59,6 @@ interface AstElement extends AstNode {
59
59
  export interface Parser {
60
60
  config: string | Config;
61
61
  i18n: string | Record<string, string> | undefined;
62
- rules: readonly LintError.Rule[];
63
- /** 获取解析设置 */
64
- getConfig(): Config;
65
62
  /**
66
63
  * 解析wikitext
67
64
  * @param include 是否嵌入
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@ import type { Config, LintError, Parser as ParserBase } from './base';
3
3
  import type { Title } from './lib/title';
4
4
  import type { Token } from './internal';
5
5
  declare interface Parser extends ParserBase {
6
+ rules: readonly LintError.Rule[];
6
7
  conversionTable: Map<string, string>;
7
8
  redirects: Map<string, string>;
8
9
  warning: boolean;
package/dist/index.js CHANGED
@@ -14,6 +14,7 @@ const diff_1 = require("./util/diff");
14
14
  * @param dir 子路径
15
15
  */
16
16
  const rootRequire = (file, dir) => require(file.startsWith('/') ? file : `../${file.includes('/') ? '' : dir}${file}`);
17
+ const promises = [Promise.resolve()];
17
18
  // eslint-disable-next-line @typescript-eslint/no-redeclare
18
19
  const Parser = {
19
20
  config: 'default',
@@ -54,14 +55,13 @@ const Parser = {
54
55
  return msg && (this.i18n?.[msg] ?? msg).replace('$1', this.msg(arg));
55
56
  },
56
57
  /** @implements */
57
- normalizeTitle(title, defaultNs = 0, include = false, config = Parser.getConfig(), halfParsed = false, decode = false, selfLink = false) {
58
+ normalizeTitle(title, defaultNs = 0, include, config = Parser.getConfig(), halfParsed, decode = false, selfLink = false) {
58
59
  const { Title } = require('./lib/title');
59
60
  if (halfParsed) {
60
61
  return new Title(title, defaultNs, config, decode, selfLink);
61
62
  }
62
63
  const { Token } = require('./src/index');
63
64
  const token = debug_1.Shadow.run(() => new Token(title, config).parseOnce(0, include).parseOnce()), titleObj = new Title(String(token), defaultNs, config, decode, selfLink);
64
- /* NOT FOR BROWSER */
65
65
  debug_1.Shadow.run(() => {
66
66
  for (const key of ['main', 'fragment']) {
67
67
  const str = titleObj[key];
@@ -70,6 +70,7 @@ const Parser = {
70
70
  }
71
71
  }
72
72
  });
73
+ /* NOT FOR BROWSER */
73
74
  titleObj.conversionTable = this.conversionTable;
74
75
  titleObj.redirects = this.redirects;
75
76
  /* NOT FOR BROWSER END */
@@ -89,27 +90,25 @@ const Parser = {
89
90
  const file = path.join(__dirname, '..', 'errors', new Date().toISOString()), stage = token.getAttribute('stage');
90
91
  fs.writeFileSync(file, stage === constants_1.MAX_STAGE ? wikitext : String(token));
91
92
  fs.writeFileSync(`${file}.err`, e.stack);
92
- fs.writeFileSync(`${file}.json`, JSON.stringify({
93
- stage, include: token.getAttribute('include'), config: this.config,
94
- }, null, '\t'));
93
+ fs.writeFileSync(`${file}.json`, JSON.stringify({ stage, include, config }, null, '\t'));
95
94
  }
96
95
  throw e;
97
96
  }
98
97
  });
99
98
  /* NOT FOR BROWSER */
100
99
  if (this.debugging) {
101
- let restored = String(root), process = '解析';
100
+ let restored = String(root), process = 'parsing';
102
101
  if (restored === wikitext) {
103
102
  const entities = { lt: '<', gt: '>', amp: '&' };
104
103
  restored = root.print().replace(/<[^<]+?>|&([lg]t|amp);/gu, (_, s) => s ? entities[s] : '');
105
- process = '渲染HTML';
104
+ process = 'printing';
106
105
  }
107
106
  if (restored !== wikitext) {
108
107
  const { diff } = require('./util/diff');
109
- const { 0: cur, length } = constants_1.promises;
110
- constants_1.promises.unshift((async () => {
108
+ const { 0: cur, length } = promises;
109
+ promises.unshift((async () => {
111
110
  await cur;
112
- this.error(`${process}过程中不可逆地修改了原始文本!`);
111
+ this.error(`Original wikitext is altered when ${process}!`);
113
112
  return diff(wikitext, restored, length);
114
113
  })());
115
114
  }
@@ -168,17 +167,16 @@ const Parser = {
168
167
  : null;
169
168
  },
170
169
  /** @implements */
171
- reparse(date) {
170
+ reparse(date = '') {
172
171
  const main = fs.readdirSync(path.join(__dirname, '..', 'errors'))
173
172
  .find(name => name.startsWith(date) && name.endsWith('Z'));
174
173
  if (!main) {
175
174
  throw new RangeError(`找不到对应时间戳的错误记录:${date}`);
176
175
  }
177
176
  const file = path.join(__dirname, '..', 'errors', main), wikitext = fs.readFileSync(file, 'utf8');
178
- const { stage, include, config } = require(`${file}.json`), { Token } = require('./src');
179
- this.config = config;
177
+ const { stage, include, config } = require(`${file}.json`), { Token } = require('./src/index');
180
178
  return debug_1.Shadow.run(() => {
181
- const halfParsed = stage < constants_1.MAX_STAGE, token = new Token(halfParsed ? wikitext : (0, string_1.tidy)(wikitext), this.getConfig());
179
+ const halfParsed = stage < constants_1.MAX_STAGE, token = new Token(halfParsed ? wikitext : (0, string_1.tidy)(wikitext), config);
182
180
  if (halfParsed) {
183
181
  token.setAttribute('stage', stage);
184
182
  token.parseOnce(stage, include);
@@ -55,6 +55,11 @@ export declare abstract class AstElement extends AstNode {
55
55
  * @param selector 选择器
56
56
  */
57
57
  closest<T = Token>(selector: string): T | undefined;
58
+ /**
59
+ * 符合选择器的所有后代节点
60
+ * @param selector 选择器
61
+ */
62
+ querySelectorAll<T = Token>(selector: string): T[];
58
63
  /**
59
64
  * 在末尾批量插入子节点
60
65
  * @param elements 插入节点
@@ -111,11 +116,6 @@ export declare abstract class AstElement extends AstNode {
111
116
  * @param id id名
112
117
  */
113
118
  getElementById<T = Token>(id: string): T | undefined;
114
- /**
115
- * 符合选择器的所有后代节点
116
- * @param selector 选择器
117
- */
118
- querySelectorAll<T = Token>(selector: string): T[];
119
119
  /**
120
120
  * 类选择器
121
121
  * @param className 类名之一
@@ -194,6 +194,31 @@ class AstElement extends node_1.AstNode {
194
194
  }
195
195
  return undefined;
196
196
  }
197
+ /**
198
+ * 符合条件的所有后代节点
199
+ * @param condition 条件
200
+ */
201
+ #getElementsBy(condition) {
202
+ const descendants = [];
203
+ for (const child of this.childNodes) {
204
+ if (child.type === 'text') {
205
+ continue;
206
+ }
207
+ else if (condition(child)) {
208
+ descendants.push(child);
209
+ }
210
+ descendants.push(...child.#getElementsBy(condition));
211
+ }
212
+ return descendants;
213
+ }
214
+ /**
215
+ * 符合选择器的所有后代节点
216
+ * @param selector 选择器
217
+ */
218
+ querySelectorAll(selector) {
219
+ const condition = this.#getCondition(selector);
220
+ return this.#getElementsBy(condition);
221
+ }
197
222
  /**
198
223
  * 在末尾批量插入子节点
199
224
  * @param elements 插入节点
@@ -533,28 +558,6 @@ class AstElement extends node_1.AstNode {
533
558
  getElementById(id) {
534
559
  return this.#getElementBy((token => 'id' in token && token.id === id));
535
560
  }
536
- /**
537
- * 符合条件的所有后代节点
538
- * @param condition 条件
539
- */
540
- #getElementsBy(condition) {
541
- const descendants = [];
542
- for (const child of this.children) {
543
- if (condition(child)) {
544
- descendants.push(child);
545
- }
546
- descendants.push(...child.#getElementsBy(condition));
547
- }
548
- return descendants;
549
- }
550
- /**
551
- * 符合选择器的所有后代节点
552
- * @param selector 选择器
553
- */
554
- querySelectorAll(selector) {
555
- const condition = this.#getCondition(selector);
556
- return this.#getElementsBy(condition);
557
- }
558
561
  /**
559
562
  * 类选择器
560
563
  * @param className 类名之一
package/dist/lib/range.js CHANGED
@@ -233,7 +233,7 @@ class AstRange {
233
233
  * 使起始和终止位置重合
234
234
  * @param toStart 重合至起始位置
235
235
  */
236
- collapse(toStart = false) {
236
+ collapse(toStart) {
237
237
  if (toStart) {
238
238
  this.#endContainer = this.startContainer;
239
239
  this.#endOffset = this.startOffset;
@@ -1,6 +1,8 @@
1
1
  /** 模拟Python的Range对象。除`step`至少为`1`外,允许负数、小数或`end < start`的情形。 */
2
2
  export declare class Range {
3
- #private;
3
+ readonly start: number;
4
+ readonly end: number;
5
+ readonly step: number;
4
6
  /**
5
7
  * @param s 表达式
6
8
  * @throws `RangeError` 起点、终点和步长均应为整数
@@ -3,11 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Ranges = exports.Range = void 0;
4
4
  const constants_1 = require("../util/constants");
5
5
  const debug_1 = require("../util/debug");
6
+ const diff_1 = require("../util/diff");
6
7
  /** 模拟Python的Range对象。除`step`至少为`1`外,允许负数、小数或`end < start`的情形。 */
7
8
  class Range {
8
- #start;
9
- #end;
10
- #step;
9
+ start;
10
+ end;
11
+ step;
11
12
  /**
12
13
  * @param s 表达式
13
14
  * @throws `RangeError` 起点、终点和步长均应为整数
@@ -24,43 +25,43 @@ class Range {
24
25
  }
25
26
  else if (str.includes(':')) {
26
27
  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} 应为整数!`);
28
+ this.start = Number(start);
29
+ this.end = Number(end?.trim() || Infinity);
30
+ this.step = Math.max(Number(step), 1);
31
+ if (!Number.isInteger(this.start)) {
32
+ throw new RangeError(`The start of a range, \`${start}\`, should be an integer!`);
32
33
  }
33
- else if (this.#end !== Infinity && !Number.isInteger(this.#end)) {
34
- throw new RangeError(`终点 ${this.#end} 应为整数!`);
34
+ else if (this.end !== Infinity && !Number.isInteger(this.end)) {
35
+ throw new RangeError(`The end of a range, \`${end}\`, should be an integer!`);
35
36
  }
36
- else if (!Number.isInteger(this.#step)) {
37
- throw new RangeError(`步长 ${this.#step} 应为整数!`);
37
+ else if (!Number.isInteger(this.step)) {
38
+ throw new RangeError(`The step of a range, \`${step}\`, should be an integer!`);
38
39
  }
39
40
  }
40
41
  else {
41
- const mt = /^([+-])?(\d+)?n(?:([+-])(\d+))?$/u
42
+ const mt = /^([+-])?(\d+)?n(?:\s*([+-])\s*(\d+))?$/u
42
43
  .exec(str);
43
44
  if (mt) {
44
45
  const [, sgnA = '+', a = 1, sgnB = '+'] = mt, b = Number(mt[4] ?? 0);
45
- this.#step = Number(a);
46
- if (this.#step === 0) {
47
- throw new RangeError(`参数 ${str} "n" 的系数不允许为 0!`);
46
+ this.step = Number(a);
47
+ if (this.step === 0) {
48
+ throw new RangeError(`In the argument \`${str}\`, the coefficient of "n" must not be 0!`);
48
49
  }
49
- else if (sgnA === '+') {
50
- this.#start = sgnB === '+' || b === 0 ? b : this.#step - 1 - (b - 1) % this.#step;
51
- this.#end = Infinity;
50
+ else if (sgnA === '+') { // `an+b` or `an-b`
51
+ this.start = sgnB === '+' || b === 0 ? b : this.step - 1 - (b - 1) % this.step;
52
+ this.end = Infinity;
52
53
  }
53
- else if (sgnB === '-') {
54
- this.#start = 0;
55
- this.#end = b > 0 ? 0 : this.#step;
54
+ else if (sgnB === '-') { // `-an-b`
55
+ this.start = 0;
56
+ this.end = b > 0 ? 0 : this.step;
56
57
  }
57
- else {
58
- this.#start = b % this.#step;
59
- this.#end = this.#step + b;
58
+ else { // `-an+b`
59
+ this.start = b % this.step;
60
+ this.end = this.step + b;
60
61
  }
61
62
  }
62
63
  else {
63
- throw new RangeError(`参数 ${str} 应写作CSS选择器的 "an+b" 形式或Python切片!`);
64
+ throw new RangeError(`The argument \`${str}\` should be either in the form of "an+b" as in CSS selectors or Python slices!`);
64
65
  }
65
66
  }
66
67
  }
@@ -69,7 +70,7 @@ class Range {
69
70
  * @param arr 参考数组`[0, 1, 2, ...]`
70
71
  */
71
72
  applyTo(arr) {
72
- return arr.slice(this.#start, this.#end).filter((_, j) => j % this.#step === 0);
73
+ return arr.slice(this.start, this.end).filter((_, j) => j % this.step === 0);
73
74
  }
74
75
  }
75
76
  exports.Range = Range;
@@ -81,7 +82,7 @@ class Ranges extends Array {
81
82
  if (a === undefined) {
82
83
  return;
83
84
  }
84
- for (const ele of Array.isArray(a) ? a : [a]) {
85
+ for (const ele of (Array.isArray(a) ? a : [a])) {
85
86
  if (ele instanceof Range) {
86
87
  this.push(ele);
87
88
  continue;
@@ -97,7 +98,11 @@ class Ranges extends Array {
97
98
  try {
98
99
  this.push(new Range(ele));
99
100
  }
100
- catch { }
101
+ catch (e) {
102
+ if (e instanceof RangeError) {
103
+ (0, diff_1.error)(e.message);
104
+ }
105
+ }
101
106
  }
102
107
  }
103
108
  }
package/dist/lib/text.js CHANGED
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AstText = void 0;
4
4
  const constants_1 = require("../util/constants");
5
5
  const debug_1 = require("../util/debug");
6
+ const string_1 = require("../util/string");
6
7
  const index_1 = require("../index");
7
8
  const node_1 = require("./node");
8
9
  // eslint-disable-next-line @typescript-eslint/no-unused-expressions
@@ -269,8 +270,7 @@ class AstText extends node_1.AstNode {
269
270
  }
270
271
  /** @override */
271
272
  print() {
272
- const entities = { '&': 'amp', '<': 'lt', '>': 'gt' };
273
- return this.data.replace(/[&<>]/gu, p => `&${entities[p]};`);
273
+ return (0, string_1.escape)(this.data);
274
274
  }
275
275
  /* NOT FOR BROWSER */
276
276
  /** 复制 */
@@ -1,28 +1,30 @@
1
- import Parser from '../index';
1
+ import type { Config } from '../base';
2
2
  /** MediaWiki页面标题对象 */
3
3
  export declare class Title {
4
4
  #private;
5
- readonly valid: boolean;
6
5
  ns: number;
7
6
  fragment: string | undefined;
8
7
  interwiki: string;
8
+ readonly valid: boolean;
9
9
  /** 不含命名空间的标题主体部分 */
10
10
  get main(): string;
11
11
  set main(title: string);
12
- /** 扩展名 */
13
- get extension(): string | undefined;
14
- set extension(extension: string | undefined);
15
12
  /** 命名空间前缀 */
16
13
  get prefix(): string;
17
14
  /** 完整标题 */
18
15
  get title(): string;
16
+ /** 扩展名 */
17
+ get extension(): string | undefined;
18
+ set extension(extension: string | undefined);
19
19
  /**
20
+ * @see MediaWikiTitleCodec::splitTitleString
21
+ *
20
22
  * @param title 标题(含或不含命名空间前缀)
21
23
  * @param defaultNs 命名空间
22
24
  * @param decode 是否需要解码
23
25
  * @param selfLink 是否允许selfLink
24
26
  */
25
- constructor(title: string, defaultNs?: number, config?: Parser.Config, decode?: boolean, selfLink?: boolean);
27
+ constructor(title: string, defaultNs: number, config: Config, decode: boolean, selfLink: boolean);
26
28
  /** 执行单向转换 */
27
29
  autoConvert(): void;
28
30
  /** 转换为主页面 */