notion-to-md 1.0.2 → 1.0.6
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 +14 -6
- package/notion-to-md.js +35 -10
- package/package.json +1 -1
- package/utils/md.js +8 -3
- package/utils/notion.js +5 -0
package/README.md
CHANGED
|
@@ -18,10 +18,12 @@ Convert notion pages, block and list of blocks to markdown (supports nesting) us
|
|
|
18
18
|
- [x] code block
|
|
19
19
|
- [x] strikethrough, underline, bold, italic
|
|
20
20
|
- [x] nested blocks
|
|
21
|
-
- [ ]
|
|
21
|
+
- [ ] pages inside pages/child page
|
|
22
|
+
- [x] embeds, bookmarks, videos, files (converted to links)
|
|
22
23
|
- [ ] tables
|
|
23
|
-
- [
|
|
24
|
-
- [x]
|
|
24
|
+
- [x] divider
|
|
25
|
+
- [x] equation block (converted to code blocks)
|
|
26
|
+
- [x] convert returned markdown object to string (`toMarkdownString()`)
|
|
25
27
|
- [ ] add tests
|
|
26
28
|
|
|
27
29
|
## Install
|
|
@@ -51,7 +53,7 @@ const n2m = new notion2md({ notionClient: notion });
|
|
|
51
53
|
|
|
52
54
|
(async () => {
|
|
53
55
|
const mdblocks = await n2m.pageToMarkdown("target_page_id");
|
|
54
|
-
const mdString = n2m.
|
|
56
|
+
const mdString = n2m.toMarkdownString(mdblocks);
|
|
55
57
|
|
|
56
58
|
//writing to file
|
|
57
59
|
fs.writeFile("test.md", mdString, (err) => {
|
|
@@ -165,10 +167,16 @@ const n2m = new notion2md({ notionClient: notion });
|
|
|
165
167
|
|
|
166
168
|
### Converting a single block to markdown string
|
|
167
169
|
|
|
168
|
-
-
|
|
170
|
+
- only takes a single notion block and returns corresponding markdown string
|
|
169
171
|
- nesting is ignored
|
|
172
|
+
- not dependent on @notionhq/client
|
|
170
173
|
|
|
171
174
|
```js
|
|
175
|
+
const notion2md = require("notion-to-md");
|
|
176
|
+
|
|
177
|
+
// notion client not required
|
|
178
|
+
const n2m = new notion2md();
|
|
179
|
+
|
|
172
180
|
const result = n2m.blockToMarkdown(block);
|
|
173
181
|
console.log(result);
|
|
174
182
|
```
|
|
@@ -181,7 +189,7 @@ console.log(result);
|
|
|
181
189
|
|
|
182
190
|
## API
|
|
183
191
|
|
|
184
|
-
### `
|
|
192
|
+
### `toMarkdownString(markdownObjects)`
|
|
185
193
|
|
|
186
194
|
- takes output of `pageToMarkdown` or `blocksToMarkdown` as argument
|
|
187
195
|
- convert to markdown string.
|
package/notion-to-md.js
CHANGED
|
@@ -3,14 +3,14 @@ const { getBlockChildren } = require("./utils/notion");
|
|
|
3
3
|
|
|
4
4
|
class notion2md {
|
|
5
5
|
constructor(options) {
|
|
6
|
-
if (!options
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
if (!options) {
|
|
7
|
+
this.notionClient = undefined;
|
|
8
|
+
} else {
|
|
9
|
+
this.notionClient = options.notionClient || undefined;
|
|
10
|
+
}
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
toMarkdownString(mdBlocks = [], nestingLevel = 0) {
|
|
14
14
|
let mdString = "";
|
|
15
15
|
mdBlocks.forEach((mdBlocks) => {
|
|
16
16
|
if (mdBlocks.parent) {
|
|
@@ -19,7 +19,7 @@ ${md.addTabSpace(mdBlocks.parent, nestingLevel)}
|
|
|
19
19
|
`;
|
|
20
20
|
}
|
|
21
21
|
if (mdBlocks.children && mdBlocks.children.length > 0) {
|
|
22
|
-
mdString += this.
|
|
22
|
+
mdString += this.toMarkdownString(mdBlocks.children, nestingLevel + 1);
|
|
23
23
|
}
|
|
24
24
|
});
|
|
25
25
|
return mdString;
|
|
@@ -37,6 +37,12 @@ ${md.addTabSpace(mdBlocks.parent, nestingLevel)}
|
|
|
37
37
|
* @returns array of md blocks with their children
|
|
38
38
|
*/
|
|
39
39
|
async blocksToMarkdown(blocks, mdBlocks = []) {
|
|
40
|
+
if (!this.notionClient) {
|
|
41
|
+
throw new Error(
|
|
42
|
+
"notion client is not provided, for more details check out https://github.com/souvikinator/notion-to-md"
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
40
46
|
for (let i = 0; i < blocks.length; i++) {
|
|
41
47
|
let block = blocks[i];
|
|
42
48
|
if (block.has_children) {
|
|
@@ -47,7 +53,7 @@ ${md.addTabSpace(mdBlocks.parent, nestingLevel)}
|
|
|
47
53
|
continue;
|
|
48
54
|
}
|
|
49
55
|
let tmp = this.blockToMarkdown(block);
|
|
50
|
-
|
|
56
|
+
|
|
51
57
|
mdBlocks.push({ parent: tmp, children: [] });
|
|
52
58
|
}
|
|
53
59
|
return mdBlocks;
|
|
@@ -58,6 +64,8 @@ ${md.addTabSpace(mdBlocks.parent, nestingLevel)}
|
|
|
58
64
|
* @returns markdown form of the passed block
|
|
59
65
|
*/
|
|
60
66
|
blockToMarkdown(block) {
|
|
67
|
+
if (!block) throw new Error("notion block required");
|
|
68
|
+
|
|
61
69
|
let parsedData = "",
|
|
62
70
|
blockContent;
|
|
63
71
|
const { type } = block;
|
|
@@ -66,6 +74,23 @@ ${md.addTabSpace(mdBlocks.parent, nestingLevel)}
|
|
|
66
74
|
const image_type = blockContent["type"];
|
|
67
75
|
|
|
68
76
|
return md.image("image", blockContent[image_type].url);
|
|
77
|
+
} else if (type === "divider") {
|
|
78
|
+
return md.divider();
|
|
79
|
+
} else if (type === "equation") {
|
|
80
|
+
return md.codeBlock(block[type].expression);
|
|
81
|
+
} else if (type === "video" || type === "file" || type === "pdf") {
|
|
82
|
+
blockContent = block[type];
|
|
83
|
+
const urlType = blockContent["type"];
|
|
84
|
+
|
|
85
|
+
return md.link(type, blockContent[urlType].url);
|
|
86
|
+
} else if (
|
|
87
|
+
type === "bookmark" ||
|
|
88
|
+
type === "embed" ||
|
|
89
|
+
type === "link_preview"
|
|
90
|
+
) {
|
|
91
|
+
blockContent = block[type];
|
|
92
|
+
|
|
93
|
+
return md.link(type, blockContent.url);
|
|
69
94
|
} else {
|
|
70
95
|
blockContent = block[type]["text"] || [];
|
|
71
96
|
blockContent.map((content) => {
|
|
@@ -80,8 +105,8 @@ ${md.addTabSpace(mdBlocks.parent, nestingLevel)}
|
|
|
80
105
|
});
|
|
81
106
|
}
|
|
82
107
|
|
|
83
|
-
|
|
84
|
-
|
|
108
|
+
if (type === "code")
|
|
109
|
+
parsedData = md.codeBlock(parsedData, block[type].language);
|
|
85
110
|
if (type === "heading_1") parsedData = md.heading1(parsedData);
|
|
86
111
|
if (type === "heading_2") parsedData = md.heading2(parsedData);
|
|
87
112
|
if (type === "heading_3") parsedData = md.heading3(parsedData);
|
package/package.json
CHANGED
package/utils/md.js
CHANGED
|
@@ -22,8 +22,8 @@ exports.link = (text, href) => {
|
|
|
22
22
|
return `[${text}](${href})`;
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
exports.codeBlock = (text) => {
|
|
26
|
-
return
|
|
25
|
+
exports.codeBlock = (text, language) => {
|
|
26
|
+
return `\`\`\`${language}
|
|
27
27
|
${text}
|
|
28
28
|
\`\`\``;
|
|
29
29
|
};
|
|
@@ -41,7 +41,8 @@ exports.heading3 = (text) => {
|
|
|
41
41
|
};
|
|
42
42
|
|
|
43
43
|
exports.quote = (text) => {
|
|
44
|
-
|
|
44
|
+
// the replace is done to handle multiple lines
|
|
45
|
+
return `> ${text.replace(/\n/g, " \n>")}`;
|
|
45
46
|
};
|
|
46
47
|
|
|
47
48
|
exports.bullet = (text) => {
|
|
@@ -61,3 +62,7 @@ exports.addTabSpace = (text, n = 0) => {
|
|
|
61
62
|
for (i = 0; i < n; i++) text = tab + text;
|
|
62
63
|
return text;
|
|
63
64
|
};
|
|
65
|
+
|
|
66
|
+
exports.divider = () => {
|
|
67
|
+
return "---";
|
|
68
|
+
};
|
package/utils/notion.js
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
exports.getBlockChildren = async (notionClient, block_id) => {
|
|
2
2
|
try {
|
|
3
|
+
if (!notionClient) {
|
|
4
|
+
throw new Error(
|
|
5
|
+
"notion client is not provided, for more details check out https://github.com/souvikinator/notion-to-md"
|
|
6
|
+
);
|
|
7
|
+
}
|
|
3
8
|
const response = await notionClient.blocks.children.list({
|
|
4
9
|
block_id,
|
|
5
10
|
});
|