@yozora/tokenizer-table 1.2.2 → 2.0.0-alpha.2

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 CHANGED
@@ -84,14 +84,14 @@ so you can use `YozoraParser` / `GfmExParser` directly.
84
84
  registered in *YastParser* as a plugin-in before it can be used.
85
85
 
86
86
  ```typescript {4,9}
87
- import { DefaultYastParser } from '@yozora/core-parser'
87
+ import { DefaultParser } from '@yozora/core-parser'
88
88
  import ParagraphTokenizer from '@yozora/tokenizer-paragraph'
89
89
  import TextTokenizer from '@yozora/tokenizer-text'
90
90
  import TableTokenizer from '@yozora/tokenizer-table'
91
91
 
92
- const parser = new DefaultYastParser()
93
- .useBlockFallbackTokenizer(new ParagraphTokenizer())
94
- .useInlineFallbackTokenizer(new TextTokenizer())
92
+ const parser = new DefaultParser()
93
+ .useFallbackTokenizer(new ParagraphTokenizer())
94
+ .useFallbackTokenizer(new TextTokenizer())
95
95
  .useTokenizer(new TableTokenizer())
96
96
 
97
97
  // parse source markdown content
@@ -227,7 +227,6 @@ Name | Type | Required | Default
227
227
  [@yozora/tokenizer-link]: https://github.com/yozorajs/yozora/tree/main/tokenizers/link#readme
228
228
  [@yozora/tokenizer-link-reference]: https://github.com/yozorajs/yozora/tree/main/tokenizers/link-reference#readme
229
229
  [@yozora/tokenizer-list]: https://github.com/yozorajs/yozora/tree/main/tokenizers/list#readme
230
- [@yozora/tokenizer-list-item]: https://github.com/yozorajs/yozora/tree/main/tokenizers/list-item#readme
231
230
  [@yozora/tokenizer-math]: https://github.com/yozorajs/yozora/tree/main/tokenizers/math#readme
232
231
  [@yozora/tokenizer-paragraph]: https://github.com/yozorajs/yozora/tree/main/tokenizers/paragraph#readme
233
232
  [@yozora/tokenizer-setext-heading]: https://github.com/yozorajs/yozora/tree/main/tokenizers/setext-heading#readme
@@ -287,7 +286,6 @@ Name | Type | Required | Default
287
286
  [doc-@yozora/tokenizer-definition]: https://yozora.guanghechen.com/docs/package/tokenizer-definition
288
287
  [doc-@yozora/tokenizer-link-reference]: https://yozora.guanghechen.com/docs/package/tokenizer-link-reference
289
288
  [doc-@yozora/tokenizer-list]: https://yozora.guanghechen.com/docs/package/tokenizer-list
290
- [doc-@yozora/tokenizer-list-item]: https://yozora.guanghechen.com/docs/package/tokenizer-list-item
291
289
  [doc-@yozora/tokenizer-math]: https://yozora.guanghechen.com/docs/package/tokenizer-math
292
290
  [doc-@yozora/tokenizer-paragraph]: https://yozora.guanghechen.com/docs/package/tokenizer-paragraph
293
291
  [doc-@yozora/tokenizer-setext-heading]: https://yozora.guanghechen.com/docs/package/tokenizer-setext-heading
package/lib/cjs/index.js CHANGED
@@ -6,21 +6,18 @@ var ast = require('@yozora/ast');
6
6
  var character = require('@yozora/character');
7
7
  var coreTokenizer = require('@yozora/core-tokenizer');
8
8
 
9
- const uniqueName = '@yozora/tokenizer-table';
10
-
11
- class TableTokenizer extends coreTokenizer.BaseBlockTokenizer {
12
- constructor(props = {}) {
13
- var _a, _b;
14
- super({
15
- name: (_a = props.name) !== null && _a !== void 0 ? _a : uniqueName,
16
- priority: (_b = props.priority) !== null && _b !== void 0 ? _b : coreTokenizer.TokenizerPriority.INTERRUPTABLE_BLOCK,
17
- });
18
- this.isContainingBlock = false;
19
- }
20
- eatOpener() {
9
+ const match = function (api) {
10
+ const { name: _tokenizer } = this;
11
+ return {
12
+ isContainingBlock: false,
13
+ eatOpener,
14
+ eatAndInterruptPreviousSibling,
15
+ eatLazyContinuationText,
16
+ };
17
+ function eatOpener() {
21
18
  return null;
22
19
  }
23
- eatAndInterruptPreviousSibling(line, prevSiblingToken, parentToken, api) {
20
+ function eatAndInterruptPreviousSibling(line, prevSiblingToken) {
24
21
  if (line.countOfPrecedeSpaces >= 4)
25
22
  return null;
26
23
  const { nodePoints, endIndex, firstNonWhitespaceIndex } = line;
@@ -28,9 +25,7 @@ class TableTokenizer extends coreTokenizer.BaseBlockTokenizer {
28
25
  return null;
29
26
  const columns = [];
30
27
  let c = nodePoints[firstNonWhitespaceIndex].codePoint;
31
- let cIndex = c === character.AsciiCodePoint.VERTICAL_SLASH
32
- ? firstNonWhitespaceIndex + 1
33
- : firstNonWhitespaceIndex;
28
+ let cIndex = c === character.AsciiCodePoint.VERTICAL_SLASH ? firstNonWhitespaceIndex + 1 : firstNonWhitespaceIndex;
34
29
  for (; cIndex < endIndex;) {
35
30
  for (; cIndex < endIndex; ++cIndex) {
36
31
  c = nodePoints[cIndex].codePoint;
@@ -103,7 +98,7 @@ class TableTokenizer extends coreTokenizer.BaseBlockTokenizer {
103
98
  cellCount += 1;
104
99
  if (cellCount !== columns.length)
105
100
  return null;
106
- const row = this.calcTableRow(api, previousLine, columns);
101
+ const row = calcTableRow(previousLine, columns);
107
102
  const nextIndex = endIndex;
108
103
  const token = {
109
104
  nodeType: ast.TableType,
@@ -112,7 +107,7 @@ class TableTokenizer extends coreTokenizer.BaseBlockTokenizer {
112
107
  end: coreTokenizer.calcEndYastNodePoint(nodePoints, nextIndex - 1),
113
108
  },
114
109
  columns,
115
- children: [row],
110
+ rows: [row],
116
111
  };
117
112
  return {
118
113
  token,
@@ -120,149 +115,17 @@ class TableTokenizer extends coreTokenizer.BaseBlockTokenizer {
120
115
  remainingSibling: api.rollbackPhrasingLines(lines.slice(0, lines.length - 1), prevSiblingToken),
121
116
  };
122
117
  }
123
- eatLazyContinuationText(line, token, parentToken, api) {
118
+ function eatLazyContinuationText(line, token) {
124
119
  if (line.firstNonWhitespaceIndex >= line.endIndex) {
125
120
  return { status: 'notMatched' };
126
121
  }
127
- const tableToken = token;
128
- const row = this.calcTableRow(api, line, tableToken.columns);
122
+ const row = calcTableRow(line, token.columns);
129
123
  if (row == null)
130
124
  return { status: 'notMatched' };
131
- tableToken.children.push(row);
125
+ token.rows.push(row);
132
126
  return { status: 'opening', nextIndex: line.endIndex };
133
127
  }
134
- parseBlock(token, children, api) {
135
- let node;
136
- switch (token.nodeType) {
137
- case ast.TableType: {
138
- node = {
139
- type: ast.TableType,
140
- columns: token.columns,
141
- children: (children || []),
142
- };
143
- break;
144
- }
145
- case ast.TableRowType: {
146
- node = {
147
- type: ast.TableRowType,
148
- children: (children || []),
149
- };
150
- break;
151
- }
152
- case ast.TableCellType: {
153
- node = {
154
- type: ast.TableCellType,
155
- children: children,
156
- };
157
- for (const phrasingContent of node.children) {
158
- if (phrasingContent.type !== coreTokenizer.PhrasingContentType)
159
- continue;
160
- const nextContents = [];
161
- const endIndex = phrasingContent.contents.length;
162
- for (let i = 0; i < endIndex; ++i) {
163
- const p = phrasingContent.contents[i];
164
- if (p.codePoint === character.AsciiCodePoint.BACKSLASH && i + 1 < endIndex) {
165
- const q = phrasingContent.contents[i + 1];
166
- if (q.codePoint !== character.AsciiCodePoint.VERTICAL_SLASH)
167
- nextContents.push(p);
168
- nextContents.push(q);
169
- i += 1;
170
- continue;
171
- }
172
- nextContents.push(p);
173
- }
174
- phrasingContent.contents = nextContents;
175
- }
176
- break;
177
- }
178
- default:
179
- return null;
180
- }
181
- return node;
182
- }
183
- calcTableColumn(nodePoints, currentLine, previousLine) {
184
- if (previousLine.firstNonWhitespaceIndex >= previousLine.endIndex) {
185
- return null;
186
- }
187
- if (currentLine.firstNonWhitespaceIndex - currentLine.startIndex >= 4)
188
- return null;
189
- const columns = [];
190
- let p = nodePoints[currentLine.firstNonWhitespaceIndex];
191
- let cIndex = p.codePoint === character.AsciiCodePoint.VERTICAL_SLASH
192
- ? currentLine.firstNonWhitespaceIndex + 1
193
- : currentLine.firstNonWhitespaceIndex;
194
- for (; cIndex < currentLine.endIndex;) {
195
- for (; cIndex < currentLine.endIndex; ++cIndex) {
196
- p = nodePoints[cIndex];
197
- if (!character.isWhitespaceCharacter(p.codePoint))
198
- break;
199
- }
200
- if (cIndex >= currentLine.endIndex)
201
- break;
202
- let leftColon = false;
203
- if (p.codePoint === character.AsciiCodePoint.COLON) {
204
- leftColon = true;
205
- cIndex += 1;
206
- }
207
- let hyphenCount = 0;
208
- for (; cIndex < currentLine.endIndex; ++cIndex) {
209
- p = nodePoints[cIndex];
210
- if (p.codePoint !== character.AsciiCodePoint.MINUS_SIGN)
211
- break;
212
- hyphenCount += 1;
213
- }
214
- if (hyphenCount <= 0)
215
- return null;
216
- let rightColon = false;
217
- if (cIndex < currentLine.endIndex &&
218
- p.codePoint === character.AsciiCodePoint.COLON) {
219
- rightColon = true;
220
- cIndex += 1;
221
- }
222
- for (; cIndex < currentLine.endIndex; ++cIndex) {
223
- p = nodePoints[cIndex];
224
- if (character.isWhitespaceCharacter(p.codePoint))
225
- continue;
226
- if (p.codePoint === character.AsciiCodePoint.VERTICAL_SLASH) {
227
- cIndex += 1;
228
- break;
229
- }
230
- return null;
231
- }
232
- let align = null;
233
- if (leftColon && rightColon)
234
- align = 'center';
235
- else if (leftColon)
236
- align = 'left';
237
- else if (rightColon)
238
- align = 'right';
239
- const column = { align };
240
- columns.push(column);
241
- }
242
- if (columns.length <= 0)
243
- return null;
244
- let cellCount = 0, hasNonWhitespaceBeforePipe = false;
245
- for (let pIndex = previousLine.startIndex; pIndex < previousLine.endIndex; ++pIndex) {
246
- const p = nodePoints[pIndex];
247
- if (character.isWhitespaceCharacter(p.codePoint))
248
- continue;
249
- if (p.codePoint === character.AsciiCodePoint.VERTICAL_SLASH) {
250
- if (hasNonWhitespaceBeforePipe || cellCount > 0)
251
- cellCount += 1;
252
- hasNonWhitespaceBeforePipe = false;
253
- continue;
254
- }
255
- hasNonWhitespaceBeforePipe = true;
256
- if (p.codePoint === character.AsciiCodePoint.BACKSLASH)
257
- pIndex += 1;
258
- }
259
- if (hasNonWhitespaceBeforePipe && columns.length > 1)
260
- cellCount += 1;
261
- if (cellCount !== columns.length)
262
- return null;
263
- return columns;
264
- }
265
- calcTableRow(api, line, columns) {
128
+ function calcTableRow(line, columns) {
266
129
  const { nodePoints, startIndex, endIndex, firstNonWhitespaceIndex } = line;
267
130
  let p = nodePoints[firstNonWhitespaceIndex];
268
131
  let i = p.codePoint === character.AsciiCodePoint.VERTICAL_SLASH
@@ -295,9 +158,9 @@ class TableTokenizer extends coreTokenizer.BaseBlockTokenizer {
295
158
  break;
296
159
  }
297
160
  const endPoint = coreTokenizer.calcEndYastNodePoint(nodePoints, i - 1);
298
- const phrasingContent = cellFirstNonWhitespaceIndex >= cellEndIndex
299
- ? null
300
- : api.buildPhrasingContentToken([
161
+ const lines = cellFirstNonWhitespaceIndex >= cellEndIndex
162
+ ? []
163
+ : [
301
164
  {
302
165
  nodePoints,
303
166
  startIndex: cellStartIndex,
@@ -305,12 +168,12 @@ class TableTokenizer extends coreTokenizer.BaseBlockTokenizer {
305
168
  firstNonWhitespaceIndex: cellFirstNonWhitespaceIndex,
306
169
  countOfPrecedeSpaces: cellFirstNonWhitespaceIndex - cellStartIndex,
307
170
  },
308
- ]);
171
+ ];
309
172
  const cell = {
310
- _tokenizer: this.name,
173
+ _tokenizer,
311
174
  nodeType: ast.TableCellType,
312
175
  position: { start: startPoint, end: endPoint },
313
- children: phrasingContent == null ? [] : [phrasingContent],
176
+ lines: lines,
314
177
  };
315
178
  cells.push(cell);
316
179
  if (cells.length >= columns.length)
@@ -320,23 +183,78 @@ class TableTokenizer extends coreTokenizer.BaseBlockTokenizer {
320
183
  const endPoint = coreTokenizer.calcEndYastNodePoint(nodePoints, endIndex - 1);
321
184
  for (let c = cells.length; c < columns.length; ++c) {
322
185
  const cell = {
323
- _tokenizer: this.name,
186
+ _tokenizer,
324
187
  nodeType: ast.TableCellType,
325
188
  position: { start: Object.assign({}, endPoint), end: Object.assign({}, endPoint) },
326
- children: [],
189
+ lines: [],
327
190
  };
328
191
  cells.push(cell);
329
192
  }
330
193
  const row = {
331
- _tokenizer: this.name,
194
+ _tokenizer,
332
195
  nodeType: ast.TableRowType,
333
196
  position: { start: startPoint, end: endPoint },
334
- children: cells,
197
+ cells,
335
198
  };
336
199
  return row;
337
200
  }
201
+ };
202
+
203
+ const parse = api => ({
204
+ parse: tokens => tokens.map(token => {
205
+ const tableRows = token.rows.map((row) => {
206
+ const tableCells = row.cells.map((cell) => {
207
+ const contents = [];
208
+ {
209
+ const nodePoints = coreTokenizer.mergeAndStripContentLines(cell.lines);
210
+ for (let i = 0, endIndex = nodePoints.length; i < endIndex; ++i) {
211
+ const p = nodePoints[i];
212
+ if (p.codePoint === character.AsciiCodePoint.BACKSLASH && i + 1 < endIndex) {
213
+ const q = nodePoints[i + 1];
214
+ if (q.codePoint !== character.AsciiCodePoint.VERTICAL_SLASH)
215
+ contents.push(p);
216
+ contents.push(q);
217
+ i += 1;
218
+ }
219
+ else {
220
+ contents.push(p);
221
+ }
222
+ }
223
+ }
224
+ const children = api.processInlines(contents);
225
+ const tableCell = api.shouldReservePosition
226
+ ? { type: ast.TableCellType, position: cell.position, children }
227
+ : { type: ast.TableCellType, children };
228
+ return tableCell;
229
+ });
230
+ const tableRow = api.shouldReservePosition
231
+ ? { type: ast.TableRowType, position: row.position, children: tableCells }
232
+ : { type: ast.TableRowType, children: tableCells };
233
+ return tableRow;
234
+ });
235
+ const table = api.shouldReservePosition
236
+ ? { type: ast.TableType, position: token.position, columns: token.columns, children: tableRows }
237
+ : { type: ast.TableType, columns: token.columns, children: tableRows };
238
+ return table;
239
+ }),
240
+ });
241
+
242
+ const uniqueName = '@yozora/tokenizer-table';
243
+
244
+ class TableTokenizer extends coreTokenizer.BaseBlockTokenizer {
245
+ constructor(props = {}) {
246
+ var _a, _b;
247
+ super({
248
+ name: (_a = props.name) !== null && _a !== void 0 ? _a : uniqueName,
249
+ priority: (_b = props.priority) !== null && _b !== void 0 ? _b : coreTokenizer.TokenizerPriority.INTERRUPTABLE_BLOCK,
250
+ });
251
+ this.match = match;
252
+ this.parse = parse;
253
+ }
338
254
  }
339
255
 
340
256
  exports.TableTokenizer = TableTokenizer;
341
257
  exports.TableTokenizerName = uniqueName;
342
- exports['default'] = TableTokenizer;
258
+ exports["default"] = TableTokenizer;
259
+ exports.tableMatch = match;
260
+ exports.tableParse = parse;
package/lib/esm/index.js CHANGED
@@ -1,22 +1,19 @@
1
1
  import { TableType, TableCellType, TableRowType } from '@yozora/ast';
2
2
  import { AsciiCodePoint, isWhitespaceCharacter } from '@yozora/character';
3
- import { BaseBlockTokenizer, TokenizerPriority, calcStartYastNodePoint, calcEndYastNodePoint, PhrasingContentType } from '@yozora/core-tokenizer';
3
+ import { calcStartYastNodePoint, calcEndYastNodePoint, mergeAndStripContentLines, BaseBlockTokenizer, TokenizerPriority } from '@yozora/core-tokenizer';
4
4
 
5
- const uniqueName = '@yozora/tokenizer-table';
6
-
7
- class TableTokenizer extends BaseBlockTokenizer {
8
- constructor(props = {}) {
9
- var _a, _b;
10
- super({
11
- name: (_a = props.name) !== null && _a !== void 0 ? _a : uniqueName,
12
- priority: (_b = props.priority) !== null && _b !== void 0 ? _b : TokenizerPriority.INTERRUPTABLE_BLOCK,
13
- });
14
- this.isContainingBlock = false;
15
- }
16
- eatOpener() {
5
+ const match = function (api) {
6
+ const { name: _tokenizer } = this;
7
+ return {
8
+ isContainingBlock: false,
9
+ eatOpener,
10
+ eatAndInterruptPreviousSibling,
11
+ eatLazyContinuationText,
12
+ };
13
+ function eatOpener() {
17
14
  return null;
18
15
  }
19
- eatAndInterruptPreviousSibling(line, prevSiblingToken, parentToken, api) {
16
+ function eatAndInterruptPreviousSibling(line, prevSiblingToken) {
20
17
  if (line.countOfPrecedeSpaces >= 4)
21
18
  return null;
22
19
  const { nodePoints, endIndex, firstNonWhitespaceIndex } = line;
@@ -24,9 +21,7 @@ class TableTokenizer extends BaseBlockTokenizer {
24
21
  return null;
25
22
  const columns = [];
26
23
  let c = nodePoints[firstNonWhitespaceIndex].codePoint;
27
- let cIndex = c === AsciiCodePoint.VERTICAL_SLASH
28
- ? firstNonWhitespaceIndex + 1
29
- : firstNonWhitespaceIndex;
24
+ let cIndex = c === AsciiCodePoint.VERTICAL_SLASH ? firstNonWhitespaceIndex + 1 : firstNonWhitespaceIndex;
30
25
  for (; cIndex < endIndex;) {
31
26
  for (; cIndex < endIndex; ++cIndex) {
32
27
  c = nodePoints[cIndex].codePoint;
@@ -99,7 +94,7 @@ class TableTokenizer extends BaseBlockTokenizer {
99
94
  cellCount += 1;
100
95
  if (cellCount !== columns.length)
101
96
  return null;
102
- const row = this.calcTableRow(api, previousLine, columns);
97
+ const row = calcTableRow(previousLine, columns);
103
98
  const nextIndex = endIndex;
104
99
  const token = {
105
100
  nodeType: TableType,
@@ -108,7 +103,7 @@ class TableTokenizer extends BaseBlockTokenizer {
108
103
  end: calcEndYastNodePoint(nodePoints, nextIndex - 1),
109
104
  },
110
105
  columns,
111
- children: [row],
106
+ rows: [row],
112
107
  };
113
108
  return {
114
109
  token,
@@ -116,149 +111,17 @@ class TableTokenizer extends BaseBlockTokenizer {
116
111
  remainingSibling: api.rollbackPhrasingLines(lines.slice(0, lines.length - 1), prevSiblingToken),
117
112
  };
118
113
  }
119
- eatLazyContinuationText(line, token, parentToken, api) {
114
+ function eatLazyContinuationText(line, token) {
120
115
  if (line.firstNonWhitespaceIndex >= line.endIndex) {
121
116
  return { status: 'notMatched' };
122
117
  }
123
- const tableToken = token;
124
- const row = this.calcTableRow(api, line, tableToken.columns);
118
+ const row = calcTableRow(line, token.columns);
125
119
  if (row == null)
126
120
  return { status: 'notMatched' };
127
- tableToken.children.push(row);
121
+ token.rows.push(row);
128
122
  return { status: 'opening', nextIndex: line.endIndex };
129
123
  }
130
- parseBlock(token, children, api) {
131
- let node;
132
- switch (token.nodeType) {
133
- case TableType: {
134
- node = {
135
- type: TableType,
136
- columns: token.columns,
137
- children: (children || []),
138
- };
139
- break;
140
- }
141
- case TableRowType: {
142
- node = {
143
- type: TableRowType,
144
- children: (children || []),
145
- };
146
- break;
147
- }
148
- case TableCellType: {
149
- node = {
150
- type: TableCellType,
151
- children: children,
152
- };
153
- for (const phrasingContent of node.children) {
154
- if (phrasingContent.type !== PhrasingContentType)
155
- continue;
156
- const nextContents = [];
157
- const endIndex = phrasingContent.contents.length;
158
- for (let i = 0; i < endIndex; ++i) {
159
- const p = phrasingContent.contents[i];
160
- if (p.codePoint === AsciiCodePoint.BACKSLASH && i + 1 < endIndex) {
161
- const q = phrasingContent.contents[i + 1];
162
- if (q.codePoint !== AsciiCodePoint.VERTICAL_SLASH)
163
- nextContents.push(p);
164
- nextContents.push(q);
165
- i += 1;
166
- continue;
167
- }
168
- nextContents.push(p);
169
- }
170
- phrasingContent.contents = nextContents;
171
- }
172
- break;
173
- }
174
- default:
175
- return null;
176
- }
177
- return node;
178
- }
179
- calcTableColumn(nodePoints, currentLine, previousLine) {
180
- if (previousLine.firstNonWhitespaceIndex >= previousLine.endIndex) {
181
- return null;
182
- }
183
- if (currentLine.firstNonWhitespaceIndex - currentLine.startIndex >= 4)
184
- return null;
185
- const columns = [];
186
- let p = nodePoints[currentLine.firstNonWhitespaceIndex];
187
- let cIndex = p.codePoint === AsciiCodePoint.VERTICAL_SLASH
188
- ? currentLine.firstNonWhitespaceIndex + 1
189
- : currentLine.firstNonWhitespaceIndex;
190
- for (; cIndex < currentLine.endIndex;) {
191
- for (; cIndex < currentLine.endIndex; ++cIndex) {
192
- p = nodePoints[cIndex];
193
- if (!isWhitespaceCharacter(p.codePoint))
194
- break;
195
- }
196
- if (cIndex >= currentLine.endIndex)
197
- break;
198
- let leftColon = false;
199
- if (p.codePoint === AsciiCodePoint.COLON) {
200
- leftColon = true;
201
- cIndex += 1;
202
- }
203
- let hyphenCount = 0;
204
- for (; cIndex < currentLine.endIndex; ++cIndex) {
205
- p = nodePoints[cIndex];
206
- if (p.codePoint !== AsciiCodePoint.MINUS_SIGN)
207
- break;
208
- hyphenCount += 1;
209
- }
210
- if (hyphenCount <= 0)
211
- return null;
212
- let rightColon = false;
213
- if (cIndex < currentLine.endIndex &&
214
- p.codePoint === AsciiCodePoint.COLON) {
215
- rightColon = true;
216
- cIndex += 1;
217
- }
218
- for (; cIndex < currentLine.endIndex; ++cIndex) {
219
- p = nodePoints[cIndex];
220
- if (isWhitespaceCharacter(p.codePoint))
221
- continue;
222
- if (p.codePoint === AsciiCodePoint.VERTICAL_SLASH) {
223
- cIndex += 1;
224
- break;
225
- }
226
- return null;
227
- }
228
- let align = null;
229
- if (leftColon && rightColon)
230
- align = 'center';
231
- else if (leftColon)
232
- align = 'left';
233
- else if (rightColon)
234
- align = 'right';
235
- const column = { align };
236
- columns.push(column);
237
- }
238
- if (columns.length <= 0)
239
- return null;
240
- let cellCount = 0, hasNonWhitespaceBeforePipe = false;
241
- for (let pIndex = previousLine.startIndex; pIndex < previousLine.endIndex; ++pIndex) {
242
- const p = nodePoints[pIndex];
243
- if (isWhitespaceCharacter(p.codePoint))
244
- continue;
245
- if (p.codePoint === AsciiCodePoint.VERTICAL_SLASH) {
246
- if (hasNonWhitespaceBeforePipe || cellCount > 0)
247
- cellCount += 1;
248
- hasNonWhitespaceBeforePipe = false;
249
- continue;
250
- }
251
- hasNonWhitespaceBeforePipe = true;
252
- if (p.codePoint === AsciiCodePoint.BACKSLASH)
253
- pIndex += 1;
254
- }
255
- if (hasNonWhitespaceBeforePipe && columns.length > 1)
256
- cellCount += 1;
257
- if (cellCount !== columns.length)
258
- return null;
259
- return columns;
260
- }
261
- calcTableRow(api, line, columns) {
124
+ function calcTableRow(line, columns) {
262
125
  const { nodePoints, startIndex, endIndex, firstNonWhitespaceIndex } = line;
263
126
  let p = nodePoints[firstNonWhitespaceIndex];
264
127
  let i = p.codePoint === AsciiCodePoint.VERTICAL_SLASH
@@ -291,9 +154,9 @@ class TableTokenizer extends BaseBlockTokenizer {
291
154
  break;
292
155
  }
293
156
  const endPoint = calcEndYastNodePoint(nodePoints, i - 1);
294
- const phrasingContent = cellFirstNonWhitespaceIndex >= cellEndIndex
295
- ? null
296
- : api.buildPhrasingContentToken([
157
+ const lines = cellFirstNonWhitespaceIndex >= cellEndIndex
158
+ ? []
159
+ : [
297
160
  {
298
161
  nodePoints,
299
162
  startIndex: cellStartIndex,
@@ -301,12 +164,12 @@ class TableTokenizer extends BaseBlockTokenizer {
301
164
  firstNonWhitespaceIndex: cellFirstNonWhitespaceIndex,
302
165
  countOfPrecedeSpaces: cellFirstNonWhitespaceIndex - cellStartIndex,
303
166
  },
304
- ]);
167
+ ];
305
168
  const cell = {
306
- _tokenizer: this.name,
169
+ _tokenizer,
307
170
  nodeType: TableCellType,
308
171
  position: { start: startPoint, end: endPoint },
309
- children: phrasingContent == null ? [] : [phrasingContent],
172
+ lines: lines,
310
173
  };
311
174
  cells.push(cell);
312
175
  if (cells.length >= columns.length)
@@ -316,21 +179,74 @@ class TableTokenizer extends BaseBlockTokenizer {
316
179
  const endPoint = calcEndYastNodePoint(nodePoints, endIndex - 1);
317
180
  for (let c = cells.length; c < columns.length; ++c) {
318
181
  const cell = {
319
- _tokenizer: this.name,
182
+ _tokenizer,
320
183
  nodeType: TableCellType,
321
184
  position: { start: Object.assign({}, endPoint), end: Object.assign({}, endPoint) },
322
- children: [],
185
+ lines: [],
323
186
  };
324
187
  cells.push(cell);
325
188
  }
326
189
  const row = {
327
- _tokenizer: this.name,
190
+ _tokenizer,
328
191
  nodeType: TableRowType,
329
192
  position: { start: startPoint, end: endPoint },
330
- children: cells,
193
+ cells,
331
194
  };
332
195
  return row;
333
196
  }
197
+ };
198
+
199
+ const parse = api => ({
200
+ parse: tokens => tokens.map(token => {
201
+ const tableRows = token.rows.map((row) => {
202
+ const tableCells = row.cells.map((cell) => {
203
+ const contents = [];
204
+ {
205
+ const nodePoints = mergeAndStripContentLines(cell.lines);
206
+ for (let i = 0, endIndex = nodePoints.length; i < endIndex; ++i) {
207
+ const p = nodePoints[i];
208
+ if (p.codePoint === AsciiCodePoint.BACKSLASH && i + 1 < endIndex) {
209
+ const q = nodePoints[i + 1];
210
+ if (q.codePoint !== AsciiCodePoint.VERTICAL_SLASH)
211
+ contents.push(p);
212
+ contents.push(q);
213
+ i += 1;
214
+ }
215
+ else {
216
+ contents.push(p);
217
+ }
218
+ }
219
+ }
220
+ const children = api.processInlines(contents);
221
+ const tableCell = api.shouldReservePosition
222
+ ? { type: TableCellType, position: cell.position, children }
223
+ : { type: TableCellType, children };
224
+ return tableCell;
225
+ });
226
+ const tableRow = api.shouldReservePosition
227
+ ? { type: TableRowType, position: row.position, children: tableCells }
228
+ : { type: TableRowType, children: tableCells };
229
+ return tableRow;
230
+ });
231
+ const table = api.shouldReservePosition
232
+ ? { type: TableType, position: token.position, columns: token.columns, children: tableRows }
233
+ : { type: TableType, columns: token.columns, children: tableRows };
234
+ return table;
235
+ }),
236
+ });
237
+
238
+ const uniqueName = '@yozora/tokenizer-table';
239
+
240
+ class TableTokenizer extends BaseBlockTokenizer {
241
+ constructor(props = {}) {
242
+ var _a, _b;
243
+ super({
244
+ name: (_a = props.name) !== null && _a !== void 0 ? _a : uniqueName,
245
+ priority: (_b = props.priority) !== null && _b !== void 0 ? _b : TokenizerPriority.INTERRUPTABLE_BLOCK,
246
+ });
247
+ this.match = match;
248
+ this.parse = parse;
249
+ }
334
250
  }
335
251
 
336
- export { TableTokenizer, uniqueName as TableTokenizerName, TableTokenizer as default };
252
+ export { TableTokenizer, uniqueName as TableTokenizerName, TableTokenizer as default, match as tableMatch, parse as tableParse };
@@ -1,5 +1,5 @@
1
- import { TableTokenizer } from './tokenizer';
2
- export { TableTokenizer } from './tokenizer';
1
+ export { match as tableMatch } from './match';
2
+ export { parse as tableParse } from './parse';
3
+ export { TableTokenizer, TableTokenizer as default } from './tokenizer';
3
4
  export { uniqueName as TableTokenizerName } from './types';
4
- export type { TableCellToken, TableRowToken, TableToken, TokenizerProps as TableTokenizerProps, } from './types';
5
- export default TableTokenizer;
5
+ export type { IThis as ITableHookContext, ITableCellToken, ITableRowToken, IToken as ITableToken, ITokenizerProps as ITableTokenizerProps, } from './types';
@@ -0,0 +1,26 @@
1
+ import type { IMatchBlockHookCreator } from '@yozora/core-tokenizer';
2
+ import type { IThis, IToken, T } from './types';
3
+ /**
4
+ * A table is an arrangement of data with rows and columns, consisting of
5
+ * a single header row, a delimiter row separating the header from the data,
6
+ * and zero or more data rows.
7
+ *
8
+ * Each row consists of cells containing arbitrary text, in which inlines
9
+ * are parsed, separated by pipes (|). A leading and trailing pipe is also
10
+ * recommended for clarity of reading, and if there’s otherwise parsing
11
+ * ambiguity. Spaces between pipes and cell content are trimmed. Block-level
12
+ * elements cannot be inserted in a table.
13
+ *
14
+ * @see https://github.github.com/gfm/#table
15
+ * @see https://github.com/syntax-tree/mdast#tablerow
16
+ * @see https://github.com/syntax-tree/mdast#tablecell
17
+ */
18
+ export declare const match: IMatchBlockHookCreator<T, IToken, IThis>;
19
+ /**
20
+ * Find delimiter row
21
+ *
22
+ * The delimiter row consists of cells whose only content are
23
+ * hyphens (-), and optionally, a leading or trailing colon (:),
24
+ * or both, to indicate left, right, or center alignment respectively.
25
+ * @see https://github.github.com/gfm/#delimiter-row
26
+ */
@@ -0,0 +1,3 @@
1
+ import type { IParseBlockHookCreator } from '@yozora/core-tokenizer';
2
+ import type { INode, IThis, IToken, T } from './types';
3
+ export declare const parse: IParseBlockHookCreator<T, IToken, INode, IThis>;
@@ -1,59 +1,14 @@
1
- import type { TableColumn, YastNode } from '@yozora/ast';
2
- import type { NodePoint } from '@yozora/character';
3
- import type { MatchBlockPhaseApi, ParseBlockPhaseApi, PhrasingContentLine, ResultOfEatAndInterruptPreviousSibling, ResultOfEatLazyContinuationText, ResultOfEatOpener, ResultOfParse, Tokenizer, TokenizerMatchBlockHook, TokenizerParseBlockHook, YastBlockToken } from '@yozora/core-tokenizer';
1
+ import type { IBlockTokenizer, IMatchBlockHookCreator, IParseBlockHookCreator } from '@yozora/core-tokenizer';
4
2
  import { BaseBlockTokenizer } from '@yozora/core-tokenizer';
5
- import type { Node, T, TableRowToken, Token, TokenizerProps } from './types';
3
+ import type { INode, IThis, IToken, ITokenizerProps, T } from './types';
6
4
  /**
7
5
  * Lexical Analyzer for Table, table-row and table-cell.
8
- *
9
- * A table is an arrangement of data with rows and columns, consisting of
10
- * a single header row, a delimiter row separating the header from the data,
11
- * and zero or more data rows.
12
- *
13
- * Each row consists of cells containing arbitrary text, in which inlines
14
- * are parsed, separated by pipes (|). A leading and trailing pipe is also
15
- * recommended for clarity of reading, and if there’s otherwise parsing
16
- * ambiguity. Spaces between pipes and cell content are trimmed. Block-level
17
- * elements cannot be inserted in a table.
18
- *
19
6
  * @see https://github.github.com/gfm/#table
20
7
  * @see https://github.com/syntax-tree/mdast#tablerow
21
8
  * @see https://github.com/syntax-tree/mdast#tablecell
22
9
  */
23
- export declare class TableTokenizer extends BaseBlockTokenizer implements Tokenizer, TokenizerMatchBlockHook<T, Token>, TokenizerParseBlockHook<T, Token, Node> {
24
- readonly isContainingBlock = false;
25
- constructor(props?: TokenizerProps);
26
- /**
27
- * @override
28
- * @see TokenizerMatchBlockHook
29
- */
30
- eatOpener(): ResultOfEatOpener<T, Token>;
31
- /**
32
- * @override
33
- * @see TokenizerMatchBlockHook
34
- */
35
- eatAndInterruptPreviousSibling(line: Readonly<PhrasingContentLine>, prevSiblingToken: Readonly<YastBlockToken>, parentToken: Readonly<YastBlockToken>, api: Readonly<MatchBlockPhaseApi>): ResultOfEatAndInterruptPreviousSibling<T, Token>;
36
- /**
37
- * @override
38
- * @see TokenizerMatchBlockHook
39
- */
40
- eatLazyContinuationText(line: Readonly<PhrasingContentLine>, token: Token, parentToken: Readonly<YastBlockToken>, api: Readonly<MatchBlockPhaseApi>): ResultOfEatLazyContinuationText;
41
- /**
42
- * @override
43
- * @see TokenizerParseBlockHook
44
- */
45
- parseBlock(token: Readonly<Token>, children: YastNode[] | undefined, api: Readonly<ParseBlockPhaseApi>): ResultOfParse<T, Node>;
46
- /**
47
- * Find delimiter row
48
- *
49
- * The delimiter row consists of cells whose only content are
50
- * hyphens (-), and optionally, a leading or trailing colon (:),
51
- * or both, to indicate left, right, or center alignment respectively.
52
- * @see https://github.github.com/gfm/#delimiter-row
53
- */
54
- protected calcTableColumn(nodePoints: ReadonlyArray<NodePoint>, currentLine: PhrasingContentLine, previousLine: PhrasingContentLine): TableColumn[] | null;
55
- /**
56
- * process table row
57
- */
58
- protected calcTableRow(api: Readonly<MatchBlockPhaseApi>, line: PhrasingContentLine, columns: TableColumn[]): TableRowToken;
10
+ export declare class TableTokenizer extends BaseBlockTokenizer<T, IToken, INode, IThis> implements IBlockTokenizer<T, IToken, INode, IThis> {
11
+ constructor(props?: ITokenizerProps);
12
+ readonly match: IMatchBlockHookCreator<T, IToken, IThis>;
13
+ readonly parse: IParseBlockHookCreator<T, IToken, INode, IThis>;
59
14
  }
@@ -1,29 +1,24 @@
1
- import type { Table, TableCell, TableCellType, TableColumn, TableRow, TableRowType, TableType } from '@yozora/ast';
2
- import type { BaseBlockTokenizerProps, PartialYastBlockToken, PhrasingContentToken, YastBlockToken } from '@yozora/core-tokenizer';
3
- export declare type T = TableType | TableRowType | TableCellType;
4
- export declare type Node = Table | TableRow | TableCell;
5
- export declare type Token = TableToken | TableRowToken | TableCellToken;
1
+ import type { ITable, ITableColumn, IYastNodePosition, TableCellType, TableRowType, TableType } from '@yozora/ast';
2
+ import type { IBaseBlockTokenizerProps, IPartialYastBlockToken, IPhrasingContentLine, ITokenizer } from '@yozora/core-tokenizer';
3
+ export declare type T = TableType;
4
+ export declare type INode = ITable;
6
5
  export declare const uniqueName = "@yozora/tokenizer-table";
7
- export interface TableToken extends PartialYastBlockToken<TableType> {
6
+ export interface IToken extends IPartialYastBlockToken<TableType> {
8
7
  /**
9
8
  * Table column configuration items
10
9
  */
11
- columns: TableColumn[];
10
+ columns: ITableColumn[];
12
11
  /**
13
12
  * Table rows
14
13
  */
15
- children: TableRowToken[];
14
+ rows: ITableRowToken[];
16
15
  }
17
- export interface TableRowToken extends YastBlockToken<TableRowType> {
18
- /**
19
- * Table cells
20
- */
21
- children: TableCellToken[];
16
+ export declare type IThis = ITokenizer;
17
+ export declare type ITokenizerProps = Partial<IBaseBlockTokenizerProps>;
18
+ export interface ITableRowToken extends IPartialYastBlockToken<TableRowType> {
19
+ cells: ITableCellToken[];
22
20
  }
23
- export interface TableCellToken extends YastBlockToken<TableCellType> {
24
- /**
25
- * Contents of table cell.
26
- */
27
- children: PhrasingContentToken[];
21
+ export interface ITableCellToken extends IPartialYastBlockToken<TableCellType> {
22
+ position: IYastNodePosition;
23
+ lines: IPhrasingContentLine[];
28
24
  }
29
- export declare type TokenizerProps = Partial<BaseBlockTokenizerProps>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yozora/tokenizer-table",
3
- "version": "1.2.2",
3
+ "version": "2.0.0-alpha.2",
4
4
  "author": {
5
5
  "name": "guanghechen",
6
6
  "url": "https://github.com/guanghechen/"
@@ -35,9 +35,9 @@
35
35
  "test": "cross-env TS_NODE_FILES=true jest --config ../../jest.config.js --rootDir ."
36
36
  },
37
37
  "dependencies": {
38
- "@yozora/ast": "^1.2.2",
39
- "@yozora/character": "^1.2.2",
40
- "@yozora/core-tokenizer": "^1.2.2"
38
+ "@yozora/ast": "^2.0.0-alpha.2",
39
+ "@yozora/character": "^2.0.0-alpha.2",
40
+ "@yozora/core-tokenizer": "^2.0.0-alpha.2"
41
41
  },
42
- "gitHead": "fb4b804548592c09259aabcf9cc4dd96176bd024"
42
+ "gitHead": "da59d85520455c59a117a35032ef1a035c10ea21"
43
43
  }