wikiparser-node 1.3.6 → 1.3.7

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/index.js CHANGED
@@ -64,7 +64,7 @@ const Parser = {
64
64
  debug_1.Shadow.run(() => {
65
65
  for (const key of ['main', 'fragment']) {
66
66
  if (titleObj[key]?.includes('\0')) {
67
- titleObj[key] = token.buildFromStr(titleObj[key], 'text');
67
+ titleObj[key] = token.buildFromStr(titleObj[key], constants_1.BuildMethod.Text);
68
68
  }
69
69
  }
70
70
  });
@@ -163,7 +163,7 @@ const Parser = {
163
163
  /** @implements */
164
164
  isInterwiki(title, { interwiki } = Parser.getConfig()) {
165
165
  return new RegExp(`^(${interwiki.join('|')})\\s*:`, 'diu')
166
- .exec(title.replaceAll('_', ' ').replace(/^\s*:?\s*/u, ''));
166
+ .exec(title.replace(/_/gu, ' ').replace(/^\s*:?\s*/u, ''));
167
167
  },
168
168
  /** @implements */
169
169
  reparse(date) {
@@ -51,7 +51,7 @@ class AstElement extends node_1.AstNode {
51
51
  }
52
52
  /** 末位非文本子节点 */
53
53
  get lastElementChild() {
54
- return this.children.at(-1);
54
+ return this.children[this.childElementCount - 1];
55
55
  }
56
56
  /** 非文本子节点总数 */
57
57
  get childElementCount() {
@@ -93,7 +93,11 @@ class AstElement extends node_1.AstNode {
93
93
  /** 内部宽度 */
94
94
  get clientWidth() {
95
95
  const { innerText } = this;
96
- return typeof innerText === 'string' ? innerText.split('\n').at(-1).length : undefined;
96
+ if (typeof innerText === 'string') {
97
+ const lines = innerText.split('\n');
98
+ return lines[lines.length - 1].length;
99
+ }
100
+ return undefined;
97
101
  }
98
102
  constructor() {
99
103
  super();
@@ -200,7 +204,8 @@ class AstElement extends node_1.AstNode {
200
204
  */
201
205
  setText(str, i = 0) {
202
206
  this.verifyChild(i);
203
- const oldText = this.childNodes.at(i), { type, constructor: { name } } = oldText;
207
+ i += i < 0 ? this.length : 0;
208
+ const oldText = this.childNodes[i], { type, constructor: { name } } = oldText;
204
209
  if (type === 'text') {
205
210
  const { data } = oldText;
206
211
  oldText.replaceData(str);
@@ -234,11 +239,6 @@ class AstElement extends node_1.AstNode {
234
239
  print(opt = {}) {
235
240
  return String(this) ? `<span class="wpb-${opt.class ?? this.type}">${(0, string_1.print)(this.childNodes, opt)}</span>` : '';
236
241
  }
237
- /* NOT FOR BROWSER */
238
- /** @private */
239
- matchesTypes(types) {
240
- return types.has(this.type);
241
- }
242
242
  /**
243
243
  * 保存为JSON
244
244
  * @param file 文件名
@@ -253,6 +253,11 @@ class AstElement extends node_1.AstNode {
253
253
  }
254
254
  return json;
255
255
  }
256
+ /* NOT FOR BROWSER */
257
+ /** @private */
258
+ matchesTypes(types) {
259
+ return types.has(this.type);
260
+ }
256
261
  /** 销毁 */
257
262
  destroy() {
258
263
  this.parentNode?.destroy();
@@ -432,7 +437,7 @@ class AstElement extends node_1.AstNode {
432
437
  const condition = [...copy], step = condition.pop();
433
438
  if (this.#matches(step)) {
434
439
  const { parentNode, previousElementSibling } = this;
435
- switch (condition.at(-1)?.relation) {
440
+ switch (condition[condition.length - 1]?.relation) {
436
441
  case undefined:
437
442
  return true;
438
443
  case '>':
package/dist/lib/node.js CHANGED
@@ -29,7 +29,7 @@ class AstNode {
29
29
  }
30
30
  /** 末位子节点 */
31
31
  get lastChild() {
32
- return this.childNodes.at(-1);
32
+ return this.childNodes[this.childNodes.length - 1];
33
33
  }
34
34
  /** 父节点 */
35
35
  get parentNode() {
@@ -118,7 +118,7 @@ class AstNode {
118
118
  if (key === 'parentNode') {
119
119
  this.#parentNode = value;
120
120
  }
121
- else if (Object.hasOwn(this, key)) {
121
+ else if (Object.prototype.hasOwnProperty.call(this, key)) {
122
122
  const descriptor = Object.getOwnPropertyDescriptor(this, key);
123
123
  if (this.#optional.has(key)) {
124
124
  descriptor.enumerable = Boolean(value);
@@ -148,21 +148,15 @@ class AstNode {
148
148
  posFromIndex(index) {
149
149
  const str = String(this);
150
150
  if (index >= -str.length && index <= str.length) {
151
- const lines = str.slice(0, index).split('\n');
152
- return {
153
- top: lines.length - 1,
154
- left: lines.at(-1).length,
155
- };
151
+ const lines = str.slice(0, index).split('\n'), top = lines.length - 1;
152
+ return { top, left: lines[top].length };
156
153
  }
157
154
  return undefined;
158
155
  }
159
156
  /** 获取行数和最后一行的列数 */
160
157
  #getDimension() {
161
- const lines = String(this).split('\n');
162
- return {
163
- height: lines.length,
164
- width: lines.at(-1).length,
165
- };
158
+ const lines = String(this).split('\n'), height = lines.length;
159
+ return { height, width: lines[height - 1].length };
166
160
  }
167
161
  /** @private */
168
162
  // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
package/dist/lib/text.js CHANGED
@@ -5,7 +5,7 @@ const constants_1 = require("../util/constants");
5
5
  const debug_1 = require("../util/debug");
6
6
  const Parser = require("../index");
7
7
  const node_1 = require("./node");
8
- const errorSyntax = /<\s*\/?([a-z]\w*)|\{+|\}+|\[{2,}|\[(?![^[]*\])|(?<=^|\])([^[]*?)\]+|\]{2,}|https?[:/]\/+/giu, errorSyntaxUrl = /<\s*\/?([a-z]\w*)|\{+|\}+|\[{2,}|\[(?![^[]*\])|(?<=^|\])([^[]*?)\]+|\]{2,}/giu, disallowedTags = [
8
+ const errorSyntax = /<\s*\/?([a-z]\w*)|\{+|\}+|\[{2,}|\[(?![^[]*\])|((?:^|\])[^[]*?)\]+|https?[:/]\/+/giu, errorSyntaxUrl = /<\s*\/?([a-z]\w*)|\{+|\}+|\[{2,}|\[(?![^[]*\])|((?:^|\])[^[]*?)\]+/giu, disallowedTags = [
9
9
  'html',
10
10
  'base',
11
11
  'head',
@@ -71,7 +71,10 @@ class AstText extends node_1.AstNode {
71
71
  constructor(text) {
72
72
  super();
73
73
  Object.defineProperties(this, {
74
- data: { value: text, writable: false },
74
+ data: {
75
+ value: text,
76
+ writable: false,
77
+ },
75
78
  childNodes: { enumerable: false, configurable: false },
76
79
  type: { enumerable: false, writable: false, configurable: false },
77
80
  });
@@ -109,17 +112,19 @@ class AstText extends node_1.AstNode {
109
112
  else {
110
113
  errorRegex = errorSyntax;
111
114
  }
112
- const errors = [...data.matchAll(errorRegex)], { ext, html } = this.getRootNode().getAttribute('config');
113
- if (errors.length > 0) {
115
+ const errors = [], { ext, html } = this.getRootNode().getAttribute('config');
116
+ if (data.search(errorRegex) !== -1) {
117
+ errorRegex.lastIndex = 0;
114
118
  const root = this.getRootNode(), { top, left } = root.posFromIndex(start), tags = new Set(['onlyinclude', 'noinclude', 'includeonly', ext, html, disallowedTags].flat(2));
115
- return errors
116
- .map(({ 0: error, 1: tag, 2: prefix, index }) => {
117
- if (prefix) {
119
+ for (let mt = errorRegex.exec(data); mt; mt = errorRegex.exec(data)) {
120
+ const [, tag, prefix] = mt;
121
+ let { 0: error, index } = mt;
122
+ if (prefix && prefix !== ']') {
118
123
  const { length } = prefix;
119
124
  index += length;
120
125
  error = error.slice(length);
121
126
  }
122
- 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, rootStr = String(root), nextChar = rootStr[endIndex], previousChar = rootStr[startIndex - 1], severity = length > 1 && (char !== '<' || /[\s/>]/u.test(nextChar ?? ''))
127
+ const startIndex = start + index, lines = data.slice(0, index).split('\n'), startLine = lines.length + top - 1, line = lines[lines.length - 1], startCol = lines.length === 1 ? left + line.length : line.length, { 0: char, length } = error, endIndex = startIndex + length, rootStr = String(root), nextChar = rootStr[endIndex], previousChar = rootStr[startIndex - 1], severity = length > 1 && (char !== '<' || /[\s/>]/u.test(nextChar ?? ''))
123
128
  || char === '{' && (nextChar === char || previousChar === '-')
124
129
  || char === '}' && (previousChar === char || nextChar === '-')
125
130
  || char === '[' && (nextChar === char
@@ -129,17 +134,20 @@ class AstText extends node_1.AstNode {
129
134
  || !data.slice(0, index).trim() && previousType === 'free-ext-link')
130
135
  ? 'error'
131
136
  : 'warning';
132
- return (char !== '<' || tags.has(tag.toLowerCase())) && {
133
- message: Parser.msg('lonely "$1"', char === 'h' ? error : char),
134
- severity,
135
- startIndex,
136
- endIndex,
137
- startLine,
138
- endLine: startLine,
139
- startCol,
140
- endCol: startCol + length,
141
- };
142
- }).filter(Boolean);
137
+ if (char !== '<' || tags.has(tag.toLowerCase())) {
138
+ errors.push({
139
+ message: Parser.msg('lonely "$1"', char === 'h' ? error : char),
140
+ severity,
141
+ startIndex,
142
+ endIndex,
143
+ startLine,
144
+ endLine: startLine,
145
+ startCol,
146
+ endCol: startCol + length,
147
+ });
148
+ }
149
+ }
150
+ return errors;
143
151
  }
144
152
  return [];
145
153
  }
package/dist/lib/title.js CHANGED
@@ -24,7 +24,7 @@ class Title {
24
24
  return this.#main;
25
25
  }
26
26
  set main(title) {
27
- title = title.replaceAll('_', ' ').trim();
27
+ title = title.replace(/_/gu, ' ').trim();
28
28
  this.#main = title && `${title[0].toUpperCase()}${title.slice(1)}`;
29
29
  }
30
30
  /** 命名空间前缀 */
@@ -35,13 +35,13 @@ class Title {
35
35
  /** 完整标题 */
36
36
  get title() {
37
37
  const prefix = `${this.interwiki}${this.interwiki && ':'}${this.prefix}`;
38
- let title = `${prefix}${this.main}`.replaceAll(' ', '_');
38
+ let title = `${prefix}${this.main}`.replace(/ /gu, '_');
39
39
  const redirected = this.redirects.get(title);
40
40
  if (redirected) {
41
41
  return redirected;
42
42
  }
43
43
  this.autoConvert();
44
- title = `${prefix}${this.main}`.replaceAll(' ', '_');
44
+ title = `${prefix}${this.main}`.replace(/ /gu, '_');
45
45
  return this.redirects.get(title) ?? title;
46
46
  }
47
47
  /** 扩展名 */
@@ -77,7 +77,7 @@ class Title {
77
77
  }
78
78
  catch { }
79
79
  }
80
- title = title.replaceAll('_', ' ').trim();
80
+ title = title.replace(/_/gu, ' ').trim();
81
81
  let ns = defaultNs;
82
82
  if (title.startsWith(':')) {
83
83
  ns = 0;
@@ -108,7 +108,7 @@ class Title {
108
108
  }
109
109
  else if (fragment.includes('.')) {
110
110
  try {
111
- fragment = decodeURIComponent(fragment.replaceAll('.', '%'));
111
+ fragment = decodeURIComponent(fragment.replace(/\./gu, '%'));
112
112
  }
113
113
  catch { }
114
114
  }
@@ -12,7 +12,7 @@ const attributesParent = (constructor, i = 0) => {
12
12
  class AttributesParent extends constructor {
13
13
  /** AttributesToken子节点 */
14
14
  get #attributesChild() {
15
- return this.childNodes.at(i);
15
+ return this.childNodes[i];
16
16
  }
17
17
  /** getAttrs()方法的getter写法 */
18
18
  get attributes() {
@@ -11,11 +11,11 @@ const singleLine = (constructor) => {
11
11
  class SingleLineToken extends constructor {
12
12
  /** @private */
13
13
  toString(omit) {
14
- return super.toString(omit).replaceAll('\n', ' ');
14
+ return super.toString(omit).replace(/\n/gu, ' ');
15
15
  }
16
16
  /** @override */
17
17
  text() {
18
- return super.text().replaceAll('\n', ' ');
18
+ return super.text().replace(/\n/gu, ' ');
19
19
  }
20
20
  }
21
21
  Object.defineProperty(SingleLineToken, 'name', { value: `SingleLine${constructor.name}` });
@@ -18,7 +18,7 @@ const parseBraces = (wikitext, config = Parser.getConfig(), accum = []) => {
18
18
  const source = `${config.excludes?.includes('heading') ? '' : '^(\0\\d+c\x7F)*={1,6}|'}\\[\\[|\\{{2,}|-\\{(?!\\{)`, { parserFunction: [, , , subst] } = config, stack = [], closes = { '=': '\n', '{': '\\}{2,}|\\|', '-': '\\}-', '[': '\\]\\]' }, marks = new Map([['!', '!'], ['!!', '+'], ['(!', '{'], ['!)', '}'], ['!-', '-'], ['=', '~']]);
19
19
  let regex = new RegExp(source, 'gmu'), mt = regex.exec(wikitext), moreBraces = wikitext.includes('}}'), lastIndex;
20
20
  while (mt
21
- || lastIndex !== undefined && lastIndex <= wikitext.length && stack.at(-1)?.[0]?.startsWith('=')) {
21
+ || lastIndex !== undefined && lastIndex <= wikitext.length && stack[stack.length - 1]?.[0]?.startsWith('=')) {
22
22
  if (mt?.[1]) {
23
23
  const [, { length }] = mt;
24
24
  mt[0] = mt[0].slice(length);
@@ -30,14 +30,14 @@ const parseBraces = (wikitext, config = Parser.getConfig(), accum = []) => {
30
30
  * @param text wikitext全文
31
31
  */
32
32
  const push = (text) => {
33
- parts.at(-1).push(text.slice(topPos, curIndex));
33
+ parts[parts.length - 1].push(text.slice(topPos, curIndex));
34
34
  };
35
35
  if (syntax === ']]' || syntax === '}-') { // 情形1:闭合内链或转换
36
36
  lastIndex = curIndex + 2;
37
37
  }
38
38
  else if (syntax === '\n') { // 情形2:闭合标题或文末
39
39
  lastIndex = curIndex + 1;
40
- const { pos, findEqual } = stack.at(-1) ?? {};
40
+ const { pos, findEqual } = stack[stack.length - 1] ?? {};
41
41
  if (pos === undefined || findEqual || (0, string_1.removeComment)(wikitext.slice(pos, index)) !== '') {
42
42
  const rmt = /^(={1,6})(.+)\1((?:\s|\0\d+c\x7F)*)$/u
43
43
  .exec(wikitext.slice(index, curIndex));
@@ -113,10 +113,10 @@ const parseBraces = (wikitext, config = Parser.getConfig(), accum = []) => {
113
113
  stack.push(...'0' in top ? [top] : [], mt);
114
114
  }
115
115
  moreBraces &&= wikitext.slice(lastIndex).includes('}}');
116
- let curTop = stack.at(-1);
116
+ let curTop = stack[stack.length - 1];
117
117
  if (!moreBraces && curTop?.[0]?.startsWith('{')) {
118
118
  stack.pop();
119
- curTop = stack.at(-1);
119
+ curTop = stack[stack.length - 1];
120
120
  }
121
121
  regex = new RegExp(source + (curTop ? `|${closes[curTop[0][0]]}${curTop.findEqual ? '|=' : ''}` : ''), 'gmu');
122
122
  regex.lastIndex = lastIndex;
@@ -50,9 +50,12 @@ const parseCommentAndExt = (wikitext, config = Parser.getConfig(), accum = [], i
50
50
  return str;
51
51
  }
52
52
  }
53
- const ext = config.ext.join('|'), noincludeRegex = includeOnly ? 'includeonly' : '(?:no|only)include', includeRegex = includeOnly ? 'noinclude' : 'includeonly', regex = new RegExp('<!--.*?(?:-->|$)|' // comment
54
- + `<${noincludeRegex}(?:\\s[^>]*?)?>|</${noincludeRegex}\\s*>|` // <noinclude>
55
- + `<(${ext})(\\s[^>]*?)?(?:/>|>(.*?)</(\\1\\s*)>)|` // 扩展标签
53
+ const ext = config.ext.join('|'), noincludeRegex = includeOnly ? 'includeonly' : '(?:no|only)include', includeRegex = includeOnly ? 'noinclude' : 'includeonly', regex = new RegExp('<!--.*?(?:-->|$)' // comment
54
+ + '|'
55
+ + `<${noincludeRegex}(?:\\s[^>]*?)?>|</${noincludeRegex}\\s*>` // <noinclude>
56
+ + '|'
57
+ + `<(${ext})(\\s[^>]*?)?(?:/>|>(.*?)</(\\1\\s*)>)` // 扩展标签
58
+ + '|'
56
59
  + `<(${includeRegex})(\\s[^>]*?)?(?:/>|>(.*?)(?:</(${includeRegex}\\s*)>|$))`, // <includeonly>
57
60
  'gisu');
58
61
  return wikitext.replace(regex, (substr, name, attr, inner, closing, include, includeAttr, includeInner, includeClosing) => {
@@ -16,10 +16,10 @@ const parseConverter = (text, config = Parser.getConfig(), accum = []) => {
16
16
  while (mt) {
17
17
  const { 0: syntax, index } = mt;
18
18
  if (syntax === '}-') {
19
- const top = stack.pop(), { length } = accum, str = text.slice(top.index + 2, index), i = str.indexOf('|'), [flags, raw] = i === -1 ? [[], str] : [str.slice(0, i).split(';'), str.slice(i + 1)],
20
- // eslint-disable-next-line regexp/prefer-lookaround
21
- temp = raw.replace(/(&[#a-z\d]+);/giu, '$1\x01'), variants = `(?:${config.variants.join('|')})`, rules = temp.split(new RegExp(`;(?=\\s*(?:${variants}|[^;]*?=>\\s*${variants})\\s*:)`, 'u'))
22
- .map(rule => rule.replaceAll('\x01', ';'));
19
+ const top = stack.pop(), { length } = accum, str = text.slice(top.index + 2, index), i = str.indexOf('|'), [flags, raw] = i === -1 ? [[], str] : [str.slice(0, i).split(';'), str.slice(i + 1)], temp = raw.replace(/(&[#a-z\d]+);/giu, '$1\x01'), variants = `(?:${config.variants.join('|')})`, rules = temp.split(new RegExp(`;(?=\\s*(?:${`(?:${variants}|[^;]*?=>\\s*${variants})\\s*:`
20
+ + '|'
21
+ + '(?:\0\\d+c\x7f(?:\\s|\0\\d+c\x7f)*)?$' // 末尾的空白
22
+ }))`, 'u')).map(rule => rule.replace(/\x01/gu, ';'));
23
23
  new converter_1.ConverterToken(flags, rules, config, accum);
24
24
  text = `${text.slice(0, top.index)}\0${length}v\x7F${text.slice(index + 2)}`;
25
25
  if (stack.length === 0) {
@@ -12,9 +12,9 @@ const magicLink_1 = require("../src/magicLink");
12
12
  * @param accum
13
13
  */
14
14
  const parseMagicLinks = (wikitext, config = Parser.getConfig(), accum = []) => {
15
- const regex = new RegExp(`(?<![\\p{L}\\d_])(?:${config.protocol})(${string_1.extUrlCharFirst}${string_1.extUrlChar})`, 'giu');
16
- return wikitext.replace(regex, (m, p1) => {
17
- let trail = '', url = m;
15
+ const regex = new RegExp(`(^|[^\\p{L}\\d_])(?:${config.protocol})(${string_1.extUrlCharFirst}${string_1.extUrlChar})`, 'giu');
16
+ return wikitext.replace(regex, (m, lead, p1) => {
17
+ let trail = '', url = lead ? m.slice(1) : m;
18
18
  const m2 = /&(?:lt|gt|nbsp|#x0*(?:3[ce]|a0)|#0*(?:6[02]|160));/iu.exec(url);
19
19
  if (m2) {
20
20
  trail = url.slice(m2.index);
@@ -33,7 +33,7 @@ const parseMagicLinks = (wikitext, config = Parser.getConfig(), accum = []) => {
33
33
  return m;
34
34
  }
35
35
  new magicLink_1.MagicLinkToken(url, false, config, accum);
36
- return `\0${accum.length - 1}w\x7F${trail}`;
36
+ return `${lead}\0${accum.length - 1}w\x7F${trail}`;
37
37
  });
38
38
  };
39
39
  exports.parseMagicLinks = parseMagicLinks;
@@ -36,7 +36,7 @@ const parseQuotes = (wikitext, config = Parser.getConfig(), accum = []) => {
36
36
  firstSpace = i;
37
37
  }
38
38
  }
39
- else if (arr[i - 1].at(-2) === ' ') {
39
+ else if (arr[i - 1].slice(-2, -1) === ' ') {
40
40
  firstSingle = i;
41
41
  }
42
42
  else {
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.parseSelector = void 0;
4
4
  const constants_1 = require("../util/constants");
5
+ const string_1 = require("../util/string");
5
6
  const Parser = require("../index");
6
7
  const simplePseudos = new Set([
7
8
  'root',
@@ -53,7 +54,7 @@ const pseudoRegex = new RegExp(`:(${complexPseudos.join('|')})$`, 'u'), regularR
53
54
  */
54
55
  const sanitize = (selector) => {
55
56
  for (const [c, escaped] of specialChars) {
56
- selector = selector.replaceAll(`\\${c}`, escaped);
57
+ selector = selector.replace(new RegExp((0, string_1.escapeRegExp)(`\\${c}`), 'gu'), escaped);
57
58
  }
58
59
  return selector;
59
60
  };
@@ -63,7 +64,7 @@ const sanitize = (selector) => {
63
64
  */
64
65
  const desanitize = (selector) => {
65
66
  for (const [c, escaped] of specialChars) {
66
- selector = selector.replaceAll(escaped, c);
67
+ selector = selector.replace(new RegExp(escaped, 'gu'), c);
67
68
  }
68
69
  return selector.trim();
69
70
  };
@@ -81,7 +81,7 @@ const parseTable = ({ firstChild: { data }, type, name }, config = Parser.getCon
81
81
  top = stack.pop();
82
82
  }
83
83
  top.close(`\n${spaces}${closing}`, true);
84
- push(attr, stack.at(-1));
84
+ push(attr, stack[stack.length - 1]);
85
85
  }
86
86
  else if (row) {
87
87
  top = pop();
@@ -146,7 +146,13 @@ const commonHtmlAttrs = new Set([
146
146
  ]),
147
147
  tabs: new Set(['plain', 'class', 'container', 'id', 'title', 'style']),
148
148
  combobox: new Set(['placeholder', 'value', 'id', 'class', 'text', 'dropdown', 'style']),
149
- }, insecureStyle = new RegExp(`${'expression'}|${'(?:filter|accelerator|-o-link(?:-source)?|-o-replace)\\s*:'}|${'(?:url|image(?:-set)?)\\s*\\('}|${'attr\\s*\\([^)]+[\\s,]url'}`, 'u');
149
+ }, insecureStyle = new RegExp('expression'
150
+ + '|'
151
+ + '(?:filter|accelerator|-o-link(?:-source)?|-o-replace)\\s*:'
152
+ + '|'
153
+ + '(?:url|image(?:-set)?)\\s*\\('
154
+ + '|'
155
+ + 'attr\\s*\\([^)]+[\\s,]url', 'u');
150
156
  /**
151
157
  * 扩展和HTML标签属性
152
158
  * @classdesc `{childNodes: [AtomToken, Token|AtomToken]}`
@@ -239,7 +245,7 @@ class AttributeToken extends (0, fixed_1.fixed)(index_1.Token) {
239
245
  /** @private */
240
246
  afterBuild() {
241
247
  if (this.#equal.includes('\0')) {
242
- this.#equal = this.buildFromStr(this.#equal, 'string');
248
+ this.#equal = this.buildFromStr(this.#equal, constants_1.BuildMethod.String);
243
249
  }
244
250
  if (this.parentNode) {
245
251
  this.setAttribute('tag', this.parentNode.name);
@@ -303,7 +309,7 @@ class AttributeToken extends (0, fixed_1.fixed)(index_1.Token) {
303
309
  if (this.#quotes[1]) {
304
310
  return value;
305
311
  }
306
- return this.#quotes[0] ? value.trimEnd() : value.trim();
312
+ return value[this.#quotes[0] ? 'trimEnd' : 'trim']();
307
313
  }
308
314
  return this.type === 'ext-attr' || '';
309
315
  }
@@ -81,12 +81,11 @@ class AttributesToken extends index_1.Token {
81
81
  this.setAttribute('name', name);
82
82
  if (attr) {
83
83
  const regex = new RegExp('([^\\s/](?:(?!\0\\d+~\x7F)[^\\s/=])*)' // 属性名
84
- + '(?:'
85
- + '((?:\\s|\0\\d+c\x7F)*' // `=`前的空白字符
86
- + '(?:=|\0\\d+~\x7F)' // `=`
87
- + '(?:\\s|\0\\d+c\x7F)*)' // `=`后的空白字符
88
- + `(?:(["'])(.*?)(\\3|$)|(\\S*))` // 属性值
89
- + ')?', 'gsu');
84
+ + `(?:${'((?:\\s|\0\\d+c\x7F)*' // `=`前的空白字符
85
+ + '(?:=|\0\\d+~\x7F)' // `=`
86
+ + '(?:\\s|\0\\d+c\x7F)*)' // `=`后的空白字符
87
+ + `(?:(["'])(.*?)(\\3|$)|(\\S*))` // 属性值
88
+ })?`, 'gsu');
90
89
  let out = '', mt = regex.exec(attr), lastIndex = 0;
91
90
  const insertDirty = /** 插入无效属性 */ () => {
92
91
  if (out) {
@@ -134,7 +133,7 @@ class AttributesToken extends index_1.Token {
134
133
  */
135
134
  getAttrToken(key) {
136
135
  const tokens = this.getAttrTokens(key);
137
- return tokens.at(-1);
136
+ return tokens[tokens.length - 1];
138
137
  }
139
138
  /**
140
139
  * 获取指定属性
@@ -15,7 +15,7 @@ class ConverterRuleToken extends index_1.Token {
15
15
  /* NOT FOR BROWSER */
16
16
  /** 语言变体 */
17
17
  get variant() {
18
- return this.childNodes.at(-2)?.text().trim() ?? '';
18
+ return this.childNodes[this.length - 2]?.text().trim() ?? '';
19
19
  }
20
20
  set variant(variant) {
21
21
  this.setVariant(variant);
@@ -122,7 +122,7 @@ class ConverterRuleToken extends index_1.Token {
122
122
  afterBuild() {
123
123
  const /** @implements */ converterRuleListener = (e, data) => {
124
124
  const { prevTarget } = e;
125
- if (this.length > 1 && this.childNodes.at(-2) === prevTarget) {
125
+ if (this.length > 1 && this.childNodes[this.length - 2] === prevTarget) {
126
126
  const { variant } = this;
127
127
  if (!this.getAttribute('config').variants.includes(variant)) {
128
128
  (0, debug_1.undo)(e, data);
@@ -171,7 +171,7 @@ class ConverterRuleToken extends index_1.Token {
171
171
  super.insertAt(debug_1.Shadow.run(() => new atom_1.AtomToken(variant, 'converter-rule-variant', config)), 0);
172
172
  }
173
173
  else {
174
- this.childNodes.at(-2).setText(variant);
174
+ this.childNodes[this.length - 2].setText(variant);
175
175
  }
176
176
  }
177
177
  /**
@@ -1,3 +1,4 @@
1
+ import { BuildMethod } from '../util/constants';
1
2
  import { AstRange } from '../lib/range';
2
3
  import * as Parser from '../index';
3
4
  import { AstElement } from '../lib/element';
package/dist/src/index.js CHANGED
@@ -151,15 +151,15 @@ class Token extends element_1.AstElement {
151
151
  if (i % 2 === 0) {
152
152
  return new text_1.AstText(s);
153
153
  }
154
- else if (Number.isNaN(Number(s.at(-1)))) {
154
+ else if (Number.isNaN(Number(s.slice(-1)))) {
155
155
  return this.#accum[Number(s.slice(0, -1))];
156
156
  }
157
157
  throw new Error(`解析错误!未正确标记的 Token:${s}`);
158
158
  });
159
- if (type === 'string') {
159
+ if (type === constants_1.BuildMethod.String) {
160
160
  return nodes.map(String).join('');
161
161
  }
162
- else if (type === 'text') {
162
+ else if (type === constants_1.BuildMethod.Text) {
163
163
  return (0, string_1.text)(nodes);
164
164
  }
165
165
  return nodes;
@@ -303,15 +303,7 @@ class Token extends element_1.AstElement {
303
303
  return this.#include;
304
304
  }
305
305
  const root = this.getRootNode();
306
- if (root !== this) {
307
- return root.getAttribute('include');
308
- }
309
- const includeToken = root.getElementByTypes('include');
310
- if (includeToken) {
311
- return (includeToken.name === 'noinclude');
312
- }
313
- const noincludeToken = root.getElementByTypes('noinclude');
314
- return (Boolean(noincludeToken) && !/^<\/?noinclude(?:\s[^>]*)?\/?>$/iu.test(String(noincludeToken)));
306
+ return (root !== this && root.getAttribute('include'));
315
307
  }
316
308
  case 'stage':
317
309
  return this.#stage;
@@ -458,7 +450,7 @@ class Token extends element_1.AstElement {
458
450
  createComment(data = '') {
459
451
  const { CommentToken } = require('./nowiki/comment');
460
452
  const config = this.getAttribute('config');
461
- return debug_1.Shadow.run(() => new CommentToken(data.replaceAll('-->', '--&gt;'), true, config));
453
+ return debug_1.Shadow.run(() => new CommentToken(data.replace(/-->/gu, '--&gt;'), true, config));
462
454
  }
463
455
  /**
464
456
  * 创建标签
@@ -61,7 +61,7 @@ class LinkBaseToken extends index_1.Token {
61
61
  this.#title = this.getTitle();
62
62
  this.setAttribute('name', this.#title.title);
63
63
  if (this.#delimiter.includes('\0')) {
64
- this.#delimiter = this.buildFromStr(this.#delimiter, 'string');
64
+ this.#delimiter = this.buildFromStr(this.#delimiter, constants_1.BuildMethod.String);
65
65
  }
66
66
  const /** @implements */ linkListener = (e, data) => {
67
67
  const { prevTarget } = e;
@@ -175,7 +175,8 @@ class FileToken extends base_1.LinkBaseToken {
175
175
  * @param key 参数名
176
176
  */
177
177
  getArg(key) {
178
- return this.getArgs(key).at(-1);
178
+ const args = this.getArgs(key);
179
+ return args[args.length - 1];
179
180
  }
180
181
  /**
181
182
  * 是否具有指定图片参数
@@ -110,6 +110,7 @@ class LinkToken extends base_1.LinkBaseToken {
110
110
  this.setLinkText(m2[1].trim());
111
111
  return;
112
112
  }
113
+ // eslint-disable-next-line es-x/no-regexp-lookbehind-assertions
113
114
  const m3 = /^:?(?:[ \w\x80-\xFF-]+:)?(.+?)(?:(?<!\()\(.+\))?(?:, |,|، )./u
114
115
  .exec(linkText);
115
116
  if (m3) {
@@ -63,9 +63,10 @@ class MagicLinkToken extends (0, syntax_1.syntax)(index_1.Token) {
63
63
  }
64
64
  rect ??= { start, ...this.getRootNode().posFromIndex(start) };
65
65
  const refError = (0, lint_1.generateForChild)(child, rect, '', 'warning');
66
- errors.push(...[...data.matchAll(regexGlobal)].map(({ index, 0: s }) => {
67
- const lines = data.slice(0, index).split('\n'), { length: top } = lines, { length: left } = lines.at(-1), startIndex = refError.startIndex + index, startLine = refError.startLine + top - 1, startCol = top === 1 ? refError.startCol + left : left;
68
- return {
66
+ regexGlobal.lastIndex = 0;
67
+ for (let mt = regexGlobal.exec(data); mt; mt = regexGlobal.exec(data)) {
68
+ const { index, 0: s } = mt, lines = data.slice(0, index).split('\n'), { length: top } = lines, { length: left } = lines[lines.length - 1], startIndex = refError.startIndex + index, startLine = refError.startLine + top - 1, startCol = top === 1 ? refError.startCol + left : left;
69
+ errors.push({
69
70
  ...refError,
70
71
  message: Parser.msg('$1 in URL', s.startsWith('|') ? '"|"' : Parser.msg('full-width punctuation')),
71
72
  startIndex,
@@ -74,8 +75,8 @@ class MagicLinkToken extends (0, syntax_1.syntax)(index_1.Token) {
74
75
  endLine: startLine,
75
76
  startCol,
76
77
  endCol: startCol + s.length,
77
- };
78
- }));
78
+ });
79
+ }
79
80
  }
80
81
  return errors;
81
82
  }
@@ -33,9 +33,9 @@ class NestedToken extends index_1.Token {
33
33
  new comment_1.CommentToken(comment.slice(4, closed ? -3 : undefined), closed, config, accum);
34
34
  }
35
35
  return str;
36
- })?.replace(/(?<=^|\0\d+[ce]\x7F)[^\0]+(?=$|\0\d+[ce]\x7F)/gu, substr => {
36
+ })?.replace(/(^|\0\d+[ce]\x7F)([^\0]+)(?=$|\0\d+[ce]\x7F)/gu, (_, lead, substr) => {
37
37
  new noinclude_1.NoincludeToken(substr, config, accum);
38
- return `\0${accum.length}c\x7F`;
38
+ return `${lead}\0${accum.length}c\x7F`;
39
39
  });
40
40
  super(wikitext, config, accum, {
41
41
  NoincludeToken: ':', ExtToken: ':',
@@ -16,7 +16,7 @@ class QuoteToken extends (0, syntax_1.syntax)(base_1.NowikiBaseToken, /^(?:'{5}|
16
16
  let refError;
17
17
  if (previousSibling?.type === 'text' && previousSibling.data.endsWith(`'`)) {
18
18
  refError = (0, lint_1.generateForSelf)(this, { start }, message);
19
- const { startIndex: endIndex, startLine: endLine, startCol: endCol } = refError, [{ length }] = /(?<!')'+$/u.exec(previousSibling.data), startIndex = start - length;
19
+ const { startIndex: endIndex, startLine: endLine, startCol: endCol } = refError, [, { length }] = /(?:^|[^'])('+)$/u.exec(previousSibling.data), startIndex = start - length;
20
20
  errors.push({
21
21
  ...refError,
22
22
  startIndex,
@@ -13,7 +13,7 @@ const index_1 = require("./index");
13
13
  * @param name 预定的参数名
14
14
  */
15
15
  const getName = (name) => name.toString(new Set(['comment', 'noinclude', 'include']))
16
- .replace(/^[ \t\n\0\v]+|(?<=[^ \t\n\0\v])[ \t\n\0\v]+$/gu, '');
16
+ .replace(/^[ \t\n\0\v]+|([^ \t\n\0\v])[ \t\n\0\v]+$/gu, '$1');
17
17
  /**
18
18
  * 模板或魔术字参数
19
19
  * @classdesc `{childNodes: [Token, Token]}`
@@ -6,6 +6,10 @@ declare const TableBaseToken_base: (abstract new (...args: any[]) => {
6
6
  readonly childNodes: Parser.AstNodes[];
7
7
  readonly "__#7@#attributesChild": Parser.AttributesToken;
8
8
  attributes: Record<string, string | true>;
9
+ /**
10
+ * 表格行,含开头的换行,不含结尾的换行
11
+ * @classdesc `{childNodes: [SyntaxToken, AttributesToken, ...Token]}`
12
+ */
9
13
  className: string;
10
14
  classList: Set<string>;
11
15
  id: string;
@@ -15,7 +15,7 @@ const attributes_1 = require("../attributes");
15
15
  */
16
16
  const escapeTable = (syntax) => {
17
17
  const wikitext = syntax.childNodes.map(child => child.type === 'text'
18
- ? child.data.replaceAll('|', '{{!}}')
18
+ ? child.data.replace(/\|/gu, '{{!}}')
19
19
  : String(child)).join(''), { childNodes } = Parser.parse(wikitext, syntax.getAttribute('include'), 2, syntax.getAttribute('config'));
20
20
  syntax.replaceChildren(...childNodes);
21
21
  };
@@ -69,7 +69,8 @@ class TableToken extends trBase_1.TrBaseToken {
69
69
  * @throws `SyntaxError` 表格的闭合部分非法
70
70
  */
71
71
  insertAt(token, i = this.length) {
72
- const previous = this.childNodes.at(i - 1);
72
+ i += i < 0 ? this.length : 0;
73
+ const previous = this.childNodes[i - 1];
73
74
  if (typeof token !== 'string' && token.type === 'td' && previous?.type === 'tr') {
74
75
  Parser.warn('改为将单元格插入当前行。');
75
76
  return previous.insertAt(token);
@@ -67,7 +67,7 @@ class TdToken extends (0, fixed_1.fixed)(base_1.TableBaseToken) {
67
67
  }
68
68
  /** 表格语法信息 */
69
69
  #getSyntax() {
70
- const syntax = this.firstChild.text(), esc = syntax.includes('{{'), char = syntax.at(-1);
70
+ const syntax = this.firstChild.text(), esc = syntax.includes('{{'), char = syntax.slice(-1);
71
71
  let subtype = 'td';
72
72
  if (char === '!') {
73
73
  subtype = 'th';
@@ -96,7 +96,7 @@ class TdToken extends (0, fixed_1.fixed)(base_1.TableBaseToken) {
96
96
  /** @private */
97
97
  afterBuild() {
98
98
  if (this.#innerSyntax.includes('\0')) {
99
- this.#innerSyntax = this.buildFromStr(this.#innerSyntax, 'string');
99
+ this.#innerSyntax = this.buildFromStr(this.#innerSyntax, constants_1.BuildMethod.String);
100
100
  }
101
101
  }
102
102
  /** @private */
@@ -126,8 +126,11 @@ class TdToken extends (0, fixed_1.fixed)(base_1.TableBaseToken) {
126
126
  const errors = super.lint(start);
127
127
  start += this.getRelativeIndex(this.length - 1);
128
128
  for (const child of this.lastChild.childNodes) {
129
- if (child.type === 'text' && child.data.includes('|')) {
130
- errors.push((0, lint_1.generateForChild)(child, { start }, 'additional "|" in a table cell', 'warning'));
129
+ if (child.type === 'text') {
130
+ const { data } = child;
131
+ if (data.includes('|')) {
132
+ errors.push((0, lint_1.generateForChild)(child, { start }, 'additional "|" in a table cell', data.includes('||') ? 'error' : 'warning'));
133
+ }
131
134
  }
132
135
  }
133
136
  return errors;
@@ -67,7 +67,8 @@ class TrBaseToken extends base_1.TableBaseToken {
67
67
  * @param i 移除位置
68
68
  */
69
69
  removeAt(i) {
70
- const child = this.childNodes.at(i);
70
+ i += i < 0 ? this.length : 0;
71
+ const child = this.childNodes[i];
71
72
  if (child instanceof td_1.TdToken && child.isIndependent()) {
72
73
  const { nextSibling } = child;
73
74
  if (nextSibling?.type === 'td') {
@@ -90,7 +91,8 @@ class TrBaseToken extends base_1.TableBaseToken {
90
91
  this.typeError('insertAt', 'TrToken', 'TdToken');
91
92
  }
92
93
  }
93
- const child = this.childNodes.at(i);
94
+ i += i < 0 ? this.length : 0;
95
+ const child = this.childNodes[i];
94
96
  if (token instanceof td_1.TdToken && token.isIndependent() && child instanceof td_1.TdToken) {
95
97
  child.independence();
96
98
  }
@@ -9,7 +9,7 @@ declare const ExtToken_base: (abstract new (...args: any[]) => {
9
9
  attributes: Record<string, string | true>;
10
10
  className: string;
11
11
  classList: Set<string>;
12
- id: string;
12
+ id: string; /** @override */
13
13
  hasAttr(key: string): boolean;
14
14
  getAttr(key: string): string | true | undefined;
15
15
  getAttrNames(): Set<string>;
@@ -39,9 +39,7 @@ class ExtToken extends (0, attributesParent_1.attributesParent)(index_2.TagPairT
39
39
  * @param closed 是否封闭
40
40
  */
41
41
  constructor(name, attr, inner, closed, config = Parser.getConfig(), accum = []) {
42
- const lcName = name.toLowerCase(), attrToken = new attributes_1.AttributesToken(!attr || attr.trimStart() !== attr
43
- ? attr
44
- : ` ${attr}`, 'ext-attrs', lcName, config, accum), newConfig = { ...config, ext: del(config.ext, lcName), excludes: [...config.excludes ?? []] };
42
+ const lcName = name.toLowerCase(), attrToken = new attributes_1.AttributesToken(!attr || attr.trimStart() !== attr ? attr : ` ${attr}`, 'ext-attrs', lcName, config, accum), newConfig = { ...config, ext: del(config.ext, lcName), excludes: [...config.excludes ?? []] };
45
43
  let innerToken;
46
44
  switch (lcName) {
47
45
  case 'tab':
@@ -146,7 +146,7 @@ class TranscludeToken extends index_1.Token {
146
146
  /** @private */
147
147
  afterBuild() {
148
148
  if (this.modifier.includes('\0')) {
149
- this.setAttribute('modifier', this.buildFromStr(this.modifier, 'string'));
149
+ this.setAttribute('modifier', this.buildFromStr(this.modifier, constants_1.BuildMethod.String));
150
150
  }
151
151
  if (this.isTemplate()) {
152
152
  const isTemplate = this.type === 'template';
@@ -304,7 +304,7 @@ class TranscludeToken extends index_1.Token {
304
304
  * @param copy 是否返回一个备份
305
305
  */
306
306
  getArgs(key, exact = false, copy = true) {
307
- const keyStr = String(key).replace(/^[ \t\n\0\v]+|(?<=[^ \t\n\0\v])[ \t\n\0\v]+$/gu, '');
307
+ const keyStr = String(key).replace(/^[ \t\n\0\v]+|([^ \t\n\0\v])[ \t\n\0\v]+$/gu, '$1');
308
308
  let args;
309
309
  if (this.#args.has(keyStr)) {
310
310
  args = this.#args.get(keyStr);
@@ -441,7 +441,8 @@ class TranscludeToken extends index_1.Token {
441
441
  * @param exact 是否匹配匿名性
442
442
  */
443
443
  getArg(key, exact = false) {
444
- return [...this.getArgs(key, exact, false)].sort((a, b) => a.compareDocumentPosition(b)).at(-1);
444
+ const args = [...this.getArgs(key, exact, false)].sort((a, b) => a.compareDocumentPosition(b));
445
+ return args[args.length - 1];
445
446
  }
446
447
  /**
447
448
  * 移除指定参数
@@ -639,6 +640,7 @@ class TranscludeToken extends index_1.Token {
639
640
  }
640
641
  else if (aggressive && (anonCount ? /\D\d+$/u : /(?:^|\D)\d+$/u).test(key)) {
641
642
  let last;
643
+ // eslint-disable-next-line es-x/no-regexp-lookbehind-assertions
642
644
  const str = key.slice(0, -/(?<!\d)\d+$/u.exec(key)[0].length), regex = new RegExp(`^${(0, string_1.escapeRegExp)(str)}\\d+$`, 'u'), series = this.getAllArgs().filter(({ name }) => regex.test(name)), ordered = series.every(({ name }, i) => {
643
645
  const j = Number(name.slice(str.length)), cmp = j <= i + 1 && (i === 0 || j >= last || name === key);
644
646
  last = j;
@@ -1,7 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.promises = exports.typeAliases = exports.aliases = exports.parsers = exports.mixins = exports.classes = exports.MAX_STAGE = void 0;
3
+ exports.promises = exports.typeAliases = exports.aliases = exports.parsers = exports.mixins = exports.classes = exports.BuildMethod = exports.MAX_STAGE = void 0;
4
4
  exports.MAX_STAGE = 11;
5
+ var BuildMethod;
6
+ (function (BuildMethod) {
7
+ BuildMethod[BuildMethod["String"] = 0] = "String";
8
+ BuildMethod[BuildMethod["Text"] = 1] = "Text";
9
+ })(BuildMethod || (exports.BuildMethod = BuildMethod = {}));
5
10
  /* NOT FOR BROWSER */
6
11
  exports.classes = {};
7
12
  exports.mixins = {};
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.normalizeSpace = exports.print = exports.noWrap = exports.decodeHtml = exports.text = exports.escapeRegExp = exports.removeComment = exports.extUrlChar = exports.extUrlCharFirst = void 0;
4
- exports.extUrlCharFirst = '(?:\\[[\\da-f:.]+\\]|[^[\\]<>"\\0-\\x1F\\x7F\\p{Zs}\\uFFFD])';
5
- exports.extUrlChar = '(?:[^[\\]<>"\\0-\\x1F\\x7F\\p{Zs}\\uFFFD]|\\0\\d+[c!~]\\x7F)*';
4
+ exports.extUrlCharFirst = '(?:\\[[\\da-f:.]+\\]|[^[\\]<>"\0-\x1F\x7F\\p{Zs}\uFFFD])';
5
+ exports.extUrlChar = '(?:[^[\\]<>"\0-\x1F\x7F\\p{Zs}\uFFFD]|\0\\d+[c!~]\x7F)*';
6
6
  /**
7
7
  * 生成正则替换函数
8
8
  * @param regex 正则表达式
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wikiparser-node",
3
- "version": "1.3.6",
3
+ "version": "1.3.7",
4
4
  "description": "A Node.js parser for MediaWiki markup with AST",
5
5
  "keywords": [
6
6
  "mediawiki",
@@ -18,7 +18,8 @@
18
18
  "/printed/README",
19
19
  "/config/",
20
20
  "/i18n/",
21
- "/dist/"
21
+ "/dist/",
22
+ "!/dist/[bt]*/"
22
23
  ],
23
24
  "main": "./dist/index.js",
24
25
  "repository": {
@@ -27,15 +28,15 @@
27
28
  },
28
29
  "scripts": {
29
30
  "toc": "node ./dist/bin/toc.js",
30
- "prepublishOnly": "npm run build; rm dist/internal.js dist/base.js dist/[bmpu]*/*.d.ts; rm -r dist/test",
31
- "build": "rm -rf dist/; tsc; grep -rl --include='*.d.ts' '@private' dist/ | xargs gsed -i '/@private/,+1d'",
31
+ "prepublishOnly": "npm run build && rm dist/internal.js dist/base.js dist/[mpu]*/*.d.ts",
32
+ "build": "rm -rf dist/; tsc && grep -rl --include='*.d.ts' '@private' dist/ | xargs gsed -i '/@private/,+1d'",
32
33
  "diff": "git diff --ignore-all-space --color-moved",
33
34
  "lint:ts": "tsc --noEmit && eslint --cache .",
34
35
  "lint:json": "ajv -s config/.schema.json -d 'config/*.json' --strict=true --strict-required=false",
35
36
  "lint": "npm run lint:ts && npm run lint:json",
36
37
  "test": "node dist/test/test.js",
37
38
  "test:real": "node dist/test/real.js",
38
- "test:single": "node dist/test/single.js; node --prof dist/test/single.js && node --prof-process isolate-0x*-v8.log > test/processed.txt && rm isolate-0x*-v8.log"
39
+ "test:single": "node dist/test/single.js && node --prof dist/test/single.js && node --prof-process isolate-0x*-v8.log > test/processed.txt && rm isolate-0x*-v8.log"
39
40
  },
40
41
  "devDependencies": {
41
42
  "@cypress/request": "^3.0.1",
@@ -46,6 +47,7 @@
46
47
  "@typescript-eslint/parser": "^6.12.0",
47
48
  "ajv-cli": "^5.0.0",
48
49
  "eslint": "^8.56.0",
50
+ "eslint-plugin-es-x": "^7.3.0",
49
51
  "eslint-plugin-eslint-comments": "^3.2.0",
50
52
  "eslint-plugin-jsdoc": "^47.0.2",
51
53
  "eslint-plugin-json-es": "^1.5.7",
package/dist/bin/toc.js DELETED
@@ -1,18 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const fs = require("fs");
4
- const path = require("path");
5
- const { argv: [, , filename] } = process;
6
- if (!filename) {
7
- throw new RangeError('请指定文档文件!');
8
- }
9
- const fullpath = path.join(__dirname, '..', '..', 'wiki', `${filename}.md`), isEnglish = filename.endsWith('-(EN)');
10
- if (!fs.existsSync(fullpath)) {
11
- throw new RangeError(`文档 ${filename}.md 不存在!`);
12
- }
13
- const content = fs.readFileSync(fullpath, 'utf8');
14
- if (/^- \[[^\]]+\]\(#[^)]+\)$/mu.test(content)) {
15
- throw new Error(`文档 ${filename}.md 中已包含目录!`);
16
- }
17
- const toc = content.split('\n').filter(line => line.startsWith('#')).map(line => line.replace(/^(#+)\s+(\S.*)$/u, (_, { length }, title) => `${'\t'.repeat(length - 1)}- [${title}](#${title.toLowerCase().replaceAll(' ', '-').replaceAll('.', '')})`)).join('\n');
18
- fs.writeFileSync(fullpath, `<details>\n\t<summary>${isEnglish ? 'Table of Contents' : '目录'}</summary>\n\n${toc}\n\n</details>\n\n# Other Languages\n\n- [${isEnglish ? '简体中文' : 'English'}](./${isEnglish ? filename.slice(0, -5) : `${filename}-%28EN%29`})\n\n${content}`);