This project's author has no affiliation with Notion
Want to render notion API blocks into HTML? This library is for you.
This package can be installed by adding notion_renderer
to your list of dependencies in mix.exs
:
def deps do
[
{:notion_renderer, "~> 0.1.0"}
]
end
- Better testing strategy and exhaustive testing
- Hex documentation (currently documentation is in this file)
Retrieving blocks via the API is not something this library handles. You need to do that and then provide blocks
to NotionRenderer.block_to_html/1,2
. In order to render child content, you also need to provide the _children
attribute which is a list of blocks. Basically, you can recursively hit the API to build up the blocks list.
Blocks are expected to be a string-based map. The blocks are taken as-is from the API, with the
added support of _children
.
# Retrieving blocks is up to you
blocks = retrieve_blocks_from_api()
# Then just pass them in!
html = NotionRenderer.block_to_html(blocks)
# or pass options
rewriter = fn href -> "modified #{href}" end
html = NotionRenderer.block_to_html(blocks, [link_rewriter: rewriter])
You can provide link_rewriter
option to rewrite all link hrefs. This option is useful to rewrite page links
into your platform's patterns.
All of the HTML renderers are replaceable via the config
property. It's undocumented at this time.
Notion's API does not provide any dimensional information. So if a video or image has been resized, then there is no access to that in the API. So, it will be max width. It's up to you to style via CSS.
Have an idea on how to best support these types? Make an issue to discuss:
- child_page
- child_database
- bookmark
- table_of_contents
- column
- column_list
- link_preview
- template
- link_to_page
- unsupported
Some types are supported but have caveats:
- bulleted_list_item (is implemented as a ul, does not follow the same display system as Notion)
- embed (is implemented as a figure containing the source)
- file (is implemented as a figure containing the source)
- pdf (is implemented as a figure containing the source)
- video (is implemented with a few common video providers embed code, but might be missing some. See
Html.VideoEmbed
for the list) - toggle (is implemented, but is just a
- )
- equation (is implemented, but you must use KaTeX to format it in JS)
- synced_block (is implemented, but only if you provide the
_children
property)
Rather than inlining styles, this code tries to use CSS classes whenever reasonable. You can overwrite these classes as needed, but the following stylesheet is a great start.
<style> .notion-callout { border-radius: 3px; padding: 1rem; white-space:pre-wrap; display:flex; gap: 10px; background-color: rgba(241, 241, 239, 1); } .notion-callout-content { flex-grow: 1; } .notion-video { margin: 0; } .notion-embed, .notion-file, .notion-pdf { margin: 1.25em 0; page-break-inside: avoid; } .notion-embed .notion-source, .notion-file .notion-source, .notion-pdf .notion-source { border: 1px solid #ddd; border-radius: 3px; padding: 1.5em; word-break: break-all; } .notion-image { border: none; margin: 1.5em 0; padding: 0; border-radius: 0; text-align: center; } .notion-caption { opacity: 0.5; font-size: 85%; margin-top: 0.5em; } .notion-video-embed-sizer { position: relative; padding-bottom: calc(9/16 * 100%); height: 0; } .notion-video-embed-sizer iframe, .notion-video-embed-sizer video { position: absolute; left: 0; top: 0; width: 100%; height: 100%; border: 0; margin: 0; } </style>