{"id":15020598,"url":"https://github.com/cobertos/md2notion","last_synced_at":"2025-10-03T22:30:41.993Z","repository":{"id":40633395,"uuid":"225092402","full_name":"Cobertos/md2notion","owner":"Cobertos","description":"A better Notion.so Markdown importer","archived":true,"fork":false,"pushed_at":"2023-11-02T06:15:32.000Z","size":478,"stargazers_count":658,"open_issues_count":29,"forks_count":67,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-01-21T00:13:48.122Z","etag":null,"topics":["markdown","notion","python","python3"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Cobertos.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2019-12-01T01:39:55.000Z","updated_at":"2025-01-07T01:34:07.000Z","dependencies_parsed_at":"2023-01-31T02:00:21.883Z","dependency_job_id":"e490b68c-f9fd-44ac-b157-2ee4a316440f","html_url":"https://github.com/Cobertos/md2notion","commit_stats":{"total_commits":72,"total_committers":7,"mean_commits":"10.285714285714286","dds":0.25,"last_synced_commit":"a1ea97ecfef2e98a1fb242caf98a988eaca8d631"},"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cobertos%2Fmd2notion","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cobertos%2Fmd2notion/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cobertos%2Fmd2notion/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cobertos%2Fmd2notion/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Cobertos","download_url":"https://codeload.github.com/Cobertos/md2notion/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":235198412,"owners_count":18951500,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["markdown","notion","python","python3"],"created_at":"2024-09-24T19:55:19.136Z","updated_at":"2025-10-03T22:30:41.634Z","avatar_url":"https://github.com/Cobertos.png","language":"Python","readme":"### This package is package is no longer maintained. I stopped using Notion.so some time ago and switched to Obsidian due to persistant problems with then Notion API.\n\n---\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://github.com/Cobertos/md2notion/actions\" target=\"_blank\"\u003e\u003cimg alt=\"build status\" src=\"https://github.com/Cobertos/md2notion/workflows/Package%20Tests/badge.svg\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://pypi.org/project/md2notion/\" target=\"_blank\"\u003e\u003cimg alt=\"pypi python versions\" src=\"https://img.shields.io/pypi/pyversions/md2notion.svg\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://cobertos.com\" target=\"_blank\"\u003e\u003cimg alt=\"cobertos\" src=\"https://img.shields.io/badge/website-cobertos.com-888888.svg\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n# Notion.so Markdown Importer\n\nAn importer for Markdown files to [Notion.so](https://notion.so) using [`notion-py`](https://github.com/jamalex/notion-py)\n\nIt provides these features over Notion.so's Markdown importer:\n\n* Picking a Notion.so page to upload to (instead of them all uploading to the root)\n* Code fences keep their original language (or as close as we can match it)\n* Code fences are formatted properly\n* Inline HTML is preserved\n* (Optionally) Upload images that are memtioned in the HTML `\u003cimg\u003e` tags.\n* Markdown frontmatter is preserved\n* Local image references will be uploaded from relative URLs\n* Image alts are loaded as captions instead of as `TextBlock`s\n* Handles nested lists properly\n* Among other improvements...\n\nSupports Python 3.6+\n\n## Usage from CLI\n\n* `pip install md2notion`\n* Then run like `python -m md2notion [token_v2] [page-url] [...markdown_path_glob_or_url]`\n* The markdown at the given path will be added as a new child to the Notion.so note at `page-url`\n\nThere are also some configuration options:\n\n* `--clear-previous`: If a child of the note at `page-url` has the same name as what you're uploading, it will first be removed.\n* `--append`: Instead of making a new child, it will append the markdown contents to the note at `page-url`\n* `--html-img`: Upload images that are memtioned in the HTML `\u003cimg\u003e` tags.\n\n## Usage from script\n\n* `pip install md2notion`\n* In your Python file:\n```python\nfrom notion.client import NotionClient\nfrom notion.block import PageBlock\nfrom md2notion.upload import upload\n\n# Follow the instructions at https://github.com/jamalex/notion-py#quickstart to setup Notion.py\nclient = NotionClient(token_v2=\"\u003ctoken_v2\u003e\")\npage = client.get_block(\"https://www.notion.so/myorg/Test-c0d20a71c0944985ae96e661ccc99821\")\n\nwith open(\"TestMarkdown.md\", \"r\", encoding=\"utf-8\") as mdFile:\n    newPage = page.children.add_new(PageBlock, title=\"TestMarkdown Upload\")\n    upload(mdFile, newPage) #Appends the converted contents of TestMarkdown.md to newPage\n```\n\nIf 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()`](https://github.com/Cobertos/md2notion/blob/master/md2notion/upload.py) for more.\n\n```python\nfrom md2notion.upload import convert, uploadBlock\n\nrendered = convert(mdFile)\n\n# Process the rendered array of `notion-py` block descriptors here\n# (just dicts with some properties to pass to `notion-py`)\n\n# Upload all the blocks\nfor blockDescriptor in rendered:\n    uploadBlock(blockDescriptor, page, mdFile.name)\n```\n\nIf you need to parse Markdown differently from the default, consider subclassing [`NotionPyRenderer`](https://github.com/Cobertos/md2notion/blob/master/md2notion/NotionPyRenderer.py) (a [`BaseRenderer` for `mistletoe`](https://github.com/miyuchina/mistletoe)). You can then pass it to `upload(..., notionPyRendererCls=NotionPyRenderer)` as a parameter.\n\n## Example, Custom Hexo Importer\n\nHere's an example that imports a Hexo blog (slghtly hacky).\n\n```python\nimport io\nimport os.path\nimport glob\nfrom pathlib import Path\nfrom notion.block import PageBlock\nfrom notion.client import NotionClient\nfrom md2notion.upload import upload\n\nclient = NotionClient(token_v2=\"\u003ctoken_v2\u003e\")\npage = client.get_block(\"https://www.notion.so/myorg/Test-c0d20a71c0944985ae96e661ccc99821\")\n\nfor fp in glob.glob(\"../source/_posts/*.md\", recursive=True):\n    with open(fp, \"r\", encoding=\"utf-8\") as mdFile:\n        #Preprocess the Markdown frontmatter into yaml code fences\n        mdStr = mdFile.read()\n        mdChunks = mdStr.split(\"---\")\n        mdStr = \\\nf\"\"\"```yaml\n{mdChunks[1]}\n`` `\n\n{'---'.join(mdChunks[2:])}\n\"\"\"\n        mdFile = io.StringIO(mdStr)\n        mdFile.__dict__[\"name\"] = fp #Set this so we can resolve images later\n\n        pageName = os.path.basename(fp)[:40]\n        newPage = page.children.add_new(PageBlock, title=pageName)\n        print(f\"Uploading {fp} to Notion.so at page {pageName}\")\n        #Get the image relative to the markdown file in the flavor that Hexo\n        #stores its images (in a folder with the same name as the md file)\n        def convertImagePath(imagePath, mdFilePath):\n            return Path(mdFilePath).parent / Path(mdFilePath).stem / Path(imagePath)\n        upload(mdFile, newPage, imagePathFunc=convertImagePath)\n```\n\n## Contributing\nSee [CONTRIBUTING.md](https://github.com/Cobertos/md2notion/blob/master/CONTRIBUTING.md)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcobertos%2Fmd2notion","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcobertos%2Fmd2notion","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcobertos%2Fmd2notion/lists"}