wikiparser-node 1.9.0 → 1.9.1
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/README.en.md +2 -2
- package/dist/addon/table.js +9 -8
- package/dist/addon/token.js +8 -5
- package/dist/addon/transclude.js +12 -10
- package/dist/base.d.ts +2 -0
- package/dist/index.d.ts +2 -4
- package/dist/index.js +5 -2
- package/dist/lib/element.d.ts +0 -5
- package/dist/lib/element.js +46 -39
- package/dist/lib/node.d.ts +1 -1
- package/dist/lib/node.js +9 -9
- package/dist/lib/rect.d.ts +18 -0
- package/dist/lib/rect.js +34 -0
- package/dist/lib/text.js +8 -13
- package/dist/mixin/attributesParent.js +2 -1
- package/dist/mixin/fixed.js +5 -3
- package/dist/mixin/flagsParent.js +2 -1
- package/dist/mixin/hidden.d.ts +2 -0
- package/dist/mixin/hidden.js +9 -4
- package/dist/mixin/magicLinkParent.js +2 -1
- package/dist/mixin/singleLine.js +3 -2
- package/dist/mixin/sol.js +3 -2
- package/dist/mixin/syntax.js +3 -6
- package/dist/parser/braces.js +13 -6
- package/dist/parser/commentAndExt.js +3 -13
- package/dist/parser/converter.js +4 -5
- package/dist/parser/externalLinks.js +2 -9
- package/dist/parser/hrAndDoubleUnderscore.js +3 -1
- package/dist/parser/html.js +1 -1
- package/dist/parser/links.js +3 -1
- package/dist/parser/magicLinks.js +7 -13
- package/dist/parser/redirect.js +1 -1
- package/dist/parser/selector.js +8 -8
- package/dist/src/arg.d.ts +0 -2
- package/dist/src/arg.js +6 -7
- package/dist/src/atom.d.ts +2 -2
- package/dist/src/atom.js +4 -5
- package/dist/src/attribute.d.ts +0 -2
- package/dist/src/attribute.js +7 -19
- package/dist/src/attributes.d.ts +0 -2
- package/dist/src/attributes.js +11 -17
- package/dist/src/converter.d.ts +0 -2
- package/dist/src/converter.js +1 -1
- package/dist/src/converterFlags.d.ts +0 -2
- package/dist/src/converterFlags.js +3 -2
- package/dist/src/converterRule.d.ts +0 -2
- package/dist/src/converterRule.js +10 -9
- package/dist/src/extLink.d.ts +0 -2
- package/dist/src/extLink.js +1 -1
- package/dist/src/gallery.d.ts +0 -2
- package/dist/src/gallery.js +3 -3
- package/dist/src/heading.d.ts +0 -2
- package/dist/src/heading.js +4 -9
- package/dist/src/hidden.d.ts +4 -1
- package/dist/src/hidden.js +69 -13
- package/dist/src/html.d.ts +2 -5
- package/dist/src/html.js +19 -38
- package/dist/src/imageParameter.d.ts +0 -2
- package/dist/src/imageParameter.js +11 -7
- package/dist/src/imagemap.d.ts +0 -2
- package/dist/src/imagemap.js +7 -6
- package/dist/src/index.d.ts +1 -13
- package/dist/src/index.js +58 -58
- package/dist/src/link/base.d.ts +0 -2
- package/dist/src/link/base.js +5 -9
- package/dist/src/link/file.js +11 -9
- package/dist/src/link/galleryImage.js +2 -2
- package/dist/src/link/index.d.ts +0 -2
- package/dist/src/link/index.js +5 -5
- package/dist/src/link/redirectTarget.d.ts +0 -12
- package/dist/src/link/redirectTarget.js +4 -10
- package/dist/src/magicLink.d.ts +1 -0
- package/dist/src/magicLink.js +29 -19
- package/dist/src/nested.js +3 -3
- package/dist/src/nowiki/base.d.ts +2 -2
- package/dist/src/nowiki/base.js +3 -4
- package/dist/src/nowiki/comment.d.ts +3 -9
- package/dist/src/nowiki/comment.js +106 -59
- package/dist/src/nowiki/doubleUnderscore.d.ts +3 -3
- package/dist/src/nowiki/doubleUnderscore.js +3 -4
- package/dist/src/nowiki/index.js +3 -1
- package/dist/src/nowiki/noinclude.d.ts +1 -1
- package/dist/src/nowiki/noinclude.js +63 -13
- package/dist/src/nowiki/quote.js +18 -24
- package/dist/src/onlyinclude.js +1 -1
- package/dist/src/paramTag/index.d.ts +0 -2
- package/dist/src/paramTag/index.js +3 -3
- package/dist/src/parameter.js +10 -9
- package/dist/src/redirect.d.ts +4 -1
- package/dist/src/redirect.js +5 -3
- package/dist/src/syntax.d.ts +2 -2
- package/dist/src/syntax.js +4 -5
- package/dist/src/table/index.d.ts +2 -3
- package/dist/src/table/index.js +9 -8
- package/dist/src/table/td.d.ts +0 -4
- package/dist/src/table/td.js +17 -7
- package/dist/src/table/tr.d.ts +2 -4
- package/dist/src/table/tr.js +2 -3
- package/dist/src/table/trBase.d.ts +0 -2
- package/dist/src/table/trBase.js +2 -2
- package/dist/src/tagPair/ext.js +5 -7
- package/dist/src/tagPair/include.d.ts +7 -5
- package/dist/src/tagPair/include.js +106 -56
- package/dist/src/tagPair/index.d.ts +2 -4
- package/dist/src/tagPair/index.js +4 -4
- package/dist/src/transclude.d.ts +0 -2
- package/dist/src/transclude.js +15 -17
- package/dist/util/debug.js +10 -1
- package/dist/util/lint.js +3 -2
- package/dist/util/string.js +5 -5
- package/package.json +12 -12
package/README.en.md
CHANGED
|
@@ -50,8 +50,8 @@ or
|
|
|
50
50
|
<script src="//unpkg.com/wikiparser-node@browser/bundle/bundle.min.js"></script>
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
-
For more browser extensions, please refer to the corresponding [documentation](https://github.com/bhsd-harry/wikiparser-node/wiki/Browser
|
|
53
|
+
For more browser extensions, please refer to the corresponding [documentation](https://github.com/bhsd-harry/wikiparser-node/wiki/Browser-%28EN%29).
|
|
54
54
|
|
|
55
55
|
# Usage
|
|
56
56
|
|
|
57
|
-
Please refer to the [Wiki](https://github.com/bhsd-harry/wikiparser-node/wiki/Home
|
|
57
|
+
Please refer to the [Wiki](https://github.com/bhsd-harry/wikiparser-node/wiki/Home-%28EN%29).
|
package/dist/addon/table.js
CHANGED
|
@@ -38,7 +38,7 @@ function occupied(layout, i, oneRow, cells) {
|
|
|
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);
|
|
40
40
|
}
|
|
41
|
-
throw new RangeError(
|
|
41
|
+
throw new RangeError(`The table layout does not contain row ${i}!`);
|
|
42
42
|
}
|
|
43
43
|
/**
|
|
44
44
|
* 设置表格格式
|
|
@@ -145,7 +145,7 @@ index_2.TableToken.prototype.insertTableCell =
|
|
|
145
145
|
const { x, y } = coords;
|
|
146
146
|
rawCoords = this.toRawCoords(coords);
|
|
147
147
|
if (!rawCoords?.start) {
|
|
148
|
-
throw new RangeError(
|
|
148
|
+
throw new RangeError(`The specified coordinates are not the starting point of any cell: (${x}, ${y})`);
|
|
149
149
|
}
|
|
150
150
|
}
|
|
151
151
|
else {
|
|
@@ -206,7 +206,7 @@ index_2.TableToken.prototype.insertTableCol =
|
|
|
206
206
|
function (x, inner, subtype, attr) {
|
|
207
207
|
const layout = this.getLayout(), rowLength = layout.map(({ length }) => length), minCol = Math.min(...rowLength);
|
|
208
208
|
if (x > minCol) {
|
|
209
|
-
throw new RangeError(
|
|
209
|
+
throw new RangeError(`Row ${rowLength.indexOf(minCol)} has only ${minCol} column(s)!`);
|
|
210
210
|
}
|
|
211
211
|
const token = (0, td_1.createTd)(inner, subtype, attr, this.getAttribute('include'), this.getAttribute('config'));
|
|
212
212
|
for (let i = 0; i < layout.length; i++) {
|
|
@@ -275,7 +275,7 @@ index_2.TableToken.prototype.mergeCells =
|
|
|
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)));
|
|
276
276
|
if ([...layout[ymin - 1] ?? [], ...layout[ymax] ?? []].some(coords => set.has(coords))
|
|
277
277
|
|| layout.some(rowLayout => set.has(rowLayout[xmin - 1]) || set.has(rowLayout[xmax]))) {
|
|
278
|
-
throw new RangeError('
|
|
278
|
+
throw new RangeError('The area to be merged overlaps with the outer area!');
|
|
279
279
|
}
|
|
280
280
|
const corner = layout[ymin][xmin], rows = this.getAllRows(), cornerCell = rows[corner.row].getNthCol(corner.column);
|
|
281
281
|
cornerCell.rowspan = ymax - ymin;
|
|
@@ -318,7 +318,8 @@ index_2.TableToken.prototype.split =
|
|
|
318
318
|
this.insertTableCell('', { x: i, y: j }, subtype, attr);
|
|
319
319
|
}
|
|
320
320
|
catch (e) {
|
|
321
|
-
if (e instanceof RangeError
|
|
321
|
+
if (e instanceof RangeError
|
|
322
|
+
&& e.message.startsWith('The specified coordinates are not the starting point of a cell: ')) {
|
|
322
323
|
break;
|
|
323
324
|
}
|
|
324
325
|
throw e;
|
|
@@ -386,7 +387,7 @@ index_2.TableToken.prototype.moveTableRowBefore =
|
|
|
386
387
|
}
|
|
387
388
|
catch (e) {
|
|
388
389
|
if (e instanceof assert.AssertionError) {
|
|
389
|
-
throw new RangeError(
|
|
390
|
+
throw new RangeError(`The structure of row ${y} is different from that of row ${before}, so it cannot be moved!`);
|
|
390
391
|
}
|
|
391
392
|
throw e;
|
|
392
393
|
}
|
|
@@ -412,7 +413,7 @@ index_2.TableToken.prototype.moveTableRowAfter =
|
|
|
412
413
|
}
|
|
413
414
|
catch (e) {
|
|
414
415
|
if (e instanceof assert.AssertionError) {
|
|
415
|
-
throw new RangeError(
|
|
416
|
+
throw new RangeError(`The structure of row ${y} is different from that of row ${after}, so it cannot be moved!`);
|
|
416
417
|
}
|
|
417
418
|
throw e;
|
|
418
419
|
}
|
|
@@ -442,7 +443,7 @@ index_2.TableToken.prototype.moveCol =
|
|
|
442
443
|
function (x, reference, after) {
|
|
443
444
|
const layout = this.getLayout();
|
|
444
445
|
if (layout.some(rowLayout => isStartCol(rowLayout, x) !== isStartCol(rowLayout, reference, after))) {
|
|
445
|
-
throw new RangeError(
|
|
446
|
+
throw new RangeError(`The structure of column ${x} is different from that of column ${reference}, so it cannot be moved!`);
|
|
446
447
|
}
|
|
447
448
|
const setX = new WeakSet(), setRef = new WeakSet(), rows = this.getAllRows();
|
|
448
449
|
for (let i = 0; i < layout.length; i++) {
|
package/dist/addon/token.js
CHANGED
|
@@ -29,7 +29,7 @@ index_1.Token.prototype.createElement =
|
|
|
29
29
|
// @ts-expect-error abstract class
|
|
30
30
|
return debug_1.Shadow.run(() => new ext_1.ExtToken(tagName, '', undefined, selfClosing ? undefined : '', config));
|
|
31
31
|
}
|
|
32
|
-
else if (config.html.
|
|
32
|
+
else if (config.html.some(tags => tags.includes(tagName))) {
|
|
33
33
|
return debug_1.Shadow.run(() => {
|
|
34
34
|
// @ts-expect-error abstract class
|
|
35
35
|
const attr = new attributes_1.AttributesToken(undefined, 'html-attrs', tagName, config);
|
|
@@ -37,7 +37,7 @@ index_1.Token.prototype.createElement =
|
|
|
37
37
|
return new html_1.HtmlToken(tagName, attr, Boolean(closing), Boolean(selfClosing), config);
|
|
38
38
|
});
|
|
39
39
|
}
|
|
40
|
-
throw new RangeError(
|
|
40
|
+
throw new RangeError(`Invalid tag name: ${tagName}`);
|
|
41
41
|
};
|
|
42
42
|
index_1.Token.prototype.caretPositionFromIndex =
|
|
43
43
|
/** @implements */
|
|
@@ -110,8 +110,11 @@ index_1.Token.prototype.findEnclosingHtml =
|
|
|
110
110
|
function (tag) {
|
|
111
111
|
tag = tag?.toLowerCase();
|
|
112
112
|
const { html } = this.getAttribute('config'), normalTags = new Set(html[0]), voidTags = new Set(html[2]);
|
|
113
|
-
if (
|
|
114
|
-
throw new RangeError(
|
|
113
|
+
if (html[2].includes(tag)) {
|
|
114
|
+
throw new RangeError(`Void tag: ${tag}`);
|
|
115
|
+
}
|
|
116
|
+
else if (tag !== undefined && !html.slice(0, 2).some(tags => tags.includes(tag))) {
|
|
117
|
+
throw new RangeError(`Invalid tag name: ${tag}`);
|
|
115
118
|
}
|
|
116
119
|
const { parentNode } = this;
|
|
117
120
|
if (!parentNode) {
|
|
@@ -155,7 +158,7 @@ index_1.Token.prototype.findEnclosingHtml =
|
|
|
155
158
|
index_1.Token.prototype.redoQuotes =
|
|
156
159
|
/** @implements */
|
|
157
160
|
function () {
|
|
158
|
-
const acceptable = this.
|
|
161
|
+
const acceptable = this.getAcceptable();
|
|
159
162
|
if (acceptable && !('QuoteToken' in acceptable)) {
|
|
160
163
|
return;
|
|
161
164
|
}
|
package/dist/addon/transclude.js
CHANGED
|
@@ -23,7 +23,7 @@ transclude_1.TranscludeToken.prototype.setValue =
|
|
|
23
23
|
/** @implements */
|
|
24
24
|
function (key, value) {
|
|
25
25
|
if (!this.isTemplate()) {
|
|
26
|
-
throw new Error('setValue
|
|
26
|
+
throw new Error('TranscludeToken.setValue method is only for templates!');
|
|
27
27
|
}
|
|
28
28
|
const arg = this.getArg(key);
|
|
29
29
|
if (arg) {
|
|
@@ -42,7 +42,7 @@ transclude_1.TranscludeToken.prototype.replaceTemplate =
|
|
|
42
42
|
/** @implements */
|
|
43
43
|
function (title) {
|
|
44
44
|
if (this.type === 'magic-word') {
|
|
45
|
-
throw new Error('replaceTemplate
|
|
45
|
+
throw new Error('TranscludeToken.replaceTemplate method is only for templates!');
|
|
46
46
|
}
|
|
47
47
|
const { childNodes } = index_1.default.parse(title, this.getAttribute('include'), 2, this.getAttribute('config'));
|
|
48
48
|
this.firstChild.replaceChildren(...childNodes);
|
|
@@ -51,7 +51,7 @@ transclude_1.TranscludeToken.prototype.replaceModule =
|
|
|
51
51
|
/** @implements */
|
|
52
52
|
function (title) {
|
|
53
53
|
if (this.type !== 'magic-word' || this.name !== 'invoke') {
|
|
54
|
-
throw new Error('replaceModule
|
|
54
|
+
throw new Error('TranscludeToken.replaceModule method is only for modules!');
|
|
55
55
|
}
|
|
56
56
|
const config = this.getAttribute('config');
|
|
57
57
|
if (this.length === 1) {
|
|
@@ -67,10 +67,10 @@ transclude_1.TranscludeToken.prototype.replaceFunction =
|
|
|
67
67
|
/** @implements */
|
|
68
68
|
function (func) {
|
|
69
69
|
if (this.type !== 'magic-word' || this.name !== 'invoke') {
|
|
70
|
-
throw new Error('replaceModule
|
|
70
|
+
throw new Error('TranscludeToken.replaceModule method is only for modules!');
|
|
71
71
|
}
|
|
72
72
|
else if (this.length < 2) {
|
|
73
|
-
throw new Error('
|
|
73
|
+
throw new Error('No module name specified!');
|
|
74
74
|
}
|
|
75
75
|
const config = this.getAttribute('config');
|
|
76
76
|
if (this.length === 2) {
|
|
@@ -129,8 +129,10 @@ transclude_1.TranscludeToken.prototype.fixDuplication =
|
|
|
129
129
|
}
|
|
130
130
|
else if (aggressive && (anonCount ? /\D\d+$/u : /(?:^|\D)\d+$/u).test(key)) {
|
|
131
131
|
let last;
|
|
132
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
133
|
+
/^a\d+$/u;
|
|
132
134
|
// eslint-disable-next-line es-x/no-regexp-lookbehind-assertions
|
|
133
|
-
const str = key.slice(0, -/(?<!\d)\d+$/u.exec(key)[0].length), regex = new RegExp(`^${(0, string_1.escapeRegExp)(str)}
|
|
135
|
+
const str = key.slice(0, -/(?<!\d)\d+$/u.exec(key)[0].length), regex = new RegExp(String.raw `^${(0, string_1.escapeRegExp)(str)}\d+$`, 'u'), series = this.getAllArgs().filter(({ name }) => regex.test(name)), ordered = series.every(({ name }, i) => {
|
|
134
136
|
const j = Number(name.slice(str.length)), cmp = j <= i + 1 && (i === 0 || j >= last || name === key);
|
|
135
137
|
last = j;
|
|
136
138
|
return cmp;
|
|
@@ -151,10 +153,10 @@ transclude_1.TranscludeToken.prototype.fixDuplication =
|
|
|
151
153
|
index_1.default.error(`${this.type === 'template'
|
|
152
154
|
? this.name
|
|
153
155
|
: this.normalizeTitle(this.childNodes[1].text(), 828)
|
|
154
|
-
.title}
|
|
156
|
+
.title} still has ${remaining} duplicated ${key} parameters:\n${[...this.getArgs(key)].map(arg => {
|
|
155
157
|
const { top, left } = arg.getBoundingClientRect();
|
|
156
|
-
return
|
|
157
|
-
}).join('
|
|
158
|
+
return `Line ${String(top)} Column ${String(left)}`;
|
|
159
|
+
}).join('\n')}`);
|
|
158
160
|
duplicatedKeys.push(key);
|
|
159
161
|
continue;
|
|
160
162
|
}
|
|
@@ -175,7 +177,7 @@ transclude_1.TranscludeToken.prototype.escapeTables =
|
|
|
175
177
|
}
|
|
176
178
|
const { firstChild, length } = index_1.default.parse(`{{${parsed.toString()}}}`, include, undefined, config);
|
|
177
179
|
if (length !== 1 || !(firstChild instanceof transclude_1.TranscludeToken)) {
|
|
178
|
-
throw new Error('
|
|
180
|
+
throw new Error('Failed to escape tables!');
|
|
179
181
|
}
|
|
180
182
|
this.safeReplaceWith(firstChild);
|
|
181
183
|
return firstChild;
|
package/dist/base.d.ts
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -13,11 +13,8 @@ declare interface Parser extends ParserBase {
|
|
|
13
13
|
* @param title 标题(含或不含命名空间前缀)
|
|
14
14
|
* @param defaultNs 命名空间
|
|
15
15
|
* @param include 是否嵌入
|
|
16
|
-
* @param halfParsed 是否是半解析状态
|
|
17
|
-
* @param decode 是否需要解码
|
|
18
|
-
* @param selfLink 是否允许selfLink
|
|
19
16
|
*/
|
|
20
|
-
normalizeTitle(title: string, defaultNs?: number, include?: boolean, config?: Config
|
|
17
|
+
normalizeTitle(title: string, defaultNs?: number, include?: boolean, config?: Config): Title;
|
|
21
18
|
parse(wikitext: string, include?: boolean, maxStage?: number, config?: Config): Token;
|
|
22
19
|
/**
|
|
23
20
|
* 是否是跨维基链接
|
|
@@ -28,6 +25,7 @@ declare interface Parser extends ParserBase {
|
|
|
28
25
|
declare const Parser: Parser;
|
|
29
26
|
// @ts-expect-error mixed export styles
|
|
30
27
|
export = Parser;
|
|
28
|
+
export default Parser;
|
|
31
29
|
export type { Config, LintError };
|
|
32
30
|
export type * from './internal';
|
|
33
31
|
declare global { type Acceptable = unknown; }
|
package/dist/index.js
CHANGED
|
@@ -144,7 +144,7 @@ const Parser = {
|
|
|
144
144
|
},
|
|
145
145
|
/** @implements */
|
|
146
146
|
async clearCache() {
|
|
147
|
-
const promise = (0, diff_1.cmd)('npm', ['run', 'build']), entries = [
|
|
147
|
+
const promise = (0, diff_1.cmd)('npm', ['run', 'build:core']), entries = [
|
|
148
148
|
...Object.entries(constants_1.classes),
|
|
149
149
|
...Object.entries(constants_1.mixins),
|
|
150
150
|
...Object.entries(constants_1.parsers),
|
|
@@ -166,8 +166,10 @@ const Parser = {
|
|
|
166
166
|
},
|
|
167
167
|
/** @implements */
|
|
168
168
|
isInterwiki(title, { interwiki } = Parser.getConfig()) {
|
|
169
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
170
|
+
/^(zh|en)\s*:/diu;
|
|
169
171
|
return interwiki.length > 0
|
|
170
|
-
? new RegExp(`^(${interwiki.join('|')})
|
|
172
|
+
? new RegExp(String.raw `^(${interwiki.join('|')})\s*:`, 'diu')
|
|
171
173
|
.exec(title.replace(/_/gu, ' ').replace(/^\s*:?\s*/u, ''))
|
|
172
174
|
: null;
|
|
173
175
|
},
|
|
@@ -215,4 +217,5 @@ for (const key in Parser) {
|
|
|
215
217
|
}
|
|
216
218
|
}
|
|
217
219
|
Object.defineProperties(Parser, def);
|
|
220
|
+
exports.default = Parser;
|
|
218
221
|
module.exports = Parser;
|
package/dist/lib/element.d.ts
CHANGED
|
@@ -27,11 +27,6 @@ export declare abstract class AstElement extends AstNode {
|
|
|
27
27
|
/** 内部宽度 */
|
|
28
28
|
get clientWidth(): number | undefined;
|
|
29
29
|
constructor();
|
|
30
|
-
/**
|
|
31
|
-
* 可见部分
|
|
32
|
-
* @param separator 子节点间的连接符
|
|
33
|
-
*/
|
|
34
|
-
text(separator?: string): string;
|
|
35
30
|
/** 合并相邻的文本子节点 */
|
|
36
31
|
normalize(): void;
|
|
37
32
|
/**
|
package/dist/lib/element.js
CHANGED
|
@@ -21,7 +21,7 @@ const toCase = (val, i) => i ? val.toLowerCase() : val;
|
|
|
21
21
|
* @param str 表达式
|
|
22
22
|
* @param i 待检查的下标
|
|
23
23
|
*/
|
|
24
|
-
const nth = (str, i) => new ranges_1.Ranges(str
|
|
24
|
+
const nth = (str, i) => new ranges_1.Ranges(str).applyTo(i + 1).includes(i);
|
|
25
25
|
/**
|
|
26
26
|
* 检测:lang()伪选择器
|
|
27
27
|
* @param node 节点
|
|
@@ -30,7 +30,7 @@ const nth = (str, i) => new ranges_1.Ranges(str.split(',')).applyTo(i + 1).inclu
|
|
|
30
30
|
*/
|
|
31
31
|
const matchesLang = ({ attributes }, regex) => {
|
|
32
32
|
const lang = attributes?.['lang'];
|
|
33
|
-
return typeof lang === 'string' && regex.test(lang);
|
|
33
|
+
return lang === undefined ? undefined : typeof lang === 'string' && regex.test(lang);
|
|
34
34
|
};
|
|
35
35
|
const primitives = new Set(['string', 'number', 'boolean', 'undefined']);
|
|
36
36
|
/* NOT FOR BROWSER END */
|
|
@@ -88,10 +88,7 @@ class AstElement extends node_1.AstNode {
|
|
|
88
88
|
this.seal('name');
|
|
89
89
|
}
|
|
90
90
|
/* NOT FOR BROWSER END */
|
|
91
|
-
/**
|
|
92
|
-
* 可见部分
|
|
93
|
-
* @param separator 子节点间的连接符
|
|
94
|
-
*/
|
|
91
|
+
/** @private */
|
|
95
92
|
text(separator) {
|
|
96
93
|
return (0, string_1.text)(this.childNodes, separator);
|
|
97
94
|
}
|
|
@@ -145,10 +142,10 @@ class AstElement extends node_1.AstNode {
|
|
|
145
142
|
insertAt(node, i = this.length) {
|
|
146
143
|
/* NOT FOR BROWSER */
|
|
147
144
|
if (node.contains(this)) {
|
|
148
|
-
throw new RangeError('
|
|
145
|
+
throw new RangeError('Cannot insert an ancestor node!');
|
|
149
146
|
}
|
|
150
|
-
if (this.childNodes.includes(node)) {
|
|
151
|
-
throw new RangeError('
|
|
147
|
+
else if (this.childNodes.includes(node)) {
|
|
148
|
+
throw new RangeError('Cannot insert its own child node!');
|
|
152
149
|
}
|
|
153
150
|
this.verifyChild(i, 1);
|
|
154
151
|
node.parentNode?.removeChild(node);
|
|
@@ -275,7 +272,7 @@ class AstElement extends node_1.AstNode {
|
|
|
275
272
|
return data;
|
|
276
273
|
}
|
|
277
274
|
/* NOT FOR BROWSER */
|
|
278
|
-
throw new RangeError(
|
|
275
|
+
throw new RangeError(`The child node at position ${i} is ${oldText.constructor.name}!`);
|
|
279
276
|
}
|
|
280
277
|
/** @private */
|
|
281
278
|
toString(separator = '') {
|
|
@@ -310,17 +307,14 @@ class AstElement extends node_1.AstNode {
|
|
|
310
307
|
};
|
|
311
308
|
for (let i = 0, cur = start + this.getAttribute('padding'); i < this.length; i++) {
|
|
312
309
|
const child = this.childNodes[i], { length } = child.toString();
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
else {
|
|
317
|
-
json.childNodes.push(child.json(undefined, cur));
|
|
318
|
-
}
|
|
310
|
+
json.childNodes.push(child.type === 'text'
|
|
311
|
+
? { data: child.data, range: [cur, cur + length] }
|
|
312
|
+
: child.json(undefined, cur));
|
|
319
313
|
cur += length + this.getGaps(i);
|
|
320
314
|
}
|
|
321
315
|
/* NOT FOR BROWSER */
|
|
322
316
|
if (typeof file === 'string') {
|
|
323
|
-
fs.writeFileSync(path.join(__dirname
|
|
317
|
+
fs.writeFileSync(path.join(__dirname, '..', '..', 'printed', file + (file.endsWith('.json') ? '' : '.json')), JSON.stringify(json, null, 2));
|
|
324
318
|
}
|
|
325
319
|
/* NOT FOR BROWSER END */
|
|
326
320
|
return json;
|
|
@@ -332,8 +326,24 @@ class AstElement extends node_1.AstNode {
|
|
|
332
326
|
if (!parentNode) {
|
|
333
327
|
return undefined;
|
|
334
328
|
}
|
|
335
|
-
const { childNodes, fixed } = parentNode
|
|
336
|
-
return fixed
|
|
329
|
+
const { childNodes, fixed } = parentNode;
|
|
330
|
+
return fixed
|
|
331
|
+
|| parentNode.getAttribute('protectedChildren').applyTo(childNodes)
|
|
332
|
+
.includes(childNodes.indexOf(this));
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* 获取属性
|
|
336
|
+
* @param key 属性键
|
|
337
|
+
*/
|
|
338
|
+
#getAttr(key) {
|
|
339
|
+
if (typeof this.getAttr === 'function') {
|
|
340
|
+
const attr = this.getAttr(key);
|
|
341
|
+
if (attr !== undefined) {
|
|
342
|
+
return attr;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
const val = this.getAttribute(key);
|
|
346
|
+
return val instanceof RegExp ? val.source : val;
|
|
337
347
|
}
|
|
338
348
|
/**
|
|
339
349
|
* 检查是否符合属性选择器
|
|
@@ -348,27 +358,17 @@ class AstElement extends node_1.AstNode {
|
|
|
348
358
|
if (!(key in this) && (!isAttr || !this.hasAttr(key))) {
|
|
349
359
|
return equal === '!=';
|
|
350
360
|
}
|
|
351
|
-
const v = toCase(val, i);
|
|
352
|
-
let thisVal = this.getAttribute(key);
|
|
353
|
-
if (isAttr) {
|
|
354
|
-
const attr = this.getAttr(key);
|
|
355
|
-
if (attr !== undefined) {
|
|
356
|
-
thisVal = attr === true ? '' : attr;
|
|
357
|
-
}
|
|
358
|
-
}
|
|
361
|
+
const v = toCase(val, i), thisVal = this.#getAttr(key);
|
|
359
362
|
if (!equal) {
|
|
360
363
|
return thisVal !== undefined && thisVal !== false;
|
|
361
364
|
}
|
|
362
|
-
else if (thisVal instanceof RegExp) {
|
|
363
|
-
thisVal = thisVal.source;
|
|
364
|
-
}
|
|
365
365
|
if (equal === '~=') {
|
|
366
366
|
const thisVals = typeof thisVal === 'string' ? thisVal.split(/\s/u) : thisVal;
|
|
367
367
|
return Boolean(thisVals?.[Symbol.iterator])
|
|
368
368
|
&& [...thisVals].some(w => typeof w === 'string' && toCase(w, i) === v);
|
|
369
369
|
}
|
|
370
370
|
else if (!primitives.has(typeof thisVal) && !(thisVal instanceof title_1.Title)) {
|
|
371
|
-
throw new RangeError(
|
|
371
|
+
throw new RangeError(`The complex attribute ${key} cannot be used in a selector!`);
|
|
372
372
|
}
|
|
373
373
|
const stringVal = toCase(String(thisVal), i);
|
|
374
374
|
switch (equal) {
|
|
@@ -430,7 +430,7 @@ class AstElement extends node_1.AstNode {
|
|
|
430
430
|
|| type === 'free-ext-link'
|
|
431
431
|
|| type === 'magic-link'
|
|
432
432
|
|| type === 'ext-link'
|
|
433
|
-
|| (type === 'file' || type === 'gallery-image' && link
|
|
433
|
+
|| (type === 'file' || type === 'gallery-image') && link;
|
|
434
434
|
case ':local-link':
|
|
435
435
|
return (type === 'link' || type === 'file' || type === 'gallery-image')
|
|
436
436
|
&& link instanceof title_1.Title
|
|
@@ -469,24 +469,31 @@ class AstElement extends node_1.AstNode {
|
|
|
469
469
|
case 'has':
|
|
470
470
|
return Boolean(this.querySelector(s));
|
|
471
471
|
case 'lang': {
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
472
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
473
|
+
/^zh(?:-|$)/iu;
|
|
474
|
+
const regex = new RegExp(`^${s}(?:-|$)`, 'iu');
|
|
475
|
+
for (let node = this; node; node = node.parentNode) {
|
|
476
|
+
const result = matchesLang(node, regex);
|
|
477
|
+
if (result !== undefined) {
|
|
478
|
+
return result;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
return false;
|
|
475
482
|
}
|
|
476
483
|
case 'regex': {
|
|
477
484
|
const mt = /^([^,]+),\s*\/(.+)\/([a-z]*)$/u.exec(s);
|
|
478
485
|
if (!mt) {
|
|
479
|
-
throw new SyntaxError(
|
|
486
|
+
throw new SyntaxError(`Wrong usage of the regex pseudo-selector. Use ":regex('attr, /re/i')" format.`);
|
|
480
487
|
}
|
|
481
488
|
try {
|
|
482
|
-
return new RegExp(mt[2], mt[3]).test(String(this
|
|
489
|
+
return new RegExp(mt[2], mt[3]).test(String(this.#getAttr(mt[1].trim())));
|
|
483
490
|
}
|
|
484
491
|
catch {
|
|
485
|
-
throw new SyntaxError(
|
|
492
|
+
throw new SyntaxError(`Invalid regular expression: /${mt[2]}/${mt[3]}`);
|
|
486
493
|
}
|
|
487
494
|
}
|
|
488
495
|
default:
|
|
489
|
-
throw new SyntaxError(
|
|
496
|
+
throw new SyntaxError(`Undefined pseudo-selector: ${pseudo}`);
|
|
490
497
|
}
|
|
491
498
|
});
|
|
492
499
|
}
|
package/dist/lib/node.d.ts
CHANGED
|
@@ -19,7 +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
|
-
|
|
22
|
+
text(): string;
|
|
23
23
|
lint(): LintError[];
|
|
24
24
|
print(): string;
|
|
25
25
|
/** 首位子节点 */
|
package/dist/lib/node.js
CHANGED
|
@@ -130,13 +130,13 @@ class AstNode {
|
|
|
130
130
|
}
|
|
131
131
|
/** 字体样式 */
|
|
132
132
|
get font() {
|
|
133
|
-
const { parentNode } = this, acceptable = parentNode?.
|
|
133
|
+
const { parentNode } = this, acceptable = parentNode?.getAcceptable();
|
|
134
134
|
if (!parentNode || acceptable && !('QuoteToken' in acceptable)) {
|
|
135
135
|
return { bold: false, italic: false };
|
|
136
136
|
}
|
|
137
|
-
const { childNodes } = parentNode,
|
|
138
|
-
let bold = false, italic = false;
|
|
139
|
-
for (let i =
|
|
137
|
+
const { childNodes, type } = parentNode, isQuote = (0, debug_1.isToken)('quote');
|
|
138
|
+
let { bold = false, italic = false } = type === 'ext-link-text' && parentNode.parentNode || {};
|
|
139
|
+
for (let i = childNodes.indexOf(this) - 1; i >= 0; i--) {
|
|
140
140
|
const child = childNodes[i];
|
|
141
141
|
if (isQuote(child)) {
|
|
142
142
|
bold = child.bold !== bold;
|
|
@@ -168,7 +168,7 @@ class AstNode {
|
|
|
168
168
|
/* NOT FOR BROWSER */
|
|
169
169
|
}
|
|
170
170
|
else if (key === 'optional') {
|
|
171
|
-
return
|
|
171
|
+
return this.#optional;
|
|
172
172
|
/* NOT FOR BROWSER END */
|
|
173
173
|
}
|
|
174
174
|
return this[key];
|
|
@@ -264,7 +264,7 @@ class AstNode {
|
|
|
264
264
|
}
|
|
265
265
|
/** @private */
|
|
266
266
|
constructorError(msg) {
|
|
267
|
-
throw new Error(`${this.constructor.name} ${msg}
|
|
267
|
+
throw new Error(`${this.constructor.name} ${msg}!`);
|
|
268
268
|
}
|
|
269
269
|
/**
|
|
270
270
|
* 是否是全同节点
|
|
@@ -292,7 +292,7 @@ class AstNode {
|
|
|
292
292
|
#insertAdjacent(nodes, offset) {
|
|
293
293
|
const { parentNode } = this;
|
|
294
294
|
if (!parentNode) {
|
|
295
|
-
throw new Error('
|
|
295
|
+
throw new Error('There is no parent node!');
|
|
296
296
|
}
|
|
297
297
|
const i = parentNode.childNodes.indexOf(this) + offset;
|
|
298
298
|
for (let j = 0; j < nodes.length; j++) {
|
|
@@ -336,7 +336,7 @@ class AstNode {
|
|
|
336
336
|
verifyChild(i, addition = 0) {
|
|
337
337
|
const { childNodes: { length } } = this;
|
|
338
338
|
if (i < -length || i >= length + addition) {
|
|
339
|
-
throw new RangeError(`The ${i}
|
|
339
|
+
throw new RangeError(`The child node at position ${i} does not exist!`);
|
|
340
340
|
}
|
|
341
341
|
}
|
|
342
342
|
/**
|
|
@@ -436,7 +436,7 @@ class AstNode {
|
|
|
436
436
|
return 1;
|
|
437
437
|
}
|
|
438
438
|
else if (this.getRootNode() !== other.getRootNode()) {
|
|
439
|
-
throw new RangeError('
|
|
439
|
+
throw new RangeError('Nodes to be compared are not in the same document!');
|
|
440
440
|
}
|
|
441
441
|
const aAncestors = [...this.getAncestors().reverse(), this], bAncestors = [...other.getAncestors().reverse(), other], depth = aAncestors.findIndex((ancestor, i) => bAncestors[i] !== ancestor), { childNodes } = aAncestors[depth - 1];
|
|
442
442
|
return childNodes.indexOf(aAncestors[depth]) - childNodes.indexOf(bAncestors[depth]);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { AstNodes, Position } from './node';
|
|
2
|
+
/** 节点位置 */
|
|
3
|
+
export declare class BoundingRect {
|
|
4
|
+
#private;
|
|
5
|
+
readonly token: AstNodes;
|
|
6
|
+
readonly start: number;
|
|
7
|
+
/** 起点行 */
|
|
8
|
+
get top(): number;
|
|
9
|
+
/** 起点列 */
|
|
10
|
+
get left(): number;
|
|
11
|
+
/**
|
|
12
|
+
* @param token 节点
|
|
13
|
+
* @param start 起点
|
|
14
|
+
*/
|
|
15
|
+
constructor(token: AstNodes, start: number);
|
|
16
|
+
/** 计算位置 */
|
|
17
|
+
getPosition(): Position;
|
|
18
|
+
}
|
package/dist/lib/rect.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BoundingRect = void 0;
|
|
4
|
+
const constants_1 = require("../util/constants");
|
|
5
|
+
/** 节点位置 */
|
|
6
|
+
class BoundingRect {
|
|
7
|
+
#pos;
|
|
8
|
+
token;
|
|
9
|
+
start;
|
|
10
|
+
/** 起点行 */
|
|
11
|
+
get top() {
|
|
12
|
+
this.#pos ??= this.getPosition();
|
|
13
|
+
return this.#pos.top;
|
|
14
|
+
}
|
|
15
|
+
/** 起点列 */
|
|
16
|
+
get left() {
|
|
17
|
+
this.#pos ??= this.getPosition();
|
|
18
|
+
return this.#pos.left;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* @param token 节点
|
|
22
|
+
* @param start 起点
|
|
23
|
+
*/
|
|
24
|
+
constructor(token, start) {
|
|
25
|
+
this.token = token;
|
|
26
|
+
this.start = start;
|
|
27
|
+
}
|
|
28
|
+
/** 计算位置 */
|
|
29
|
+
getPosition() {
|
|
30
|
+
return this.token.getRootNode().posFromIndex(this.start);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.BoundingRect = BoundingRect;
|
|
34
|
+
constants_1.classes['BoundingRect'] = __filename;
|
package/dist/lib/text.js
CHANGED
|
@@ -6,16 +6,11 @@ const debug_1 = require("../util/debug");
|
|
|
6
6
|
const string_1 = require("../util/string");
|
|
7
7
|
const index_1 = require("../index");
|
|
8
8
|
const node_1 = require("./node");
|
|
9
|
-
|
|
9
|
+
/* eslint-disable @typescript-eslint/no-unused-expressions */
|
|
10
10
|
/<\s*(?:\/\s*)?([a-z]\w*)|\{+|\}+|\[{2,}|\[(?![^[]*?\])|((?:^|\])[^[]*?)\]+|https?[:/]\/+/giu;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
+ '|'
|
|
15
|
-
+ '\\[{2,}|\\[(?![^[]*?\\])' // `[`
|
|
16
|
-
+ '|'
|
|
17
|
-
+ '((?:^|\\])[^[]*?)\\]+', // `]`
|
|
18
|
-
errorSyntax = new RegExp(`${source}|https?[:/]\\/+`, 'giu'), errorSyntaxUrl = new RegExp(source, 'giu'), extImage = new RegExp(`^https?:\\/\\/${string_1.extUrlCharFirst}${string_1.extUrlChar}\\.(?:gif|png|jpg|jpeg)$`, 'iu'), regexes = {
|
|
11
|
+
/^https?:\/\/(?:\[[\da-f:.]+\]|[^[\]<>"\t\n\p{Zs}])[^[\]<>"\t\n\p{Zs}]*\.(?:gif|png|jpg|jpeg)$/iu;
|
|
12
|
+
/* eslint-enable @typescript-eslint/no-unused-expressions */
|
|
13
|
+
const source = String.raw `<\s*(?:/\s*)?([a-z]\w*)|\{+|\}+|\[{2,}|\[(?![^[]*?\])|((?:^|\])[^[]*?)\]+`, errorSyntax = new RegExp(String.raw `${source}|https?[:/]/+`, 'giu'), errorSyntaxUrl = new RegExp(source, 'giu'), extImage = new RegExp(String.raw `^https?://${string_1.extUrlCharFirst}${string_1.extUrlChar}\.(?:gif|png|jpg|jpeg)$`, 'iu'), regexes = {
|
|
19
14
|
'[': /[[\]]/u,
|
|
20
15
|
'{': /[{}]/u,
|
|
21
16
|
']': /[[\]](?=[^[\]]*$)/u,
|
|
@@ -114,7 +109,7 @@ class AstText extends node_1.AstNode {
|
|
|
114
109
|
lint(start = this.getAbsoluteIndex(), errorRegex) {
|
|
115
110
|
const { data, parentNode, nextSibling, previousSibling } = this;
|
|
116
111
|
if (!parentNode) {
|
|
117
|
-
throw new Error('
|
|
112
|
+
throw new Error('An isolated text node cannot be linted!');
|
|
118
113
|
}
|
|
119
114
|
const { type, name, parentNode: grandparent } = parentNode;
|
|
120
115
|
let isHtmlAttrVal = false;
|
|
@@ -312,11 +307,11 @@ class AstText extends node_1.AstNode {
|
|
|
312
307
|
*/
|
|
313
308
|
splitText(offset) {
|
|
314
309
|
if (offset > this.length || offset < -this.length) {
|
|
315
|
-
throw new RangeError(
|
|
310
|
+
throw new RangeError(`Wrong offset to split: ${offset}`);
|
|
316
311
|
}
|
|
317
312
|
const { parentNode, data } = this;
|
|
318
313
|
if (!parentNode) {
|
|
319
|
-
throw new Error('
|
|
314
|
+
throw new Error('The text node to be split has no parent node!');
|
|
320
315
|
}
|
|
321
316
|
const newText = new AstText(data.slice(offset));
|
|
322
317
|
(0, debug_1.setChildNodes)(parentNode, parentNode.childNodes.indexOf(this) + 1, 0, [newText]);
|
|
@@ -329,7 +324,7 @@ class AstText extends node_1.AstNode {
|
|
|
329
324
|
return super.getRelativeIndex();
|
|
330
325
|
}
|
|
331
326
|
else if (j < 0 || j > this.length) {
|
|
332
|
-
throw new RangeError('
|
|
327
|
+
throw new RangeError('Exceeding the text length range!');
|
|
333
328
|
}
|
|
334
329
|
return j;
|
|
335
330
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.attributesParent = void 0;
|
|
4
|
+
const debug_1 = require("../util/debug");
|
|
4
5
|
const constants_1 = require("../util/constants");
|
|
5
6
|
/**
|
|
6
7
|
* 子节点含有AttributesToken的类
|
|
@@ -74,7 +75,7 @@ const attributesParent = (i = 0) => (constructor, _) => {
|
|
|
74
75
|
this.#attributesChild.toggleAttr(key, force);
|
|
75
76
|
}
|
|
76
77
|
}
|
|
77
|
-
|
|
78
|
+
(0, debug_1.mixin)(AttributesParent, constructor);
|
|
78
79
|
return AttributesParent;
|
|
79
80
|
};
|
|
80
81
|
exports.attributesParent = attributesParent;
|