Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 117 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,37 @@
![Stars](https://img.shields.io/github/stars/9gustin/react-notion-render.svg?style=social)

## Table of contents
- [Description](#description)
- [Installation](#installation)
- [Examples](#examples)
- [Basic example](#basic-example)
- [Blog with Notion as CMS](#blog-with-notion-as-cms)
- [Notion page to single page](#notion-page-to-single-page)
- [Usage](#usage)
- [Override built-in components (new)](#override-built-in-components-new)
- [Giving Styles](#giving-styles)
- [...moreProps](#moreprops)
- [Custom Components](#custom-components)
- [Display a custom table of contents](#display-a-custom-table-of-contents)
- [Guides](#guides)
- [How to use code blocks](https://github.com/9gustin/react-notion-render/wiki/About-code-blocks-and-how-to-colorize-it-%F0%9F%8E%A8)
- [Supported blocks](#supported-blocks)
- [Contributions](#contributions)
- [Table of contents](#table-of-contents)
- [Description](#description)
- [Installation](#installation)
- [Examples](#examples)
- [Basic example](#basic-example)
- [Fetching data with @notionhq/client](#fetching-data-with-notionhqclient)
- [Blog with Notion as CMS](#blog-with-notion-as-cms)
- [Notion page to single page](#notion-page-to-single-page)
- [Usage](#usage)
- [Override built-in components (new)](#override-built-in-components-new)
- [How works?](#how-works)
- [Mapping page url](#mapping-page-url)
- [Giving styles](#giving-styles)
- [Using default styles](#using-default-styles)
- [Using your own styles](#using-your-own-styles)
- [...moreProps](#moreprops)
- [Custom title url](#custom-title-url)
- [Preserve empty blocks](#preserve-empty-blocks)
- [Custom components](#custom-components)
- [Link](#link)
- [Image](#image)
- [Video](#video)
- [Display a custom table of contents](#display-a-custom-table-of-contents)
- [Guides](#guides)
- [How to use code blocks](#how-to-use-code-blocks)
- [Supported blocks](#supported-blocks)
- [Contributions:](#contributions)
- [Running the dev example](#running-the-dev-example)
- [Running another example](#running-another-example)
- [Project structure](#project-structure)
- [License](#license)

## Description

Expand Down Expand Up @@ -62,6 +77,89 @@ export const getStaticProps = async () => {
}
```

### Fetching data with @notionhq/client

```jsx
// e.g. /lib/notion-cms.ts

import { Client } from '@notionhq/client'

// Initialize a new client
const DATABASE_ID = '54d0ff3097694ad08bd21932d598b93d'
const notion = new Client({ auth: process.env.NOTION_TOKEN })

export const fetchPages = cache(() => {
return notion.databases.query({
database_id: DATABASE_ID,
filter: {
property: "status",
status: {
equals: "live",
}
} // if you have a status property for controlling the post status, you can easily filter it

})
})

// If you have a slug property you can use this function to get the page by slug
export const fetchBySlug = cache((slug: string) => {
return notion.databases.query({
database_id: notionBlogDatabaseId,
filter: {
property: "slug",
rich_text: {
equals: slug,
},
}
})
.then((res) => res.results[0] as PageObjectResponse | undefined)
})

// OR - you can simply just use the page id
export const getPageById = cache((pageId: string) => {
return notion.pages.retrieve({
page_id: pageId,
})
})

// This is a function to get the blocks of a page (and the children blocks)
export const getBlocksWithChildren = cache(async (pageId: string) => {
const response = await notion.blocks.children.list({
block_id: pageId,
})
const blocks = response.results as BlockObjectResponse[];

const childBlocks = await Promise.all(
blocks
.filter((block) => block.has_children)
.map(async (block) => {
return {
id: block.id,
children: await fetchPageBlock(block.id)
}
})
);

const blocksWithChildren = blocks.map((block) => {
// Add child blocks if the block should contain children but none exists
if (block.has_children) {
const blockType = block.type;
if (blockType in block && !(block as any)[blockType].children) {
(block as any)[blockType].children = childBlocks.find(
(x) => x.id === block.id
)?.children;
}
}
return block
});

return blocksWithChildren;
})
```

After initializing this, you can use the functions in the example above to get the blocks of a page. See the basic example above.


### Blog with Notion as CMS

I've maded a template to blog page, that use this package and allows you have a blog using notion as CMS. <br />
Expand Down Expand Up @@ -177,6 +275,8 @@ This is independient to the prop **useStyles**, you can combinate them or use se
| rnr-table_of_contents | Table of contents | ul |
| rnr-table | Table | table |
| rnr-table_row | Table row | tr |
| rnr-column_list | ColumnList | div |
| rnr-column | Column | div |


**Text Styles** <br />
Expand Down Expand Up @@ -344,6 +444,7 @@ Most common block types are supported. We happily accept pull requests to add su
| Table Of Contents | ✅ |
| Table | ✅ |
| Synced blocks | ✅ |
| Columns | ✅ |
| Web Bookmark | ❌ |

## Contributions:
Expand Down
168 changes: 168 additions & 0 deletions dev-example/data/columnListBlocks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
{
"object": "list",
"results": [{
"object": "block",
"id": "dummy-id-1",
"parent": {
"type": "page_id",
"page_id": "dummy-page-id-1"
},
"created_time": "2024-12-05T10:34:00.000Z",
"last_edited_time": "2024-12-05T10:34:00.000Z",
"created_by": {
"object": "user",
"id": "dummy-user-id-1"
},
"last_edited_by": {
"object": "user",
"id": "dummy-user-id-1"
},
"has_children": true,
"archived": false,
"in_trash": false,
"type": "column_list",
"column_list": {
"children": [
{
"object": "block",
"id": "dummy-id-2",
"parent": {
"type": "block_id",
"block_id": "dummy-id-1"
},
"created_time": "2024-12-05T10:34:00.000Z",
"last_edited_time": "2024-12-05T10:34:00.000Z",
"created_by": {
"object": "user",
"id": "dummy-user-id-1"
},
"last_edited_by": {
"object": "user",
"id": "dummy-user-id-1"
},
"has_children": true,
"archived": false,
"in_trash": false,
"type": "column",
"column": {
"children": [
{
"object": "block",
"id": "dummy-id-3",
"parent": {
"type": "block_id",
"block_id": "dummy-id-2"
},
"created_time": "2024-12-05T10:34:00.000Z",
"last_edited_time": "2024-12-05T13:23:00.000Z",
"created_by": {
"object": "user",
"id": "dummy-user-id-1"
},
"last_edited_by": {
"object": "user",
"id": "dummy-user-id-1"
},
"has_children": false,
"archived": false,
"in_trash": false,
"type": "paragraph",
"paragraph": {
"rich_text": [
{
"type": "text",
"text": {
"content": "LeftCol",
"link": null
},
"annotations": {
"bold": false,
"italic": false,
"strikethrough": false,
"underline": false,
"code": false,
"color": "default"
},
"plain_text": "LeftCol",
"href": null
}
],
"color": "default"
}
}
]
}
},
{
"object": "block",
"id": "dummy-id-4",
"parent": {
"type": "block_id",
"block_id": "dummy-id-1"
},
"created_time": "2024-12-05T10:34:00.000Z",
"last_edited_time": "2024-12-05T10:34:00.000Z",
"created_by": {
"object": "user",
"id": "dummy-user-id-1"
},
"last_edited_by": {
"object": "user",
"id": "dummy-user-id-1"
},
"has_children": true,
"archived": false,
"in_trash": false,
"type": "column",
"column": {
"children": [
{
"object": "block",
"id": "dummy-id-5",
"parent": {
"type": "block_id",
"block_id": "dummy-id-4"
},
"created_time": "2024-12-05T10:34:00.000Z",
"last_edited_time": "2024-12-05T13:23:00.000Z",
"created_by": {
"object": "user",
"id": "dummy-user-id-1"
},
"last_edited_by": {
"object": "user",
"id": "dummy-user-id-1"
},
"has_children": false,
"archived": false,
"in_trash": false,
"type": "paragraph",
"paragraph": {
"rich_text": [
{
"type": "text",
"text": {
"content": "RightCol",
"link": null
},
"annotations": {
"bold": false,
"italic": false,
"strikethrough": false,
"underline": false,
"code": false,
"color": "default"
},
"plain_text": "RightCol",
"href": null
}
],
"color": "default"
}
}
]
}
}
]
}
}]}
35 changes: 35 additions & 0 deletions dev-example/lib/notion.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,38 @@ export const getBlocks = async (blockId) => {
})
return response.results
}



export const getBlocksWithChildren = async (pageId) => {
const response = await notion.blocks.children.list({
block_id: pageId,
})
const blocks = response.results;

const childBlocks = await Promise.all(
blocks
.filter((block) => block.has_children)
.map(async (block) => {
return {
id: block.id,
children: await getBlocksWithChildren(block.id)
}
})
);

const blocksWithChildren = blocks.map((block) => {
// Add child blocks if the block should contain children but none exists
if (block.has_children) {
const blockType = block.type;
if (blockType in block && !block[blockType].children) {
block[blockType].children = childBlocks.find(
(x) => x.id === block.id
)?.children;
}
}
return block
});

return blocksWithChildren;
}
Loading