notion-to-md 1.0.4 → 1.0.8

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
@@ -66,6 +66,8 @@ const n2m = new notion2md({ notionClient: notion });
66
66
 
67
67
  ![output](https://imgur.com/XrUYrZ0.png)
68
68
 
69
+ > **Note:** Details on provided methods can be found in [API section](https://github.com/souvikinator/notion-to-md#api)
70
+
69
71
  ### converting page to markdown object
70
72
 
71
73
  This is how the notion page looks for this example:
@@ -84,11 +86,17 @@ const notion = new Client({
84
86
  const n2m = new notion2md({ notionClient: notion });
85
87
 
86
88
  (async () => {
87
- const x = await n2m.pageToMarkdown("target_page_id");
89
+ // notice second argument, totalPage.
90
+ const x = await n2m.pageToMarkdown("target_page_id", 2);
88
91
  console.log(x);
89
92
  })();
90
93
  ```
91
94
 
95
+ > `totalPage`: Default value is `1` which means only `100` blocks will be converted to markdown and rest will be ignored (due to notion api limitations, ref: [#9](https://github.com/souvikinator/notion-to-md/pull/9)).
96
+ >
97
+ > - if the notion page contains less than or equal `100` blocks then `totalPage` arg is not required.
98
+ > - if the notion page contains `150` blocks then `totalPage` argument should be greater than or equal to `2` leading to `pageSize = 2 * 100` and rendering all `150` blocks.
99
+
92
100
  **Output:**
93
101
 
94
102
  ```json
@@ -167,10 +175,16 @@ const n2m = new notion2md({ notionClient: notion });
167
175
 
168
176
  ### Converting a single block to markdown string
169
177
 
170
- - just takes a single notion block and returns corresponding markdown string
178
+ - only takes a single notion block and returns corresponding markdown string
171
179
  - nesting is ignored
180
+ - not dependent on @notionhq/client
172
181
 
173
182
  ```js
183
+ const notion2md = require("notion-to-md");
184
+
185
+ // notion client not required
186
+ const n2m = new notion2md();
187
+
174
188
  const result = n2m.blockToMarkdown(block);
175
189
  console.log(result);
176
190
  ```
@@ -188,26 +202,33 @@ console.log(result);
188
202
  - takes output of `pageToMarkdown` or `blocksToMarkdown` as argument
189
203
  - convert to markdown string.
190
204
 
191
- ### `pageToMarkdown(page_id)`
205
+ ### `pageToMarkdown(page_id,totalPage)`
192
206
 
193
- - Takes page_id as input and converts all the blocks in the page to corresponding markdown
194
207
  - Uses `blocksToMarkdown` internally.
208
+ - Takes `page_id` as input and converts all the blocks in the page to corresponding markdown object
209
+ - `totalPage` is the retrieve block children request number i.e `page_size Maximum = totalPage * 100`.
195
210
 
196
- ### `blockToMarkdown(block)`
197
-
198
- - Takes one notion block and converts to markdown
199
- - does not deal with nested notion blocks
200
- - This method doesn't require the `notion-sdk-js`.
201
- - Refer docs to know more about [notion blocks](https://developers.notion.com/reference/block)
211
+ > `totalPage`: Default value is `1` which means only `100` blocks will be converted to markdown and rest will be ignored (due to notion api limitations, ref: [#9](https://github.com/souvikinator/notion-to-md/pull/9)).
212
+ >
213
+ > - if the notion page contains less than or equal `100` blocks then `totalPage` arg is not required.
214
+ > - if the notion page contains `150` blocks then `totalPage` argument should be greater than or equal to `2` leading to `pageSize = 2 * 100` and rendering all blocks withing limit `200`.
202
215
 
203
- ### `blocksToMarkdown(blocks)`
216
+ ### `blocksToMarkdown(blocks,totalPage)`
204
217
 
205
218
  > **Note**: requires <u>**notion-sdk-js**</u> unlike `blockToMarkdown`
206
219
 
207
220
  - `blocks`: array of notion blocks
221
+ - `totalPage`: the retrieve block children request number i.e `page_size Maximum = totalPage * 100`.
208
222
  - deals with <u>**nested blocks**</u>
209
223
  - uses `blockToMarkdown` internally.
210
224
 
225
+ ### `blockToMarkdown(block)`
226
+
227
+ - Takes single notion block and converts to markdown string
228
+ - does not deal with nested notion blocks
229
+ - This method doesn't require the `notion-sdk-js`.
230
+ - Refer docs to know more about [notion blocks](https://developers.notion.com/reference/block)
231
+
211
232
  ## Contribution
212
233
 
213
234
  Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
package/main.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ interface MdBlock {
2
+ parent: string;
3
+ children: MdBlock[];
4
+ }
5
+
6
+ declare module "notion-to-md" {
7
+ export default class Notion2md {
8
+ constructor({ notionClient }: { notionClient: any });
9
+ pageToMarkdown(page_id: string, totalPage: number = 1): Promise<MdBlock[]>;
10
+ toMarkdownString(mdBlocks: MdBlock[]): string;
11
+ blocksToMarkdown(
12
+ blocks: any,
13
+ mdBlocks: MdBlock[],
14
+ totalPage: number = 1
15
+ ): Promise<MdBlock[]>;
16
+ blockToMarkdown(block: any): string;
17
+ }
18
+ }
package/notion-to-md.js CHANGED
@@ -1,13 +1,12 @@
1
1
  const md = require("./utils/md");
2
2
  const { getBlockChildren } = require("./utils/notion");
3
-
4
3
  class notion2md {
5
4
  constructor(options) {
6
- if (!options || !options.notionClient)
7
- throw new Error(
8
- "notion2md takes notion client as argument, for more details check out https://github.com/souvikinator/notion2md"
9
- );
10
- this.notionClient = options.notionClient;
5
+ if (!options) {
6
+ this.notionClient = undefined;
7
+ } else {
8
+ this.notionClient = options.notionClient || undefined;
9
+ }
11
10
  }
12
11
 
13
12
  toMarkdownString(mdBlocks = [], nestingLevel = 0) {
@@ -25,22 +24,36 @@ ${md.addTabSpace(mdBlocks.parent, nestingLevel)}
25
24
  return mdString;
26
25
  }
27
26
 
28
- async pageToMarkdown(id) {
27
+ /**
28
+ * @param {number} totalPage - Retrieve block children request number, page_size Maximum = totalPage * 100
29
+ */
30
+ async pageToMarkdown(id, totalPage = 1) {
29
31
  if (!id) throw new Error("pageToMarkdown takes page_id as argument");
30
- const blocks = await getBlockChildren(this.notionClient, id);
32
+ const blocks = await getBlockChildren(this.notionClient, id, totalPage);
31
33
  const parsedData = await this.blocksToMarkdown(blocks);
32
34
  return parsedData;
33
35
  }
34
36
 
35
37
  /**
36
38
  * @param {object} blocks - list of notion blocks
39
+ * @param {number} totalPage - Retrieve block children request number, page_size Maximum = totalPage * 100
37
40
  * @returns array of md blocks with their children
38
41
  */
39
- async blocksToMarkdown(blocks, mdBlocks = []) {
42
+ async blocksToMarkdown(blocks, mdBlocks = [], totalPage = 1) {
43
+ if (!this.notionClient) {
44
+ throw new Error(
45
+ "notion client is not provided, for more details check out https://github.com/souvikinator/notion-to-md"
46
+ );
47
+ }
48
+
40
49
  for (let i = 0; i < blocks.length; i++) {
41
50
  let block = blocks[i];
42
51
  if (block.has_children) {
43
- let child_blocks = await getBlockChildren(this.notionClient, block.id);
52
+ let child_blocks = await getBlockChildren(
53
+ this.notionClient,
54
+ block.id,
55
+ totalPage
56
+ );
44
57
  mdBlocks.push({ parent: this.blockToMarkdown(block), children: [] });
45
58
  let l = mdBlocks.length;
46
59
  await this.blocksToMarkdown(child_blocks, mdBlocks[l - 1].children);
@@ -58,6 +71,8 @@ ${md.addTabSpace(mdBlocks.parent, nestingLevel)}
58
71
  * @returns markdown form of the passed block
59
72
  */
60
73
  blockToMarkdown(block) {
74
+ if (!block) throw new Error("notion block required");
75
+
61
76
  let parsedData = "",
62
77
  blockContent;
63
78
  const { type } = block;
@@ -97,7 +112,8 @@ ${md.addTabSpace(mdBlocks.parent, nestingLevel)}
97
112
  });
98
113
  }
99
114
 
100
- if (type === "code") parsedData = md.codeBlock(parsedData);
115
+ if (type === "code")
116
+ parsedData = md.codeBlock(parsedData, block[type].language);
101
117
  if (type === "heading_1") parsedData = md.heading1(parsedData);
102
118
  if (type === "heading_2") parsedData = md.heading2(parsedData);
103
119
  if (type === "heading_3") parsedData = md.heading3(parsedData);
@@ -116,13 +132,19 @@ ${md.addTabSpace(mdBlocks.parent, nestingLevel)}
116
132
  * @param {object} annotations annotation object of a notion block
117
133
  */
118
134
  annotatePlainText(text, annotations) {
119
- if (annotations.code) text = md.inlineCode(text);
120
- if (annotations.bold) text = md.bold(text);
121
- if (annotations.italic) text = md.italic(text);
122
- if (annotations.strikethrough) text = md.strikethrough(text);
123
- if (annotations.underline) text = md.underline(text);
135
+ const leading_space = text.match(/^\s*/)[0];
136
+ const trailing_space = text.match(/\s*$/)[0];
137
+ text = text.trim();
138
+
139
+ if (text !== "") {
140
+ if (annotations.code) text = md.inlineCode(text);
141
+ if (annotations.bold) text = md.bold(text);
142
+ if (annotations.italic) text = md.italic(text);
143
+ if (annotations.strikethrough) text = md.strikethrough(text);
144
+ if (annotations.underline) text = md.underline(text);
145
+ }
124
146
 
125
- return text;
147
+ return leading_space + text + trailing_space;
126
148
  }
127
149
  }
128
150
 
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "notion-to-md",
3
- "version": "1.0.4",
4
- "main": "notion-to-md.js",
3
+ "version": "1.0.8",
4
+ "main": "main.js",
5
+ "typings": "main.d.ts",
5
6
  "scripts": {
6
7
  "test": "echo \"Error: no test specified\" && exit 1"
7
8
  },
@@ -24,5 +25,8 @@
24
25
  "url": "https://github.com/souvikinator/notion-to-md/issues"
25
26
  },
26
27
  "homepage": "https://github.com/souvikinator/notion-to-md#readme",
27
- "description": "convert notion pages, block and list of blocks to markdown (supports nesting)"
28
+ "description": "convert notion pages, block and list of blocks to markdown (supports nesting)",
29
+ "dependencies": {
30
+ "@notionhq/client": "^0.4.11"
31
+ }
28
32
  }
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
- return `| ${text}`;
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) => {
package/utils/notion.js CHANGED
@@ -1,9 +1,33 @@
1
- exports.getBlockChildren = async (notionClient, block_id) => {
1
+ exports.getBlockChildren = async (notionClient, block_id, totalPage) => {
2
2
  try {
3
- const response = await notionClient.blocks.children.list({
4
- block_id,
5
- });
6
- return response.results;
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
+ }
8
+ let result = [];
9
+ let start_cursor;
10
+ let pageSize = 100;
11
+ for (i = 0; i < totalPage; i++) {
12
+ // contain start_cursor
13
+ const response = await notionClient.blocks.children.list({
14
+ start_cursor: start_cursor,
15
+ page_size: pageSize,
16
+ block_id: block_id,
17
+ });
18
+ let current = response.results;
19
+ // delete start_cursor
20
+ if (start_cursor) {
21
+ current.shift();
22
+ }
23
+ result.push(...current);
24
+ if (current.length < 100) {
25
+ break;
26
+ }
27
+ pageSize = 101;
28
+ start_cursor = current[current.length - 1].id;
29
+ }
30
+ return result;
7
31
  } catch (e) {
8
32
  console.log(e);
9
33
  }