wikiparser-node 1.5.7 → 1.6.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/table.d.ts +1 -6
- package/dist/addon/table.js +2 -81
- package/dist/mixin/attributesParent.d.ts +4 -4
- package/dist/mixin/attributesParent.js +7 -4
- package/dist/src/index.js +40 -1
- package/dist/src/link/base.js +1 -2
- package/dist/src/table/base.d.ts +1 -4
- package/dist/src/table/base.js +50 -101
- package/dist/src/table/index.d.ts +39 -30
- package/dist/src/table/index.js +135 -55
- package/dist/src/table/td.d.ts +9 -9
- package/dist/src/table/td.js +18 -17
- package/dist/src/table/trBase.d.ts +10 -10
- package/dist/src/table/trBase.js +32 -28
- package/dist/util/debug.js +1 -1
- package/package.json +1 -1
package/dist/addon/table.d.ts
CHANGED
package/dist/addon/table.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/* eslint @stylistic/operator-linebreak: [2, "before", {overrides: {"=": "after"}}] */
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.Layout = void 0;
|
|
5
4
|
const assert = require("assert/strict");
|
|
6
5
|
const debug_1 = require("../util/debug");
|
|
7
6
|
const constants_1 = require("../util/constants");
|
|
@@ -24,11 +23,6 @@ const cmpCoords = (coords1, coords2) => {
|
|
|
24
23
|
const diff = coords1.row - coords2.row;
|
|
25
24
|
return diff === 0 ? coords1.column - coords2.column : diff;
|
|
26
25
|
};
|
|
27
|
-
/**
|
|
28
|
-
* 是否是行尾
|
|
29
|
-
* @param {Token} cell 表格单元格
|
|
30
|
-
*/
|
|
31
|
-
const isRowEnd = ({ type }) => type === 'tr' || type === 'table-syntax';
|
|
32
26
|
/**
|
|
33
27
|
* 是否是合并单元格的第一列
|
|
34
28
|
* @param rowLayout 行布局
|
|
@@ -82,79 +76,6 @@ const fill = (y, rowToken, layout, maxCol, token) => {
|
|
|
82
76
|
}
|
|
83
77
|
});
|
|
84
78
|
};
|
|
85
|
-
/** @extends {Array<TableCoords[]>} */
|
|
86
|
-
class Layout extends Array {
|
|
87
|
-
/** 打印表格布局 */
|
|
88
|
-
print() {
|
|
89
|
-
const hBorders = (0, debug_1.emptyArray)(this.length + 1, i => {
|
|
90
|
-
const prev = this[i - 1] ?? [], next = this[i] ?? [];
|
|
91
|
-
return (0, debug_1.emptyArray)(Math.max(prev.length, next.length), j => prev[j] !== next[j]);
|
|
92
|
-
}), vBorders = this.map(cur => (0, debug_1.emptyArray)(cur.length + 1, j => cur[j - 1] !== cur[j]));
|
|
93
|
-
let out = '';
|
|
94
|
-
for (let i = 0; i <= this.length; i++) {
|
|
95
|
-
const hBorder = hBorders[i].map(Number), vBorderTop = (vBorders[i - 1] ?? []).map(Number), vBorderBottom = (vBorders[i] ?? []).map(Number),
|
|
96
|
-
// eslint-disable-next-line no-sparse-arrays
|
|
97
|
-
border = [' ', , , '┌', , '┐', '─', '┬', , '│', '└', '├', '┘', '┤', '┴', '┼'];
|
|
98
|
-
for (let j = 0; j <= hBorder.length; j++) {
|
|
99
|
-
const bit = (vBorderTop[j] << 3) + (vBorderBottom[j] << 0)
|
|
100
|
-
+ (hBorder[j - 1] << 2) + (hBorder[j] << 1);
|
|
101
|
-
out += `${border[bit]}${hBorder[j] ? '─' : ' '}`;
|
|
102
|
-
}
|
|
103
|
-
out += '\n';
|
|
104
|
-
}
|
|
105
|
-
console.log(out.slice(0, -1));
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
exports.Layout = Layout;
|
|
109
|
-
table_1.TableToken.prototype.getNthCell =
|
|
110
|
-
/** @implements */
|
|
111
|
-
function (coords) {
|
|
112
|
-
const rawCoords = coords.row === undefined ? this.toRawCoords(coords) : coords;
|
|
113
|
-
return rawCoords && this.getNthRow(rawCoords.row, false, false)?.getNthCol(rawCoords.column);
|
|
114
|
-
};
|
|
115
|
-
table_1.TableToken.prototype.getLayout =
|
|
116
|
-
/** @implements */
|
|
117
|
-
function (stop) {
|
|
118
|
-
const rows = this.getAllRows(), { length } = rows, layout = new Layout(...(0, debug_1.emptyArray)(length, () => []));
|
|
119
|
-
for (let i = 0; i < length; i++) {
|
|
120
|
-
if (i > (stop?.row ?? stop?.y ?? NaN)) {
|
|
121
|
-
break;
|
|
122
|
-
}
|
|
123
|
-
const rowLayout = layout[i];
|
|
124
|
-
let j = 0, k = 0, last;
|
|
125
|
-
for (const cell of rows[i].childNodes.slice(2)) {
|
|
126
|
-
if (cell.type === 'td') {
|
|
127
|
-
if (cell.isIndependent()) {
|
|
128
|
-
last = cell.subtype !== 'caption';
|
|
129
|
-
}
|
|
130
|
-
if (last) {
|
|
131
|
-
const coords = { row: i, column: j }, { rowspan, colspan } = cell;
|
|
132
|
-
j++;
|
|
133
|
-
while (rowLayout[k]) {
|
|
134
|
-
k++;
|
|
135
|
-
}
|
|
136
|
-
if (i === stop?.row && j > (stop.column ?? NaN)) {
|
|
137
|
-
layout[i][k] = coords;
|
|
138
|
-
return layout;
|
|
139
|
-
}
|
|
140
|
-
for (let y = i; y < Math.min(i + rowspan, length); y++) {
|
|
141
|
-
for (let x = k; x < k + colspan; x++) {
|
|
142
|
-
layout[y][x] = coords;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
k += colspan;
|
|
146
|
-
if (i === stop?.y && k > (stop.x ?? NaN)) {
|
|
147
|
-
return layout;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
else if (isRowEnd(cell)) {
|
|
152
|
-
break;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
return layout;
|
|
157
|
-
};
|
|
158
79
|
table_1.TableToken.prototype.printLayout =
|
|
159
80
|
/** @implements */
|
|
160
81
|
function () {
|
|
@@ -508,7 +429,7 @@ table_1.TableToken.prototype.moveTableRowAfter =
|
|
|
508
429
|
}
|
|
509
430
|
}
|
|
510
431
|
if (afterToken === this) {
|
|
511
|
-
const index = this.childNodes.slice(2).findIndex(isRowEnd);
|
|
432
|
+
const index = this.childNodes.slice(2).findIndex(table_1.isRowEnd);
|
|
512
433
|
this.insertAt(rowToken, index + 2);
|
|
513
434
|
}
|
|
514
435
|
else {
|
|
@@ -546,7 +467,7 @@ table_1.TableToken.prototype.moveCol =
|
|
|
546
467
|
}
|
|
547
468
|
if (start) {
|
|
548
469
|
const col = rowLayout.slice(reference + Number(after)).find(({ row }) => row === i)?.column;
|
|
549
|
-
rowToken.insertBefore(token, col === undefined ? rowToken.childNodes.slice(2).find(isRowEnd) : rowToken.getNthCol(col));
|
|
470
|
+
rowToken.insertBefore(token, col === undefined ? rowToken.childNodes.slice(2).find(table_1.isRowEnd) : rowToken.getNthCol(col));
|
|
550
471
|
}
|
|
551
472
|
}
|
|
552
473
|
}
|
|
@@ -8,15 +8,15 @@ export interface AttributesParentBase {
|
|
|
8
8
|
/** id属性 */
|
|
9
9
|
id: string;
|
|
10
10
|
/**
|
|
11
|
-
* AttributesToken
|
|
11
|
+
* 获取AttributesToken子节点的属性
|
|
12
12
|
* @param key 属性键
|
|
13
13
|
*/
|
|
14
|
-
|
|
14
|
+
getAttr(key: string): string | true | undefined;
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
16
|
+
* AttributesToken子节点是否具有某属性
|
|
17
17
|
* @param key 属性键
|
|
18
18
|
*/
|
|
19
|
-
|
|
19
|
+
hasAttr(key: string): boolean;
|
|
20
20
|
/** 列举AttributesToken子节点的属性键 */
|
|
21
21
|
getAttrNames(): Set<string>;
|
|
22
22
|
/** 获取AttributesToken子节点的全部标签属性 */
|
|
@@ -15,6 +15,7 @@ const attributesParent = (i = 0) => (constructor, _) => {
|
|
|
15
15
|
get #attributesChild() {
|
|
16
16
|
return this.childNodes[i];
|
|
17
17
|
}
|
|
18
|
+
/* NOT FOR BROWSER */
|
|
18
19
|
/** @implements */
|
|
19
20
|
get attributes() {
|
|
20
21
|
return this.#attributesChild.attributes;
|
|
@@ -43,14 +44,16 @@ const attributesParent = (i = 0) => (constructor, _) => {
|
|
|
43
44
|
set id(id) {
|
|
44
45
|
this.#attributesChild.id = id;
|
|
45
46
|
}
|
|
46
|
-
|
|
47
|
-
hasAttr(key) {
|
|
48
|
-
return this.#attributesChild.hasAttr(key);
|
|
49
|
-
}
|
|
47
|
+
/* NOT FOR BROWSER END */
|
|
50
48
|
/** @implements */
|
|
51
49
|
getAttr(key) {
|
|
52
50
|
return this.#attributesChild.getAttr(key);
|
|
53
51
|
}
|
|
52
|
+
/* NOT FOR BROWSER */
|
|
53
|
+
/** @implements */
|
|
54
|
+
hasAttr(key) {
|
|
55
|
+
return this.#attributesChild.hasAttr(key);
|
|
56
|
+
}
|
|
54
57
|
/** @implements */
|
|
55
58
|
getAttrNames() {
|
|
56
59
|
return this.#attributesChild.getAttrNames();
|
package/dist/src/index.js
CHANGED
|
@@ -397,7 +397,6 @@ class Token extends element_1.AstElement {
|
|
|
397
397
|
normalizeTitle(title, defaultNs = 0, halfParsed = false, decode = false, selfLink = false) {
|
|
398
398
|
return index_1.default.normalizeTitle(title, defaultNs, this.#include, this.#config, halfParsed, decode, selfLink);
|
|
399
399
|
}
|
|
400
|
-
/* NOT FOR BROWSER */
|
|
401
400
|
/** @override */
|
|
402
401
|
lint(start = this.getAbsoluteIndex(), re) {
|
|
403
402
|
const errors = super.lint(start, re);
|
|
@@ -428,8 +427,48 @@ class Token extends element_1.AstElement {
|
|
|
428
427
|
}
|
|
429
428
|
}
|
|
430
429
|
}
|
|
430
|
+
if (this.type === 'root') {
|
|
431
|
+
const regex = /<!--\s*lint-(disable(?:(?:-next)?-line)?|enable)(\s[\sa-z,-]*)?-->/gu, wikitext = String(this), ignores = [];
|
|
432
|
+
let mt = regex.exec(wikitext), last = 0, curLine = 0;
|
|
433
|
+
while (mt) {
|
|
434
|
+
const { 1: type, index } = mt, detail = mt[2]?.trim();
|
|
435
|
+
curLine += wikitext.slice(last, index).split('\n').length - 1;
|
|
436
|
+
last = index;
|
|
437
|
+
ignores.push({
|
|
438
|
+
line: curLine + (type === 'disable-line' ? 0 : 1),
|
|
439
|
+
from: type === 'disable' ? regex.lastIndex : undefined,
|
|
440
|
+
to: type === 'enable' ? regex.lastIndex : undefined,
|
|
441
|
+
rules: detail ? new Set(detail.split(',').map(r => r.trim())) : undefined,
|
|
442
|
+
});
|
|
443
|
+
mt = regex.exec(wikitext);
|
|
444
|
+
}
|
|
445
|
+
return errors.filter(({ rule, startLine, startIndex }) => {
|
|
446
|
+
const nearest = { pos: 0 };
|
|
447
|
+
for (const { line, from, to, rules } of ignores) {
|
|
448
|
+
if (line > startLine + 1) {
|
|
449
|
+
break;
|
|
450
|
+
}
|
|
451
|
+
else if (rules && !rules.has(rule)) {
|
|
452
|
+
continue;
|
|
453
|
+
}
|
|
454
|
+
else if (line === startLine && from === undefined && to === undefined) {
|
|
455
|
+
return false;
|
|
456
|
+
}
|
|
457
|
+
else if (from <= startIndex && from > nearest.pos) {
|
|
458
|
+
nearest.pos = from;
|
|
459
|
+
nearest.type = 'from';
|
|
460
|
+
}
|
|
461
|
+
else if (to <= startIndex && to > nearest.pos) {
|
|
462
|
+
nearest.pos = to;
|
|
463
|
+
nearest.type = 'to';
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
return nearest.type !== 'from';
|
|
467
|
+
});
|
|
468
|
+
}
|
|
431
469
|
return errors;
|
|
432
470
|
}
|
|
471
|
+
/* NOT FOR BROWSER */
|
|
433
472
|
/** @private */
|
|
434
473
|
protectChildren(...args) {
|
|
435
474
|
this.#protectedChildren.push(...new ranges_1.Ranges(args));
|
package/dist/src/link/base.js
CHANGED
|
@@ -12,7 +12,6 @@ const atom_1 = require("../atom");
|
|
|
12
12
|
* @classdesc `{childNodes: [AtomToken, ...Token]}`
|
|
13
13
|
*/
|
|
14
14
|
class LinkBaseToken extends index_2.Token {
|
|
15
|
-
/* NOT FOR BROWSER END */
|
|
16
15
|
#bracket = true;
|
|
17
16
|
#delimiter;
|
|
18
17
|
#title;
|
|
@@ -63,8 +62,8 @@ class LinkBaseToken extends index_2.Token {
|
|
|
63
62
|
if (this.#delimiter.includes('\0')) {
|
|
64
63
|
this.#delimiter = this.buildFromStr(this.#delimiter, constants_1.BuildMethod.String);
|
|
65
64
|
}
|
|
66
|
-
/* NOT FOR BROWSER */
|
|
67
65
|
this.setAttribute('name', this.#title.title);
|
|
66
|
+
/* NOT FOR BROWSER */
|
|
68
67
|
const /** @implements */ linkListener = (e, data) => {
|
|
69
68
|
const { prevTarget } = e;
|
|
70
69
|
if (prevTarget?.type === 'link-target') {
|
package/dist/src/table/base.d.ts
CHANGED
|
@@ -5,10 +5,6 @@ import { AttributesToken } from '../attributes';
|
|
|
5
5
|
import type { AttributesParentBase } from '../../mixin/attributesParent';
|
|
6
6
|
export interface TableBaseToken extends AttributesParentBase {
|
|
7
7
|
}
|
|
8
|
-
/**
|
|
9
|
-
* 表格行,含开头的换行,不含结尾的换行
|
|
10
|
-
* @classdesc `{childNodes: [SyntaxToken, AttributesToken, ...Token]}`
|
|
11
|
-
*/
|
|
12
8
|
export declare abstract class TableBaseToken extends Token {
|
|
13
9
|
type: 'table' | 'tr' | 'td';
|
|
14
10
|
readonly childNodes: readonly [SyntaxToken, AttributesToken, ...Token[]];
|
|
@@ -28,3 +24,4 @@ export declare abstract class TableBaseToken extends Token {
|
|
|
28
24
|
/** 转义表格语法 */
|
|
29
25
|
escape(): void;
|
|
30
26
|
}
|
|
27
|
+
export {};
|
package/dist/src/table/base.js
CHANGED
|
@@ -1,38 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
3
|
-
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
|
4
|
-
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
5
|
-
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
6
|
-
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
7
|
-
var _, done = false;
|
|
8
|
-
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
9
|
-
var context = {};
|
|
10
|
-
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
11
|
-
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
12
|
-
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
|
|
13
|
-
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
|
|
14
|
-
if (kind === "accessor") {
|
|
15
|
-
if (result === void 0) continue;
|
|
16
|
-
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
17
|
-
if (_ = accept(result.get)) descriptor.get = _;
|
|
18
|
-
if (_ = accept(result.set)) descriptor.set = _;
|
|
19
|
-
if (_ = accept(result.init)) initializers.unshift(_);
|
|
20
|
-
}
|
|
21
|
-
else if (_ = accept(result)) {
|
|
22
|
-
if (kind === "field") initializers.unshift(_);
|
|
23
|
-
else descriptor[key] = _;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
27
|
-
done = true;
|
|
28
|
-
};
|
|
29
|
-
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
|
|
30
|
-
var useValue = arguments.length > 2;
|
|
31
|
-
for (var i = 0; i < initializers.length; i++) {
|
|
32
|
-
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
33
|
-
}
|
|
34
|
-
return useValue ? value : void 0;
|
|
35
|
-
};
|
|
36
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
3
|
exports.TableBaseToken = void 0;
|
|
38
4
|
const debug_1 = require("../../util/debug");
|
|
@@ -53,80 +19,63 @@ const escapeTable = (syntax) => {
|
|
|
53
19
|
: String(child)).join(''), { childNodes } = index_1.default.parse(wikitext, syntax.getAttribute('include'), 2, syntax.getAttribute('config'));
|
|
54
20
|
syntax.replaceChildren(...childNodes);
|
|
55
21
|
};
|
|
56
|
-
/* NOT FOR BROWSER END */
|
|
57
22
|
/**
|
|
58
23
|
* 表格行,含开头的换行,不含结尾的换行
|
|
59
24
|
* @classdesc `{childNodes: [SyntaxToken, AttributesToken, ...Token]}`
|
|
60
25
|
*/
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
/* NOT FOR BROWSER END */
|
|
77
|
-
/**
|
|
78
|
-
* @param pattern 表格语法正则
|
|
79
|
-
* @param syntax 表格语法
|
|
80
|
-
* @param attr 表格属性
|
|
81
|
-
*/
|
|
82
|
-
constructor(pattern, syntax, attr, config = index_1.default.getConfig(), accum = [], acceptable = {}) {
|
|
83
|
-
super(undefined, config, accum, acceptable);
|
|
84
|
-
this.append(new syntax_1.SyntaxToken(syntax, pattern, 'table-syntax', config, accum, {
|
|
85
|
-
'Stage-1': ':', '!ExtToken': '', TranscludeToken: ':',
|
|
86
|
-
}),
|
|
87
|
-
// @ts-expect-error abstract class
|
|
88
|
-
new attributes_1.AttributesToken(attr, 'table-attrs', this.type, config, accum));
|
|
89
|
-
/* NOT FOR BROWSER */
|
|
90
|
-
this.protectChildren(0, 1);
|
|
91
|
-
}
|
|
26
|
+
class TableBaseToken extends (0, attributesParent_1.attributesParent)(1)(index_2.Token) {
|
|
27
|
+
/* NOT FOR BROWSER END */
|
|
28
|
+
/**
|
|
29
|
+
* @param pattern 表格语法正则
|
|
30
|
+
* @param syntax 表格语法
|
|
31
|
+
* @param attr 表格属性
|
|
32
|
+
*/
|
|
33
|
+
constructor(pattern, syntax, attr, config = index_1.default.getConfig(), accum = [], acceptable = {}) {
|
|
34
|
+
super(undefined, config, accum, acceptable);
|
|
35
|
+
this.append(new syntax_1.SyntaxToken(syntax, pattern, 'table-syntax', config, accum, {
|
|
36
|
+
'Stage-1': ':', '!ExtToken': '', TranscludeToken: ':',
|
|
37
|
+
}),
|
|
38
|
+
// @ts-expect-error abstract class
|
|
39
|
+
new attributes_1.AttributesToken(attr, 'table-attrs', this.type, config, accum));
|
|
92
40
|
/* NOT FOR BROWSER */
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
106
|
-
return token;
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
/** 转义表格语法 */
|
|
110
|
-
escape() {
|
|
111
|
-
for (const child of this.childNodes) {
|
|
112
|
-
if (child instanceof syntax_1.SyntaxToken) {
|
|
113
|
-
escapeTable(child);
|
|
114
|
-
}
|
|
115
|
-
else if (child instanceof TableBaseToken) {
|
|
116
|
-
child.escape();
|
|
117
|
-
}
|
|
41
|
+
this.protectChildren(0, 1);
|
|
42
|
+
}
|
|
43
|
+
/* NOT FOR BROWSER */
|
|
44
|
+
/** @override */
|
|
45
|
+
cloneNode() {
|
|
46
|
+
const [syntax, attr, ...cloned] = this.cloneChildNodes();
|
|
47
|
+
return debug_1.Shadow.run(() => {
|
|
48
|
+
const { constructor } = this, token = new constructor(undefined, undefined, this.getAttribute('config'));
|
|
49
|
+
token.firstChild.safeReplaceWith(syntax);
|
|
50
|
+
token.childNodes[1].safeReplaceWith(attr);
|
|
51
|
+
if (token.type === 'td') { // TdToken
|
|
52
|
+
token.childNodes[2].safeReplaceWith(cloned[0]);
|
|
118
53
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
54
|
+
else {
|
|
55
|
+
token.append(...cloned);
|
|
56
|
+
}
|
|
57
|
+
return token;
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
/** 转义表格语法 */
|
|
61
|
+
escape() {
|
|
62
|
+
for (const child of this.childNodes) {
|
|
63
|
+
if (child instanceof syntax_1.SyntaxToken) {
|
|
64
|
+
escapeTable(child);
|
|
126
65
|
}
|
|
66
|
+
else if (child instanceof TableBaseToken) {
|
|
67
|
+
child.escape();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/** @private */
|
|
72
|
+
setSyntax(syntax, esc = false) {
|
|
73
|
+
const { firstChild } = this;
|
|
74
|
+
firstChild.replaceChildren(syntax);
|
|
75
|
+
if (esc) {
|
|
76
|
+
escapeTable(firstChild);
|
|
127
77
|
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
})();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
131
80
|
exports.TableBaseToken = TableBaseToken;
|
|
132
81
|
constants_1.classes['TableBaseToken'] = __filename;
|
|
@@ -6,7 +6,6 @@ import type { SyntaxBase } from '../../mixin/syntax';
|
|
|
6
6
|
import type { AttributesToken, TdToken, TrToken, Token } from '../../internal';
|
|
7
7
|
import type { TableCoords } from './trBase';
|
|
8
8
|
import type { TdAttrs, TdSubtypes, TdSpanAttrs } from './td';
|
|
9
|
-
import type { Layout } from '../../addon/table';
|
|
10
9
|
export interface TableRenderedCoords {
|
|
11
10
|
readonly row?: undefined;
|
|
12
11
|
readonly column?: undefined;
|
|
@@ -15,6 +14,16 @@ export interface TableRenderedCoords {
|
|
|
15
14
|
}
|
|
16
15
|
export interface TableToken extends SyntaxBase {
|
|
17
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* 是否是行尾
|
|
19
|
+
* @param {Token} cell 表格单元格
|
|
20
|
+
*/
|
|
21
|
+
export declare const isRowEnd: ({ type }: Token) => boolean;
|
|
22
|
+
/** @extends {Array<TableCoords[]>} */
|
|
23
|
+
export declare class Layout extends Array<TableCoords[]> {
|
|
24
|
+
/** 打印表格布局 */
|
|
25
|
+
print(): void;
|
|
26
|
+
}
|
|
18
27
|
/**
|
|
19
28
|
* 表格
|
|
20
29
|
* @classdesc `{childNodes: [SyntaxToken, AttributesToken, ?Token, ...TdToken, ...TrToken, ?SyntaxToken]}`
|
|
@@ -41,35 +50,6 @@ export declare abstract class TableToken extends TrBaseToken {
|
|
|
41
50
|
* @param halfParsed
|
|
42
51
|
*/
|
|
43
52
|
close(syntax?: string, halfParsed?: boolean): void;
|
|
44
|
-
/** @override */
|
|
45
|
-
json(): AST;
|
|
46
|
-
/**
|
|
47
|
-
* @override
|
|
48
|
-
* @param token 待插入的子节点
|
|
49
|
-
* @param i 插入位置
|
|
50
|
-
* @throws `SyntaxError` 表格的闭合部分非法
|
|
51
|
-
*/
|
|
52
|
-
insertAt<T extends Token>(token: T, i?: number): T;
|
|
53
|
-
/** @override */
|
|
54
|
-
getRowCount(): number;
|
|
55
|
-
/** 获取下一行 */
|
|
56
|
-
getNextRow(): TrToken | undefined;
|
|
57
|
-
/**
|
|
58
|
-
* 获取第n行
|
|
59
|
-
* @param n 行号
|
|
60
|
-
* @param force 是否将表格自身视为第一行
|
|
61
|
-
* @param insert 是否用于判断插入新行的位置
|
|
62
|
-
* @throws `RangeError` 不存在该行
|
|
63
|
-
*/
|
|
64
|
-
getNthRow(n: number, force?: boolean, insert?: false): TrToken | this | undefined;
|
|
65
|
-
getNthRow(n: number, force: boolean, insert: true): TrToken | this | SyntaxToken | undefined;
|
|
66
|
-
/** 获取所有行 */
|
|
67
|
-
getAllRows(): (TrToken | this)[];
|
|
68
|
-
/**
|
|
69
|
-
* 获取指定坐标的单元格
|
|
70
|
-
* @param coords 表格坐标
|
|
71
|
-
*/
|
|
72
|
-
getNthCell(coords: TableCoords | TableRenderedCoords): TdToken | undefined;
|
|
73
53
|
/**
|
|
74
54
|
* 获取表格布局
|
|
75
55
|
* @param stop 中止条件
|
|
@@ -84,6 +64,35 @@ export declare abstract class TableToken extends TrBaseToken {
|
|
|
84
64
|
x?: number;
|
|
85
65
|
y?: number;
|
|
86
66
|
}): Layout;
|
|
67
|
+
/** 获取所有行 */
|
|
68
|
+
getAllRows(): (TrToken | this)[];
|
|
69
|
+
/**
|
|
70
|
+
* 获取指定坐标的单元格
|
|
71
|
+
* @param coords 表格坐标
|
|
72
|
+
*/
|
|
73
|
+
getNthCell(coords: TableCoords | TableRenderedCoords): TdToken | undefined;
|
|
74
|
+
/**
|
|
75
|
+
* 获取第n行
|
|
76
|
+
* @param n 行号
|
|
77
|
+
* @param force 是否将表格自身视为第一行
|
|
78
|
+
* @param insert 是否用于判断插入新行的位置
|
|
79
|
+
* @throws `RangeError` 不存在该行
|
|
80
|
+
*/
|
|
81
|
+
getNthRow(n: number, force?: boolean, insert?: false): TrToken | this | undefined;
|
|
82
|
+
getNthRow(n: number, force: boolean, insert: true): TrToken | this | SyntaxToken | undefined;
|
|
83
|
+
/** @override */
|
|
84
|
+
json(): AST;
|
|
85
|
+
/**
|
|
86
|
+
* @override
|
|
87
|
+
* @param token 待插入的子节点
|
|
88
|
+
* @param i 插入位置
|
|
89
|
+
* @throws `SyntaxError` 表格的闭合部分非法
|
|
90
|
+
*/
|
|
91
|
+
insertAt<T extends Token>(token: T, i?: number): T;
|
|
92
|
+
/** @override */
|
|
93
|
+
getRowCount(): number;
|
|
94
|
+
/** 获取下一行 */
|
|
95
|
+
getNextRow(): TrToken | undefined;
|
|
87
96
|
/** 打印表格布局 */
|
|
88
97
|
printLayout(): void;
|
|
89
98
|
/**
|
package/dist/src/table/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.TableToken = void 0;
|
|
3
|
+
exports.TableToken = exports.Layout = exports.isRowEnd = void 0;
|
|
4
4
|
const lint_1 = require("../../util/lint");
|
|
5
5
|
const debug_1 = require("../../util/debug");
|
|
6
6
|
const string_1 = require("../../util/string");
|
|
@@ -10,6 +10,37 @@ const trBase_1 = require("./trBase");
|
|
|
10
10
|
const syntax_1 = require("../syntax");
|
|
11
11
|
/* NOT FOR BROWSER END */
|
|
12
12
|
const closingPattern = /^\n[^\S\n]*(?:\|\}|\{\{\s*!\s*\}\}\}|\{\{\s*!\)\s*\}\})$/u;
|
|
13
|
+
/**
|
|
14
|
+
* 是否是行尾
|
|
15
|
+
* @param {Token} cell 表格单元格
|
|
16
|
+
*/
|
|
17
|
+
const isRowEnd = ({ type }) => type === 'tr' || type === 'table-syntax';
|
|
18
|
+
exports.isRowEnd = isRowEnd;
|
|
19
|
+
/** @extends {Array<TableCoords[]>} */
|
|
20
|
+
class Layout extends Array {
|
|
21
|
+
/* NOT FOR BROWSER */
|
|
22
|
+
/** 打印表格布局 */
|
|
23
|
+
print() {
|
|
24
|
+
const hBorders = (0, debug_1.emptyArray)(this.length + 1, i => {
|
|
25
|
+
const prev = this[i - 1] ?? [], next = this[i] ?? [];
|
|
26
|
+
return (0, debug_1.emptyArray)(Math.max(prev.length, next.length), j => prev[j] !== next[j]);
|
|
27
|
+
}), vBorders = this.map(cur => (0, debug_1.emptyArray)(cur.length + 1, j => cur[j - 1] !== cur[j]));
|
|
28
|
+
let out = '';
|
|
29
|
+
for (let i = 0; i <= this.length; i++) {
|
|
30
|
+
const hBorder = hBorders[i].map(Number), vBorderTop = (vBorders[i - 1] ?? []).map(Number), vBorderBottom = (vBorders[i] ?? []).map(Number),
|
|
31
|
+
// eslint-disable-next-line no-sparse-arrays
|
|
32
|
+
border = [' ', , , '┌', , '┐', '─', '┬', , '│', '└', '├', '┘', '┤', '┴', '┼'];
|
|
33
|
+
for (let j = 0; j <= hBorder.length; j++) {
|
|
34
|
+
const bit = (vBorderTop[j] << 3) + (vBorderBottom[j] << 0)
|
|
35
|
+
+ (hBorder[j - 1] << 2) + (hBorder[j] << 1);
|
|
36
|
+
out += `${border[bit]}${hBorder[j] ? '─' : ' '}`;
|
|
37
|
+
}
|
|
38
|
+
out += '\n';
|
|
39
|
+
}
|
|
40
|
+
console.log(out.slice(0, -1));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
exports.Layout = Layout;
|
|
13
44
|
/**
|
|
14
45
|
* 表格
|
|
15
46
|
* @classdesc `{childNodes: [SyntaxToken, AttributesToken, ?Token, ...TdToken, ...TrToken, ?SyntaxToken]}`
|
|
@@ -43,7 +74,6 @@ class TableToken extends trBase_1.TrBaseToken {
|
|
|
43
74
|
if (!this.closed) {
|
|
44
75
|
errors.push((0, lint_1.generateForChild)(this.firstChild, { start }, 'unclosed-table', index_1.default.msg('unclosed $1', 'table')));
|
|
45
76
|
}
|
|
46
|
-
/* NOT FOR BROWSER */
|
|
47
77
|
const layout = this.getLayout(), { length } = layout;
|
|
48
78
|
if (length > 1) {
|
|
49
79
|
let low = 1, high = Infinity, j = 0;
|
|
@@ -67,7 +97,6 @@ class TableToken extends trBase_1.TrBaseToken {
|
|
|
67
97
|
errors.push((0, lint_1.generateForChild)(this.getNthRow(j), { start }, 'table-layout', 'inconsistent table layout', 'warning'));
|
|
68
98
|
}
|
|
69
99
|
}
|
|
70
|
-
/* NOT FOR BROWSER END */
|
|
71
100
|
return errors;
|
|
72
101
|
}
|
|
73
102
|
/**
|
|
@@ -87,47 +116,91 @@ class TableToken extends trBase_1.TrBaseToken {
|
|
|
87
116
|
}
|
|
88
117
|
this.lastChild.replaceChildren(...inner);
|
|
89
118
|
}
|
|
90
|
-
/** @override */
|
|
91
|
-
json() {
|
|
92
|
-
const json = super.json();
|
|
93
|
-
json['closed'] = this.closed;
|
|
94
|
-
return json;
|
|
95
|
-
}
|
|
96
|
-
/* NOT FOR BROWSER */
|
|
97
119
|
/**
|
|
98
|
-
*
|
|
99
|
-
* @param
|
|
100
|
-
* @param
|
|
101
|
-
* @
|
|
120
|
+
* 获取表格布局
|
|
121
|
+
* @param stop 中止条件
|
|
122
|
+
* @param stop.row 中止行
|
|
123
|
+
* @param stop.column 中止列
|
|
124
|
+
* @param stop.x 中止行
|
|
125
|
+
* @param stop.y 中止列
|
|
102
126
|
*/
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
127
|
+
getLayout(stop) {
|
|
128
|
+
const rows = this.getAllRows(), { length } = rows, layout = new Layout(...(0, debug_1.emptyArray)(length, () => []));
|
|
129
|
+
for (let i = 0; i < length; i++) {
|
|
130
|
+
/* NOT FOR BROWSER */
|
|
131
|
+
if (i > (stop?.row ?? stop?.y ?? NaN)) {
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
/* NOT FOR BROWSER END */
|
|
135
|
+
const rowLayout = layout[i];
|
|
136
|
+
let j = 0, k = 0, last;
|
|
137
|
+
for (const cell of rows[i].childNodes.slice(2)) {
|
|
138
|
+
if (cell.type === 'td') {
|
|
139
|
+
if (cell.isIndependent()) {
|
|
140
|
+
last = cell.subtype !== 'caption';
|
|
141
|
+
}
|
|
142
|
+
if (last) {
|
|
143
|
+
const coords = { row: i, column: j }, { rowspan, colspan } = cell;
|
|
144
|
+
j++;
|
|
145
|
+
while (rowLayout[k]) {
|
|
146
|
+
k++;
|
|
147
|
+
}
|
|
148
|
+
/* NOT FOR BROWSER */
|
|
149
|
+
if (i === stop?.row && j > stop.column) {
|
|
150
|
+
layout[i][k] = coords;
|
|
151
|
+
return layout;
|
|
152
|
+
}
|
|
153
|
+
/* NOT FOR BROWSER END */
|
|
154
|
+
for (let y = i; y < Math.min(i + rowspan, length); y++) {
|
|
155
|
+
for (let x = k; x < k + colspan; x++) {
|
|
156
|
+
layout[y][x] = coords;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
k += colspan;
|
|
160
|
+
/* NOT FOR BROWSER */
|
|
161
|
+
if (i === stop?.y && k > (stop.x ?? NaN)) {
|
|
162
|
+
return layout;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
else if ((0, exports.isRowEnd)(cell)) {
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
112
170
|
}
|
|
113
|
-
return
|
|
171
|
+
return layout;
|
|
114
172
|
}
|
|
115
|
-
/**
|
|
116
|
-
|
|
117
|
-
return
|
|
173
|
+
/** 获取所有行 */
|
|
174
|
+
getAllRows() {
|
|
175
|
+
return [
|
|
176
|
+
...super.getRowCount() ? [this] : [],
|
|
177
|
+
...this.childNodes.slice(1)
|
|
178
|
+
.filter((child) => child.type === 'tr' && child.getRowCount() > 0),
|
|
179
|
+
];
|
|
118
180
|
}
|
|
119
|
-
/**
|
|
120
|
-
|
|
121
|
-
|
|
181
|
+
/**
|
|
182
|
+
* 获取指定坐标的单元格
|
|
183
|
+
* @param coords 表格坐标
|
|
184
|
+
*/
|
|
185
|
+
getNthCell(coords) {
|
|
186
|
+
const rawCoords = coords.row === undefined ? this.toRawCoords(coords) : coords;
|
|
187
|
+
return rawCoords && this.getNthRow(rawCoords.row, false, false)?.getNthCol(rawCoords.column);
|
|
122
188
|
}
|
|
123
189
|
getNthRow(n, force = false, insert = false) {
|
|
124
|
-
const
|
|
190
|
+
const isRow = super.getRowCount();
|
|
191
|
+
/* NOT FOR BROWSER */
|
|
192
|
+
const nRows = this.getRowCount();
|
|
125
193
|
n += n < 0 ? nRows : 0;
|
|
126
|
-
|
|
194
|
+
/* NOT FOR BROWSER END */
|
|
195
|
+
if (n === 0
|
|
196
|
+
&& (isRow
|
|
197
|
+
|| force && nRows === 0)) {
|
|
127
198
|
return this;
|
|
199
|
+
/* NOT FOR BROWSER */
|
|
128
200
|
}
|
|
129
201
|
else if (n < 0 || n > nRows || n === nRows && !insert) {
|
|
130
202
|
throw new RangeError(`不存在第 ${n} 行!`);
|
|
203
|
+
/* NOT FOR BROWSER END */
|
|
131
204
|
}
|
|
132
205
|
else if (isRow) {
|
|
133
206
|
n--;
|
|
@@ -138,40 +211,47 @@ class TableToken extends trBase_1.TrBaseToken {
|
|
|
138
211
|
if (n < 0) {
|
|
139
212
|
return child;
|
|
140
213
|
}
|
|
214
|
+
/* NOT FOR BROWSER */
|
|
141
215
|
}
|
|
142
216
|
else if (child.type === 'table-syntax') {
|
|
143
217
|
return child;
|
|
218
|
+
/* NOT FOR BROWSER END */
|
|
144
219
|
}
|
|
145
220
|
}
|
|
146
221
|
return undefined;
|
|
147
222
|
}
|
|
148
|
-
/**
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
.filter((child) => child.type === 'tr' && child.getRowCount() > 0),
|
|
154
|
-
];
|
|
223
|
+
/** @override */
|
|
224
|
+
json() {
|
|
225
|
+
const json = super.json();
|
|
226
|
+
json['closed'] = this.closed;
|
|
227
|
+
return json;
|
|
155
228
|
}
|
|
229
|
+
/* NOT FOR BROWSER */
|
|
156
230
|
/**
|
|
157
|
-
*
|
|
158
|
-
* @param
|
|
231
|
+
* @override
|
|
232
|
+
* @param token 待插入的子节点
|
|
233
|
+
* @param i 插入位置
|
|
234
|
+
* @throws `SyntaxError` 表格的闭合部分非法
|
|
159
235
|
*/
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
236
|
+
insertAt(token, i = this.length) {
|
|
237
|
+
i += i < 0 ? this.length : 0;
|
|
238
|
+
const previous = this.childNodes[i - 1];
|
|
239
|
+
if (typeof token !== 'string' && token.type === 'td' && previous?.type === 'tr') {
|
|
240
|
+
index_1.default.warn('改为将单元格插入当前行。');
|
|
241
|
+
return previous.insertAt(token);
|
|
242
|
+
}
|
|
243
|
+
else if (i > 0 && token instanceof syntax_1.SyntaxToken && token.pattern !== closingPattern) {
|
|
244
|
+
throw new SyntaxError(`表格的闭合部分不符合语法:${(0, string_1.noWrap)(String(token))}`);
|
|
245
|
+
}
|
|
246
|
+
return super.insertAt(token, i);
|
|
163
247
|
}
|
|
164
|
-
/**
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
*/
|
|
172
|
-
getLayout(stop) {
|
|
173
|
-
require('../../addon/table');
|
|
174
|
-
return this.getLayout(stop);
|
|
248
|
+
/** @override */
|
|
249
|
+
getRowCount() {
|
|
250
|
+
return super.getRowCount() + this.childNodes.filter(child => child.type === 'tr' && child.getRowCount()).length;
|
|
251
|
+
}
|
|
252
|
+
/** 获取下一行 */
|
|
253
|
+
getNextRow() {
|
|
254
|
+
return this.getNthRow(super.getRowCount() ? 1 : 0, false, false);
|
|
175
255
|
}
|
|
176
256
|
/** 打印表格布局 */
|
|
177
257
|
printLayout() {
|
package/dist/src/table/td.d.ts
CHANGED
|
@@ -25,14 +25,14 @@ export declare abstract class TdToken extends TableBaseToken {
|
|
|
25
25
|
abstract get children(): [SyntaxToken, AttributesToken, Token];
|
|
26
26
|
abstract get parentElement(): TrToken | TableToken | undefined;
|
|
27
27
|
abstract get nextElementSibling(): this | TrToken | SyntaxToken | undefined;
|
|
28
|
-
/** 单元格类型 */
|
|
29
|
-
get subtype(): TdSubtypes;
|
|
30
|
-
set subtype(subtype: TdSubtypes);
|
|
31
28
|
/** rowspan */
|
|
32
29
|
get rowspan(): number;
|
|
33
|
-
set rowspan(rowspan: number);
|
|
34
30
|
/** colspan */
|
|
35
31
|
get colspan(): number;
|
|
32
|
+
/** 单元格类型 */
|
|
33
|
+
get subtype(): TdSubtypes;
|
|
34
|
+
set subtype(subtype: TdSubtypes);
|
|
35
|
+
set rowspan(rowspan: number);
|
|
36
36
|
set colspan(colspan: number);
|
|
37
37
|
/** 内部wikitext */
|
|
38
38
|
get innerText(): string;
|
|
@@ -48,6 +48,11 @@ export declare abstract class TdToken extends TableBaseToken {
|
|
|
48
48
|
lint(start?: number, re?: RegExp): LintError[];
|
|
49
49
|
/** 是否位于行首 */
|
|
50
50
|
isIndependent(): boolean;
|
|
51
|
+
/**
|
|
52
|
+
* @override
|
|
53
|
+
* @param key 属性键
|
|
54
|
+
*/
|
|
55
|
+
getAttr<T extends string>(key: T): TdAttrGetter<T>;
|
|
51
56
|
/** @override */
|
|
52
57
|
print(): string;
|
|
53
58
|
/** @override */
|
|
@@ -56,11 +61,6 @@ export declare abstract class TdToken extends TableBaseToken {
|
|
|
56
61
|
cloneNode(): this;
|
|
57
62
|
/** 改为独占一行 */
|
|
58
63
|
independence(): void;
|
|
59
|
-
/**
|
|
60
|
-
* @override
|
|
61
|
-
* @param key 属性键
|
|
62
|
-
*/
|
|
63
|
-
getAttr<T extends string>(key: T): TdAttrGetter<T>;
|
|
64
64
|
/** @override */
|
|
65
65
|
getAttrs(): TdAttrs;
|
|
66
66
|
/**
|
package/dist/src/table/td.js
CHANGED
|
@@ -42,6 +42,7 @@ const fixed_1 = require("../../mixin/fixed");
|
|
|
42
42
|
const index_1 = require("../../index");
|
|
43
43
|
const index_2 = require("../index");
|
|
44
44
|
const base_1 = require("./base");
|
|
45
|
+
/* NOT FOR BROWSER END */
|
|
45
46
|
/**
|
|
46
47
|
* `<td>`、`<th>`和`<caption>`
|
|
47
48
|
* @classdesc `{childNodes: [SyntaxToken, AttributesToken, Token]}`
|
|
@@ -65,6 +66,14 @@ let TdToken = (() => {
|
|
|
65
66
|
type = 'td';
|
|
66
67
|
#innerSyntax = '';
|
|
67
68
|
/* NOT FOR BROWSER END */
|
|
69
|
+
/** rowspan */
|
|
70
|
+
get rowspan() {
|
|
71
|
+
return this.getAttr('rowspan');
|
|
72
|
+
}
|
|
73
|
+
/** colspan */
|
|
74
|
+
get colspan() {
|
|
75
|
+
return this.getAttr('colspan');
|
|
76
|
+
}
|
|
68
77
|
/** 单元格类型 */
|
|
69
78
|
get subtype() {
|
|
70
79
|
return this.#getSyntax().subtype;
|
|
@@ -73,17 +82,9 @@ let TdToken = (() => {
|
|
|
73
82
|
set subtype(subtype) {
|
|
74
83
|
this.setSyntax(subtype);
|
|
75
84
|
}
|
|
76
|
-
/** rowspan */
|
|
77
|
-
get rowspan() {
|
|
78
|
-
return this.getAttr('rowspan');
|
|
79
|
-
}
|
|
80
85
|
set rowspan(rowspan) {
|
|
81
86
|
this.setAttr('rowspan', rowspan);
|
|
82
87
|
}
|
|
83
|
-
/** colspan */
|
|
84
|
-
get colspan() {
|
|
85
|
-
return this.getAttr('colspan');
|
|
86
|
-
}
|
|
87
88
|
set colspan(colspan) {
|
|
88
89
|
this.setAttr('colspan', colspan);
|
|
89
90
|
}
|
|
@@ -223,6 +224,15 @@ let TdToken = (() => {
|
|
|
223
224
|
isIndependent() {
|
|
224
225
|
return this.firstChild.text().startsWith('\n');
|
|
225
226
|
}
|
|
227
|
+
/**
|
|
228
|
+
* @override
|
|
229
|
+
* @param key 属性键
|
|
230
|
+
*/
|
|
231
|
+
getAttr(key) {
|
|
232
|
+
const value = super.getAttr(key);
|
|
233
|
+
key = key.toLowerCase().trim();
|
|
234
|
+
return (key === 'rowspan' || key === 'colspan' ? Number(value) || 1 : value);
|
|
235
|
+
}
|
|
226
236
|
/** @override */
|
|
227
237
|
print() {
|
|
228
238
|
const { childNodes: [syntax, attr, inner] } = this;
|
|
@@ -276,15 +286,6 @@ let TdToken = (() => {
|
|
|
276
286
|
this.setSyntax(subtype, escape);
|
|
277
287
|
}
|
|
278
288
|
}
|
|
279
|
-
/**
|
|
280
|
-
* @override
|
|
281
|
-
* @param key 属性键
|
|
282
|
-
*/
|
|
283
|
-
getAttr(key) {
|
|
284
|
-
const value = super.getAttr(key);
|
|
285
|
-
key = key.toLowerCase().trim();
|
|
286
|
-
return (key === 'rowspan' || key === 'colspan' ? Number(value) || 1 : value);
|
|
287
|
-
}
|
|
288
289
|
/** @override */
|
|
289
290
|
getAttrs() {
|
|
290
291
|
const attr = super.getAttrs();
|
|
@@ -17,6 +17,16 @@ export declare abstract class TrBaseToken extends TableBaseToken {
|
|
|
17
17
|
type: 'table' | 'tr';
|
|
18
18
|
/** @override */
|
|
19
19
|
lint(start?: number, re?: RegExp): LintError[];
|
|
20
|
+
/** 获取行数 */
|
|
21
|
+
getRowCount(): number;
|
|
22
|
+
/**
|
|
23
|
+
* 获取第n列
|
|
24
|
+
* @param n 列号
|
|
25
|
+
* @param insert 是否用于判断插入新列的位置
|
|
26
|
+
* @throws `RangeError` 不存在对应单元格
|
|
27
|
+
*/
|
|
28
|
+
getNthCol(n: number, insert?: false): TdToken | undefined;
|
|
29
|
+
getNthCol(n: number, insert: true): TdToken | TrToken | SyntaxToken | undefined;
|
|
20
30
|
/** @override */
|
|
21
31
|
text(): string;
|
|
22
32
|
/**
|
|
@@ -30,18 +40,8 @@ export declare abstract class TrBaseToken extends TableBaseToken {
|
|
|
30
40
|
* @param i 插入位置
|
|
31
41
|
*/
|
|
32
42
|
insertAt<T extends Token>(token: T, i?: number): T;
|
|
33
|
-
/** 获取行数 */
|
|
34
|
-
getRowCount(): number;
|
|
35
43
|
/** 获取列数 */
|
|
36
44
|
getColCount(): number;
|
|
37
|
-
/**
|
|
38
|
-
* 获取第n列
|
|
39
|
-
* @param n 列号
|
|
40
|
-
* @param insert 是否用于判断插入新列的位置
|
|
41
|
-
* @throws `RangeError` 不存在对应单元格
|
|
42
|
-
*/
|
|
43
|
-
getNthCol(n: number, insert?: false): TdToken | undefined;
|
|
44
|
-
getNthCol(n: number, insert: true): TdToken | TrToken | SyntaxToken | undefined;
|
|
45
45
|
/**
|
|
46
46
|
* 插入新的单元格
|
|
47
47
|
* @param inner 单元格内部wikitext
|
package/dist/src/table/trBase.js
CHANGED
|
@@ -37,6 +37,38 @@ class TrBaseToken extends base_1.TableBaseToken {
|
|
|
37
37
|
errors.push(error);
|
|
38
38
|
return errors;
|
|
39
39
|
}
|
|
40
|
+
/** 获取行数 */
|
|
41
|
+
getRowCount() {
|
|
42
|
+
return Number(this.childNodes.some(child => child instanceof td_1.TdToken && child.isIndependent() && !child.firstChild.text().endsWith('+')));
|
|
43
|
+
}
|
|
44
|
+
getNthCol(n, insert = false) {
|
|
45
|
+
/* NOT FOR BROWSER */
|
|
46
|
+
const nCols = this.getColCount();
|
|
47
|
+
n += n < 0 ? nCols : 0;
|
|
48
|
+
if (n < 0 || n > nCols || n === nCols && !insert) {
|
|
49
|
+
throw new RangeError(`不存在第 ${n} 个单元格!`);
|
|
50
|
+
}
|
|
51
|
+
const isTr = (0, debug_1.isToken)('tr'), isSyntax = (0, debug_1.isToken)('table-syntax');
|
|
52
|
+
/* NOT FOR BROWSER END */
|
|
53
|
+
let last = 0;
|
|
54
|
+
for (const child of this.childNodes.slice(2)) {
|
|
55
|
+
if (child instanceof td_1.TdToken) {
|
|
56
|
+
if (child.isIndependent()) {
|
|
57
|
+
last = Number(child.subtype !== 'caption');
|
|
58
|
+
}
|
|
59
|
+
n -= last;
|
|
60
|
+
if (n < 0) {
|
|
61
|
+
return child;
|
|
62
|
+
}
|
|
63
|
+
/* NOT FOR BROWSER */
|
|
64
|
+
}
|
|
65
|
+
else if (isTr(child) || isSyntax(child)) {
|
|
66
|
+
return child;
|
|
67
|
+
/* NOT FOR BROWSER END */
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
40
72
|
/* NOT FOR BROWSER */
|
|
41
73
|
/** 修复简单的表格语法错误 */
|
|
42
74
|
#correct() {
|
|
@@ -97,10 +129,6 @@ class TrBaseToken extends base_1.TableBaseToken {
|
|
|
97
129
|
}
|
|
98
130
|
return super.insertAt(token, i);
|
|
99
131
|
}
|
|
100
|
-
/** 获取行数 */
|
|
101
|
-
getRowCount() {
|
|
102
|
-
return Number(this.childNodes.some(child => child instanceof td_1.TdToken && child.isIndependent() && !child.firstChild.text().endsWith('+')));
|
|
103
|
-
}
|
|
104
132
|
/** 获取列数 */
|
|
105
133
|
getColCount() {
|
|
106
134
|
let count = 0, last = 0;
|
|
@@ -112,30 +140,6 @@ class TrBaseToken extends base_1.TableBaseToken {
|
|
|
112
140
|
}
|
|
113
141
|
return count;
|
|
114
142
|
}
|
|
115
|
-
getNthCol(n, insert = false) {
|
|
116
|
-
const nCols = this.getColCount();
|
|
117
|
-
n += n < 0 ? nCols : 0;
|
|
118
|
-
if (n < 0 || n > nCols || n === nCols && !insert) {
|
|
119
|
-
throw new RangeError(`不存在第 ${n} 个单元格!`);
|
|
120
|
-
}
|
|
121
|
-
let last = 0;
|
|
122
|
-
const isTr = (0, debug_1.isToken)('tr'), isSyntax = (0, debug_1.isToken)('table-syntax');
|
|
123
|
-
for (const child of this.childNodes.slice(2)) {
|
|
124
|
-
if (child instanceof td_1.TdToken) {
|
|
125
|
-
if (child.isIndependent()) {
|
|
126
|
-
last = Number(child.subtype !== 'caption');
|
|
127
|
-
}
|
|
128
|
-
n -= last;
|
|
129
|
-
if (n < 0) {
|
|
130
|
-
return child;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
else if (isTr(child) || isSyntax(child)) {
|
|
134
|
-
return child;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
return undefined;
|
|
138
|
-
}
|
|
139
143
|
/**
|
|
140
144
|
* 插入新的单元格
|
|
141
145
|
* @param inner 单元格内部wikitext
|
package/dist/util/debug.js
CHANGED
|
@@ -50,7 +50,6 @@ const setChildNodes = (parent, position, deleteCount, inserted = []) => {
|
|
|
50
50
|
return removed;
|
|
51
51
|
};
|
|
52
52
|
exports.setChildNodes = setChildNodes;
|
|
53
|
-
/* NOT FOR BROWSER */
|
|
54
53
|
/**
|
|
55
54
|
* 生成一个指定长度的空数组
|
|
56
55
|
* @param n 数组长度
|
|
@@ -58,6 +57,7 @@ exports.setChildNodes = setChildNodes;
|
|
|
58
57
|
*/
|
|
59
58
|
const emptyArray = (n, callback) => new Array(n).fill(undefined).map((_, i) => callback(i));
|
|
60
59
|
exports.emptyArray = emptyArray;
|
|
60
|
+
/* NOT FOR BROWSER */
|
|
61
61
|
/**
|
|
62
62
|
* 撤销最近一次Mutation
|
|
63
63
|
* @param e 事件
|