markdown-it-adv-table 0.1.0 → 0.1.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.md +191 -0
- package/dist/table-builder.js +3 -3
- package/dist/table.d.ts +5 -3
- package/dist/table.js +19 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,2 +1,193 @@
|
|
|
1
|
+
|
|
1
2
|
# markdown-it-adv-table
|
|
2
3
|
|
|
4
|
+
A [markdown-it](https://www.npmjs.com/package/markdown-it) plugin to enable advanced table rendering in Markdown. The custom syntax allows to create complex tables supporting:
|
|
5
|
+
|
|
6
|
+
- Rowspan and colspan for merged cells
|
|
7
|
+
- Custom column widths
|
|
8
|
+
- Horizontal cell alignment
|
|
9
|
+
- Table styling with css classes
|
|
10
|
+
- Header rows and columns (using `<th>`)
|
|
11
|
+
- Multiple blocks and nested markdown within cells
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install markdown-it-adv-table
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
```js
|
|
20
|
+
import markdownit from "markdown-it";
|
|
21
|
+
import advTable from "markdown-it-adv-table";
|
|
22
|
+
|
|
23
|
+
const md = markdownit();
|
|
24
|
+
md.use(advTable);
|
|
25
|
+
const html = md.render("text...");
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Documentation
|
|
29
|
+
|
|
30
|
+
To Be Documented
|
|
31
|
+
|
|
32
|
+
## Examples
|
|
33
|
+
|
|
34
|
+
``````
|
|
35
|
+
```table cols=4 header-rows=2 header-cols=1
|
|
36
|
+
r2| Category
|
|
37
|
+
c3| Q1 Sales
|
|
38
|
+
|
|
39
|
+
| January
|
|
40
|
+
| February
|
|
41
|
+
| March
|
|
42
|
+
|
|
43
|
+
| Electronics
|
|
44
|
+
| $10,000
|
|
45
|
+
| $12,000
|
|
46
|
+
| $11,500
|
|
47
|
+
|
|
48
|
+
| Clothing
|
|
49
|
+
| $8,000
|
|
50
|
+
| $9,500
|
|
51
|
+
| $9,000
|
|
52
|
+
|
|
53
|
+
| Books
|
|
54
|
+
| $3,500
|
|
55
|
+
| $4,000
|
|
56
|
+
| $4,200
|
|
57
|
+
``````
|
|
58
|
+
|
|
59
|
+
<table>
|
|
60
|
+
<thead>
|
|
61
|
+
<tr>
|
|
62
|
+
<th rowspan="2">Category</th>
|
|
63
|
+
<th colspan="3">Q1 Sales</th>
|
|
64
|
+
</tr>
|
|
65
|
+
<tr>
|
|
66
|
+
<th>January</th>
|
|
67
|
+
<th>February</th>
|
|
68
|
+
<th>March</th>
|
|
69
|
+
</tr>
|
|
70
|
+
</thead>
|
|
71
|
+
<tbody>
|
|
72
|
+
<tr>
|
|
73
|
+
<th>Electronics</th>
|
|
74
|
+
<td>$10,000</td>
|
|
75
|
+
<td>$12,000</td>
|
|
76
|
+
<td>$11,500</td>
|
|
77
|
+
</tr>
|
|
78
|
+
<tr>
|
|
79
|
+
<th>Clothing</th>
|
|
80
|
+
<td>$8,000</td>
|
|
81
|
+
<td>$9,500</td>
|
|
82
|
+
<td>$9,000</td>
|
|
83
|
+
</tr>
|
|
84
|
+
<tr>
|
|
85
|
+
<th>Books</th>
|
|
86
|
+
<td>$3,500</td>
|
|
87
|
+
<td>$4,000</td>
|
|
88
|
+
<td>$4,200</td>
|
|
89
|
+
</tr>
|
|
90
|
+
</tbody>
|
|
91
|
+
</table>
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
``````
|
|
97
|
+
```table cols="12,12,12,64" header-rows=1 class=products-list
|
|
98
|
+
^| Category
|
|
99
|
+
^| Item Name
|
|
100
|
+
^| Price
|
|
101
|
+
^| Description
|
|
102
|
+
|
|
103
|
+
r3| Fruits
|
|
104
|
+
| Apple
|
|
105
|
+
>| $1.00
|
|
106
|
+
| A smooth, round fruit with shiny red skin.
|
|
107
|
+
|
|
108
|
+
| Banana
|
|
109
|
+
>| $0.50
|
|
110
|
+
| A long, curved fruit with yellow peel
|
|
111
|
+
|
|
112
|
+
| Orange
|
|
113
|
+
>| $0.80
|
|
114
|
+
| A round fruit with dimpled bright orange rind
|
|
115
|
+
|
|
116
|
+
**Country of origin**
|
|
117
|
+
|
|
118
|
+
1. Brazil
|
|
119
|
+
2. India
|
|
120
|
+
3. China
|
|
121
|
+
|
|
122
|
+
| Nutrient | Per 100 g |
|
|
123
|
+
|-----------|------------|
|
|
124
|
+
| Calories | 47 kcal |
|
|
125
|
+
| Vitamin C | 53.2 mg |
|
|
126
|
+
| Sugar | 9.0 g |
|
|
127
|
+
```
|
|
128
|
+
``````
|
|
129
|
+
|
|
130
|
+
<table class="products-list">
|
|
131
|
+
<colgroup>
|
|
132
|
+
<col style="width: 12%">
|
|
133
|
+
<col style="width: 12%">
|
|
134
|
+
<col style="width: 12%">
|
|
135
|
+
<col style="width: 64%">
|
|
136
|
+
</colgroup>
|
|
137
|
+
<thead>
|
|
138
|
+
<tr>
|
|
139
|
+
<th style="text-align: center">Category</th>
|
|
140
|
+
<th style="text-align: center">Item Name</th>
|
|
141
|
+
<th style="text-align: center">Price</th>
|
|
142
|
+
<th style="text-align: center">Description</th>
|
|
143
|
+
</tr>
|
|
144
|
+
</thead>
|
|
145
|
+
<tbody>
|
|
146
|
+
<tr>
|
|
147
|
+
<td rowspan="3">Fruits</td>
|
|
148
|
+
<td>Apple</td>
|
|
149
|
+
<td style="text-align: right">$1.00</td>
|
|
150
|
+
<td>A smooth, round fruit with shiny red skin.</td>
|
|
151
|
+
</tr>
|
|
152
|
+
<tr>
|
|
153
|
+
<td>Banana</td>
|
|
154
|
+
<td style="text-align: right">$0.50</td>
|
|
155
|
+
<td>A long, curved fruit with yellow peel</td>
|
|
156
|
+
</tr>
|
|
157
|
+
<tr>
|
|
158
|
+
<td>Orange</td>
|
|
159
|
+
<td style="text-align: right">$0.80</td>
|
|
160
|
+
<td>
|
|
161
|
+
<p>A round fruit with dimpled bright orange rind</p>
|
|
162
|
+
<p><strong>Country of origin</strong></p>
|
|
163
|
+
<ol>
|
|
164
|
+
<li>Brazil</li>
|
|
165
|
+
<li>India</li>
|
|
166
|
+
<li>China</li>
|
|
167
|
+
</ol>
|
|
168
|
+
<table>
|
|
169
|
+
<thead>
|
|
170
|
+
<tr>
|
|
171
|
+
<th>Nutrient</th>
|
|
172
|
+
<th>Per 100 g</th>
|
|
173
|
+
</tr>
|
|
174
|
+
</thead>
|
|
175
|
+
<tbody>
|
|
176
|
+
<tr>
|
|
177
|
+
<td>Calories</td>
|
|
178
|
+
<td>47 kcal</td>
|
|
179
|
+
</tr>
|
|
180
|
+
<tr>
|
|
181
|
+
<td>Vitamin C</td>
|
|
182
|
+
<td>53.2 mg</td>
|
|
183
|
+
</tr>
|
|
184
|
+
<tr>
|
|
185
|
+
<td>Sugar</td>
|
|
186
|
+
<td>9.0 g</td>
|
|
187
|
+
</tr>
|
|
188
|
+
</tbody>
|
|
189
|
+
</table>
|
|
190
|
+
</td>
|
|
191
|
+
</tr>
|
|
192
|
+
</tbody>
|
|
193
|
+
</table>
|
package/dist/table-builder.js
CHANGED
|
@@ -23,8 +23,8 @@ export class TableBuilder {
|
|
|
23
23
|
}
|
|
24
24
|
startTable() {
|
|
25
25
|
const token = this.state.push("table_open", "table", 1);
|
|
26
|
-
this.tableSpec.
|
|
27
|
-
token.attrJoin("class",
|
|
26
|
+
this.tableSpec.classes.forEach(name => {
|
|
27
|
+
token.attrJoin("class", name);
|
|
28
28
|
});
|
|
29
29
|
if (this.tableSpec.attr["caption"] !== undefined) {
|
|
30
30
|
this.setCaption(this.tableSpec.attr["caption"]);
|
|
@@ -52,7 +52,7 @@ export class TableBuilder {
|
|
|
52
52
|
|| row < this.tableSpec.headerRows
|
|
53
53
|
|| col < this.tableSpec.headerCols ? "th" : "td";
|
|
54
54
|
if (isRowFirst) {
|
|
55
|
-
if (this.useTHead && row
|
|
55
|
+
if (this.useTHead && row === 0) {
|
|
56
56
|
this.startTHead();
|
|
57
57
|
}
|
|
58
58
|
else if (this.useTBody && row === this.tableSpec.headerRows) {
|
package/dist/table.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
type HAlign = "left" | "center" | "right";
|
|
2
|
-
type TableAttrKeys = "cols" | "
|
|
2
|
+
type TableAttrKeys = "cols" | "class" | "header-rows" | "header-cols" | "format";
|
|
3
3
|
export type TableAttr = {
|
|
4
4
|
[key in TableAttrKeys]?: string;
|
|
5
5
|
} & {
|
|
@@ -20,13 +20,13 @@ export type CellAttr = {
|
|
|
20
20
|
*/
|
|
21
21
|
export declare class TableSpec {
|
|
22
22
|
readonly attr: TableAttr;
|
|
23
|
-
readonly
|
|
23
|
+
readonly classes: string[];
|
|
24
24
|
readonly headerRows: number;
|
|
25
25
|
readonly headerCols: number;
|
|
26
26
|
readonly colspecs: ColSpecs;
|
|
27
27
|
constructor(attr: TableAttr);
|
|
28
28
|
get numCols(): number;
|
|
29
|
-
static
|
|
29
|
+
static parseClass(classnames: string): string[];
|
|
30
30
|
static parseInfoString(info: string): TableAttr;
|
|
31
31
|
static awareKeys(): TableAttrKeys[];
|
|
32
32
|
}
|
|
@@ -52,6 +52,8 @@ export declare class TableCell {
|
|
|
52
52
|
constructor(row: number, col: number, attr: CellAttr);
|
|
53
53
|
get colspan(): number;
|
|
54
54
|
get rowspan(): number;
|
|
55
|
+
get endcol(): number;
|
|
56
|
+
get endrow(): number;
|
|
55
57
|
is(row: number, col: number): boolean;
|
|
56
58
|
isIn(row: number, col: number, rspan: number, cspan: number): boolean;
|
|
57
59
|
contains(row: number, col: number): boolean;
|
package/dist/table.js
CHANGED
|
@@ -4,22 +4,26 @@ import { Lexer, unwrapLiteral } from "./lexer.js";
|
|
|
4
4
|
*/
|
|
5
5
|
export class TableSpec {
|
|
6
6
|
attr;
|
|
7
|
-
|
|
7
|
+
classes;
|
|
8
8
|
headerRows;
|
|
9
9
|
headerCols;
|
|
10
10
|
colspecs;
|
|
11
11
|
constructor(attr) {
|
|
12
12
|
this.attr = attr;
|
|
13
13
|
this.headerRows = parseInt(attr["header-rows"] ?? "0");
|
|
14
|
-
this.headerCols = parseInt(attr["header-
|
|
14
|
+
this.headerCols = parseInt(attr["header-cols"] ?? "0");
|
|
15
15
|
this.colspecs = new ColSpecs(attr.cols ?? "");
|
|
16
|
-
this.
|
|
16
|
+
this.classes = TableSpec.parseClass(attr.class ?? "");
|
|
17
17
|
}
|
|
18
18
|
get numCols() {
|
|
19
19
|
return this.colspecs.numCols;
|
|
20
20
|
}
|
|
21
|
-
static
|
|
22
|
-
return
|
|
21
|
+
static parseClass(classnames) {
|
|
22
|
+
return classnames
|
|
23
|
+
.split(",")
|
|
24
|
+
.map((s) => s.trim())
|
|
25
|
+
.filter(s => s.length > 0)
|
|
26
|
+
.filter((s, i, arr) => arr.indexOf(s) === i); // uniq
|
|
23
27
|
}
|
|
24
28
|
static parseInfoString(info) {
|
|
25
29
|
const lexer = new Lexer(info);
|
|
@@ -78,9 +82,9 @@ export class TableSpec {
|
|
|
78
82
|
const k = {
|
|
79
83
|
cols: "",
|
|
80
84
|
align: "",
|
|
81
|
-
"header-
|
|
85
|
+
"header-cols": "",
|
|
82
86
|
"header-rows": "",
|
|
83
|
-
|
|
87
|
+
class: "",
|
|
84
88
|
format: ""
|
|
85
89
|
};
|
|
86
90
|
return Object.keys(k);
|
|
@@ -185,6 +189,12 @@ export class TableCell {
|
|
|
185
189
|
get rowspan() {
|
|
186
190
|
return this.attr.rowspan || 1;
|
|
187
191
|
}
|
|
192
|
+
get endcol() {
|
|
193
|
+
return this.col + this.colspan - 1;
|
|
194
|
+
}
|
|
195
|
+
get endrow() {
|
|
196
|
+
return this.row + this.rowspan - 1;
|
|
197
|
+
}
|
|
188
198
|
is(row, col) {
|
|
189
199
|
return this.row === row && this.col === col;
|
|
190
200
|
}
|
|
@@ -370,8 +380,8 @@ export class CellState {
|
|
|
370
380
|
const span = this.spannedBy(row, col + 1);
|
|
371
381
|
// recursively check right cell
|
|
372
382
|
if (span !== undefined) {
|
|
373
|
-
if (span.
|
|
374
|
-
col = span.
|
|
383
|
+
if (span.endcol > col) {
|
|
384
|
+
col = span.endcol;
|
|
375
385
|
}
|
|
376
386
|
else {
|
|
377
387
|
throw new Error("never happen. check implementation");
|