@adobe/helix-markdown-support 3.1.8 → 4.0.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/.circleci/config.yml +8 -19
- package/.eslintrc.cjs +1 -0
- package/CHANGELOG.md +12 -0
- package/package.json +16 -7
- package/src/gridtable/README.md +207 -0
- package/src/gridtable/from-markdown.js +273 -0
- package/src/gridtable/index.js +91 -0
- package/src/gridtable/mdast2hast-handler.js +101 -0
- package/src/gridtable/remark-plugin.js +36 -0
- package/src/gridtable/syntax.js +352 -0
- package/src/gridtable/to-markdown.js +534 -0
- package/src/gridtable/types.js +17 -0
- package/src/index.js +2 -1
- package/src/{remark-matter → matter}/from-markdown.js +4 -3
- package/src/{remark-matter → matter}/index.js +2 -19
- package/src/matter/remark-plugin.js +31 -0
- package/src/{remark-matter → matter}/syntax.js +3 -2
- package/src/{remark-matter → matter}/to-markdown.js +3 -1
- package/src/matter/types.js +12 -0
- package/src/mdast-dereference.js +65 -0
- package/src/mdast-image-references.js +55 -0
- package/src/mdast-robust-tables.js +1 -1
package/.circleci/config.yml
CHANGED
|
@@ -1,35 +1,26 @@
|
|
|
1
1
|
version: 2.1
|
|
2
2
|
executors:
|
|
3
|
-
|
|
3
|
+
node16:
|
|
4
4
|
docker:
|
|
5
|
-
- image:
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
- image: cimg/node:16.16
|
|
6
|
+
|
|
7
|
+
orbs:
|
|
8
|
+
codecov: codecov/codecov@3.2.3
|
|
8
9
|
|
|
9
10
|
commands:
|
|
10
11
|
setup:
|
|
11
12
|
steps:
|
|
12
13
|
- checkout
|
|
13
|
-
- restore_cache:
|
|
14
|
-
keys:
|
|
15
|
-
- v1-dependencies-{{ arch }}-{{ checksum "package-lock.json" }}
|
|
16
|
-
- run:
|
|
17
|
-
name: install latest npm
|
|
18
|
-
command: sudo npm -g install npm
|
|
19
14
|
- run:
|
|
20
15
|
name: Installing Dependencies
|
|
21
16
|
command: npm ci
|
|
22
|
-
- save_cache:
|
|
23
|
-
paths:
|
|
24
|
-
- node_modules
|
|
25
|
-
key: v1-dependencies-{{ arch }}-{{ checksum "package-lock.json" }}
|
|
26
17
|
- run:
|
|
27
18
|
name: prepare test git user
|
|
28
19
|
command: git config --global user.email "circleci@example.com" && git config --global user.name "CircleCi Build"
|
|
29
20
|
|
|
30
21
|
jobs:
|
|
31
22
|
build:
|
|
32
|
-
executor:
|
|
23
|
+
executor: node16
|
|
33
24
|
|
|
34
25
|
steps:
|
|
35
26
|
- setup
|
|
@@ -37,14 +28,12 @@ jobs:
|
|
|
37
28
|
- run:
|
|
38
29
|
name: Lint
|
|
39
30
|
command: npm run lint
|
|
40
|
-
|
|
41
31
|
- run:
|
|
42
32
|
name: Getting Code Coverage
|
|
43
|
-
command: npm run test
|
|
44
|
-
|
|
33
|
+
command: npm run test
|
|
34
|
+
- codecov/upload
|
|
45
35
|
- store_test_results:
|
|
46
36
|
path: junit
|
|
47
|
-
|
|
48
37
|
- store_artifacts:
|
|
49
38
|
path: junit
|
|
50
39
|
|
package/.eslintrc.cjs
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
# [4.0.0](https://github.com/adobe/helix-markdown-support/compare/v3.1.8...v4.0.0) (2022-09-02)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* markdown gridtables ([1f3d7d2](https://github.com/adobe/helix-markdown-support/commit/1f3d7d27045c3d31556c73b2631fc7b1b910ef46))
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### BREAKING CHANGES
|
|
10
|
+
|
|
11
|
+
* the remarkMatter plugin export changed.
|
|
12
|
+
|
|
1
13
|
## [3.1.8](https://github.com/adobe/helix-markdown-support/compare/v3.1.7...v3.1.8) (2022-07-28)
|
|
2
14
|
|
|
3
15
|
|
package/package.json
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adobe/helix-markdown-support",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "Helix Markdown Support",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"test": "c8 mocha",
|
|
8
|
-
"test-ci": "c8 mocha && codecov",
|
|
9
8
|
"lint": "eslint .",
|
|
10
9
|
"semantic-release": "semantic-release",
|
|
11
10
|
"prepare": "husky install"
|
|
@@ -21,14 +20,21 @@
|
|
|
21
20
|
},
|
|
22
21
|
"homepage": "https://github.com/adobe/helix-markdown-support#readme",
|
|
23
22
|
"main": "src/index.js",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": "./src/index.js",
|
|
25
|
+
"./gridtable": "./src/gridtable/index.js",
|
|
26
|
+
"./matter": "./src/matter/index.js"
|
|
27
|
+
},
|
|
24
28
|
"dependencies": {
|
|
25
29
|
"hast-util-to-html": "8.0.3",
|
|
26
30
|
"js-yaml": "4.1.0",
|
|
27
|
-
"mdast-util-
|
|
31
|
+
"mdast-util-from-markdown": "1.2.0",
|
|
32
|
+
"mdast-util-to-hast": "12.2.1",
|
|
33
|
+
"mdast-util-to-markdown": "1.3.0",
|
|
28
34
|
"micromark-util-character": "1.1.0",
|
|
29
35
|
"micromark-util-symbol": "1.0.1",
|
|
30
36
|
"unist-util-find": "1.0.2",
|
|
31
|
-
"unist-util-visit": "4.1.
|
|
37
|
+
"unist-util-visit": "4.1.1"
|
|
32
38
|
},
|
|
33
39
|
"mocha": {
|
|
34
40
|
"spec": "test/**/*.test.js",
|
|
@@ -40,13 +46,15 @@
|
|
|
40
46
|
"peerDependencies": {
|
|
41
47
|
"unified": "10.x"
|
|
42
48
|
},
|
|
49
|
+
"engines": {
|
|
50
|
+
"node": ">=14"
|
|
51
|
+
},
|
|
43
52
|
"devDependencies": {
|
|
44
53
|
"@adobe/eslint-config-helix": "1.3.2",
|
|
45
54
|
"@semantic-release/changelog": "6.0.1",
|
|
46
55
|
"@semantic-release/git": "10.0.1",
|
|
47
56
|
"c8": "7.12.0",
|
|
48
|
-
"
|
|
49
|
-
"eslint": "8.20.0",
|
|
57
|
+
"eslint": "8.23.0",
|
|
50
58
|
"eslint-plugin-header": "3.1.1",
|
|
51
59
|
"eslint-plugin-import": "2.26.0",
|
|
52
60
|
"husky": "8.0.1",
|
|
@@ -55,10 +63,11 @@
|
|
|
55
63
|
"mdast-builder": "1.1.1",
|
|
56
64
|
"mocha": "10.0.0",
|
|
57
65
|
"mocha-multi-reporters": "1.5.1",
|
|
66
|
+
"rehype-format": "4.0.1",
|
|
58
67
|
"remark-gfm": "3.0.1",
|
|
59
68
|
"remark-parse": "10.0.1",
|
|
60
69
|
"remark-stringify": "10.0.2",
|
|
61
|
-
"semantic-release": "19.0.
|
|
70
|
+
"semantic-release": "19.0.5",
|
|
62
71
|
"unified": "10.1.2",
|
|
63
72
|
"unist-util-inspect": "7.0.1"
|
|
64
73
|
},
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# Grid Tables
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
GridTables look like this:
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
+-------------------+------+
|
|
9
|
+
| Table Headings | Here |
|
|
10
|
+
+--------+----------+------+
|
|
11
|
+
| Sub | Headings | Too |
|
|
12
|
+
+========+=================+
|
|
13
|
+
| cell | column spanning |
|
|
14
|
+
| spans +---------:+------+
|
|
15
|
+
| rows | normal | cell |
|
|
16
|
+
+---v----+:---------------:+
|
|
17
|
+
| | cells can be |
|
|
18
|
+
| | *formatted* |
|
|
19
|
+
| | **paragraphs** |
|
|
20
|
+
| | ``` |
|
|
21
|
+
| multi | and contain |
|
|
22
|
+
| line | blocks |
|
|
23
|
+
| cells | ``` |
|
|
24
|
+
+========+=========<+======+
|
|
25
|
+
| footer | cells | |
|
|
26
|
+
+--------+----------+------+
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
- the top of a cell must be indicated by `+-` followed by some `-` or `+` and finished by `-+`.
|
|
30
|
+
- if the table contains a footer but no header, the top row should use `=` as grid line.
|
|
31
|
+
- col spans are indicated by missing column (`|`) delimiters
|
|
32
|
+
- row spans are indicated by missing row (`-`) delimiters
|
|
33
|
+
- cells can be left, center, right, or justify aligned; indicated by the placement of `:` or `><`
|
|
34
|
+
- cells can be top, middle, or bottom v-aligned; indicated by the placement of arrows (`v` `^` `x`)
|
|
35
|
+
- the header and footer sections are delimited by section delimiters (`=`).
|
|
36
|
+
- if no section delimiters are present, all cells are placed in the table body.
|
|
37
|
+
- if only 1 section delimiter is present, it delimits header from body.
|
|
38
|
+
- the content in cells can be a full Markdown document again. note, that the cell boundaries (`|`)
|
|
39
|
+
need to exactly match with the column markers (`+`) in the row delimiters, if the cell content
|
|
40
|
+
contains `|`, otherwise the correct layout of the table can't be guaranteed.
|
|
41
|
+
|
|
42
|
+
Layout
|
|
43
|
+
======
|
|
44
|
+
|
|
45
|
+
The table layout tries to keep the table within a certain width (default 120). For example,
|
|
46
|
+
if the table has 3 columns, each column will be max 40 characters wide. If all text in a column
|
|
47
|
+
is smaller, it will shrink the columns. However, cells have a minimum width (default 10) when
|
|
48
|
+
text needs to be broken. If the cell contents need more space, e.g. with a nested table or
|
|
49
|
+
code block, it will grow accordingly.
|
|
50
|
+
|
|
51
|
+
Align
|
|
52
|
+
=====
|
|
53
|
+
|
|
54
|
+
Horizontal align is indicated by placing markers at the grid line above the cell:
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
Justify Center Left Right
|
|
58
|
+
+>-----<+ +:-----:+ +:------+ +------:+
|
|
59
|
+
| A b C | | ABC | | ABC | | ABC |
|
|
60
|
+
+-------+ +-------+ +-------+ +-------+
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Vertical align is indicated by placing markers at the center of the grid line above the cell:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
Top Middle Bottom
|
|
67
|
+
+---^---+ +---x---+ +---v---+
|
|
68
|
+
| Larum | | | | |
|
|
69
|
+
| Ipsum | | Larum | | |
|
|
70
|
+
| | | Ipsum | | Larum |
|
|
71
|
+
| | | | | Ipsum |
|
|
72
|
+
+-------+ +-------+ +-------+
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Syntax
|
|
76
|
+
|
|
77
|
+
```ebfn
|
|
78
|
+
|
|
79
|
+
gridTable := gridLine cellLine+ gridLine;
|
|
80
|
+
gridLine := gridCell+ "+";
|
|
81
|
+
cellLine := ( gridCell | cellContent )+ ( "+" | "|" );
|
|
82
|
+
gridCell := "+" alignMarkerStart? ("-" | "=")+ vAlignMarker? ("-" | "=")* alignMarkerEnd?;
|
|
83
|
+
cellContent := ( "+" | "|" ) " " content " " ;
|
|
84
|
+
alignMarkerStart := ":" | ">";
|
|
85
|
+
alignMarkerEnd := ":" | "<";
|
|
86
|
+
vAlignMarker := "^" | "v" | "x"
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## MDAST Syntax tree
|
|
90
|
+
|
|
91
|
+
The following interfaces are added to **[mdast][]** by this utility.
|
|
92
|
+
|
|
93
|
+
### Nodes
|
|
94
|
+
|
|
95
|
+
#### `GridTable`
|
|
96
|
+
|
|
97
|
+
```idl
|
|
98
|
+
interface GridTable <: Parent {
|
|
99
|
+
type: "gridTable"
|
|
100
|
+
children: [GridTableHeader|GridTableBody|GridTableFooter]
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
#### `GridTableHeader`
|
|
105
|
+
|
|
106
|
+
```idl
|
|
107
|
+
interface GridTableHeader <: Parent {
|
|
108
|
+
type: "gtHead"
|
|
109
|
+
children: [GridTableRow]
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
#### `GridTableBody`
|
|
114
|
+
|
|
115
|
+
```idl
|
|
116
|
+
interface GridTableBody <: Parent {
|
|
117
|
+
type: "gtBody"
|
|
118
|
+
children: [GridTableRow]
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
#### `GridTableFoot`
|
|
123
|
+
|
|
124
|
+
```idl
|
|
125
|
+
interface GridTableFooter <: Parent {
|
|
126
|
+
type: "gtFoot"
|
|
127
|
+
children: [GridTableRow]
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
#### `GridTableRow`
|
|
132
|
+
|
|
133
|
+
```idl
|
|
134
|
+
interface GridTableRow <: Parent {
|
|
135
|
+
type: "gtRow"
|
|
136
|
+
children: [GridTableCell]
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
#### `GridTableCell`
|
|
141
|
+
|
|
142
|
+
```idl
|
|
143
|
+
interface GridTableCell <: Parent {
|
|
144
|
+
type: "gtCell"
|
|
145
|
+
colSpan: number >= 1
|
|
146
|
+
rowSpan: number >= 1
|
|
147
|
+
align: alignType
|
|
148
|
+
valign: valignType
|
|
149
|
+
children: [MdastContent]
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
**GridTableCell** ([**Parent**][dfn-parent]) represents a header cell in a
|
|
154
|
+
[**GridTable**][dfn-table], if its parent is a [*gridTableHead*][term-head], or a data
|
|
155
|
+
cell otherwise.
|
|
156
|
+
|
|
157
|
+
**GridTableCell** can be used where [**gridTableRow**][dfn-row-content] content is expected.
|
|
158
|
+
Its content model is [**mdast**][dfn-phrasing-content] content, allowing full mdast documents.
|
|
159
|
+
|
|
160
|
+
### Enumeration
|
|
161
|
+
|
|
162
|
+
#### `alignType`
|
|
163
|
+
|
|
164
|
+
```idl
|
|
165
|
+
enum alignType {
|
|
166
|
+
"left" | "right" | "center" | "justify" | null
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
#### `valignType`
|
|
171
|
+
|
|
172
|
+
```idl
|
|
173
|
+
enum alignType {
|
|
174
|
+
"top" | "bottom" | "middle" | null
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Usage
|
|
179
|
+
|
|
180
|
+
### Parsing with unified
|
|
181
|
+
|
|
182
|
+
```js
|
|
183
|
+
import { unified } from 'unified';
|
|
184
|
+
import remarkParse from 'remark-parse';
|
|
185
|
+
import { remarkGridTable } from '@adobe/helix-markdown-support/gridtable';
|
|
186
|
+
|
|
187
|
+
const mdast = unified()
|
|
188
|
+
.use(remarkParse)
|
|
189
|
+
.use(remarkGridTable)
|
|
190
|
+
.parse(markdown);
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Generating HAST
|
|
194
|
+
|
|
195
|
+
```js
|
|
196
|
+
import { toHast, defaultHandlers } from 'mdast-util-to-hast';
|
|
197
|
+
import { mdast2hastGridTableHandler, TYPE_TABLE } from '@adobe/helix-markdown-support/gridtable';
|
|
198
|
+
|
|
199
|
+
const hast = toHast(mdast, {
|
|
200
|
+
handlers: {
|
|
201
|
+
...defaultHandlers,
|
|
202
|
+
[TYPE_TABLE]: mdast2hastGridTableHandler(),
|
|
203
|
+
},
|
|
204
|
+
allowDangerousHtml: true,
|
|
205
|
+
});
|
|
206
|
+
```
|
|
207
|
+
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2022 Adobe. All rights reserved.
|
|
3
|
+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
*
|
|
7
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
* governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
/* eslint-disable no-underscore-dangle */
|
|
13
|
+
import { fromMarkdown } from 'mdast-util-from-markdown';
|
|
14
|
+
import { CONTINUE, visit } from 'unist-util-visit';
|
|
15
|
+
import {
|
|
16
|
+
TYPE_BODY, TYPE_CELL, TYPE_HEADER, TYPE_FOOTER, TYPE_ROW, TYPE_TABLE,
|
|
17
|
+
} from './types.js';
|
|
18
|
+
|
|
19
|
+
function unescapeDelimsInCode(tree) {
|
|
20
|
+
visit(tree, (node) => {
|
|
21
|
+
if (node.type === 'inlineCode' || node.type === 'code') {
|
|
22
|
+
// eslint-disable-next-line no-param-reassign
|
|
23
|
+
node.value = node.value.replace(/\\([+|])/gm, '$1');
|
|
24
|
+
}
|
|
25
|
+
return CONTINUE;
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function multiline(lines) {
|
|
30
|
+
// remove empty trailing lines
|
|
31
|
+
while (lines.length > 0 && lines[lines.length - 1].match(/^\s*$/)) {
|
|
32
|
+
lines.pop();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// calculate common indent
|
|
36
|
+
const prefixLen = lines
|
|
37
|
+
.filter((line) => !line.match(/^\s*$/))
|
|
38
|
+
.map((line) => line.match(/^ */)[0].length)
|
|
39
|
+
.reduce((min, len) => Math.min(len, min), Infinity);
|
|
40
|
+
|
|
41
|
+
// remove prefix
|
|
42
|
+
return lines
|
|
43
|
+
.map((line) => line.substring(prefixLen).trimEnd());
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function getColSpan(info, token) {
|
|
47
|
+
const i0 = info.cols.indexOf(token._colStart);
|
|
48
|
+
const i1 = info.cols.indexOf(token._colEnd);
|
|
49
|
+
return i1 - i0;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function enterTable(token) {
|
|
53
|
+
this.enter({ type: TYPE_TABLE, children: [] }, token);
|
|
54
|
+
this.setData('tableInfo', {
|
|
55
|
+
// the column positions of the table
|
|
56
|
+
cols: token._cols,
|
|
57
|
+
// the current column
|
|
58
|
+
colPos: 0,
|
|
59
|
+
// list of all cells
|
|
60
|
+
allCells: [],
|
|
61
|
+
// cells that are still open via rowSpan
|
|
62
|
+
pendingCells: [],
|
|
63
|
+
// the current cells of a row
|
|
64
|
+
cells: [],
|
|
65
|
+
// the grid dividers use for align the cells
|
|
66
|
+
dividers: [],
|
|
67
|
+
// the link/image reference definitions
|
|
68
|
+
definitions: token._definitions,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function createExitTable(options) {
|
|
73
|
+
const { processor } = options;
|
|
74
|
+
|
|
75
|
+
return function exitTable(token) {
|
|
76
|
+
// render cells
|
|
77
|
+
const info = this.getData('tableInfo');
|
|
78
|
+
for (const cell of info.allCells) {
|
|
79
|
+
const {
|
|
80
|
+
node, lines, colSpan, rowSpan,
|
|
81
|
+
align, valign,
|
|
82
|
+
} = cell;
|
|
83
|
+
|
|
84
|
+
// add fake definitions...
|
|
85
|
+
const sanitizedLines = multiline(lines);
|
|
86
|
+
for (const def of info.definitions) {
|
|
87
|
+
sanitizedLines.push('');
|
|
88
|
+
sanitizedLines.push(`[${def}]: dummy`);
|
|
89
|
+
}
|
|
90
|
+
const cellContent = sanitizedLines.join('\n');
|
|
91
|
+
|
|
92
|
+
const tree = fromMarkdown(cellContent, {
|
|
93
|
+
extensions: processor.data('micromarkExtensions'),
|
|
94
|
+
mdastExtensions: processor.data('fromMarkdownExtensions'),
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// remove previously added definitions
|
|
98
|
+
for (let i = 0; i < tree.children.length; i += 1) {
|
|
99
|
+
const child = tree.children[i];
|
|
100
|
+
if (child.type === 'definition' && info.definitions.includes(child.label)) {
|
|
101
|
+
tree.children.splice(i, 1);
|
|
102
|
+
i -= 1;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// remove escaped pipes and plusses in code
|
|
107
|
+
unescapeDelimsInCode(tree);
|
|
108
|
+
|
|
109
|
+
node.children = tree.children;
|
|
110
|
+
if (colSpan > 1) {
|
|
111
|
+
node.colSpan = colSpan;
|
|
112
|
+
}
|
|
113
|
+
if (rowSpan > 1) {
|
|
114
|
+
node.rowSpan = rowSpan;
|
|
115
|
+
}
|
|
116
|
+
if (align) {
|
|
117
|
+
node.align = align;
|
|
118
|
+
}
|
|
119
|
+
if (valign) {
|
|
120
|
+
node.valign = valign;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
this.exit(token);
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function enter(token) {
|
|
128
|
+
this.enter({ type: token.type, children: [] }, token);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function enterCell() {
|
|
132
|
+
this.buffer();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function exitCell(token) {
|
|
136
|
+
this.config.enter.data.call(this, token);
|
|
137
|
+
this.config.exit.data.call(this, token);
|
|
138
|
+
const data = this.resume();
|
|
139
|
+
const info = this.getData('tableInfo');
|
|
140
|
+
const colSpan = getColSpan(info, token);
|
|
141
|
+
|
|
142
|
+
let cell = info.pendingCells[info.colPos];
|
|
143
|
+
|
|
144
|
+
// open rowspan if we are on a divider line
|
|
145
|
+
if (info.isDivider) {
|
|
146
|
+
if (!cell) {
|
|
147
|
+
cell = info.cells[info.colPos];
|
|
148
|
+
info.pendingCells[info.colPos] = cell;
|
|
149
|
+
}
|
|
150
|
+
if (!cell) {
|
|
151
|
+
// throw Error('no matching rowspan');
|
|
152
|
+
} else {
|
|
153
|
+
cell.rowSpan += 1;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// if a rowspan is open, append to its cell
|
|
158
|
+
if (cell) {
|
|
159
|
+
cell.lines.push(data);
|
|
160
|
+
info.colPos += colSpan;
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// otherwise append to regular cell
|
|
165
|
+
cell = info.cells[info.colPos];
|
|
166
|
+
if (!cell) {
|
|
167
|
+
const div = info.dividers[info.colPos];
|
|
168
|
+
cell = {
|
|
169
|
+
rowSpan: 1,
|
|
170
|
+
colSpan,
|
|
171
|
+
align: div?._align,
|
|
172
|
+
valign: div?._valign,
|
|
173
|
+
node: {
|
|
174
|
+
type: TYPE_CELL,
|
|
175
|
+
},
|
|
176
|
+
lines: [],
|
|
177
|
+
};
|
|
178
|
+
info.cells[info.colPos] = cell;
|
|
179
|
+
info.allCells.push(cell);
|
|
180
|
+
}
|
|
181
|
+
cell.lines.push(data);
|
|
182
|
+
info.colPos += colSpan;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function enterGridDivider(token) {
|
|
186
|
+
const info = this.getData('tableInfo');
|
|
187
|
+
// clear pending rowspans and set divider info
|
|
188
|
+
let colSpan = getColSpan(info, token);
|
|
189
|
+
while (colSpan > 0) {
|
|
190
|
+
colSpan -= 1;
|
|
191
|
+
info.pendingCells[info.colPos] = null;
|
|
192
|
+
info.dividers[info.colPos] = token;
|
|
193
|
+
info.colPos += 1;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function enterRowLine(token) {
|
|
198
|
+
const info = this.getData('tableInfo');
|
|
199
|
+
info.isDivider = token._type;
|
|
200
|
+
info.colPos = 0;
|
|
201
|
+
if (info.isDivider) {
|
|
202
|
+
info.dividers = [];
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function commitRow(info) {
|
|
207
|
+
// create fake token for 'gtRow'
|
|
208
|
+
const rowToken = {
|
|
209
|
+
type: TYPE_ROW,
|
|
210
|
+
start: { line: 0, column: 0, offset: 0 },
|
|
211
|
+
end: { line: 0, column: 0, offset: 0 },
|
|
212
|
+
};
|
|
213
|
+
this.enter({ type: TYPE_ROW, children: [] }, rowToken);
|
|
214
|
+
|
|
215
|
+
// emit cells
|
|
216
|
+
for (const cell of info.cells) {
|
|
217
|
+
if (cell) {
|
|
218
|
+
const cellToken = {
|
|
219
|
+
type: TYPE_CELL,
|
|
220
|
+
start: { line: 0, column: 0, offset: 0 },
|
|
221
|
+
end: { line: 0, column: 0, offset: 0 },
|
|
222
|
+
};
|
|
223
|
+
this.enter(cell.node, cellToken);
|
|
224
|
+
this.exit(cellToken);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
this.exit(rowToken);
|
|
229
|
+
// eslint-disable-next-line no-param-reassign
|
|
230
|
+
info.cells = [];
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function exitHeader(token) {
|
|
234
|
+
const info = this.getData('tableInfo');
|
|
235
|
+
// commit row has some cells
|
|
236
|
+
if (info.cells.length) {
|
|
237
|
+
commitRow.call(this, info);
|
|
238
|
+
// also close all rowspans.
|
|
239
|
+
info.pendingCells = [];
|
|
240
|
+
}
|
|
241
|
+
this.exit(token);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function exitRowLine() {
|
|
245
|
+
const info = this.getData('tableInfo');
|
|
246
|
+
// commit row if on a divider and has some cells
|
|
247
|
+
if (info.isDivider && info.cells.length) {
|
|
248
|
+
commitRow.call(this, info);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// eslint-disable-next-line no-unused-vars
|
|
253
|
+
export default function handler(options = {}) {
|
|
254
|
+
return {
|
|
255
|
+
enter: {
|
|
256
|
+
[TYPE_TABLE]: enterTable,
|
|
257
|
+
[TYPE_HEADER]: enter,
|
|
258
|
+
[TYPE_BODY]: enter,
|
|
259
|
+
[TYPE_FOOTER]: enter,
|
|
260
|
+
[TYPE_CELL]: enterCell,
|
|
261
|
+
gridDivider: enterGridDivider,
|
|
262
|
+
rowLine: enterRowLine,
|
|
263
|
+
},
|
|
264
|
+
exit: {
|
|
265
|
+
[TYPE_TABLE]: createExitTable(options),
|
|
266
|
+
[TYPE_HEADER]: exitHeader,
|
|
267
|
+
[TYPE_BODY]: exitHeader,
|
|
268
|
+
[TYPE_FOOTER]: exitHeader,
|
|
269
|
+
[TYPE_CELL]: exitCell,
|
|
270
|
+
rowLine: exitRowLine,
|
|
271
|
+
},
|
|
272
|
+
};
|
|
273
|
+
}
|