notion-to-md 1.0.3 → 1.0.7
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 +12 -4
- package/notion-to-md.js +45 -14
- 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
|
|
@@ -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
|
```
|
package/notion-to-md.js
CHANGED
|
@@ -3,11 +3,11 @@ 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) {
|
|
@@ -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);
|
|
@@ -100,13 +125,19 @@ ${md.addTabSpace(mdBlocks.parent, nestingLevel)}
|
|
|
100
125
|
* @param {object} annotations annotation object of a notion block
|
|
101
126
|
*/
|
|
102
127
|
annotatePlainText(text, annotations) {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
if (
|
|
128
|
+
const leading_space = text.match(/^\s*/)[0];
|
|
129
|
+
const trailing_space = text.match(/\s*$/)[0];
|
|
130
|
+
text = text.trim();
|
|
131
|
+
|
|
132
|
+
if (text !== '') {
|
|
133
|
+
if (annotations.code) text = md.inlineCode(text);
|
|
134
|
+
if (annotations.bold) text = md.bold(text);
|
|
135
|
+
if (annotations.italic) text = md.italic(text);
|
|
136
|
+
if (annotations.strikethrough) text = md.strikethrough(text);
|
|
137
|
+
if (annotations.underline) text = md.underline(text);
|
|
138
|
+
}
|
|
108
139
|
|
|
109
|
-
return text;
|
|
140
|
+
return leading_space + text + trailing_space;
|
|
110
141
|
}
|
|
111
142
|
}
|
|
112
143
|
|
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
|
});
|