wikiparser-node 1.1.3 → 1.1.4

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.
@@ -30,15 +30,15 @@
30
30
  "type": "string"
31
31
  }
32
32
  },
33
- "required": [
34
- "6",
35
- "10"
36
- ],
37
33
  "additionalProperties": false
38
34
  },
39
35
  "nsid": {
40
36
  "description": "namespace IDs",
41
37
  "type": "object",
38
+ "required": [
39
+ "file",
40
+ "category"
41
+ ],
42
42
  "additionalProperties": {
43
43
  "type": "integer"
44
44
  }
@@ -70,11 +70,11 @@
70
70
  "img"
71
71
  ]
72
72
  ],
73
- "namespaces": {
74
- "6": "File",
75
- "10": "Template"
73
+ "namespaces": {},
74
+ "nsid": {
75
+ "file": 6,
76
+ "category": 14
76
77
  },
77
- "nsid": {},
78
78
  "parserFunction": [
79
79
  {
80
80
  "#language": "language",
@@ -114,7 +114,7 @@ table_1.TableToken.prototype.getLayout =
114
114
  const rowLayout = layout[i];
115
115
  let j = 0, k = 0, last;
116
116
  for (const cell of rows[i].childNodes.slice(2)) {
117
- if (cell instanceof td_1.TdToken) {
117
+ if (cell.type === 'td') {
118
118
  if (cell.isIndependent()) {
119
119
  last = cell.subtype !== 'caption';
120
120
  }
@@ -478,7 +478,7 @@ table_1.TableToken.prototype.moveTableRowBefore =
478
478
  table_1.TableToken.prototype.moveTableRowAfter =
479
479
  /** @implements */
480
480
  function (y, after) {
481
- const layout = this.getLayout(), afterToken = this.getNthRow(after), cells = afterToken.childNodes.filter(child => child instanceof td_1.TdToken && child.subtype !== 'caption'),
481
+ const layout = this.getLayout(), afterToken = this.getNthRow(after), cells = afterToken.childNodes.filter(child => child.type === 'td' && child.subtype !== 'caption'),
482
482
  /** @ignore */
483
483
  occupied = (i, oneRow = false) => layout[i].map(({ row, column }, j) => row === i && (!oneRow || cells[column].rowspan === 1) ? j : undefined).filter(j => j !== undefined);
484
484
  try {
package/dist/index.d.ts CHANGED
@@ -18,11 +18,6 @@ declare interface Parser extends ParserBase {
18
18
  * @param selfLink 是否允许selfLink
19
19
  */
20
20
  normalizeTitle(title: string, defaultNs?: number, include?: boolean, config?: Config, halfParsed?: boolean, decode?: boolean, selfLink?: boolean): Title;
21
- /**
22
- * @override
23
- * @param include 是否嵌入
24
- * @param maxStage 最大解析层级
25
- */
26
21
  parse(wikitext: string, include?: boolean, maxStage?: number, config?: Config): Token;
27
22
  /**
28
23
  * 是否是跨维基链接
@@ -47,7 +47,7 @@ export declare abstract class AstElement extends AstNode {
47
47
  * 插入子节点
48
48
  * @param node 待插入的子节点
49
49
  * @param i 插入位置
50
- * @throws `RangeError` 不能插入祖先节点
50
+ * @throws `RangeError` 不能插入祖先或子节点
51
51
  */
52
52
  insertAt<T extends AstNodes>(node: T, i?: number): T;
53
53
  /**
@@ -4,7 +4,6 @@ exports.AstElement = void 0;
4
4
  const fs = require("fs");
5
5
  const path = require("path");
6
6
  const string_1 = require("../util/string");
7
- const debug_1 = require("../util/debug");
8
7
  const constants_1 = require("../util/constants");
9
8
  const selector_1 = require("../parser/selector");
10
9
  const ranges_1 = require("./ranges");
@@ -149,35 +148,32 @@ class AstElement extends node_1.AstNode {
149
148
  */
150
149
  removeAt(i) {
151
150
  this.verifyChild(i);
152
- const childNodes = [...this.childNodes], e = new Event('remove', { bubbles: true }), [node] = childNodes.splice(i, 1);
151
+ const childNodes = [...this.childNodes], [node] = childNodes.splice(i, 1);
153
152
  node.setAttribute('parentNode', undefined);
154
153
  this.setAttribute('childNodes', childNodes);
155
- this.dispatchEvent(e, { position: i, removed: node });
156
154
  return node;
157
155
  }
158
156
  /**
159
157
  * 插入子节点
160
158
  * @param node 待插入的子节点
161
159
  * @param i 插入位置
162
- * @throws `RangeError` 不能插入祖先节点
160
+ * @throws `RangeError` 不能插入祖先或子节点
163
161
  */
164
162
  insertAt(node, i = this.length) {
165
163
  if (node.contains(this)) {
166
164
  Parser.error('不能插入祖先节点!', node);
167
165
  throw new RangeError('不能插入祖先节点!');
168
166
  }
169
- this.verifyChild(i, 1);
170
- const childNodes = [...this.childNodes], e = new Event('insert', { bubbles: true }), j = debug_1.Shadow.running ? -1 : childNodes.indexOf(node);
171
- if (j === -1) {
172
- node.parentNode?.removeChild(node);
173
- node.setAttribute('parentNode', this);
174
- }
175
- else {
176
- childNodes.splice(j, 1);
167
+ const childNodes = [...this.childNodes];
168
+ if (childNodes.includes(node)) {
169
+ Parser.error('不能插入子节点!', node);
170
+ throw new RangeError('不能插入子节点!');
177
171
  }
172
+ this.verifyChild(i, 1);
173
+ node.parentNode?.removeChild(node);
174
+ node.setAttribute('parentNode', this);
178
175
  childNodes.splice(i, 0, node);
179
176
  this.setAttribute('childNodes', childNodes);
180
- this.dispatchEvent(e, { position: i < 0 ? i + this.length - 1 : i, inserted: node });
181
177
  return node;
182
178
  }
183
179
  /**
@@ -126,7 +126,7 @@ export declare abstract class AstNode implements AstNodeBase {
126
126
  * @param e 事件对象
127
127
  * @param data 事件数据
128
128
  */
129
- dispatchEvent(e: Event, data: unknown): void;
129
+ dispatchEvent(e: Event, data: AstEventData): void;
130
130
  /** 获取所有祖先节点 */
131
131
  getAncestors(): Token[];
132
132
  /**
@@ -15,6 +15,7 @@ export declare class AstText extends AstNode {
15
15
  /**
16
16
  * @override
17
17
  * @param start
18
+ * @throws `Error` 孤立文本节点
18
19
  */
19
20
  lint(start?: number): LintError[];
20
21
  /**
@@ -56,10 +57,6 @@ export declare class AstText extends AstNode {
56
57
  * @throws `Error` 没有父节点
57
58
  */
58
59
  splitText(offset: number): AstText;
59
- /**
60
- * @override
61
- * @param j 字符位置
62
- * @throws `RangeError` 超出文本长度范围
63
- */
64
- getRelativeIndex(j?: number): number;
60
+ /** 转义 `=` */
61
+ escape(): void;
65
62
  }
package/dist/lib/text.js CHANGED
@@ -56,7 +56,6 @@ const errorSyntax = /https?:\/\/|\{+|\}+|\[{2,}|\[(?![^[]*\])|(?<=^|\])([^[]*?)\
56
56
  'param',
57
57
  'xmp',
58
58
  ];
59
- const entities = { '&': 'amp', '<': 'lt', '>': 'gt' };
60
59
  /** 文本节点 */
61
60
  class AstText extends node_1.AstNode {
62
61
  type = 'text';
@@ -87,9 +86,14 @@ class AstText extends node_1.AstNode {
87
86
  /**
88
87
  * @override
89
88
  * @param start
89
+ * @throws `Error` 孤立文本节点
90
90
  */
91
91
  lint(start = this.getAbsoluteIndex()) {
92
- const { data, parentNode, nextSibling, previousSibling } = this, type = parentNode?.type, name = parentNode?.name, nextType = nextSibling?.type, previousType = previousSibling?.type, errorRegex = type === 'free-ext-link' || type === 'ext-link-url' || type === 'image-parameter' && name === 'link'
92
+ const { data, parentNode, nextSibling, previousSibling } = this;
93
+ if (!parentNode) {
94
+ throw new Error('无法对孤立文本节点进行语法分析!');
95
+ }
96
+ const { type, name } = parentNode, nextType = nextSibling?.type, previousType = previousSibling?.type, errorRegex = type === 'free-ext-link' || type === 'ext-link-url' || type === 'image-parameter' && name === 'link'
93
97
  ? errorSyntaxUrl
94
98
  : errorSyntax, errors = [...data.matchAll(errorRegex)], { ext, html } = this.getRootNode().getAttribute('config');
95
99
  if (errors.length > 0) {
@@ -133,7 +137,7 @@ class AstText extends node_1.AstNode {
133
137
  const { data } = this, e = new Event('text', { bubbles: true });
134
138
  this.setAttribute('data', text);
135
139
  if (data !== text) {
136
- this.dispatchEvent(e, { oldText: data, newText: text });
140
+ this.dispatchEvent(e, { type: 'text', oldText: data });
137
141
  }
138
142
  }
139
143
  /**
@@ -145,6 +149,7 @@ class AstText extends node_1.AstNode {
145
149
  }
146
150
  /** @override */
147
151
  print() {
152
+ const entities = { '&': 'amp', '<': 'lt', '>': 'gt' };
148
153
  return this.data.replace(/[&<>]/gu, p => `&${entities[p]};`);
149
154
  }
150
155
  /* NOT FOR BROWSER */
@@ -204,11 +209,7 @@ class AstText extends node_1.AstNode {
204
209
  parentNode.setAttribute('childNodes', childNodes);
205
210
  return newText;
206
211
  }
207
- /**
208
- * @override
209
- * @param j 字符位置
210
- * @throws `RangeError` 超出文本长度范围
211
- */
212
+ /** @private */
212
213
  getRelativeIndex(j) {
213
214
  if (j === undefined) {
214
215
  return super.getRelativeIndex();
@@ -218,6 +219,17 @@ class AstText extends node_1.AstNode {
218
219
  }
219
220
  return j;
220
221
  }
222
+ /** 转义 `=` */
223
+ escape() {
224
+ const { TranscludeToken } = require('../src/transclude');
225
+ for (let i = this.data.lastIndexOf('='); i >= 0; i = this.data.lastIndexOf('=', i - 1)) {
226
+ if (i < this.length - 1) {
227
+ this.splitText(i + 1);
228
+ }
229
+ this.after(new TranscludeToken('=', [], this.parentNode.getAttribute('config')));
230
+ this.setAttribute('data', this.data.slice(0, i));
231
+ }
232
+ }
221
233
  }
222
234
  exports.AstText = AstText;
223
235
  constants_1.classes['AstText'] = __filename;
@@ -19,7 +19,7 @@ const fixed = (constructor) => {
19
19
  throw new Error(`${this.constructor.name} 不可删除元素!`);
20
20
  }
21
21
  /** @ignore */
22
- insertAt(token, i = this.length) {
22
+ insertAt(token, i) {
23
23
  if (debug_1.Shadow.running) {
24
24
  return super.insertAt(token, i);
25
25
  }
@@ -109,7 +109,7 @@ class GalleryToken extends index_1.Token {
109
109
  * @param i 插入位置
110
110
  * @throws `SyntaxError` 非法的文件名
111
111
  */
112
- insertImage(file, i = this.length) {
112
+ insertImage(file, i) {
113
113
  if (this.#checkFile(file)) {
114
114
  const token = debug_1.Shadow.run(() => new galleryImage_1.GalleryImageToken('gallery', file, undefined, this.getAttribute('config')));
115
115
  token.afterBuild();
@@ -118,7 +118,7 @@ class GalleryToken extends index_1.Token {
118
118
  throw new SyntaxError(`非法的文件名:${file}`);
119
119
  }
120
120
  /** @ignore */
121
- insertAt(token, i = 0) {
121
+ insertAt(token, i = this.length) {
122
122
  if (typeof token === 'string' && token.trim() || token instanceof hidden_1.HiddenToken) {
123
123
  throw new RangeError('请勿向图库中插入不可见内容!');
124
124
  }
@@ -208,7 +208,7 @@ class ImageParameterToken extends index_1.Token {
208
208
  return this.#syntax && !this.#syntax.includes('$1');
209
209
  }
210
210
  /** @ignore */
211
- insertAt(token, i = this.length) {
211
+ insertAt(token, i) {
212
212
  if (!debug_1.Shadow.running && this.#isVoid()) {
213
213
  throw new Error(`图片参数 ${this.name} 不接受自定义输入!`);
214
214
  }
@@ -113,7 +113,7 @@ class ImagemapToken extends index_1.Token {
113
113
  return super.print({ sep: '\n' });
114
114
  }
115
115
  /** @ignore */
116
- insertAt(token, i = 0) {
116
+ insertAt(token, i) {
117
117
  const { image } = this;
118
118
  if (!image && (typeof token === 'string' || token.type === 'imagemap-link' || token.type === 'text')) {
119
119
  throw new Error('当前缺少一张合法图片!');
package/dist/src/index.js CHANGED
@@ -366,6 +366,8 @@ class Token extends element_1.AstElement {
366
366
  }
367
367
  }
368
368
  super.insertAt(token, i);
369
+ const e = new Event('insert', { bubbles: true });
370
+ this.dispatchEvent(e, { type: 'insert', position: i < 0 ? i + this.length - 1 : i, inserted: token });
369
371
  if (token.constructor === Token && this.getAttribute('plain')) {
370
372
  Parser.warn('您正将一个普通节点作为另一个普通节点的子节点,请考虑要不要执行 flatten 方法。');
371
373
  }
@@ -409,7 +411,10 @@ class Token extends element_1.AstElement {
409
411
  }
410
412
  }
411
413
  }
412
- return super.removeAt(i);
414
+ const node = super.removeAt(i);
415
+ const e = new Event('remove', { bubbles: true });
416
+ this.dispatchEvent(e, { type: 'remove', position: i, removed: node });
417
+ return node;
413
418
  }
414
419
  /**
415
420
  * 替换为同类节点
@@ -441,7 +446,7 @@ class Token extends element_1.AstElement {
441
446
  token.type = 'plain';
442
447
  }
443
448
  const e = new Event('replace', { bubbles: true });
444
- token.dispatchEvent(e, { position: i, oldToken: this, newToken: token });
449
+ token.dispatchEvent(e, { type: 'replace', position: i, oldToken: this, newToken: token });
445
450
  }
446
451
  /**
447
452
  * 创建HTML注释
@@ -1,7 +1,7 @@
1
1
  import * as Parser from '../index';
2
2
  import { Token } from './index';
3
3
  import type { LintError } from '../base';
4
- import type { AstText, CommentToken, IncludeToken, NoincludeToken } from '../internal';
4
+ import type { AstNodes, AstText, CommentToken, IncludeToken, NoincludeToken, TranscludeToken } from '../internal';
5
5
  declare const MagicLinkToken_base: (abstract new (...args: any[]) => {
6
6
  "__#5@#pattern": RegExp;
7
7
  afterBuild(): void;
@@ -20,12 +20,12 @@ declare const MagicLinkToken_base: (abstract new (...args: any[]) => {
20
20
  */
21
21
  export declare class MagicLinkToken extends MagicLinkToken_base {
22
22
  type: 'free-ext-link' | 'ext-link-url';
23
- childNodes: (AstText | CommentToken | IncludeToken | NoincludeToken)[];
24
- abstract get children(): (CommentToken | IncludeToken | NoincludeToken)[];
25
- abstract get firstChild(): AstText | CommentToken | IncludeToken | NoincludeToken;
26
- abstract get firstElementChild(): CommentToken | IncludeToken | NoincludeToken | undefined;
27
- abstract get lastChild(): AstText | CommentToken | IncludeToken | NoincludeToken;
28
- abstract get lastElementChild(): CommentToken | IncludeToken | NoincludeToken | undefined;
23
+ childNodes: (AstText | CommentToken | IncludeToken | NoincludeToken | TranscludeToken)[];
24
+ abstract get children(): (CommentToken | IncludeToken | NoincludeToken | TranscludeToken)[];
25
+ abstract get firstChild(): AstText | TranscludeToken;
26
+ abstract get firstElementChild(): CommentToken | IncludeToken | NoincludeToken | TranscludeToken | undefined;
27
+ abstract get lastChild(): AstText | CommentToken | IncludeToken | NoincludeToken | TranscludeToken;
28
+ abstract get lastElementChild(): CommentToken | IncludeToken | NoincludeToken | TranscludeToken | undefined;
29
29
  /** 协议 */
30
30
  get protocol(): string | undefined;
31
31
  /** @throws `Error` 特殊外链无法更改协议n */
@@ -42,6 +42,15 @@ export declare class MagicLinkToken extends MagicLinkToken_base {
42
42
  lint(start?: number): LintError[];
43
43
  /** @override */
44
44
  cloneNode(): this;
45
+ /**
46
+ * @override
47
+ * @param token 待插入的节点
48
+ * @param i 插入位置
49
+ * @throws `RangeError` 插入`{{!}}`或`{{=}}`以外的魔术字或模板
50
+ */
51
+ insertAt(token: string, i?: number): AstText;
52
+ /** @ignore */
53
+ insertAt<T extends AstNodes>(token: T, i?: number): T;
45
54
  /**
46
55
  * 获取网址
47
56
  * @throws `Error` 非标准协议
@@ -54,5 +63,7 @@ export declare class MagicLinkToken extends MagicLinkToken_base {
54
63
  setTarget(url: string): void;
55
64
  /** 是否是模板或魔术字参数 */
56
65
  isParamValue(): boolean;
66
+ /** 转义 `=` */
67
+ escape(): void;
57
68
  }
58
69
  export {};
@@ -4,6 +4,7 @@ exports.MagicLinkToken = void 0;
4
4
  const lint_1 = require("../util/lint");
5
5
  const debug_1 = require("../util/debug");
6
6
  const constants_1 = require("../util/constants");
7
+ const string_1 = require("../util/string");
7
8
  const syntax_1 = require("../mixin/syntax");
8
9
  const Parser = require("../index");
9
10
  const index_1 = require("./index");
@@ -30,7 +31,11 @@ class MagicLinkToken extends (0, syntax_1.syntax)(index_1.Token) {
30
31
  }
31
32
  /** 和内链保持一致 */
32
33
  get link() {
33
- return this.text();
34
+ const map = { '!': '|', '=': '=' };
35
+ return (0, string_1.text)(this.childNodes.map(child => {
36
+ const { type, name } = child;
37
+ return type === 'magic-word' && name in map ? map[name] : child;
38
+ }));
34
39
  }
35
40
  set link(url) {
36
41
  this.setTarget(url);
@@ -42,7 +47,7 @@ class MagicLinkToken extends (0, syntax_1.syntax)(index_1.Token) {
42
47
  */
43
48
  constructor(url, doubleSlash = false, config = Parser.getConfig(), accum = []) {
44
49
  super(url, config, accum, {
45
- 'Stage-1': ':', '!ExtToken': '',
50
+ 'Stage-1': '1:', '!ExtToken': '', AstText: ':', TranscludeToken: ':',
46
51
  });
47
52
  this.type = doubleSlash ? 'ext-link-url' : 'free-ext-link';
48
53
  this.setAttribute('pattern', new RegExp(`^(?:${config.protocol}${doubleSlash ? '|//' : ''})`, 'iu'));
@@ -86,21 +91,34 @@ class MagicLinkToken extends (0, syntax_1.syntax)(index_1.Token) {
86
91
  return token;
87
92
  });
88
93
  }
94
+ /** @ignore */
95
+ insertAt(token, i) {
96
+ if (typeof token !== 'string') {
97
+ const { type, name } = token;
98
+ if (type === 'template') {
99
+ throw new RangeError(`${this.constructor.name} 不可插入模板!`);
100
+ }
101
+ else if (!debug_1.Shadow.running && type === 'magic-word' && name !== '!' && name !== '=') {
102
+ throw new RangeError(`${this.constructor.name} 不可插入 \`{{!}}\` 或 \`{{=}}\` 以外的魔术字!`);
103
+ }
104
+ }
105
+ return super.insertAt(token, i);
106
+ }
89
107
  /**
90
108
  * 获取网址
91
109
  * @throws `Error` 非标准协议
92
110
  */
93
111
  getUrl() {
94
- let url = this.text();
95
- if (url.startsWith('//')) {
96
- url = `https:${url}`;
112
+ let { link } = this;
113
+ if (link.startsWith('//')) {
114
+ link = `https:${link}`;
97
115
  }
98
116
  try {
99
- return new URL(url);
117
+ return new URL(link);
100
118
  }
101
119
  catch (e) {
102
120
  if (e instanceof TypeError && e.message === 'Invalid URL') {
103
- throw new Error(`非标准协议的外部链接:${url}`);
121
+ throw new Error(`非标准协议的外部链接:${link}`);
104
122
  }
105
123
  throw e;
106
124
  }
@@ -110,13 +128,21 @@ class MagicLinkToken extends (0, syntax_1.syntax)(index_1.Token) {
110
128
  * @param url 含协议的网址
111
129
  */
112
130
  setTarget(url) {
113
- const { childNodes } = Parser.parse(url, this.getAttribute('include'), 1, this.getAttribute('config'));
131
+ const { childNodes } = Parser.parse(url, this.getAttribute('include'), 2, this.getAttribute('config'));
114
132
  this.replaceChildren(...childNodes);
115
133
  }
116
134
  /** 是否是模板或魔术字参数 */
117
135
  isParamValue() {
118
136
  return this.closest('parameter')?.getValue() === this.text();
119
137
  }
138
+ /** 转义 `=` */
139
+ escape() {
140
+ for (const child of this.childNodes) {
141
+ if (child.type === 'text') {
142
+ child.escape();
143
+ }
144
+ }
145
+ }
120
146
  }
121
147
  exports.MagicLinkToken = MagicLinkToken;
122
148
  constants_1.classes['MagicLinkToken'] = __filename;
@@ -67,7 +67,7 @@ class NestedToken extends index_1.Token {
67
67
  * @param i 插入位置
68
68
  * @throws `TypeError` 不是许可的标签
69
69
  */
70
- insertAt(token, i = this.length) {
70
+ insertAt(token, i) {
71
71
  if (typeof token !== 'string' && token.type === 'ext' && !this.#tags.includes(token.name)) {
72
72
  throw new TypeError(`${this.constructor.name}只能以${this.#tags.join('或')}标签作为子节点!`);
73
73
  }
@@ -78,5 +78,7 @@ export declare class ParameterToken extends ParameterToken_base {
78
78
  * @throws `RangeError` 更名造成重复参数
79
79
  */
80
80
  rename(key: string, force?: boolean): void;
81
+ /** 转义 `=` */
82
+ escape(): void;
81
83
  }
82
84
  export {};
@@ -193,6 +193,14 @@ class ParameterToken extends (0, fixed_1.fixed)(index_1.Token) {
193
193
  }
194
194
  this.firstChild.replaceChildren(...root.childNodes);
195
195
  }
196
+ /** 转义 `=` */
197
+ escape() {
198
+ for (const child of this.lastChild.childNodes) {
199
+ if (child.type === 'text') {
200
+ child.escape();
201
+ }
202
+ }
203
+ }
196
204
  }
197
205
  exports.ParameterToken = ParameterToken;
198
206
  constants_1.classes['ParameterToken'] = __filename;
@@ -52,7 +52,7 @@ class TableToken extends trBase_1.TrBaseToken {
52
52
  */
53
53
  close(syntax = '\n|}', halfParsed = false) {
54
54
  const config = this.getAttribute('config'), accum = this.getAttribute('accum'), inner = halfParsed ? [syntax] : Parser.parse(syntax, this.getAttribute('include'), 2, config).childNodes;
55
- if (!(this.lastChild instanceof syntax_1.SyntaxToken)) {
55
+ if (this.lastChild.type !== 'table-syntax') {
56
56
  const token = debug_1.Shadow.run(() => super.insertAt(new syntax_1.SyntaxToken(undefined, closingPattern, 'table-syntax', config, accum, {
57
57
  'Stage-1': ':', '!ExtToken': '', TranscludeToken: ':',
58
58
  })));
@@ -29,7 +29,7 @@ exports.Shadow = {
29
29
  */
30
30
  const undo = (e, data) => {
31
31
  const { target, type } = e;
32
- switch (type) {
32
+ switch (data.type) {
33
33
  case 'remove': {
34
34
  const childNodes = [...target.childNodes];
35
35
  childNodes.splice(data.position, 0, data.removed);
@@ -40,6 +40,7 @@ const undo = (e, data) => {
40
40
  case 'insert': {
41
41
  const childNodes = [...target.childNodes];
42
42
  childNodes.splice(data.position, 1);
43
+ data.inserted.setAttribute('parentNode', undefined);
43
44
  target.setAttribute('childNodes', childNodes);
44
45
  break;
45
46
  }
@@ -47,6 +48,7 @@ const undo = (e, data) => {
47
48
  const { parentNode } = target, childNodes = [...parentNode.childNodes];
48
49
  childNodes.splice(data.position, 1, data.oldToken);
49
50
  data.oldToken.setAttribute('parentNode', parentNode);
51
+ data.newToken.setAttribute('parentNode', undefined);
50
52
  parentNode.setAttribute('childNodes', childNodes);
51
53
  break;
52
54
  }
@@ -2,7 +2,7 @@
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
4
  exports.extUrlCharFirst = '(?:\\[[\\da-f:.]+\\]|[^[\\]<>"\\0-\\x1F\\x7F\\p{Zs}\\uFFFD])';
5
- exports.extUrlChar = '(?:[^[\\]<>"\\0-\\x1F\\x7F\\p{Zs}\\uFFFD]|\\0\\d+c\\x7F)*';
5
+ exports.extUrlChar = '(?:[^[\\]<>"\\0-\\x1F\\x7F\\p{Zs}\\uFFFD]|\\0\\d+[c!~]\\x7F)*';
6
6
  /**
7
7
  * remove half-parsed comment-like tokens
8
8
  * @param str 原字符串
@@ -26,7 +26,7 @@ exports.text = text;
26
26
  * decode HTML entities
27
27
  * @param str 原字符串
28
28
  */
29
- const decodeHtml = (str) => str.replace(/&#(\d+|x[\da-f]+);/giu, (_, code) => String.fromCodePoint(Number(`${code[0].toLowerCase() === 'x' ? '0' : ''}${code}`)));
29
+ const decodeHtml = (str) => str.replace(/&#(\d+|x[\da-f]+);/giu, (_, code) => String.fromCodePoint(Number(`${code.toLowerCase().startsWith('x') ? '0' : ''}${code}`)));
30
30
  exports.decodeHtml = decodeHtml;
31
31
  /**
32
32
  * escape newlines
@@ -53,7 +53,7 @@ const normalizeSpace = (token) => {
53
53
  if (token) {
54
54
  for (const child of token.childNodes) {
55
55
  if (child.type === 'text') {
56
- child.replaceData(child.data.replaceAll('\n', ' '));
56
+ child.replaceData(child.data.replace(/\n+/gu, ' '));
57
57
  }
58
58
  }
59
59
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wikiparser-node",
3
- "version": "1.1.3",
3
+ "version": "1.1.4",
4
4
  "description": "A Node.js parser for MediaWiki markup with AST",
5
5
  "keywords": [
6
6
  "mediawiki",