wikiparser-node 1.7.1 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/addon/token.js +41 -24
- package/dist/lib/element.d.ts +0 -11
- package/dist/lib/element.js +0 -31
- package/dist/lib/node.d.ts +21 -0
- package/dist/lib/node.js +60 -0
- package/dist/src/index.d.ts +2 -2
- package/dist/src/nowiki/quote.d.ts +7 -2
- package/dist/src/nowiki/quote.js +8 -2
- package/dist/util/string.js +1 -1
- package/package.json +1 -1
- package/dist/addon/table.d.ts +0 -1
- package/dist/addon/token.d.ts +0 -1
- package/dist/addon/transclude.d.ts +0 -1
package/dist/addon/token.js
CHANGED
|
@@ -77,62 +77,79 @@ index_1.Token.prototype.sections =
|
|
|
77
77
|
if (this.type !== 'root') {
|
|
78
78
|
return undefined;
|
|
79
79
|
}
|
|
80
|
-
const { childNodes } = this, headings = [...childNodes.entries()]
|
|
80
|
+
const { childNodes, length } = this, headings = [...childNodes.entries()]
|
|
81
81
|
.filter((entry) => entry[1].type === 'heading')
|
|
82
|
-
.map(([i, { level }]) => [i, level]), lastHeading = [-1, -1, -1, -1, -1, -1], sections =
|
|
82
|
+
.map(([i, { level }]) => [i, level]), lastHeading = [-1, -1, -1, -1, -1, -1], sections = headings.map(([i]) => {
|
|
83
|
+
const range = this.createRange();
|
|
84
|
+
range.setStart(this, i);
|
|
85
|
+
return range;
|
|
86
|
+
});
|
|
83
87
|
for (let i = 0; i < headings.length; i++) {
|
|
84
88
|
const [index, level] = headings[i];
|
|
85
89
|
for (let j = level; j < 6; j++) {
|
|
86
90
|
const last = lastHeading[j];
|
|
87
91
|
if (last >= 0) {
|
|
88
|
-
sections[last]
|
|
92
|
+
sections[last].setEnd(this, index);
|
|
89
93
|
}
|
|
90
94
|
lastHeading[j] = j === level ? i : -1;
|
|
91
95
|
}
|
|
92
96
|
}
|
|
93
97
|
for (const last of lastHeading) {
|
|
94
98
|
if (last >= 0) {
|
|
95
|
-
sections[last]
|
|
99
|
+
sections[last].setEnd(this, length);
|
|
96
100
|
}
|
|
97
101
|
}
|
|
98
|
-
|
|
102
|
+
const range = this.createRange();
|
|
103
|
+
range.setStart(this, 0);
|
|
104
|
+
range.setEnd(this, headings[0]?.[0] ?? length);
|
|
105
|
+
sections.unshift(range);
|
|
99
106
|
return sections;
|
|
100
107
|
};
|
|
101
108
|
index_1.Token.prototype.findEnclosingHtml =
|
|
102
109
|
/** @implements */
|
|
103
110
|
function (tag) {
|
|
104
111
|
tag = tag?.toLowerCase();
|
|
105
|
-
|
|
112
|
+
const { html } = this.getAttribute('config'), normalTags = new Set(html[0]), voidTags = new Set(html[2]);
|
|
113
|
+
if (tag !== undefined && !html.slice(0, 2).flat().includes(tag)) {
|
|
106
114
|
throw new RangeError(`非法的标签或空标签:${tag}`);
|
|
107
115
|
}
|
|
108
116
|
const { parentNode } = this;
|
|
109
117
|
if (!parentNode) {
|
|
110
118
|
return undefined;
|
|
111
119
|
}
|
|
112
|
-
const isHtml = (0, debug_1.isToken)('html'),
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
120
|
+
const isHtml = (0, debug_1.isToken)('html'),
|
|
121
|
+
/**
|
|
122
|
+
* 检查是否为指定的 HTML 标签
|
|
123
|
+
* @param node 节点
|
|
124
|
+
* @param name 标签名
|
|
125
|
+
* @param closing 是否为闭合标签
|
|
126
|
+
*/
|
|
127
|
+
checkHtml = (node, name, closing) => isHtml(node)
|
|
128
|
+
&& (!name && !voidTags.has(node.name) || node.name === name)
|
|
129
|
+
&& (normalTags.has(node.name) || !node.selfClosing)
|
|
130
|
+
&& node.closing === closing;
|
|
131
|
+
const { childNodes, length } = parentNode, index = childNodes.indexOf(this);
|
|
132
|
+
let i = index - 1, j = length;
|
|
133
|
+
for (; i >= 0; i--) {
|
|
134
|
+
const open = childNodes[i];
|
|
135
|
+
if (checkHtml(open, tag, false)) {
|
|
136
|
+
for (j = index + 1; j < length; j++) {
|
|
137
|
+
const close = childNodes[j];
|
|
138
|
+
if (checkHtml(close, open.name, true)) {
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
if (j < length) {
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
118
145
|
}
|
|
119
146
|
}
|
|
120
147
|
if (i === -1) {
|
|
121
148
|
return parentNode.findEnclosingHtml(tag);
|
|
122
149
|
}
|
|
123
|
-
const opening = childNodes[i];
|
|
124
|
-
for (i = index + 1; i < length; i++) {
|
|
125
|
-
const child = childNodes[i];
|
|
126
|
-
if (isHtml(child) && child.name === opening.name && !child.selfClosing && child.closing) {
|
|
127
|
-
break;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
if (i === length) {
|
|
131
|
-
return parentNode.findEnclosingHtml(tag);
|
|
132
|
-
}
|
|
133
150
|
const range = this.createRange();
|
|
134
|
-
range.
|
|
135
|
-
range.setEnd(parentNode,
|
|
151
|
+
range.setStart(parentNode, i);
|
|
152
|
+
range.setEnd(parentNode, j + 1);
|
|
136
153
|
return range;
|
|
137
154
|
};
|
|
138
155
|
index_1.Token.prototype.redoQuotes =
|
package/dist/lib/element.d.ts
CHANGED
|
@@ -22,10 +22,6 @@ export declare abstract class AstElement extends AstNode {
|
|
|
22
22
|
get outerText(): string;
|
|
23
23
|
/** 不可见 */
|
|
24
24
|
get hidden(): boolean;
|
|
25
|
-
/** 后一个可见的兄弟节点 */
|
|
26
|
-
get nextVisibleSibling(): AstNodes | undefined;
|
|
27
|
-
/** 前一个可见的兄弟节点 */
|
|
28
|
-
get previousVisibleSibling(): AstNodes | undefined;
|
|
29
25
|
/** 内部高度 */
|
|
30
26
|
get clientHeight(): number | undefined;
|
|
31
27
|
/** 内部宽度 */
|
|
@@ -99,8 +95,6 @@ export declare abstract class AstElement extends AstNode {
|
|
|
99
95
|
* @param start
|
|
100
96
|
*/
|
|
101
97
|
json(file?: string, start?: number): AST;
|
|
102
|
-
/** 销毁 */
|
|
103
|
-
destroy(): void;
|
|
104
98
|
/**
|
|
105
99
|
* 检查是否符合选择器
|
|
106
100
|
* @param selector 选择器
|
|
@@ -126,11 +120,6 @@ export declare abstract class AstElement extends AstNode {
|
|
|
126
120
|
* @param tag 标签名
|
|
127
121
|
*/
|
|
128
122
|
getElementsByTagName<T = Token>(tag: string): T[];
|
|
129
|
-
/**
|
|
130
|
-
* 获取某一行的wikitext
|
|
131
|
-
* @param n 行号
|
|
132
|
-
*/
|
|
133
|
-
getLine(n: number): string | undefined;
|
|
134
123
|
/**
|
|
135
124
|
* 在开头批量插入子节点
|
|
136
125
|
* @param elements 插入节点
|
package/dist/lib/element.js
CHANGED
|
@@ -69,22 +69,6 @@ class AstElement extends node_1.AstNode {
|
|
|
69
69
|
get hidden() {
|
|
70
70
|
return this.text() === '';
|
|
71
71
|
}
|
|
72
|
-
/** 后一个可见的兄弟节点 */
|
|
73
|
-
get nextVisibleSibling() {
|
|
74
|
-
let { nextSibling } = this;
|
|
75
|
-
while (nextSibling?.text() === '') {
|
|
76
|
-
({ nextSibling } = nextSibling);
|
|
77
|
-
}
|
|
78
|
-
return nextSibling;
|
|
79
|
-
}
|
|
80
|
-
/** 前一个可见的兄弟节点 */
|
|
81
|
-
get previousVisibleSibling() {
|
|
82
|
-
let { previousSibling } = this;
|
|
83
|
-
while (previousSibling?.text() === '') {
|
|
84
|
-
({ previousSibling } = previousSibling);
|
|
85
|
-
}
|
|
86
|
-
return previousSibling;
|
|
87
|
-
}
|
|
88
72
|
/** 内部高度 */
|
|
89
73
|
get clientHeight() {
|
|
90
74
|
const { innerText } = this;
|
|
@@ -347,14 +331,6 @@ class AstElement extends node_1.AstNode {
|
|
|
347
331
|
return json;
|
|
348
332
|
}
|
|
349
333
|
/* NOT FOR BROWSER */
|
|
350
|
-
/** 销毁 */
|
|
351
|
-
destroy() {
|
|
352
|
-
this.parentNode?.destroy();
|
|
353
|
-
for (const child of this.childNodes) {
|
|
354
|
-
child.setAttribute('parentNode', undefined);
|
|
355
|
-
}
|
|
356
|
-
Object.setPrototypeOf(this, null);
|
|
357
|
-
}
|
|
358
334
|
/** 是否受保护。保护条件来自Token,这里仅提前用于:required和:optional伪选择器。 */
|
|
359
335
|
#isProtected() {
|
|
360
336
|
const { parentNode } = this;
|
|
@@ -583,13 +559,6 @@ class AstElement extends node_1.AstNode {
|
|
|
583
559
|
getElementsByTagName(tag) {
|
|
584
560
|
return this.#getElementsBy((({ type, name }) => name === tag && (type === 'html' || type === 'ext')));
|
|
585
561
|
}
|
|
586
|
-
/**
|
|
587
|
-
* 获取某一行的wikitext
|
|
588
|
-
* @param n 行号
|
|
589
|
-
*/
|
|
590
|
-
getLine(n) {
|
|
591
|
-
return String(this).split('\n', n + 1)[n];
|
|
592
|
-
}
|
|
593
562
|
/**
|
|
594
563
|
* 在开头批量插入子节点
|
|
595
564
|
* @param elements 插入节点
|
package/dist/lib/node.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export declare abstract class AstNode implements AstNodeBase {
|
|
|
19
19
|
type: TokenTypes | 'text';
|
|
20
20
|
data?: string | undefined;
|
|
21
21
|
readonly childNodes: readonly AstNodes[];
|
|
22
|
+
abstract text(): string;
|
|
22
23
|
abstract lint(): LintError[];
|
|
23
24
|
abstract print(): string;
|
|
24
25
|
/** 首位子节点 */
|
|
@@ -39,6 +40,10 @@ export declare abstract class AstNode implements AstNodeBase {
|
|
|
39
40
|
get nextElementSibling(): Token | undefined;
|
|
40
41
|
/** 前一个非文本兄弟节点 */
|
|
41
42
|
get previousElementSibling(): Token | undefined;
|
|
43
|
+
/** 后一个可见的兄弟节点 */
|
|
44
|
+
get nextVisibleSibling(): AstNodes | undefined;
|
|
45
|
+
/** 前一个可见的兄弟节点 */
|
|
46
|
+
get previousVisibleSibling(): AstNodes | undefined;
|
|
42
47
|
/** 是否具有根节点 */
|
|
43
48
|
get isConnected(): boolean;
|
|
44
49
|
/** 后方是否还有其他节点(不含后代) */
|
|
@@ -51,6 +56,15 @@ export declare abstract class AstNode implements AstNodeBase {
|
|
|
51
56
|
get style(): Position & Dimension & {
|
|
52
57
|
padding: number;
|
|
53
58
|
};
|
|
59
|
+
/** 字体样式 */
|
|
60
|
+
get font(): {
|
|
61
|
+
bold: boolean;
|
|
62
|
+
italic: boolean;
|
|
63
|
+
};
|
|
64
|
+
/** 是否粗体 */
|
|
65
|
+
get bold(): boolean;
|
|
66
|
+
/** 是否斜体 */
|
|
67
|
+
get italic(): boolean;
|
|
54
68
|
constructor();
|
|
55
69
|
/** 获取根节点 */
|
|
56
70
|
getRootNode(): Token | this;
|
|
@@ -142,4 +156,11 @@ export declare abstract class AstNode implements AstNodeBase {
|
|
|
142
156
|
indexFromPos(top: number, left: number): number | undefined;
|
|
143
157
|
/** 获取当前节点的行列位置和大小 */
|
|
144
158
|
getBoundingClientRect(): Dimension & Position;
|
|
159
|
+
/** 销毁 */
|
|
160
|
+
destroy(): void;
|
|
161
|
+
/**
|
|
162
|
+
* 获取某一行的wikitext
|
|
163
|
+
* @param n 行号
|
|
164
|
+
*/
|
|
165
|
+
getLine(n: number): string | undefined;
|
|
145
166
|
}
|
package/dist/lib/node.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.AstNode = void 0;
|
|
|
4
4
|
const assert = require("assert/strict");
|
|
5
5
|
const EventEmitter = require("events");
|
|
6
6
|
const constants_1 = require("../util/constants");
|
|
7
|
+
const debug_1 = require("../util/debug");
|
|
7
8
|
/**
|
|
8
9
|
* 计算字符串的行列数
|
|
9
10
|
* @param str 字符串
|
|
@@ -79,6 +80,22 @@ class AstNode {
|
|
|
79
80
|
const childNodes = this.parentNode?.childNodes, i = childNodes?.indexOf(this);
|
|
80
81
|
return childNodes?.slice(0, i).reverse().find((child) => child.type !== 'text');
|
|
81
82
|
}
|
|
83
|
+
/** 后一个可见的兄弟节点 */
|
|
84
|
+
get nextVisibleSibling() {
|
|
85
|
+
let { nextSibling } = this;
|
|
86
|
+
while (nextSibling?.text() === '') {
|
|
87
|
+
({ nextSibling } = nextSibling);
|
|
88
|
+
}
|
|
89
|
+
return nextSibling;
|
|
90
|
+
}
|
|
91
|
+
/** 前一个可见的兄弟节点 */
|
|
92
|
+
get previousVisibleSibling() {
|
|
93
|
+
let { previousSibling } = this;
|
|
94
|
+
while (previousSibling?.text() === '') {
|
|
95
|
+
({ previousSibling } = previousSibling);
|
|
96
|
+
}
|
|
97
|
+
return previousSibling;
|
|
98
|
+
}
|
|
82
99
|
/** 是否具有根节点 */
|
|
83
100
|
get isConnected() {
|
|
84
101
|
return this.getRootNode().type === 'root';
|
|
@@ -111,6 +128,34 @@ class AstNode {
|
|
|
111
128
|
get fixed() {
|
|
112
129
|
return false;
|
|
113
130
|
}
|
|
131
|
+
/** 字体样式 */
|
|
132
|
+
get font() {
|
|
133
|
+
const { parentNode } = this, acceptable = parentNode?.getAttribute('acceptable');
|
|
134
|
+
if (!parentNode || acceptable && !('QuoteToken' in acceptable)) {
|
|
135
|
+
return { bold: false, italic: false };
|
|
136
|
+
}
|
|
137
|
+
const { childNodes } = parentNode, index = childNodes.indexOf(this), isQuote = (0, debug_1.isToken)('quote');
|
|
138
|
+
let bold = false, italic = false;
|
|
139
|
+
for (let i = index - 1; i >= 0; i--) {
|
|
140
|
+
const child = childNodes[i];
|
|
141
|
+
if (isQuote(child)) {
|
|
142
|
+
bold = child.bold ? !bold : bold;
|
|
143
|
+
italic = child.italic ? !italic : italic;
|
|
144
|
+
}
|
|
145
|
+
else if (child.type === 'text' && child.data.includes('\n')) {
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return { bold, italic };
|
|
150
|
+
}
|
|
151
|
+
/** 是否粗体 */
|
|
152
|
+
get bold() {
|
|
153
|
+
return this.font.bold;
|
|
154
|
+
}
|
|
155
|
+
/** 是否斜体 */
|
|
156
|
+
get italic() {
|
|
157
|
+
return this.font.italic;
|
|
158
|
+
}
|
|
114
159
|
constructor() {
|
|
115
160
|
Object.defineProperty(this, 'childNodes', { writable: false });
|
|
116
161
|
Object.freeze(this.childNodes);
|
|
@@ -415,6 +460,21 @@ class AstNode {
|
|
|
415
460
|
getBoundingClientRect() {
|
|
416
461
|
return { ...this.#getDimension(), ...this.getRootNode().posFromIndex(this.getAbsoluteIndex()) };
|
|
417
462
|
}
|
|
463
|
+
/** 销毁 */
|
|
464
|
+
destroy() {
|
|
465
|
+
this.parentNode?.destroy();
|
|
466
|
+
for (const child of this.childNodes) {
|
|
467
|
+
child.setAttribute('parentNode', undefined);
|
|
468
|
+
}
|
|
469
|
+
Object.setPrototypeOf(this, null);
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* 获取某一行的wikitext
|
|
473
|
+
* @param n 行号
|
|
474
|
+
*/
|
|
475
|
+
getLine(n) {
|
|
476
|
+
return String(this).split('\n', n + 1)[n];
|
|
477
|
+
}
|
|
418
478
|
}
|
|
419
479
|
exports.AstNode = AstNode;
|
|
420
480
|
constants_1.classes['AstNode'] = __filename;
|
package/dist/src/index.d.ts
CHANGED
|
@@ -119,12 +119,12 @@ export declare class Token extends AstElement {
|
|
|
119
119
|
/** 深拷贝节点 */
|
|
120
120
|
cloneNode(): this;
|
|
121
121
|
/** 获取全部章节 */
|
|
122
|
-
sections():
|
|
122
|
+
sections(): AstRange[] | undefined;
|
|
123
123
|
/**
|
|
124
124
|
* 获取指定章节
|
|
125
125
|
* @param n 章节序号
|
|
126
126
|
*/
|
|
127
|
-
section(n: number):
|
|
127
|
+
section(n: number): AstRange | undefined;
|
|
128
128
|
/**
|
|
129
129
|
* 获取指定的外层HTML标签
|
|
130
130
|
* @param tag HTML标签名
|
|
@@ -3,11 +3,16 @@ import type { LintError, AST } from '../../base';
|
|
|
3
3
|
/** `''`和`'''` */
|
|
4
4
|
export declare abstract class QuoteToken extends NowikiBaseToken {
|
|
5
5
|
readonly type = "quote";
|
|
6
|
-
/**
|
|
6
|
+
/** @override */
|
|
7
7
|
get bold(): boolean;
|
|
8
|
-
/**
|
|
8
|
+
/** @override */
|
|
9
9
|
get italic(): boolean;
|
|
10
10
|
/** @override */
|
|
11
|
+
get font(): {
|
|
12
|
+
bold: boolean;
|
|
13
|
+
italic: boolean;
|
|
14
|
+
};
|
|
15
|
+
/** @override */
|
|
11
16
|
lint(start?: number): LintError[];
|
|
12
17
|
/** @override */
|
|
13
18
|
json(): AST;
|
package/dist/src/nowiki/quote.js
CHANGED
|
@@ -57,14 +57,20 @@ let QuoteToken = (() => {
|
|
|
57
57
|
__runInitializers(_classThis, _classExtraInitializers);
|
|
58
58
|
}
|
|
59
59
|
type = 'quote';
|
|
60
|
-
/**
|
|
60
|
+
/** @override */
|
|
61
61
|
get bold() {
|
|
62
62
|
return this.innerText.length !== 2;
|
|
63
63
|
}
|
|
64
|
-
/**
|
|
64
|
+
/** @override */
|
|
65
65
|
get italic() {
|
|
66
66
|
return this.innerText.length !== 3;
|
|
67
67
|
}
|
|
68
|
+
/* NOT FOR BROWSER */
|
|
69
|
+
/** @override */
|
|
70
|
+
get font() {
|
|
71
|
+
return { bold: this.bold, italic: this.italic };
|
|
72
|
+
}
|
|
73
|
+
/* NOT FOR BROWSER END */
|
|
68
74
|
/** @override */
|
|
69
75
|
lint(start = this.getAbsoluteIndex()) {
|
|
70
76
|
const { previousSibling, nextSibling, bold } = this, message = index_1.default.msg('lonely "$1"', `'`), errors = [];
|
package/dist/util/string.js
CHANGED
|
@@ -11,7 +11,7 @@ exports.extUrlChar = `(?:${commonExtUrlChar}|\0\\d+[c!~]\x7F)*`;
|
|
|
11
11
|
*/
|
|
12
12
|
const factory = (regex, replace) => (str) => str.replace(regex, replace);
|
|
13
13
|
/** 清理解析专用的不可见字符 */
|
|
14
|
-
exports.tidy = factory(/[\0\x7F]
|
|
14
|
+
exports.tidy = factory(/[\0\x7F]|\r$/gmu, '');
|
|
15
15
|
/** remove half-parsed comment-like tokens */
|
|
16
16
|
exports.removeComment = factory(/\0\d+c\x7F/gu, '');
|
|
17
17
|
/** escape special chars for RegExp constructor */
|
package/package.json
CHANGED
package/dist/addon/table.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/addon/token.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|