@markitdownjs/ast 0.1.0 → 0.1.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/LICENSE +21 -0
- package/README.md +64 -0
- package/dist/__tests__/renderers.test.js +27 -27
- package/dist/ast-utils.d.ts +2 -2
- package/dist/ast-utils.js +5 -5
- package/dist/html-renderer.d.ts +1 -1
- package/dist/html-renderer.js +65 -65
- package/dist/index.d.ts +5 -5
- package/dist/index.js +5 -5
- package/dist/json-renderer.d.ts +1 -1
- package/dist/markdown-renderer.d.ts +1 -1
- package/dist/markdown-renderer.js +61 -61
- package/dist/plaintext-renderer.d.ts +1 -1
- package/dist/plaintext-renderer.js +56 -56
- package/package.json +2 -2
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 MarkItDownJS Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# @markitdownjs/ast
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@markitdownjs/ast)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
AST utilities and multi-format renderers for MarkItDownJS. Convert a `DocumentNode` AST to Markdown, HTML, plain text, or JSON.
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install @markitdownjs/ast
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
import { MarkdownRenderer, HtmlRenderer } from "@markitdownjs/ast";
|
|
18
|
+
|
|
19
|
+
const md = new MarkdownRenderer().render(documentNode);
|
|
20
|
+
const html = new HtmlRenderer().render(documentNode);
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Key Exports
|
|
24
|
+
|
|
25
|
+
### Renderers
|
|
26
|
+
|
|
27
|
+
| Export | Output format |
|
|
28
|
+
|---|---|
|
|
29
|
+
| `MarkdownRenderer` | GitHub-flavored Markdown |
|
|
30
|
+
| `HtmlRenderer` | Semantic HTML5 |
|
|
31
|
+
| `PlaintextRenderer` | Stripped plain text |
|
|
32
|
+
| `JsonRenderer` | Serialized AST as JSON |
|
|
33
|
+
|
|
34
|
+
All renderers implement the same interface:
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
interface Renderer {
|
|
38
|
+
render(node: DocumentNode): string;
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Utilities
|
|
43
|
+
|
|
44
|
+
| Export | Description |
|
|
45
|
+
|---|---|
|
|
46
|
+
| `AstUtils` | Traverse, query, and transform `DocumentNode` trees |
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import { AstUtils } from "@markitdownjs/ast";
|
|
50
|
+
|
|
51
|
+
const headings = AstUtils.selectAll(documentNode, "HeadingNode");
|
|
52
|
+
const text = AstUtils.extractText(documentNode);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Renderer Options
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
const renderer = new HtmlRenderer({ includeIds: true, wrapInDocument: false });
|
|
59
|
+
const html = renderer.render(documentNode);
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
Part of the [MarkItDownJS](https://github.com/markitdownjs/markitdownjs) monorepo.
|
|
@@ -1,54 +1,54 @@
|
|
|
1
|
-
import { describe, it, expect } from
|
|
2
|
-
import { MarkdownRenderer } from
|
|
3
|
-
import { HtmlRenderer } from
|
|
4
|
-
import { PlainTextRenderer } from
|
|
5
|
-
import { JsonRenderer } from
|
|
6
|
-
import { createNode } from
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { MarkdownRenderer } from "../markdown-renderer.js";
|
|
3
|
+
import { HtmlRenderer } from "../html-renderer.js";
|
|
4
|
+
import { PlainTextRenderer } from "../plaintext-renderer.js";
|
|
5
|
+
import { JsonRenderer } from "../json-renderer.js";
|
|
6
|
+
import { createNode } from "@markitdownjs/shared";
|
|
7
7
|
const testAst = createNode({
|
|
8
|
-
type:
|
|
8
|
+
type: "document",
|
|
9
9
|
children: [
|
|
10
10
|
createNode({
|
|
11
|
-
type:
|
|
11
|
+
type: "heading",
|
|
12
12
|
level: 1,
|
|
13
|
-
children: [createNode({ type:
|
|
13
|
+
children: [createNode({ type: "text", value: "Hello World" })],
|
|
14
14
|
}),
|
|
15
15
|
createNode({
|
|
16
|
-
type:
|
|
17
|
-
children: [createNode({ type:
|
|
16
|
+
type: "paragraph",
|
|
17
|
+
children: [createNode({ type: "text", value: "This is a test document." })],
|
|
18
18
|
}),
|
|
19
19
|
],
|
|
20
20
|
});
|
|
21
|
-
describe(
|
|
22
|
-
it(
|
|
21
|
+
describe("MarkdownRenderer", () => {
|
|
22
|
+
it("should render AST to markdown", () => {
|
|
23
23
|
const renderer = new MarkdownRenderer();
|
|
24
24
|
const md = renderer.render(testAst);
|
|
25
|
-
expect(md).toContain(
|
|
26
|
-
expect(md).toContain(
|
|
25
|
+
expect(md).toContain("# Hello World");
|
|
26
|
+
expect(md).toContain("This is a test document.");
|
|
27
27
|
});
|
|
28
28
|
});
|
|
29
|
-
describe(
|
|
30
|
-
it(
|
|
29
|
+
describe("HtmlRenderer", () => {
|
|
30
|
+
it("should render AST to HTML", () => {
|
|
31
31
|
const renderer = new HtmlRenderer();
|
|
32
32
|
const html = renderer.render(testAst);
|
|
33
|
-
expect(html).toContain(
|
|
34
|
-
expect(html).toContain(
|
|
33
|
+
expect(html).toContain("<h1>Hello World</h1>");
|
|
34
|
+
expect(html).toContain("<p>This is a test document.</p>");
|
|
35
35
|
});
|
|
36
36
|
});
|
|
37
|
-
describe(
|
|
38
|
-
it(
|
|
37
|
+
describe("PlainTextRenderer", () => {
|
|
38
|
+
it("should render AST to plain text", () => {
|
|
39
39
|
const renderer = new PlainTextRenderer();
|
|
40
40
|
const text = renderer.render(testAst);
|
|
41
|
-
expect(text).toContain(
|
|
42
|
-
expect(text).toContain(
|
|
43
|
-
expect(text).not.toContain(
|
|
41
|
+
expect(text).toContain("Hello World");
|
|
42
|
+
expect(text).toContain("This is a test document.");
|
|
43
|
+
expect(text).not.toContain("#");
|
|
44
44
|
});
|
|
45
45
|
});
|
|
46
|
-
describe(
|
|
47
|
-
it(
|
|
46
|
+
describe("JsonRenderer", () => {
|
|
47
|
+
it("should render AST to JSON", () => {
|
|
48
48
|
const renderer = new JsonRenderer();
|
|
49
49
|
const json = renderer.render(testAst);
|
|
50
50
|
const parsed = JSON.parse(json);
|
|
51
|
-
expect(parsed.type).toBe(
|
|
51
|
+
expect(parsed.type).toBe("document");
|
|
52
52
|
});
|
|
53
53
|
});
|
|
54
54
|
//# sourceMappingURL=renderers.test.js.map
|
package/dist/ast-utils.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { AnyNode, DocumentNode, HeadingInfo } from
|
|
2
|
-
export type { HeadingInfo } from
|
|
1
|
+
import { AnyNode, DocumentNode, HeadingInfo } from "@markitdownjs/shared";
|
|
2
|
+
export type { HeadingInfo } from "@markitdownjs/shared";
|
|
3
3
|
export declare function extractText(node: AnyNode): string;
|
|
4
4
|
export declare function extractHeadings(node: AnyNode): HeadingInfo[];
|
|
5
5
|
export declare function countTokens(node: AnyNode): number;
|
package/dist/ast-utils.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { walkAst, getNodeText, findNodesOfType, countTokens as sharedCountTokens, } from
|
|
1
|
+
import { walkAst, getNodeText, findNodesOfType, countTokens as sharedCountTokens, } from "@markitdownjs/shared";
|
|
2
2
|
export function extractText(node) {
|
|
3
3
|
return getNodeText(node);
|
|
4
4
|
}
|
|
5
5
|
export function extractHeadings(node) {
|
|
6
|
-
const headings = findNodesOfType(node,
|
|
6
|
+
const headings = findNodesOfType(node, "heading");
|
|
7
7
|
return headings.map((h) => ({
|
|
8
8
|
level: h.level,
|
|
9
9
|
text: getNodeText(h),
|
|
@@ -16,7 +16,7 @@ export function countTokens(node) {
|
|
|
16
16
|
export function findNodeById(node, id) {
|
|
17
17
|
let found = null;
|
|
18
18
|
walkAst(node, (n) => {
|
|
19
|
-
if (
|
|
19
|
+
if ("id" in n && n.id === id) {
|
|
20
20
|
found = n;
|
|
21
21
|
return false;
|
|
22
22
|
}
|
|
@@ -29,7 +29,7 @@ export function getDepth(node) {
|
|
|
29
29
|
const visit = (n, depth) => {
|
|
30
30
|
if (depth > maxDepth)
|
|
31
31
|
maxDepth = depth;
|
|
32
|
-
if (
|
|
32
|
+
if ("children" in n && Array.isArray(n.children)) {
|
|
33
33
|
for (const child of n.children) {
|
|
34
34
|
visit(child, depth + 1);
|
|
35
35
|
}
|
|
@@ -54,7 +54,7 @@ export function mergeDocuments(...nodes) {
|
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
return {
|
|
57
|
-
type:
|
|
57
|
+
type: "document",
|
|
58
58
|
children,
|
|
59
59
|
};
|
|
60
60
|
}
|
package/dist/html-renderer.d.ts
CHANGED
package/dist/html-renderer.js
CHANGED
|
@@ -1,140 +1,140 @@
|
|
|
1
|
-
import { getNodeText, } from
|
|
1
|
+
import { getNodeText, } from "@markitdownjs/shared";
|
|
2
2
|
function escapeHtml(text) {
|
|
3
3
|
return text
|
|
4
|
-
.replace(/&/g,
|
|
5
|
-
.replace(/</g,
|
|
6
|
-
.replace(/>/g,
|
|
7
|
-
.replace(/"/g,
|
|
8
|
-
.replace(/'/g,
|
|
4
|
+
.replace(/&/g, "&")
|
|
5
|
+
.replace(/</g, "<")
|
|
6
|
+
.replace(/>/g, ">")
|
|
7
|
+
.replace(/"/g, """)
|
|
8
|
+
.replace(/'/g, "'");
|
|
9
9
|
}
|
|
10
10
|
export class HtmlRenderer {
|
|
11
11
|
render(node) {
|
|
12
12
|
switch (node.type) {
|
|
13
|
-
case
|
|
13
|
+
case "document": {
|
|
14
14
|
const children = node.children ?? [];
|
|
15
|
-
return
|
|
15
|
+
return "<div>" + children.map((c) => this.render(c)).join("\n") + "</div>";
|
|
16
16
|
}
|
|
17
|
-
case
|
|
17
|
+
case "heading": {
|
|
18
18
|
const heading = node;
|
|
19
19
|
const tag = `h${heading.level}`;
|
|
20
|
-
const id = heading.id ? ` id="${heading.id}"` :
|
|
21
|
-
const children = heading.children.map((c) => this.render(c)).join(
|
|
20
|
+
const id = heading.id ? ` id="${heading.id}"` : "";
|
|
21
|
+
const children = heading.children.map((c) => this.render(c)).join("");
|
|
22
22
|
return `<${tag}${id}>${children}</${tag}>`;
|
|
23
23
|
}
|
|
24
|
-
case
|
|
24
|
+
case "paragraph": {
|
|
25
25
|
const paragraph = node;
|
|
26
|
-
const children = paragraph.children.map((c) => this.render(c)).join(
|
|
26
|
+
const children = paragraph.children.map((c) => this.render(c)).join("");
|
|
27
27
|
return `<p>${children}</p>`;
|
|
28
28
|
}
|
|
29
|
-
case
|
|
29
|
+
case "text": {
|
|
30
30
|
return escapeHtml(node.value);
|
|
31
31
|
}
|
|
32
|
-
case
|
|
32
|
+
case "emphasis": {
|
|
33
33
|
const emphasis = node;
|
|
34
|
-
const children = emphasis.children.map((c) => this.render(c)).join(
|
|
34
|
+
const children = emphasis.children.map((c) => this.render(c)).join("");
|
|
35
35
|
return `<em>${children}</em>`;
|
|
36
36
|
}
|
|
37
|
-
case
|
|
37
|
+
case "strong": {
|
|
38
38
|
const strong = node;
|
|
39
|
-
const children = strong.children.map((c) => this.render(c)).join(
|
|
39
|
+
const children = strong.children.map((c) => this.render(c)).join("");
|
|
40
40
|
return `<strong>${children}</strong>`;
|
|
41
41
|
}
|
|
42
|
-
case
|
|
42
|
+
case "inline-code": {
|
|
43
43
|
return `<code>${escapeHtml(node.value)}</code>`;
|
|
44
44
|
}
|
|
45
|
-
case
|
|
45
|
+
case "code": {
|
|
46
46
|
const code = node;
|
|
47
|
-
const lang = code.language ? ` class="language-${code.language}"` :
|
|
47
|
+
const lang = code.language ? ` class="language-${code.language}"` : "";
|
|
48
48
|
return `<pre><code${lang}>${escapeHtml(code.value)}</code></pre>`;
|
|
49
49
|
}
|
|
50
|
-
case
|
|
50
|
+
case "link": {
|
|
51
51
|
const link = node;
|
|
52
|
-
const children = link.children.map((c) => this.render(c)).join(
|
|
53
|
-
const title = link.title ? ` title="${escapeHtml(link.title)}"` :
|
|
52
|
+
const children = link.children.map((c) => this.render(c)).join("");
|
|
53
|
+
const title = link.title ? ` title="${escapeHtml(link.title)}"` : "";
|
|
54
54
|
return `<a href="${escapeHtml(link.href)}"${title}>${children}</a>`;
|
|
55
55
|
}
|
|
56
|
-
case
|
|
56
|
+
case "image": {
|
|
57
57
|
const image = node;
|
|
58
|
-
const alt = image.alt ? ` alt="${escapeHtml(image.alt)}"` :
|
|
59
|
-
const title = image.title ? ` title="${escapeHtml(image.title)}"` :
|
|
58
|
+
const alt = image.alt ? ` alt="${escapeHtml(image.alt)}"` : "";
|
|
59
|
+
const title = image.title ? ` title="${escapeHtml(image.title)}"` : "";
|
|
60
60
|
return `<img src="${escapeHtml(image.src)}"${alt}${title} />`;
|
|
61
61
|
}
|
|
62
|
-
case
|
|
62
|
+
case "list": {
|
|
63
63
|
const list = node;
|
|
64
|
-
const tag = list.ordered ?
|
|
65
|
-
const children = list.children.map((c) => this.render(c)).join(
|
|
64
|
+
const tag = list.ordered ? "ol" : "ul";
|
|
65
|
+
const children = list.children.map((c) => this.render(c)).join("\n");
|
|
66
66
|
return `<${tag}>\n${children}\n</${tag}>`;
|
|
67
67
|
}
|
|
68
|
-
case
|
|
68
|
+
case "list-item": {
|
|
69
69
|
const listItem = node;
|
|
70
|
-
const children = listItem.children.map((c) => this.render(c)).join(
|
|
70
|
+
const children = listItem.children.map((c) => this.render(c)).join("");
|
|
71
71
|
return `<li>${children}</li>`;
|
|
72
72
|
}
|
|
73
|
-
case
|
|
73
|
+
case "table": {
|
|
74
74
|
return this.renderTable(node);
|
|
75
75
|
}
|
|
76
|
-
case
|
|
76
|
+
case "table-row": {
|
|
77
77
|
const row = node;
|
|
78
|
-
const tag = row.isHeader ?
|
|
78
|
+
const tag = row.isHeader ? "th" : "td";
|
|
79
79
|
const cells = row.children.map((c) => {
|
|
80
|
-
const content = c.children.map((cc) => this.render(cc)).join(
|
|
80
|
+
const content = c.children.map((cc) => this.render(cc)).join("");
|
|
81
81
|
return `<${tag}>${content}</${tag}>`;
|
|
82
82
|
});
|
|
83
|
-
return `<tr>\n${cells.join(
|
|
83
|
+
return `<tr>\n${cells.join("\n")}\n</tr>`;
|
|
84
84
|
}
|
|
85
|
-
case
|
|
85
|
+
case "table-cell": {
|
|
86
86
|
const cell = node;
|
|
87
|
-
return cell.children.map((c) => this.render(c)).join(
|
|
87
|
+
return cell.children.map((c) => this.render(c)).join("");
|
|
88
88
|
}
|
|
89
|
-
case
|
|
89
|
+
case "blockquote": {
|
|
90
90
|
const blockquote = node;
|
|
91
|
-
const children = blockquote.children.map((c) => this.render(c)).join(
|
|
91
|
+
const children = blockquote.children.map((c) => this.render(c)).join("\n");
|
|
92
92
|
return `<blockquote>\n${children}\n</blockquote>`;
|
|
93
93
|
}
|
|
94
|
-
case
|
|
95
|
-
case
|
|
96
|
-
return
|
|
97
|
-
case
|
|
94
|
+
case "thematic-break":
|
|
95
|
+
case "horizontal-rule":
|
|
96
|
+
return "<hr />";
|
|
97
|
+
case "html": {
|
|
98
98
|
return node.value;
|
|
99
99
|
}
|
|
100
|
-
case
|
|
100
|
+
case "footnote": {
|
|
101
101
|
const footnote = node;
|
|
102
102
|
const id = footnote.identifier;
|
|
103
103
|
return `<sup><a href="#fn-${id}">${id}</a></sup>`;
|
|
104
104
|
}
|
|
105
|
-
case
|
|
105
|
+
case "page-break":
|
|
106
106
|
return '<div class="page-break"></div>';
|
|
107
|
-
case
|
|
107
|
+
case "section": {
|
|
108
108
|
const section = node;
|
|
109
|
-
const children = section.children.map((c) => this.render(c)).join(
|
|
109
|
+
const children = section.children.map((c) => this.render(c)).join("\n");
|
|
110
110
|
return `<section>\n${children}\n</section>`;
|
|
111
111
|
}
|
|
112
|
-
case
|
|
112
|
+
case "strikethrough": {
|
|
113
113
|
const strikethrough = node;
|
|
114
|
-
const children = strikethrough.children.map((c) => this.render(c)).join(
|
|
114
|
+
const children = strikethrough.children.map((c) => this.render(c)).join("");
|
|
115
115
|
return `<del>${children}</del>`;
|
|
116
116
|
}
|
|
117
|
-
case
|
|
117
|
+
case "math": {
|
|
118
118
|
const math = node;
|
|
119
119
|
return `<span class="math">${escapeHtml(math.value)}</span>`;
|
|
120
120
|
}
|
|
121
|
-
case
|
|
121
|
+
case "raw": {
|
|
122
122
|
return node.value;
|
|
123
123
|
}
|
|
124
|
-
case
|
|
125
|
-
case
|
|
126
|
-
case
|
|
127
|
-
case
|
|
124
|
+
case "definition":
|
|
125
|
+
case "quote":
|
|
126
|
+
case "subscript":
|
|
127
|
+
case "superscript": {
|
|
128
128
|
return escapeHtml(getNodeText(node));
|
|
129
129
|
}
|
|
130
130
|
default:
|
|
131
|
-
return
|
|
131
|
+
return "";
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
134
|
renderTable(table) {
|
|
135
135
|
const rows = table.children;
|
|
136
136
|
if (rows.length === 0)
|
|
137
|
-
return
|
|
137
|
+
return "";
|
|
138
138
|
let hasHeader = false;
|
|
139
139
|
const bodyRows = [];
|
|
140
140
|
for (const row of rows) {
|
|
@@ -146,20 +146,20 @@ export class HtmlRenderer {
|
|
|
146
146
|
}
|
|
147
147
|
}
|
|
148
148
|
const renderRow = (row) => {
|
|
149
|
-
return
|
|
149
|
+
return "<tr>\n" + row.children.map((c) => this.render(c)).join("\n") + "\n</tr>";
|
|
150
150
|
};
|
|
151
|
-
let html =
|
|
151
|
+
let html = "<table>\n";
|
|
152
152
|
if (hasHeader) {
|
|
153
153
|
const headerRow = rows.find((r) => r.isHeader);
|
|
154
154
|
if (headerRow) {
|
|
155
|
-
html +=
|
|
155
|
+
html += "<thead>\n" + renderRow(headerRow) + "\n</thead>\n";
|
|
156
156
|
}
|
|
157
157
|
}
|
|
158
|
-
html +=
|
|
158
|
+
html += "<tbody>\n";
|
|
159
159
|
for (const row of bodyRows) {
|
|
160
|
-
html += renderRow(row) +
|
|
160
|
+
html += renderRow(row) + "\n";
|
|
161
161
|
}
|
|
162
|
-
html +=
|
|
162
|
+
html += "</tbody>\n</table>";
|
|
163
163
|
return html;
|
|
164
164
|
}
|
|
165
165
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { MarkdownRenderer } from
|
|
2
|
-
export { HtmlRenderer } from
|
|
3
|
-
export { PlainTextRenderer } from
|
|
4
|
-
export { JsonRenderer } from
|
|
5
|
-
export * from
|
|
1
|
+
export { MarkdownRenderer } from "./markdown-renderer.js";
|
|
2
|
+
export { HtmlRenderer } from "./html-renderer.js";
|
|
3
|
+
export { PlainTextRenderer } from "./plaintext-renderer.js";
|
|
4
|
+
export { JsonRenderer } from "./json-renderer.js";
|
|
5
|
+
export * from "./ast-utils.js";
|
|
6
6
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { MarkdownRenderer } from
|
|
2
|
-
export { HtmlRenderer } from
|
|
3
|
-
export { PlainTextRenderer } from
|
|
4
|
-
export { JsonRenderer } from
|
|
5
|
-
export * from
|
|
1
|
+
export { MarkdownRenderer } from "./markdown-renderer.js";
|
|
2
|
+
export { HtmlRenderer } from "./html-renderer.js";
|
|
3
|
+
export { PlainTextRenderer } from "./plaintext-renderer.js";
|
|
4
|
+
export { JsonRenderer } from "./json-renderer.js";
|
|
5
|
+
export * from "./ast-utils.js";
|
|
6
6
|
//# sourceMappingURL=index.js.map
|
package/dist/json-renderer.d.ts
CHANGED
|
@@ -1,134 +1,134 @@
|
|
|
1
|
-
import { getNodeText, } from
|
|
1
|
+
import { getNodeText, } from "@markitdownjs/shared";
|
|
2
2
|
export class MarkdownRenderer {
|
|
3
3
|
render(node) {
|
|
4
4
|
switch (node.type) {
|
|
5
|
-
case
|
|
5
|
+
case "document": {
|
|
6
6
|
const children = node.children ?? [];
|
|
7
|
-
return children.map((child) => this.render(child)).join(
|
|
7
|
+
return children.map((child) => this.render(child)).join("\n\n");
|
|
8
8
|
}
|
|
9
|
-
case
|
|
9
|
+
case "heading": {
|
|
10
10
|
const heading = node;
|
|
11
|
-
const prefix =
|
|
12
|
-
const children = heading.children.map((c) => this.render(c)).join(
|
|
11
|
+
const prefix = "#".repeat(heading.level);
|
|
12
|
+
const children = heading.children.map((c) => this.render(c)).join("");
|
|
13
13
|
return `${prefix} ${children}`;
|
|
14
14
|
}
|
|
15
|
-
case
|
|
15
|
+
case "paragraph": {
|
|
16
16
|
const paragraph = node;
|
|
17
|
-
return paragraph.children.map((c) => this.render(c)).join(
|
|
17
|
+
return paragraph.children.map((c) => this.render(c)).join("");
|
|
18
18
|
}
|
|
19
|
-
case
|
|
19
|
+
case "text": {
|
|
20
20
|
return node.value;
|
|
21
21
|
}
|
|
22
|
-
case
|
|
22
|
+
case "emphasis": {
|
|
23
23
|
const emphasis = node;
|
|
24
|
-
const children = emphasis.children.map((c) => this.render(c)).join(
|
|
24
|
+
const children = emphasis.children.map((c) => this.render(c)).join("");
|
|
25
25
|
return `*${children}*`;
|
|
26
26
|
}
|
|
27
|
-
case
|
|
27
|
+
case "strong": {
|
|
28
28
|
const strong = node;
|
|
29
|
-
const children = strong.children.map((c) => this.render(c)).join(
|
|
29
|
+
const children = strong.children.map((c) => this.render(c)).join("");
|
|
30
30
|
return `**${children}**`;
|
|
31
31
|
}
|
|
32
|
-
case
|
|
32
|
+
case "inline-code": {
|
|
33
33
|
return `\`${node.value}\``;
|
|
34
34
|
}
|
|
35
|
-
case
|
|
35
|
+
case "code": {
|
|
36
36
|
const code = node;
|
|
37
|
-
const lang = code.language ??
|
|
37
|
+
const lang = code.language ?? "";
|
|
38
38
|
return `\`\`\`${lang}\n${code.value}\n\`\`\``;
|
|
39
39
|
}
|
|
40
|
-
case
|
|
40
|
+
case "link": {
|
|
41
41
|
const link = node;
|
|
42
|
-
const children = link.children.map((c) => this.render(c)).join(
|
|
43
|
-
const title = link.title ? ` "${link.title}"` :
|
|
42
|
+
const children = link.children.map((c) => this.render(c)).join("");
|
|
43
|
+
const title = link.title ? ` "${link.title}"` : "";
|
|
44
44
|
return `[${children}](${link.href}${title})`;
|
|
45
45
|
}
|
|
46
|
-
case
|
|
46
|
+
case "image": {
|
|
47
47
|
const image = node;
|
|
48
|
-
const alt = image.alt ??
|
|
49
|
-
const title = image.title ? ` "${image.title}"` :
|
|
48
|
+
const alt = image.alt ?? "";
|
|
49
|
+
const title = image.title ? ` "${image.title}"` : "";
|
|
50
50
|
return ``;
|
|
51
51
|
}
|
|
52
|
-
case
|
|
52
|
+
case "list": {
|
|
53
53
|
const list = node;
|
|
54
54
|
return list.children
|
|
55
55
|
.map((item, index) => {
|
|
56
|
-
const prefix = list.ordered ? `${(list.start ?? 1) + index}. ` :
|
|
57
|
-
const content = item.children.map((c) => this.render(c)).join(
|
|
56
|
+
const prefix = list.ordered ? `${(list.start ?? 1) + index}. ` : "- ";
|
|
57
|
+
const content = item.children.map((c) => this.render(c)).join("");
|
|
58
58
|
return `${prefix}${content}`;
|
|
59
59
|
})
|
|
60
|
-
.join(
|
|
60
|
+
.join("\n");
|
|
61
61
|
}
|
|
62
|
-
case
|
|
62
|
+
case "list-item": {
|
|
63
63
|
const listItem = node;
|
|
64
|
-
return listItem.children.map((c) => this.render(c)).join(
|
|
64
|
+
return listItem.children.map((c) => this.render(c)).join("");
|
|
65
65
|
}
|
|
66
|
-
case
|
|
66
|
+
case "table": {
|
|
67
67
|
return this.renderTable(node);
|
|
68
68
|
}
|
|
69
|
-
case
|
|
69
|
+
case "table-row": {
|
|
70
70
|
const row = node;
|
|
71
|
-
return
|
|
71
|
+
return "| " + row.children.map((c) => this.render(c)).join(" | ") + " |";
|
|
72
72
|
}
|
|
73
|
-
case
|
|
73
|
+
case "table-cell": {
|
|
74
74
|
const cell = node;
|
|
75
|
-
return cell.children.map((c) => this.render(c)).join(
|
|
75
|
+
return cell.children.map((c) => this.render(c)).join("");
|
|
76
76
|
}
|
|
77
|
-
case
|
|
77
|
+
case "blockquote": {
|
|
78
78
|
const blockquote = node;
|
|
79
|
-
const children = blockquote.children.map((c) => this.render(c)).join(
|
|
79
|
+
const children = blockquote.children.map((c) => this.render(c)).join("\n");
|
|
80
80
|
return children
|
|
81
|
-
.split(
|
|
81
|
+
.split("\n")
|
|
82
82
|
.map((line) => `> ${line}`)
|
|
83
|
-
.join(
|
|
83
|
+
.join("\n");
|
|
84
84
|
}
|
|
85
|
-
case
|
|
86
|
-
case
|
|
87
|
-
return
|
|
88
|
-
case
|
|
85
|
+
case "thematic-break":
|
|
86
|
+
case "horizontal-rule":
|
|
87
|
+
return "---";
|
|
88
|
+
case "html": {
|
|
89
89
|
return node.value;
|
|
90
90
|
}
|
|
91
|
-
case
|
|
91
|
+
case "footnote": {
|
|
92
92
|
const footnote = node;
|
|
93
|
-
const children = footnote.children.map((c) => this.render(c)).join(
|
|
93
|
+
const children = footnote.children.map((c) => this.render(c)).join("");
|
|
94
94
|
return `[^${footnote.identifier}]: ${children}`;
|
|
95
95
|
}
|
|
96
|
-
case
|
|
97
|
-
return
|
|
98
|
-
case
|
|
96
|
+
case "page-break":
|
|
97
|
+
return "\n---\n";
|
|
98
|
+
case "section": {
|
|
99
99
|
const section = node;
|
|
100
|
-
const children = section.children.map((c) => this.render(c)).join(
|
|
100
|
+
const children = section.children.map((c) => this.render(c)).join("\n\n");
|
|
101
101
|
return children;
|
|
102
102
|
}
|
|
103
|
-
case
|
|
103
|
+
case "strikethrough": {
|
|
104
104
|
const strikethrough = node;
|
|
105
|
-
const children = strikethrough.children.map((c) => this.render(c)).join(
|
|
105
|
+
const children = strikethrough.children.map((c) => this.render(c)).join("");
|
|
106
106
|
return `~~${children}~~`;
|
|
107
107
|
}
|
|
108
|
-
case
|
|
108
|
+
case "math": {
|
|
109
109
|
const math = node;
|
|
110
110
|
if (math.inline) {
|
|
111
111
|
return `$${math.value}$`;
|
|
112
112
|
}
|
|
113
113
|
return `$$\n${math.value}\n$$`;
|
|
114
114
|
}
|
|
115
|
-
case
|
|
115
|
+
case "raw": {
|
|
116
116
|
return node.value;
|
|
117
117
|
}
|
|
118
|
-
case
|
|
119
|
-
case
|
|
120
|
-
case
|
|
121
|
-
case
|
|
118
|
+
case "definition":
|
|
119
|
+
case "quote":
|
|
120
|
+
case "subscript":
|
|
121
|
+
case "superscript": {
|
|
122
122
|
return getNodeText(node);
|
|
123
123
|
}
|
|
124
124
|
default:
|
|
125
|
-
return
|
|
125
|
+
return "";
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
128
|
renderTable(table) {
|
|
129
129
|
const rows = table.children;
|
|
130
130
|
if (rows.length === 0)
|
|
131
|
-
return
|
|
131
|
+
return "";
|
|
132
132
|
const columnCount = Math.max(...rows.map((r) => r.children.length));
|
|
133
133
|
const widths = Array.from({ length: columnCount }, () => 0);
|
|
134
134
|
for (const row of rows) {
|
|
@@ -146,16 +146,16 @@ export class MarkdownRenderer {
|
|
|
146
146
|
const cells = [];
|
|
147
147
|
for (let ci = 0; ci < columnCount; ci++) {
|
|
148
148
|
const cell = row.children[ci];
|
|
149
|
-
const text = cell ? getNodeText(cell) :
|
|
149
|
+
const text = cell ? getNodeText(cell) : "";
|
|
150
150
|
const width = widths[ci] ?? 0;
|
|
151
151
|
cells.push(text.padEnd(width));
|
|
152
152
|
}
|
|
153
|
-
lines.push(
|
|
153
|
+
lines.push("| " + cells.join(" | ") + " |");
|
|
154
154
|
if (row.isHeader) {
|
|
155
|
-
lines.push(
|
|
155
|
+
lines.push("| " + widths.map((w) => "-".repeat(w)).join(" | ") + " |");
|
|
156
156
|
}
|
|
157
157
|
}
|
|
158
|
-
return lines.join(
|
|
158
|
+
return lines.join("\n");
|
|
159
159
|
}
|
|
160
160
|
}
|
|
161
161
|
//# sourceMappingURL=markdown-renderer.js.map
|
|
@@ -1,130 +1,130 @@
|
|
|
1
|
-
import { getNodeText, } from
|
|
1
|
+
import { getNodeText, } from "@markitdownjs/shared";
|
|
2
2
|
export class PlainTextRenderer {
|
|
3
3
|
render(node) {
|
|
4
4
|
switch (node.type) {
|
|
5
|
-
case
|
|
5
|
+
case "document": {
|
|
6
6
|
const children = node.children ?? [];
|
|
7
|
-
return children.map((c) => this.render(c)).join(
|
|
7
|
+
return children.map((c) => this.render(c)).join("\n\n");
|
|
8
8
|
}
|
|
9
|
-
case
|
|
9
|
+
case "heading": {
|
|
10
10
|
const heading = node;
|
|
11
|
-
return heading.children.map((c) => this.render(c)).join(
|
|
11
|
+
return heading.children.map((c) => this.render(c)).join("");
|
|
12
12
|
}
|
|
13
|
-
case
|
|
13
|
+
case "paragraph": {
|
|
14
14
|
const paragraph = node;
|
|
15
|
-
return paragraph.children.map((c) => this.render(c)).join(
|
|
15
|
+
return paragraph.children.map((c) => this.render(c)).join("");
|
|
16
16
|
}
|
|
17
|
-
case
|
|
17
|
+
case "text": {
|
|
18
18
|
return node.value;
|
|
19
19
|
}
|
|
20
|
-
case
|
|
20
|
+
case "emphasis": {
|
|
21
21
|
const emphasis = node;
|
|
22
|
-
return emphasis.children.map((c) => this.render(c)).join(
|
|
22
|
+
return emphasis.children.map((c) => this.render(c)).join("");
|
|
23
23
|
}
|
|
24
|
-
case
|
|
24
|
+
case "strong": {
|
|
25
25
|
const strong = node;
|
|
26
|
-
return strong.children.map((c) => this.render(c)).join(
|
|
26
|
+
return strong.children.map((c) => this.render(c)).join("");
|
|
27
27
|
}
|
|
28
|
-
case
|
|
28
|
+
case "inline-code": {
|
|
29
29
|
return node.value;
|
|
30
30
|
}
|
|
31
|
-
case
|
|
31
|
+
case "code": {
|
|
32
32
|
const code = node;
|
|
33
33
|
return code.value;
|
|
34
34
|
}
|
|
35
|
-
case
|
|
35
|
+
case "link": {
|
|
36
36
|
const link = node;
|
|
37
|
-
return link.children.map((c) => this.render(c)).join(
|
|
37
|
+
return link.children.map((c) => this.render(c)).join("");
|
|
38
38
|
}
|
|
39
|
-
case
|
|
39
|
+
case "image": {
|
|
40
40
|
const image = node;
|
|
41
|
-
return image.alt ??
|
|
41
|
+
return image.alt ?? "";
|
|
42
42
|
}
|
|
43
|
-
case
|
|
43
|
+
case "list": {
|
|
44
44
|
const list = node;
|
|
45
45
|
return list.children
|
|
46
46
|
.map((item, index) => {
|
|
47
|
-
const prefix = list.ordered ? `${(list.start ?? 1) + index}. ` :
|
|
48
|
-
const content = item.children.map((c) => this.render(c)).join(
|
|
47
|
+
const prefix = list.ordered ? `${(list.start ?? 1) + index}. ` : "- ";
|
|
48
|
+
const content = item.children.map((c) => this.render(c)).join("");
|
|
49
49
|
return `${prefix}${content}`;
|
|
50
50
|
})
|
|
51
|
-
.join(
|
|
51
|
+
.join("\n");
|
|
52
52
|
}
|
|
53
|
-
case
|
|
53
|
+
case "list-item": {
|
|
54
54
|
const listItem = node;
|
|
55
|
-
return listItem.children.map((c) => this.render(c)).join(
|
|
55
|
+
return listItem.children.map((c) => this.render(c)).join("");
|
|
56
56
|
}
|
|
57
|
-
case
|
|
57
|
+
case "table": {
|
|
58
58
|
return this.renderTable(node);
|
|
59
59
|
}
|
|
60
|
-
case
|
|
60
|
+
case "table-row": {
|
|
61
61
|
const row = node;
|
|
62
|
-
return row.children.map((c) => this.render(c)).join(
|
|
62
|
+
return row.children.map((c) => this.render(c)).join("\t");
|
|
63
63
|
}
|
|
64
|
-
case
|
|
64
|
+
case "table-cell": {
|
|
65
65
|
const cell = node;
|
|
66
|
-
return cell.children.map((c) => this.render(c)).join(
|
|
66
|
+
return cell.children.map((c) => this.render(c)).join("");
|
|
67
67
|
}
|
|
68
|
-
case
|
|
68
|
+
case "blockquote": {
|
|
69
69
|
const blockquote = node;
|
|
70
|
-
const children = blockquote.children.map((c) => this.render(c)).join(
|
|
70
|
+
const children = blockquote.children.map((c) => this.render(c)).join("\n");
|
|
71
71
|
return children
|
|
72
|
-
.split(
|
|
72
|
+
.split("\n")
|
|
73
73
|
.map((line) => `> ${line}`)
|
|
74
|
-
.join(
|
|
74
|
+
.join("\n");
|
|
75
75
|
}
|
|
76
|
-
case
|
|
77
|
-
case
|
|
78
|
-
return
|
|
79
|
-
case
|
|
76
|
+
case "thematic-break":
|
|
77
|
+
case "horizontal-rule":
|
|
78
|
+
return "---";
|
|
79
|
+
case "html": {
|
|
80
80
|
return node.value;
|
|
81
81
|
}
|
|
82
|
-
case
|
|
82
|
+
case "footnote": {
|
|
83
83
|
const footnote = node;
|
|
84
|
-
const children = footnote.children.map((c) => this.render(c)).join(
|
|
84
|
+
const children = footnote.children.map((c) => this.render(c)).join("");
|
|
85
85
|
return `[${footnote.identifier}]: ${children}`;
|
|
86
86
|
}
|
|
87
|
-
case
|
|
88
|
-
return
|
|
89
|
-
case
|
|
87
|
+
case "page-break":
|
|
88
|
+
return "\n---\n";
|
|
89
|
+
case "section": {
|
|
90
90
|
const section = node;
|
|
91
|
-
return section.children.map((c) => this.render(c)).join(
|
|
91
|
+
return section.children.map((c) => this.render(c)).join("\n\n");
|
|
92
92
|
}
|
|
93
|
-
case
|
|
93
|
+
case "strikethrough": {
|
|
94
94
|
const strikethrough = node;
|
|
95
|
-
return strikethrough.children.map((c) => this.render(c)).join(
|
|
95
|
+
return strikethrough.children.map((c) => this.render(c)).join("");
|
|
96
96
|
}
|
|
97
|
-
case
|
|
97
|
+
case "math": {
|
|
98
98
|
return node.value;
|
|
99
99
|
}
|
|
100
|
-
case
|
|
100
|
+
case "raw": {
|
|
101
101
|
return node.value;
|
|
102
102
|
}
|
|
103
|
-
case
|
|
104
|
-
case
|
|
105
|
-
case
|
|
106
|
-
case
|
|
103
|
+
case "definition":
|
|
104
|
+
case "quote":
|
|
105
|
+
case "subscript":
|
|
106
|
+
case "superscript": {
|
|
107
107
|
return getNodeText(node);
|
|
108
108
|
}
|
|
109
109
|
default:
|
|
110
|
-
return
|
|
110
|
+
return "";
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
113
|
renderTable(table) {
|
|
114
114
|
const rows = table.children;
|
|
115
115
|
if (rows.length === 0)
|
|
116
|
-
return
|
|
116
|
+
return "";
|
|
117
117
|
const columnCount = Math.max(...rows.map((r) => r.children.length));
|
|
118
118
|
return rows
|
|
119
119
|
.map((row) => {
|
|
120
120
|
const cells = [];
|
|
121
121
|
for (let i = 0; i < columnCount; i++) {
|
|
122
122
|
const cell = row.children[i];
|
|
123
|
-
cells.push(cell ? this.render(cell) :
|
|
123
|
+
cells.push(cell ? this.render(cell) : "");
|
|
124
124
|
}
|
|
125
|
-
return cells.join(
|
|
125
|
+
return cells.join("\t");
|
|
126
126
|
})
|
|
127
|
-
.join(
|
|
127
|
+
.join("\n");
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
130
|
//# sourceMappingURL=plaintext-renderer.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markitdownjs/ast",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Unified AST types and renderers for MarkItDownJS",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"dist"
|
|
18
18
|
],
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@markitdownjs/shared": "0.
|
|
20
|
+
"@markitdownjs/shared": "0.2.0"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"typescript": "^5.5.0"
|