@tabnas/markdown 0.5.0 → 0.5.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 +65 -10
- package/dist/ast.d.ts +31 -1
- package/dist/ast.js +26 -1
- package/dist/ast.js.map +1 -1
- package/dist/block.js +448 -8
- package/dist/block.js.map +1 -1
- package/dist/html.d.ts +9 -3
- package/dist/html.js +137 -14
- package/dist/html.js.map +1 -1
- package/dist/inline.d.ts +7 -1
- package/dist/inline.js +431 -2
- package/dist/inline.js.map +1 -1
- package/dist/markdown.d.ts +5 -2
- package/dist/markdown.js.map +1 -1
- package/dist/node.d.ts +39 -1
- package/dist/node.js +36 -0
- package/dist/node.js.map +1 -1
- package/dist/options.d.ts +9 -4
- package/dist/options.js.map +1 -1
- package/package.json +2 -1
- package/src/ast.ts +56 -2
- package/src/block.ts +495 -10
- package/src/html.ts +140 -15
- package/src/inline.ts +463 -2
- package/src/markdown.ts +7 -1
- package/src/node.ts +53 -0
- package/src/options.ts +9 -4
package/dist/node.d.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
export type NodeType = 'document' | 'block_quote' | 'list' | 'item' | 'paragraph' | 'heading' | 'thematic_break' | 'code_block' | 'html_block' | 'text' | 'softbreak' | 'linebreak' | 'code' | 'html_inline' | 'emph' | 'strong' | 'link' | 'image' | 'del';
|
|
1
|
+
export type NodeType = 'document' | 'block_quote' | 'list' | 'item' | 'paragraph' | 'heading' | 'thematic_break' | 'code_block' | 'html_block' | 'table' | 'table_row' | 'table_cell' | 'text' | 'softbreak' | 'linebreak' | 'code' | 'html_inline' | 'emph' | 'strong' | 'link' | 'image' | 'del';
|
|
2
|
+
/**
|
|
3
|
+
* Per-column alignment of a GFM table, from the colons in its delimiter row:
|
|
4
|
+
* `:--` left, `--:` right, `:-:` center, `---` none.
|
|
5
|
+
*/
|
|
6
|
+
export type TableAlign = 'left' | 'right' | 'center' | null;
|
|
2
7
|
export type ListType = 'bullet' | 'ordered';
|
|
3
8
|
export type ListData = {
|
|
4
9
|
type: ListType;
|
|
@@ -41,6 +46,39 @@ export declare class MdNode {
|
|
|
41
46
|
fenceLength: number;
|
|
42
47
|
fenceOffset: number;
|
|
43
48
|
listData: ListData | null;
|
|
49
|
+
/**
|
|
50
|
+
* GFM tables: one entry per column, in order, set on the **table** node by
|
|
51
|
+
* the block phase from the delimiter row. Every row of the table — header
|
|
52
|
+
* and body alike — has exactly this many cells, because short rows are
|
|
53
|
+
* padded and long ones are truncated. Null on every other node type.
|
|
54
|
+
*/
|
|
55
|
+
tableAlign: TableAlign[] | null;
|
|
56
|
+
/**
|
|
57
|
+
* GFM tables: true on the one `table_row` that is the header row, which is
|
|
58
|
+
* always the table's first child. mdast has no header flag and relies on
|
|
59
|
+
* that convention, but the renderer needs to choose `<th>` over `<td>`
|
|
60
|
+
* without walking back up to the table.
|
|
61
|
+
*/
|
|
62
|
+
isHeaderRow: boolean;
|
|
63
|
+
/**
|
|
64
|
+
* GFM task list items (`- [x] foo`): `true`/`false` for a checked/unchecked
|
|
65
|
+
* item, `null` for an ordinary one. Set on `item` nodes by the block phase
|
|
66
|
+
* when `gfm` is on, once the marker has been consumed from the item's first
|
|
67
|
+
* paragraph. mdast's field and mdast's semantics — `ast.ts` projects it
|
|
68
|
+
* straight through to `listItem.checked`.
|
|
69
|
+
*/
|
|
70
|
+
checked: boolean | null;
|
|
71
|
+
/**
|
|
72
|
+
* The `gfm` parse option, recorded on the **document** node by the block
|
|
73
|
+
* phase and meaningless anywhere else.
|
|
74
|
+
*
|
|
75
|
+
* The renderer needs it because GFM's disallowed-raw-HTML filter is a
|
|
76
|
+
* render-time concern, and `renderHTML(tree)` may be called with no options
|
|
77
|
+
* at all. Without this the default (`gfm: true`) would apply the filter to a
|
|
78
|
+
* tree that was parsed as plain CommonMark, which is exactly the case the
|
|
79
|
+
* conformance runner exercises.
|
|
80
|
+
*/
|
|
81
|
+
gfm: boolean;
|
|
44
82
|
/** Open blocks accept further lines; closed ones are finalized. */
|
|
45
83
|
open: boolean;
|
|
46
84
|
/** Accumulated raw content, consumed by the inline phase. */
|
package/dist/node.js
CHANGED
|
@@ -9,6 +9,9 @@ const CONTAINER_TYPES = {
|
|
|
9
9
|
item: true,
|
|
10
10
|
paragraph: true,
|
|
11
11
|
heading: true,
|
|
12
|
+
table: true,
|
|
13
|
+
table_row: true,
|
|
14
|
+
table_cell: true,
|
|
12
15
|
emph: true,
|
|
13
16
|
strong: true,
|
|
14
17
|
link: true,
|
|
@@ -38,6 +41,39 @@ class MdNode {
|
|
|
38
41
|
this.fenceLength = 0;
|
|
39
42
|
this.fenceOffset = 0;
|
|
40
43
|
this.listData = null;
|
|
44
|
+
/**
|
|
45
|
+
* GFM tables: one entry per column, in order, set on the **table** node by
|
|
46
|
+
* the block phase from the delimiter row. Every row of the table — header
|
|
47
|
+
* and body alike — has exactly this many cells, because short rows are
|
|
48
|
+
* padded and long ones are truncated. Null on every other node type.
|
|
49
|
+
*/
|
|
50
|
+
this.tableAlign = null;
|
|
51
|
+
/**
|
|
52
|
+
* GFM tables: true on the one `table_row` that is the header row, which is
|
|
53
|
+
* always the table's first child. mdast has no header flag and relies on
|
|
54
|
+
* that convention, but the renderer needs to choose `<th>` over `<td>`
|
|
55
|
+
* without walking back up to the table.
|
|
56
|
+
*/
|
|
57
|
+
this.isHeaderRow = false;
|
|
58
|
+
/**
|
|
59
|
+
* GFM task list items (`- [x] foo`): `true`/`false` for a checked/unchecked
|
|
60
|
+
* item, `null` for an ordinary one. Set on `item` nodes by the block phase
|
|
61
|
+
* when `gfm` is on, once the marker has been consumed from the item's first
|
|
62
|
+
* paragraph. mdast's field and mdast's semantics — `ast.ts` projects it
|
|
63
|
+
* straight through to `listItem.checked`.
|
|
64
|
+
*/
|
|
65
|
+
this.checked = null;
|
|
66
|
+
/**
|
|
67
|
+
* The `gfm` parse option, recorded on the **document** node by the block
|
|
68
|
+
* phase and meaningless anywhere else.
|
|
69
|
+
*
|
|
70
|
+
* The renderer needs it because GFM's disallowed-raw-HTML filter is a
|
|
71
|
+
* render-time concern, and `renderHTML(tree)` may be called with no options
|
|
72
|
+
* at all. Without this the default (`gfm: true`) would apply the filter to a
|
|
73
|
+
* tree that was parsed as plain CommonMark, which is exactly the case the
|
|
74
|
+
* conformance runner exercises.
|
|
75
|
+
*/
|
|
76
|
+
this.gfm = true;
|
|
41
77
|
// --- block-phase bookkeeping (not part of the rendered tree) ---
|
|
42
78
|
/** Open blocks accept further lines; closed ones are finalized. */
|
|
43
79
|
this.open = true;
|
package/dist/node.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.js","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":";AAAA,yDAAyD;;;
|
|
1
|
+
{"version":3,"file":"node.js","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"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"}
|
package/dist/options.d.ts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
export type ParserOptions = {
|
|
2
2
|
/**
|
|
3
|
-
* Enable GFM
|
|
3
|
+
* Enable the GFM extensions. Default true.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* Five are implemented, and this one flag gates all of them together:
|
|
6
|
+
* tables, strikethrough (`~~x~~`), task list items (`- [x] foo`), autolink
|
|
7
|
+
* literals (bare `www.` / `http://` / `https://` / `ftp://` / `a@b.co`) and
|
|
8
|
+
* the disallowed-raw-HTML filter. Footnotes are not implemented.
|
|
9
|
+
*
|
|
10
|
+
* The first four are parse-time; the raw-HTML filter is applied by the
|
|
11
|
+
* renderer, which is why `html.ts` reads this option too. With `gfm:false`
|
|
12
|
+
* the output is plain CommonMark, byte for byte.
|
|
8
13
|
*/
|
|
9
14
|
gfm: boolean;
|
|
10
15
|
/** Render soft line breaks as hard breaks. */
|
package/dist/options.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options.js","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":";AAAA,yDAAyD;;;
|
|
1
|
+
{"version":3,"file":"options.js","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":";AAAA,yDAAyD;;;AA6BzD,wCAKC;AAVY,QAAA,eAAe,GAAkB;IAC5C,GAAG,EAAE,IAAI;IACT,MAAM,EAAE,KAAK;CACd,CAAA;AAED,SAAgB,cAAc,CAAC,IAA6B;IAC1D,OAAO;QACL,GAAG,EAAE,IAAI,EAAE,GAAG,IAAI,uBAAe,CAAC,GAAG;QACrC,MAAM,EAAE,IAAI,EAAE,MAAM,IAAI,uBAAe,CAAC,MAAM;KAC/C,CAAA;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tabnas/markdown",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "A Tabnas parser plugin for CommonMark/GFM Markdown — headings, lists, blockquotes, code, emphasis, links and more, into a JSON AST.",
|
|
5
5
|
"main": "dist/markdown.js",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"scripts": {
|
|
24
24
|
"test": "node --enable-source-maps --test \"dist-test/*.test.js\"",
|
|
25
25
|
"conformance": "node tools/conformance.mjs",
|
|
26
|
+
"conformance-gfm": "node tools/gfm-conformance.mjs",
|
|
26
27
|
"test-some": "node --enable-source-maps --test-name-pattern=\"$npm_config_pattern\" --test \"dist-test/*.test.js\"",
|
|
27
28
|
"test-watch": "node --test --watch dist-test/markdown.test.js",
|
|
28
29
|
"embed": "node embed-grammar.js",
|
package/src/ast.ts
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
// field carried no information; nothing can have depended on it.
|
|
19
19
|
|
|
20
20
|
import { MdNode } from './node.ts'
|
|
21
|
+
import type { TableAlign } from './node.ts'
|
|
21
22
|
import type { ParserOptions } from './options.ts'
|
|
22
23
|
|
|
23
24
|
export type DocumentNode = { type: 'document'; children: Block[] }
|
|
@@ -31,6 +32,7 @@ export type Block =
|
|
|
31
32
|
| CodeNode
|
|
32
33
|
| HtmlNode
|
|
33
34
|
| ThematicBreakNode
|
|
35
|
+
| TableNode
|
|
34
36
|
|
|
35
37
|
export type HeadingNode = {
|
|
36
38
|
type: 'heading'
|
|
@@ -46,7 +48,17 @@ export type ListNode = {
|
|
|
46
48
|
spread: boolean
|
|
47
49
|
children: ListItemNode[]
|
|
48
50
|
}
|
|
49
|
-
export type ListItemNode = {
|
|
51
|
+
export type ListItemNode = {
|
|
52
|
+
type: 'listItem'
|
|
53
|
+
spread: boolean
|
|
54
|
+
/**
|
|
55
|
+
* mdast's task list field: `true`/`false` for a GFM task list item
|
|
56
|
+
* (`- [x] foo`), `null` for an ordinary item — and therefore `null`
|
|
57
|
+
* everywhere when `gfm` is off.
|
|
58
|
+
*/
|
|
59
|
+
checked: boolean | null
|
|
60
|
+
children: Block[]
|
|
61
|
+
}
|
|
50
62
|
export type CodeNode = {
|
|
51
63
|
type: 'code'
|
|
52
64
|
lang: string | null
|
|
@@ -56,6 +68,24 @@ export type CodeNode = {
|
|
|
56
68
|
export type HtmlNode = { type: 'html'; value: string }
|
|
57
69
|
export type ThematicBreakNode = { type: 'thematicBreak' }
|
|
58
70
|
|
|
71
|
+
/**
|
|
72
|
+
* A GFM table, in mdast's shape.
|
|
73
|
+
*
|
|
74
|
+
* `align` has one entry per column — `null` where the delimiter row gave no
|
|
75
|
+
* colon — and every row has exactly that many cells, since the block phase
|
|
76
|
+
* pads short rows and truncates long ones.
|
|
77
|
+
*
|
|
78
|
+
* mdast has no header flag: the **first** row is the header row, by
|
|
79
|
+
* convention, and this projection preserves that ordering from the tree.
|
|
80
|
+
*/
|
|
81
|
+
export type TableNode = {
|
|
82
|
+
type: 'table'
|
|
83
|
+
align: TableAlign[]
|
|
84
|
+
children: TableRowNode[]
|
|
85
|
+
}
|
|
86
|
+
export type TableRowNode = { type: 'tableRow'; children: TableCellNode[] }
|
|
87
|
+
export type TableCellNode = { type: 'tableCell'; children: Inline[] }
|
|
88
|
+
|
|
59
89
|
export type Inline =
|
|
60
90
|
| TextNode
|
|
61
91
|
| EmphasisNode
|
|
@@ -312,6 +342,24 @@ function buildBlock(
|
|
|
312
342
|
case 'html_block':
|
|
313
343
|
return { type: 'html', value: node.literal ?? '' }
|
|
314
344
|
|
|
345
|
+
case 'table': {
|
|
346
|
+
// Built here rather than through `built`, because a table's children are
|
|
347
|
+
// rows and cells rather than blocks — `blockChildren` never descends
|
|
348
|
+
// into one. The nesting is a fixed three levels deep, so unlike the
|
|
349
|
+
// block containers this cannot be driven past the stack by input.
|
|
350
|
+
const rows: TableRowNode[] = []
|
|
351
|
+
for (let row = node.firstChild; row; row = row.next) {
|
|
352
|
+
if ('table_row' !== row.type) continue
|
|
353
|
+
const cells: TableCellNode[] = []
|
|
354
|
+
for (let cell = row.firstChild; cell; cell = cell.next) {
|
|
355
|
+
if ('table_cell' !== cell.type) continue
|
|
356
|
+
cells.push({ type: 'tableCell', children: inlineChildren(cell, opts) })
|
|
357
|
+
}
|
|
358
|
+
rows.push({ type: 'tableRow', children: cells })
|
|
359
|
+
}
|
|
360
|
+
return { type: 'table', align: node.tableAlign ?? [], children: rows }
|
|
361
|
+
}
|
|
362
|
+
|
|
315
363
|
case 'list': {
|
|
316
364
|
const data = node.listData
|
|
317
365
|
const ordered = 'ordered' === data?.type
|
|
@@ -322,6 +370,7 @@ function buildBlock(
|
|
|
322
370
|
items.push({
|
|
323
371
|
type: 'listItem',
|
|
324
372
|
spread: itemIsSpread(child),
|
|
373
|
+
checked: child.checked,
|
|
325
374
|
children: builtChildren(child, built),
|
|
326
375
|
})
|
|
327
376
|
}
|
|
@@ -339,7 +388,12 @@ function buildBlock(
|
|
|
339
388
|
case 'item':
|
|
340
389
|
// Only reachable if an item is somehow detached from its list; a list
|
|
341
390
|
// builds its own items above.
|
|
342
|
-
return {
|
|
391
|
+
return {
|
|
392
|
+
type: 'listItem',
|
|
393
|
+
spread: itemIsSpread(node),
|
|
394
|
+
checked: node.checked,
|
|
395
|
+
children: builtChildren(node, built),
|
|
396
|
+
}
|
|
343
397
|
|
|
344
398
|
default:
|
|
345
399
|
return null
|