Skip to content
A better Notion.so Markdown importer
Python
Branch: master
Clone or download

Latest commit

Fetching latest commit…
Cannot retrieve the latest commit at this time.

Files

Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.github/workflows
md2notion
tests
.gitignore
CONTRIBUTING.md Support CollectionViewBlock, support nested lists (fixes #1), add mor… Jan 1, 2020
LICENSE.txt Added README, LICENSE, and setup.py Dec 1, 2019
README.md
requirements-ci.txt
requirements-dev.txt
requirements.txt
setup.py

README.md

build status pypi python versions twitter twitter

Notion.so Markdown Importer

An importer for Markdown files to Notion.so using notion-py

It provides these features over Notion.so's Markdown importer:

  • Picking a Notion.so page to upload to (instead of them all uploading to the root)
  • Code fences keep their original language (or as close as we can match it)
  • Code fences are formatted properly
  • Inline HTML is preserved
  • Markdown frontmatter is preserved
  • Local image references will be uploaded from relative URLs
  • Image alts are loaded as captions instead of as TextBlocks
  • Handles nested lists properly
  • Among other improvements...

Usage with Python 3.6+

  • pip install md2notion

  • From the command link you can run python -m md2notion.upload [token_v2] [page-url] [...markdown_path_glob_or_url]

  • OR In your Python file:

from notion.client import NotionClient
from md2notion.upload import upload

# Follow the instructions at https://github.com/jamalex/notion-py#quickstart to setup Notion.py
client = NotionClient(token_v2="<token_v2>")
page = client.get_block("https://www.notion.so/myorg/Test-c0d20a71c0944985ae96e661ccc99821")

with open("TestMarkdown.md", "r", encoding="utf-8") as mdFile:
    newPage = page.children.add_new(PageBlock, title="TestMarkdown Upload")
    upload(mdFile, newPage) #Appends the converted contents of TestMarkdown.md to newPage

If you need to process notion-py block descriptors after parsing from Markdown but before uploading, consider using convert and uploadBlock separately. Take a look at upload.py#upload() for more.

from md2notion.upload import convert, uploadBlock

rendered = convert(mdFile)

# Process the rendered array of `notion-py` block descriptors here
# (just dicts with some properties to pass to `notion-py`)

# Upload all the blocks
for blockDescriptor in rendered:
    uploadBlock(blockDescriptor, page, mdFile.name)

If you need to parse Markdown differently from the default, consider subclassing NotionPyRenderer (a BaseRenderer for mistletoe). You can then pass it to upload(..., notionPyRendererCls=NotionPyRenderer) as a parameter.

Example, Custom Hexo Importer

Here's an example that imports a Hexo blog (slghtly hacky).

import io
import os.path
import glob
from pathlib import Path
from notion.block import PageBlock
from notion.client import NotionClient
from md2notion.upload import upload

client = NotionClient(token_v2="<token_v2>")
page = client.get_block("https://www.notion.so/myorg/Test-c0d20a71c0944985ae96e661ccc99821")

for fp in glob.glob("../source/_posts/*.md", recursive=True):
    with open(fp, "r", encoding="utf-8") as mdFile:
        #Preprocess the Markdown frontmatter into yaml code fences
        mdStr = mdFile.read()
        mdChunks = mdStr.split("---")
        mdStr = \
f"""```yaml
{mdChunks[1]}
`` `

{'---'.join(mdChunks[2:])}
"""
        mdFile = io.StringIO(mdStr)
        mdFile.__dict__["name"] = fp #Set this so we can resolve images later

        pageName = os.path.basename(fp)[:40]
        newPage = page.children.add_new(PageBlock, title=pageName)
        print(f"Uploading {fp} to Notion.so at page {pageName}")
        #Get the image relative to the markdown file in the flavor that Hexo
        #stores its images (in a folder with the same name as the md file)
        def convertImagePath(imagePath, mdFilePath):
            return Path(mdFilePath).parent / Path(mdFilePath).stem / Path(imagePath)
        upload(mdFile, newPage, imagePathFunc=convertImagePath)

Contributing

See CONTRIBUTING.md

You can’t perform that action at this time.