wikiparser-node 1.0.0-beta.4 → 1.0.0-beta.6

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.
Files changed (132) hide show
  1. package/README.md +10 -9
  2. package/dist/addon/table.d.ts +6 -0
  3. package/dist/addon/table.js +529 -0
  4. package/dist/bin/toc.js +18 -0
  5. package/dist/index.d.ts +0 -4
  6. package/dist/index.js +17 -9
  7. package/dist/internal.d.ts +5 -5
  8. package/dist/lib/element.d.ts +3 -38
  9. package/dist/lib/element.js +46 -66
  10. package/dist/lib/node.d.ts +12 -45
  11. package/dist/lib/node.js +30 -68
  12. package/dist/lib/range.d.ts +18 -9
  13. package/dist/lib/range.js +72 -35
  14. package/dist/lib/ranges.d.ts +1 -1
  15. package/dist/lib/ranges.js +6 -11
  16. package/dist/lib/text.d.ts +2 -17
  17. package/dist/lib/text.js +7 -18
  18. package/dist/lib/title.d.ts +7 -15
  19. package/dist/lib/title.js +29 -18
  20. package/dist/mixin/attributesParent.js +6 -5
  21. package/dist/mixin/fixed.js +0 -1
  22. package/dist/mixin/flagsParent.js +70 -0
  23. package/dist/mixin/hidden.js +0 -1
  24. package/dist/mixin/magicLinkParent.js +41 -0
  25. package/dist/mixin/singleLine.js +1 -2
  26. package/dist/mixin/sol.js +10 -13
  27. package/dist/mixin/syntax.js +55 -0
  28. package/dist/parser/hrAndDoubleUnderscore.js +4 -4
  29. package/dist/parser/links.js +3 -3
  30. package/dist/parser/selector.js +6 -6
  31. package/dist/parser/table.js +7 -6
  32. package/dist/src/arg.d.ts +10 -30
  33. package/dist/src/arg.js +33 -48
  34. package/dist/src/atom.d.ts +2 -2
  35. package/dist/src/atom.js +5 -4
  36. package/dist/src/attribute.d.ts +19 -39
  37. package/dist/src/attribute.js +45 -98
  38. package/dist/src/attributes.d.ts +19 -33
  39. package/dist/src/attributes.js +52 -78
  40. package/dist/src/converter.d.ts +31 -52
  41. package/dist/src/converter.js +15 -67
  42. package/dist/src/converterFlags.d.ts +10 -31
  43. package/dist/src/converterFlags.js +23 -39
  44. package/dist/src/converterRule.d.ts +3 -19
  45. package/dist/src/converterRule.js +23 -57
  46. package/dist/src/extLink.d.ts +23 -34
  47. package/dist/src/extLink.js +23 -60
  48. package/dist/src/gallery.d.ts +6 -23
  49. package/dist/src/gallery.js +20 -26
  50. package/dist/src/heading.d.ts +19 -28
  51. package/dist/src/heading.js +25 -36
  52. package/dist/src/hidden.d.ts +5 -4
  53. package/dist/src/hidden.js +3 -7
  54. package/dist/src/html.d.ts +19 -35
  55. package/dist/src/html.js +16 -38
  56. package/dist/src/imageParameter.d.ts +14 -31
  57. package/dist/src/imageParameter.js +49 -61
  58. package/dist/src/imagemap.d.ts +10 -32
  59. package/dist/src/imagemap.js +13 -33
  60. package/dist/src/imagemapLink.d.ts +12 -4
  61. package/dist/src/imagemapLink.js +7 -7
  62. package/dist/src/index.d.ts +7 -19
  63. package/dist/src/index.js +62 -99
  64. package/dist/src/link/base.d.ts +6 -21
  65. package/dist/src/link/base.js +49 -67
  66. package/dist/src/link/category.d.ts +1 -2
  67. package/dist/src/link/category.js +3 -3
  68. package/dist/src/link/file.d.ts +14 -24
  69. package/dist/src/link/file.js +31 -51
  70. package/dist/src/link/galleryImage.d.ts +14 -9
  71. package/dist/src/link/galleryImage.js +35 -39
  72. package/dist/src/link/index.d.ts +0 -2
  73. package/dist/src/link/index.js +4 -28
  74. package/dist/src/magicLink.d.ts +24 -13
  75. package/dist/src/magicLink.js +19 -29
  76. package/dist/src/nested.d.ts +2 -7
  77. package/dist/src/nested.js +7 -10
  78. package/dist/src/nowiki/base.d.ts +9 -2
  79. package/dist/src/nowiki/base.js +16 -7
  80. package/dist/src/nowiki/comment.d.ts +16 -20
  81. package/dist/src/nowiki/comment.js +26 -23
  82. package/dist/src/nowiki/dd.d.ts +3 -20
  83. package/dist/src/nowiki/dd.js +7 -36
  84. package/dist/src/nowiki/doubleUnderscore.d.ts +27 -17
  85. package/dist/src/nowiki/doubleUnderscore.js +22 -21
  86. package/dist/src/nowiki/hr.d.ts +17 -10
  87. package/dist/src/nowiki/hr.js +2 -17
  88. package/dist/src/nowiki/index.d.ts +1 -5
  89. package/dist/src/nowiki/index.js +3 -7
  90. package/dist/src/nowiki/list.d.ts +10 -3
  91. package/dist/src/nowiki/list.js +20 -3
  92. package/dist/src/nowiki/listBase.d.ts +28 -0
  93. package/dist/src/nowiki/listBase.js +34 -0
  94. package/dist/src/nowiki/noinclude.d.ts +6 -1
  95. package/dist/src/nowiki/noinclude.js +2 -2
  96. package/dist/src/nowiki/quote.d.ts +16 -14
  97. package/dist/src/nowiki/quote.js +3 -21
  98. package/dist/src/onlyinclude.d.ts +4 -27
  99. package/dist/src/onlyinclude.js +15 -25
  100. package/dist/src/paramTag/index.d.ts +6 -21
  101. package/dist/src/paramTag/index.js +12 -24
  102. package/dist/src/paramTag/inputbox.d.ts +3 -3
  103. package/dist/src/paramTag/inputbox.js +3 -3
  104. package/dist/src/parameter.d.ts +13 -27
  105. package/dist/src/parameter.js +47 -52
  106. package/dist/src/pre.d.ts +2 -3
  107. package/dist/src/pre.js +5 -5
  108. package/dist/src/syntax.d.ts +15 -14
  109. package/dist/src/syntax.js +9 -48
  110. package/dist/src/table/base.d.ts +10 -13
  111. package/dist/src/table/base.js +9 -7
  112. package/dist/src/table/index.d.ts +9 -28
  113. package/dist/src/table/index.js +71 -491
  114. package/dist/src/table/td.d.ts +20 -39
  115. package/dist/src/table/td.js +45 -53
  116. package/dist/src/table/tr.d.ts +0 -2
  117. package/dist/src/table/tr.js +1 -2
  118. package/dist/src/table/trBase.d.ts +2 -10
  119. package/dist/src/table/trBase.js +6 -12
  120. package/dist/src/tagPair/ext.d.ts +11 -11
  121. package/dist/src/tagPair/ext.js +12 -12
  122. package/dist/src/tagPair/include.d.ts +10 -4
  123. package/dist/src/tagPair/include.js +20 -6
  124. package/dist/src/tagPair/index.d.ts +9 -19
  125. package/dist/src/tagPair/index.js +10 -23
  126. package/dist/src/transclude.d.ts +10 -44
  127. package/dist/src/transclude.js +76 -117
  128. package/dist/util/diff.js +4 -3
  129. package/dist/util/string.js +2 -14
  130. package/i18n/zh-hans.json +1 -0
  131. package/i18n/zh-hant.json +1 -0
  132. package/package.json +11 -10
package/README.md CHANGED
@@ -1,15 +1,16 @@
1
1
  [![npm version](https://badge.fury.io/js/wikiparser-node.svg)](https://www.npmjs.com/package/wikiparser-node)
2
- [![CodeQL](https://github.com/bhsd-harry/wikiparser-node/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/bhsd-harry/wikiparser-node/actions/workflows/github-code-scanning/codeql)
2
+ [![CodeQL](https://github.com/bhsd-harry/wikiparser-node/actions/workflows/codeql.yml/badge.svg)](https://github.com/bhsd-harry/wikiparser-node/actions/workflows/codeql.yml)
3
+ [![CI](https://github.com/bhsd-harry/wikiparser-node/actions/workflows/node.js.yml/badge.svg)](https://github.com/bhsd-harry/wikiparser-node/actions/workflows/node.js.yml)
3
4
 
4
5
  # 简介
5
6
 
6
- wikiparser-node 是一款由 Bhsd 开发的基于 [Node.js](https://nodejs.org/en/) 环境的离线[维基文本](https://www.mediawiki.org/wiki/Wikitext)语法解析器,可以解析绝大部分的维基语法并生成[语法树](https://en.wikipedia.org/wiki/Abstract_syntax_tree),还可以很方便地对语法树进行查询和修改,最后返回修改后的维基文本。
7
+ wikiparser-node 是一款由 Bhsd 开发的基于 [Node.js](https://nodejs.org/) 环境的离线[维基文本](https://www.mediawiki.org/wiki/Wikitext)语法解析器,可以解析几乎全部的维基语法并生成[语法树](https://en.wikipedia.org/wiki/Abstract_syntax_tree),还可以很方便地对语法树进行查询和修改,最后返回修改后的维基文本。
7
8
 
8
9
  # 其他版本
9
10
 
10
- ## Mini
11
+ ## Mini (又名 [wikilint](https://www.npmjs.com/package/wikilint))
11
12
 
12
- 仅保留了解析功能和[语法错误分析](https://github.com/bhsd-harry/wikiparser-node/wiki/AstElement#lint)功能的轻量版本,解析生成的语法树不能修改。这个版本被应用于 [eslint-plugin-wikitext](/bhsd-harry/eslint-plugin-wikitext) 插件。
13
+ 提供了 [CLI](https://en.wikipedia.org/wiki/Command-line_interface),但仅保留了解析功能和语法错误分析功能,解析生成的语法树不能修改。这个版本被应用于 [eslint-plugin-wikitext](https://www.npmjs.com/package/eslint-plugin-wikitext) 插件。
13
14
 
14
15
  ## Browser
15
16
 
@@ -19,16 +20,16 @@ wikiparser-node 是一款由 Bhsd 开发的基于 [Node.js](https://nodejs.org/e
19
20
 
20
21
  ## Node.js
21
22
 
22
- 请根据需要需要安装对应的版本(`latest` 或 `mini`),如:
23
+ 请根据需要需要安装对应的版本(`wikiparser-node` 或 `wikilint`),如:
23
24
 
24
25
  ```sh
25
- npm i wikiparser-node # 默认为latest
26
+ npm i wikiparser-node
26
27
  ```
27
28
 
28
29
 
29
30
 
30
31
  ```sh
31
- npm i wikiparser-node@mini
32
+ npm i wikilint
32
33
  ```
33
34
 
34
35
  ## 浏览器
@@ -45,8 +46,8 @@ npm i wikiparser-node@mini
45
46
  <script src="//unpkg.com/wikiparser-node@browser/bundle/bundle.min.js"></script>
46
47
  ```
47
48
 
48
- 更多浏览器端可用的插件请查阅对应[文档](https://github.com/bhsd-harry/wikiparser-node/wiki/Browser)。
49
+ 更多浏览器端可用的插件请查阅对应文档。
49
50
 
50
51
  # 使用方法
51
52
 
52
- 请查阅 [Wiki](https://github.com/bhsd-harry/wikiparser-node/wiki/Parser)。
53
+ 请查阅 [Wiki](https://github.com/bhsd-harry/wikiparser-node/wiki)。
@@ -0,0 +1,6 @@
1
+ import type { TableCoords } from '../src/table/trBase';
2
+ /** @extends {Array<TableCoords[]>} */
3
+ export declare class Layout extends Array<TableCoords[]> {
4
+ /** 打印表格布局 */
5
+ print(): void;
6
+ }
@@ -0,0 +1,529 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Layout = void 0;
4
+ const assert = require("assert/strict");
5
+ const Parser = require("../index");
6
+ const src_1 = require("../src");
7
+ const tr_1 = require("../src/table/tr");
8
+ const table_1 = require("../src/table");
9
+ const td_1 = require("../src/table/td");
10
+ const trBase_1 = require("../src/table/trBase");
11
+ /**
12
+ * 比较两个表格坐标
13
+ * @param coords1 坐标1
14
+ * @param coords2 坐标2
15
+ */
16
+ const cmpCoords = (coords1, coords2) => {
17
+ const diff = coords1.row - coords2.row;
18
+ return diff === 0 ? coords1.column - coords2.column : diff;
19
+ };
20
+ /**
21
+ * 是否是行尾
22
+ * @param {Token} cell 表格单元格
23
+ */
24
+ const isRowEnd = ({ type }) => type === 'tr' || type === 'table-syntax';
25
+ /**
26
+ * 是否是合并单元格的第一列
27
+ * @param rowLayout 行布局
28
+ * @param i 单元格序号
29
+ * @param oneCol 是否仅有一列
30
+ */
31
+ const isStartCol = (rowLayout, i, oneCol = false) => {
32
+ const coords = rowLayout[i];
33
+ return rowLayout[i - 1] !== coords && (!oneCol || rowLayout[i + 1] !== coords);
34
+ };
35
+ /**
36
+ * 设置表格格式
37
+ * @param cells 单元格
38
+ * @param attr 属性
39
+ * @param multi 是否对所有单元格设置,或是仅对行首单元格设置
40
+ */
41
+ const format = (cells, attr = {}, multi = false) => {
42
+ for (const [token, start] of cells) {
43
+ if (multi || start) {
44
+ if (typeof attr === 'string') {
45
+ token.setSyntax(attr);
46
+ }
47
+ else {
48
+ for (const [k, v] of Object.entries(attr)) {
49
+ token.setAttr(k, v);
50
+ }
51
+ }
52
+ }
53
+ }
54
+ };
55
+ /**
56
+ * 填补缺失单元格
57
+ * @param y 行号
58
+ * @param rowToken 表格行
59
+ * @param layout 表格布局
60
+ * @param maxCol 最大列数
61
+ * @param token 待填充的单元格
62
+ */
63
+ const fill = (y, rowToken, layout, maxCol, token) => {
64
+ const rowLayout = layout[y], lastIndex = rowToken.childNodes.findLastIndex(child => child instanceof td_1.TdToken && child.subtype !== 'caption'), pos = lastIndex + 1 || undefined;
65
+ Parser.run(() => {
66
+ for (let i = 0; i < maxCol; i++) {
67
+ if (!rowLayout[i]) {
68
+ rowToken.insertAt(token.cloneNode(), pos);
69
+ }
70
+ }
71
+ });
72
+ };
73
+ /** @extends {Array<TableCoords[]>} */
74
+ class Layout extends Array {
75
+ /** 打印表格布局 */
76
+ print() {
77
+ const hBorders = new Array(this.length + 1).fill(undefined).map((_, i) => {
78
+ const prev = this[i - 1] ?? [], next = this[i] ?? [];
79
+ return new Array(Math.max(prev.length, next.length)).fill(undefined)
80
+ .map((__, j) => prev[j] !== next[j]);
81
+ }), vBorders = this.map(cur => new Array(cur.length + 1).fill(undefined).map((_, j) => cur[j - 1] !== cur[j]));
82
+ let out = '';
83
+ for (let i = 0; i <= this.length; i++) {
84
+ const hBorder = hBorders[i].map(Number), vBorderTop = (vBorders[i - 1] ?? []).map(Number), vBorderBottom = (vBorders[i] ?? []).map(Number),
85
+ // eslint-disable-next-line no-sparse-arrays
86
+ border = [' ', , , '┌', , '┐', '─', '┬', , '│', '└', '├', '┘', '┤', '┴', '┼'];
87
+ for (let j = 0; j <= hBorder.length; j++) {
88
+ const bit = (vBorderTop[j] << 3) + (vBorderBottom[j] << 0)
89
+ + (hBorder[j - 1] << 2) + (hBorder[j] << 1);
90
+ out += `${border[bit]}${hBorder[j] ? '─' : ' '}`;
91
+ }
92
+ out += '\n';
93
+ }
94
+ console.log(out.slice(0, -1));
95
+ }
96
+ }
97
+ exports.Layout = Layout;
98
+ Object.assign(table_1.TableToken.prototype, {
99
+ /** @implements */
100
+ getNthCell(coords) {
101
+ const rawCoords = coords.row === undefined ? this.toRawCoords(coords) : coords;
102
+ return rawCoords && this.getNthRow(rawCoords.row, false, false)?.getNthCol(rawCoords.column);
103
+ },
104
+ /** @implements */
105
+ getLayout(stop) {
106
+ const rows = this.getAllRows(), { length } = rows, layout = new Layout(...new Array(length).fill(undefined).map(() => []));
107
+ for (let i = 0; i < length; i++) {
108
+ if (i > (stop?.row ?? stop?.y ?? NaN)) {
109
+ break;
110
+ }
111
+ const rowLayout = layout[i];
112
+ let j = 0, k = 0, last;
113
+ for (const cell of rows[i].childNodes.slice(2)) {
114
+ if (cell instanceof td_1.TdToken) {
115
+ if (cell.isIndependent()) {
116
+ last = cell.subtype !== 'caption';
117
+ }
118
+ if (last) {
119
+ const coords = { row: i, column: j }, { rowspan, colspan } = cell;
120
+ j++;
121
+ while (rowLayout[k]) {
122
+ k++;
123
+ }
124
+ if (i === stop?.row && j > (stop.column ?? NaN)) {
125
+ layout[i][k] = coords;
126
+ return layout;
127
+ }
128
+ for (let y = i; y < Math.min(i + rowspan, length); y++) {
129
+ for (let x = k; x < k + colspan; x++) {
130
+ layout[y][x] = coords;
131
+ }
132
+ }
133
+ k += colspan;
134
+ if (i === stop?.y && k > (stop.x ?? NaN)) {
135
+ return layout;
136
+ }
137
+ }
138
+ }
139
+ else if (isRowEnd(cell)) {
140
+ break;
141
+ }
142
+ }
143
+ }
144
+ return layout;
145
+ },
146
+ /** @implements */
147
+ printLayout() {
148
+ this.getLayout().print();
149
+ },
150
+ /** @implements */
151
+ toRenderedCoords({ row, column }) {
152
+ const rowLayout = this.getLayout({ row, column })[row], x = rowLayout?.findIndex(coords => cmpCoords(coords, { row, column }) === 0);
153
+ return rowLayout && (x === -1 ? undefined : { y: row, x: x });
154
+ },
155
+ /** @implements */
156
+ toRawCoords({ x, y }) {
157
+ const rowLayout = this.getLayout({ x, y })[y], coords = rowLayout?.[x];
158
+ if (coords) {
159
+ return { ...coords, start: coords.row === y && rowLayout[x - 1] !== coords };
160
+ }
161
+ else if (rowLayout || y > 0) {
162
+ return x === rowLayout?.length
163
+ ? { row: y, column: (rowLayout.findLast(({ row }) => row === y)?.column ?? -1) + 1, start: true }
164
+ : undefined;
165
+ }
166
+ return { row: 0, column: 0, start: true };
167
+ },
168
+ /** @implements */
169
+ getFullRow(y) {
170
+ const rows = this.getAllRows();
171
+ return new Map(this.getLayout({ y })[y]?.map(({ row, column }) => [rows[row].getNthCol(column), row === y]));
172
+ },
173
+ /** @implements */
174
+ getFullCol(x) {
175
+ const layout = this.getLayout(), colLayout = layout.map(row => row[x]).filter(Boolean), rows = this.getAllRows();
176
+ return new Map(colLayout.map(coords => [rows[coords.row].getNthCol(coords.column), layout[coords.row][x - 1] !== coords]));
177
+ },
178
+ /** @implements */
179
+ formatTableRow(y, attr = {}, multiRow = false) {
180
+ format(this.getFullRow(y), attr, multiRow);
181
+ },
182
+ /** @implements */
183
+ formatTableCol(x, attr = {}, multiCol = false) {
184
+ format(this.getFullCol(x), attr, multiCol);
185
+ },
186
+ /** @implements */
187
+ fillTableRow(y, inner, subtype = 'td', attr = {}) {
188
+ const rowToken = this.getNthRow(y), layout = this.getLayout({ y }), maxCol = Math.max(...layout.map(({ length }) => length)), token = (0, td_1.createTd)(inner, subtype, attr, this.getAttribute('include'), this.getAttribute('config'));
189
+ fill(y, rowToken, layout, maxCol, token);
190
+ },
191
+ /** @implements */
192
+ fillTable(inner, subtype = 'td', attr = {}) {
193
+ const rowTokens = this.getAllRows(), layout = this.getLayout(), maxCol = Math.max(...layout.map(({ length }) => length)), token = (0, td_1.createTd)(inner, subtype, attr, this.getAttribute('include'), this.getAttribute('config'));
194
+ for (let y = 0; y < rowTokens.length; y++) {
195
+ fill(y, rowTokens[y], layout, maxCol, token);
196
+ }
197
+ },
198
+ /** @implements */
199
+ insertTableCell(inner, coords, subtype = 'td', attr = {}) {
200
+ let rawCoords;
201
+ if (coords.column === undefined) {
202
+ const { x, y } = coords;
203
+ rawCoords = this.toRawCoords(coords);
204
+ if (!rawCoords?.start) {
205
+ throw new RangeError(`指定的坐标不是单元格起始点:(${x}, ${y})`);
206
+ }
207
+ }
208
+ else {
209
+ rawCoords = coords;
210
+ }
211
+ const rowToken = this.getNthRow(rawCoords.row, true);
212
+ return rowToken === this
213
+ ? trBase_1.TrBaseToken.prototype.insertTableCell.call(this, inner, rawCoords, subtype, attr)
214
+ : rowToken.insertTableCell(inner, rawCoords, subtype, attr);
215
+ },
216
+ /** @implements */
217
+ prependTableRow() {
218
+ const row = Parser.run(() => new tr_1.TrToken('\n|-', undefined, this.getAttribute('config'))), { childNodes } = this, [, , plain] = childNodes, start = plain?.constructor === src_1.Token ? 3 : 2, tdChildren = childNodes.slice(start), index = tdChildren.findIndex(({ type }) => type !== 'td');
219
+ this.insertAt(row, index === -1 ? -1 : index + start);
220
+ Parser.run(() => {
221
+ for (const cell of tdChildren.slice(0, index === -1 ? undefined : index)) {
222
+ if (cell.subtype !== 'caption') {
223
+ row.insertAt(cell);
224
+ }
225
+ }
226
+ });
227
+ return row;
228
+ },
229
+ /** @implements */
230
+ insertTableRow(y, attr = {}, inner, subtype = 'td', innerAttr = {}) {
231
+ let reference = this.getNthRow(y, false, true);
232
+ const token = Parser.run(() => new tr_1.TrToken('\n|-', undefined, this.getAttribute('config')));
233
+ for (const [k, v] of Object.entries(attr)) {
234
+ token.setAttr(k, v);
235
+ }
236
+ if (reference?.type === 'table') { // `row === 0`且表格自身是有效行
237
+ reference = this.prependTableRow();
238
+ }
239
+ this.insertBefore(token, reference);
240
+ if (inner !== undefined) {
241
+ const td = token.insertTableCell(inner, { row: 0, column: 0 }, subtype, innerAttr), set = new WeakSet(), layout = this.getLayout({ y }), maxCol = Math.max(...layout.map(({ length }) => length)), rowLayout = layout[y];
242
+ Parser.run(() => {
243
+ for (let i = 0; i < maxCol; i++) {
244
+ const coords = rowLayout[i];
245
+ if (!coords) {
246
+ token.insertAt(td.cloneNode());
247
+ }
248
+ else if (!set.has(coords)) {
249
+ set.add(coords);
250
+ if (coords.row < y) {
251
+ this.getNthCell(coords).rowspan++;
252
+ }
253
+ }
254
+ }
255
+ });
256
+ }
257
+ return token;
258
+ },
259
+ /** @implements */
260
+ insertTableCol(x, inner, subtype = 'td', attr = {}) {
261
+ const layout = this.getLayout(), rowLength = layout.map(({ length }) => length), minCol = Math.min(...rowLength);
262
+ if (x > minCol) {
263
+ throw new RangeError(`表格第 ${rowLength.indexOf(minCol)} 行仅有 ${minCol} 列!`);
264
+ }
265
+ const token = (0, td_1.createTd)(inner, subtype, attr, this.getAttribute('include'), this.getAttribute('config'));
266
+ for (let i = 0; i < layout.length; i++) {
267
+ const coords = layout[i][x], prevCoords = x === 0 ? true : layout[i][x - 1];
268
+ if (!prevCoords) {
269
+ continue;
270
+ }
271
+ else if (prevCoords !== coords) {
272
+ const rowToken = this.getNthRow(i);
273
+ rowToken.insertBefore(token.cloneNode(), rowToken.getNthCol(coords.column, true));
274
+ }
275
+ else if (coords.row === i) {
276
+ this.getNthCell(coords).colspan++;
277
+ }
278
+ }
279
+ },
280
+ /** @implements */
281
+ removeTableRow(y) {
282
+ const rows = this.getAllRows(), layout = this.getLayout(), rowLayout = layout[y], set = new WeakSet();
283
+ for (let x = rowLayout.length - 1; x >= 0; x--) {
284
+ const coords = rowLayout[x];
285
+ if (set.has(coords)) {
286
+ continue;
287
+ }
288
+ set.add(coords);
289
+ const token = rows[coords.row].getNthCol(coords.column);
290
+ let { rowspan } = token;
291
+ if (rowspan > 1) {
292
+ token.rowspan = --rowspan;
293
+ if (coords.row === y) {
294
+ const { colspan, subtype } = token, attr = token.getAttrs();
295
+ for (let i = y + 1; rowspan && i < rows.length; i++, rowspan--) {
296
+ const { column } = layout[i].slice(x + colspan).find(({ row }) => row === i) ?? {};
297
+ if (column !== undefined) {
298
+ rows[i].insertTableCell('', { row: 0, column }, subtype, { ...attr, rowspan });
299
+ break;
300
+ }
301
+ }
302
+ }
303
+ }
304
+ }
305
+ const rowToken = rows[y].type === 'table' ? this.prependTableRow() : rows[y];
306
+ rowToken.remove();
307
+ return rowToken;
308
+ },
309
+ /** @implements */
310
+ removeTableCol(x) {
311
+ for (const [token, start] of this.getFullCol(x)) {
312
+ const { colspan, lastChild } = token;
313
+ if (colspan > 1) {
314
+ token.colspan = colspan - 1;
315
+ if (start) {
316
+ lastChild.replaceChildren();
317
+ }
318
+ }
319
+ else {
320
+ token.remove();
321
+ }
322
+ }
323
+ },
324
+ /** @implements */
325
+ mergeCells(xlim, ylim) {
326
+ const layout = this.getLayout(), maxCol = Math.max(...layout.map(({ length }) => length)), posXlim = xlim.map(x => x < 0 ? x + maxCol : x), posYlim = ylim.map(y => y < 0 ? y + layout.length : y), [xmin, xmax] = posXlim.sort(), [ymin, ymax] = posYlim.sort(), set = new Set(layout.slice(ymin, ymax).flatMap(rowLayout => rowLayout.slice(xmin, xmax)));
327
+ if ([...layout[ymin - 1] ?? [], ...layout[ymax] ?? []].some(coords => set.has(coords))
328
+ || layout.some(rowLayout => set.has(rowLayout[xmin - 1]) || set.has(rowLayout[xmax]))) {
329
+ throw new RangeError('待合并区域与外侧区域有重叠!');
330
+ }
331
+ const corner = layout[ymin][xmin], rows = this.getAllRows(), cornerCell = rows[corner.row].getNthCol(corner.column);
332
+ cornerCell.rowspan = ymax - ymin;
333
+ cornerCell.colspan = xmax - xmin;
334
+ set.delete(corner);
335
+ for (const token of [...set].map(({ row, column }) => rows[row].getNthCol(column))) {
336
+ token.remove();
337
+ }
338
+ return cornerCell;
339
+ },
340
+ /** @implements */
341
+ split(coords, dirs) {
342
+ const cell = this.getNthCell(coords), attr = cell.getAttrs(), { subtype } = cell;
343
+ attr.rowspan ||= 1;
344
+ attr.colspan ||= 1;
345
+ for (const dir of dirs) {
346
+ if (attr[dir] === 1) {
347
+ dirs.delete(dir);
348
+ }
349
+ }
350
+ if (dirs.size === 0) {
351
+ return;
352
+ }
353
+ let { x, y } = coords;
354
+ const rawCoords = x === undefined ? coords : this.toRawCoords(coords);
355
+ if (rawCoords.start === false || x === undefined) {
356
+ ({ x, y } = this.toRenderedCoords(rawCoords));
357
+ }
358
+ const splitting = { rowspan: 1, colspan: 1 };
359
+ for (const dir of dirs) {
360
+ cell.setAttr(dir, 1);
361
+ splitting[dir] = attr[dir];
362
+ delete attr[dir];
363
+ }
364
+ for (let j = y; j < y + splitting.rowspan; j++) {
365
+ for (let i = x; i < x + splitting.colspan; i++) {
366
+ if (i > x || j > y) {
367
+ try {
368
+ this.insertTableCell('', { x: i, y: j }, subtype, attr);
369
+ }
370
+ catch (e) {
371
+ if (e instanceof RangeError && e.message.startsWith('指定的坐标不是单元格起始点:')) {
372
+ break;
373
+ }
374
+ throw e;
375
+ }
376
+ }
377
+ }
378
+ }
379
+ },
380
+ /** @implements */
381
+ splitIntoRows(coords) {
382
+ this.split(coords, new Set(['rowspan']));
383
+ },
384
+ /** @implements */
385
+ splitIntoCols(coords) {
386
+ this.split(coords, new Set(['colspan']));
387
+ },
388
+ /** @implements */
389
+ splitIntoCells(coords) {
390
+ this.split(coords, new Set(['rowspan', 'colspan']));
391
+ },
392
+ /** @implements */
393
+ replicateTableRow(row) {
394
+ let rowToken = this.getNthRow(row);
395
+ if (rowToken.type === 'table') {
396
+ rowToken = this.prependTableRow();
397
+ }
398
+ const replicated = this.insertBefore(rowToken.cloneNode(), rowToken);
399
+ for (const [token, start] of this.getFullRow(row)) {
400
+ if (start) {
401
+ token.rowspan = 1;
402
+ }
403
+ else {
404
+ token.rowspan++;
405
+ }
406
+ }
407
+ return replicated;
408
+ },
409
+ /** @implements */
410
+ replicateTableCol(x) {
411
+ const replicated = [];
412
+ for (const [token, start] of this.getFullCol(x)) {
413
+ if (start) {
414
+ const newToken = token.cloneNode();
415
+ newToken.colspan = 1;
416
+ token.before(newToken);
417
+ replicated.push(newToken);
418
+ }
419
+ else {
420
+ token.colspan++;
421
+ }
422
+ }
423
+ return replicated;
424
+ },
425
+ /** @implements */
426
+ moveTableRowBefore(y, before) {
427
+ const layout = this.getLayout(),
428
+ /** @ignore */
429
+ occupied = (i) => layout[i].map(({ row }, j) => row === i ? j : undefined).filter(j => j !== undefined);
430
+ try {
431
+ assert.deepEqual(occupied(y), occupied(before));
432
+ }
433
+ catch (e) {
434
+ if (e instanceof assert.AssertionError) {
435
+ throw new RangeError(`第 ${y} 行与第 ${before} 行的构造不同,无法移动!`);
436
+ }
437
+ throw e;
438
+ }
439
+ const rowToken = this.removeTableRow(y);
440
+ for (const coords of layout[before]) {
441
+ if (coords.row < before) {
442
+ this.getNthCell(coords).rowspan++;
443
+ }
444
+ }
445
+ let beforeToken = this.getNthRow(before);
446
+ if (beforeToken.type === 'table') {
447
+ beforeToken = this.prependTableRow();
448
+ }
449
+ this.insertBefore(rowToken, beforeToken);
450
+ return rowToken;
451
+ },
452
+ /** @implements */
453
+ moveTableRowAfter(y, after) {
454
+ const layout = this.getLayout(), afterToken = this.getNthRow(after), cells = afterToken.childNodes.filter(child => child instanceof td_1.TdToken && child.subtype !== 'caption'),
455
+ /** @ignore */
456
+ occupied = (i, oneRow = false) => layout[i].map(({ row, column }, j) => row === i && (!oneRow || cells[column].rowspan === 1) ? j : undefined).filter(j => j !== undefined);
457
+ try {
458
+ assert.deepEqual(occupied(y), occupied(after, true));
459
+ }
460
+ catch (e) {
461
+ if (e instanceof assert.AssertionError) {
462
+ throw new RangeError(`第 ${y} 行与第 ${after} 行的构造不同,无法移动!`);
463
+ }
464
+ throw e;
465
+ }
466
+ const rowToken = this.removeTableRow(y);
467
+ for (const coords of layout[after]) {
468
+ if (coords.row < after) {
469
+ this.getNthCell(coords).rowspan++;
470
+ }
471
+ else {
472
+ const cell = cells[coords.column], { rowspan } = cell;
473
+ if (rowspan > 1) {
474
+ cell.rowspan = rowspan + 1;
475
+ }
476
+ }
477
+ }
478
+ if (afterToken === this) {
479
+ const index = this.childNodes.slice(2).findIndex(isRowEnd);
480
+ this.insertAt(rowToken, index + 2);
481
+ }
482
+ else {
483
+ this.insertBefore(rowToken, afterToken);
484
+ }
485
+ return rowToken;
486
+ },
487
+ /** @implements */
488
+ moveCol(x, reference, after = false) {
489
+ const layout = this.getLayout();
490
+ if (layout.some(rowLayout => isStartCol(rowLayout, x) !== isStartCol(rowLayout, reference, after))) {
491
+ throw new RangeError(`第 ${x} 列与第 ${reference} 列的构造不同,无法移动!`);
492
+ }
493
+ const setX = new WeakSet(), setRef = new WeakSet(), rows = this.getAllRows();
494
+ for (let i = 0; i < layout.length; i++) {
495
+ const rowLayout = layout[i], coords = rowLayout[x], refCoords = rowLayout[reference], start = isStartCol(rowLayout, x);
496
+ if (refCoords && !start && !setRef.has(refCoords)) {
497
+ setRef.add(refCoords);
498
+ rows[refCoords.row].getNthCol(refCoords.column).colspan++;
499
+ }
500
+ if (coords && !setX.has(coords)) {
501
+ setX.add(coords);
502
+ const rowToken = rows[i];
503
+ let token = rowToken.getNthCol(coords.column);
504
+ const { colspan } = token;
505
+ if (colspan > 1) {
506
+ token.colspan = colspan - 1;
507
+ if (start) {
508
+ const original = token;
509
+ token = token.cloneNode();
510
+ original.lastChild.replaceChildren();
511
+ token.colspan = 1;
512
+ }
513
+ }
514
+ if (start) {
515
+ const col = rowLayout.slice(reference + Number(after)).find(({ row }) => row === i)?.column;
516
+ rowToken.insertBefore(token, col === undefined ? rowToken.childNodes.slice(2).find(isRowEnd) : rowToken.getNthCol(col));
517
+ }
518
+ }
519
+ }
520
+ },
521
+ /** @implements */
522
+ moveTableColBefore(x, before) {
523
+ this.moveCol(x, before);
524
+ },
525
+ /** @implements */
526
+ moveTableColAfter(x, after) {
527
+ this.moveCol(x, after, true);
528
+ },
529
+ });
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+ const { argv: [, , filename] } = process;
6
+ if (!filename) {
7
+ throw new RangeError('请指定文档文件!');
8
+ }
9
+ const fullpath = path.join(__dirname, '..', '..', 'wiki', `${filename}.md`);
10
+ if (!fs.existsSync(fullpath)) {
11
+ throw new RangeError(`文档 ${filename}.md 不存在!`);
12
+ }
13
+ const content = fs.readFileSync(fullpath, 'utf8');
14
+ if (/^- \[[^\]]+\]\(#[^)]+\)$/mu.test(content)) {
15
+ throw new Error(`文档 ${filename}.md 中已包含目录!`);
16
+ }
17
+ const toc = content.split('\n').filter(line => line.startsWith('#')).map(line => line.replace(/^(#+)\s+(\S.*)$/u, (_, { length }, title) => `${'\t'.repeat(length - 1)}- [${title}](#${title.toLowerCase().replaceAll(' ', '-').replaceAll('.', '')})`)).join('\n');
18
+ fs.writeFileSync(fullpath, `<details>\n\t<summary>目录</summary>\n\n${toc}\n</details>\n\n${content}`);
package/dist/index.d.ts CHANGED
@@ -27,15 +27,12 @@ export interface LintError {
27
27
  excerpt: string;
28
28
  }
29
29
  declare interface Parser {
30
- /** @browser */
31
30
  config: string | Config;
32
- /** @browser */
33
31
  i18n?: string | Record<string, string>;
34
32
  conversionTable: Map<string, string>;
35
33
  redirects: Map<string, string>;
36
34
  /**
37
35
  * 规范化页面标题
38
- * @browser
39
36
  * @param title 标题(含或不含命名空间前缀)
40
37
  * @param defaultNs 命名空间
41
38
  * @param include 是否嵌入
@@ -46,7 +43,6 @@ declare interface Parser {
46
43
  normalizeTitle(title: string, defaultNs?: number, include?: boolean, config?: Config, halfParsed?: boolean, decode?: boolean, selfLink?: boolean): Title;
47
44
  /**
48
45
  * 解析wikitext
49
- * @browser
50
46
  * @param include 是否嵌入
51
47
  * @param maxStage 最大解析层级
52
48
  */