python_notion_to_md


Namepython_notion_to_md JSON
Version 0.1.6 PyPI version JSON
download
home_pageNone
SummaryConvert Notion pages to Markdown - Python port of notion-to-md
upload_time2025-02-04 05:04:17
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseMIT
keywords api-client converter markdown notion
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # notion_to_md (Python)

Convert Notion pages to clean, readable Markdown. Python port of [notion-to-md](https://github.com/souvikinator/notion-to-md).

## Quick Start

1. Install the package:
```bash
pip install notion_to_md
```

2. Basic usage:
```python
from notion_client import AsyncClient
from notion_to_md import NotionToMarkdown

async def convert_page(notion_token: str, page_id: str) -> str:
    # Initialize clients
    notion = AsyncClient(auth=notion_token)
    n2m = NotionToMarkdown(notion_client=notion)
    
    # Convert page to markdown
    md_blocks = await n2m.page_to_markdown(page_id)
    md_string = await n2m.to_markdown_string(md_blocks)
    
    return md_string['parent']  # Returns the main page content

# Usage
result = await convert_page("your-notion-token", "your-page-id")
print(result)
```

## Features

- 🎯 Supports all common Notion blocks (text, lists, tables, code, etc.)
- 📝 Preserves formatting (bold, italic, code, colors)
- 🖼️ Handles images (with optional base64 conversion)
- 📑 Supports nested content (child pages, synced blocks)
- ⚡ Modern async/await API
- 🔁 Built-in error handling and API retry logic

## Configuration

Control the converter's behavior with configuration options:

```python
from notion_to_md import NotionToMarkdown, ConfigurationOptions

n2m = NotionToMarkdown(
    notion_client=notion,
    config=ConfigurationOptions(
        # Core Options
        separate_child_page=False,  # True to split child pages into separate files
        parse_child_pages=True,     # False to skip child pages entirely
        
        # Image Handling
        convert_images_to_base64=False,  # True to embed images as base64
        
        # API Behavior
        api_retry_attempts=3,          # Number of retries for failed API calls
        api_rate_limit_delay=0.5,      # Delay between API calls
        max_concurrent_requests=5,      # Max concurrent API requests
        
        # Debugging
        debug_mode=False               # Enable detailed error tracking
    )
)
```

## Advanced Usage

### 1. Handling Child Pages

```python
# Convert page with child pages as separate files
md_blocks = await n2m.page_to_markdown(page_id)
md_string = await n2m.to_markdown_string(md_blocks)

# Main page content
main_content = md_string['parent']

# Child pages (if separate_child_page=True)
for page_id, content in md_string.items():
    if page_id != 'parent':
        # Each child page content
        print(f"Child page {page_id}: {content}")
```

### 2. Custom Block Transformers

Add custom handling for specific block types:

```python
def custom_code_block(block):
    """Custom transformer for code blocks"""
    if block["type"] != "code":
        return False  # Let default handler process it
        
    language = block["code"].get("language", "")
    code = "".join(text["plain_text"] for text in block["code"].get("rich_text", []))
    return f"```{language}\n{code}\n```"

# Register the transformer
n2m.set_custom_transformer("code", custom_code_block)
```

### 3. Error Handling and Debugging

Enable debug mode for detailed error tracking:

```python
n2m = NotionToMarkdown(
    notion_client=notion,
    config=ConfigurationOptions(debug_mode=True)
)

# Convert your page
md_blocks = await n2m.page_to_markdown(page_id)

# Get debug information
debug_info = n2m.get_debug_info()
if debug_info:
    print(f"Success rate: {debug_info['success_rate']}")
    print(f"Errors: {len(debug_info['errors'])}")
    print(f"Unhandled types: {debug_info['unhandled_types']}")
```

## Complete Example

Here's a full example that exports a Notion page to a Markdown file with metadata:

```python
async def export_notion_page(notion_token: str, page_id: str, output_file: str):
    notion = AsyncClient(auth=notion_token)
    n2m = NotionToMarkdown(notion_client=notion)
    
    try:
        # Get page metadata
        page = await notion.pages.retrieve(page_id=page_id)
        title = page.get('properties', {}).get('title', {}).get('title', [{}])[0].get('plain_text', 'Untitled')
        
        # Convert to markdown
        md_blocks = await n2m.page_to_markdown(page_id)
        md_string = await n2m.to_markdown_string(md_blocks)
        
        # Add metadata
        content = f"""---
title: {title}
notion_url: {page.get('url')}
last_edited: {page.get('last_edited_time')}
---

{md_string['parent']}"""
        
        # Save to file
        with open(output_file, 'w', encoding='utf-8') as f:
            f.write(content)
            
        print(f"✓ Exported: {title} -> {output_file}")
        
    except Exception as e:
        print(f"Error: {str(e)}")
```

## Supported Content

### Block Types
- Text (paragraphs, headings)
- Lists (bulleted, numbered, to-do)
- Media (images, videos, files)
- Embeds (bookmarks, PDFs)
- Structural (tables, columns, toggles)
- Interactive (equations, code blocks)
- Organizational (child pages, databases)

### Text Formatting
- Basic (bold, italic, strikethrough)
- Code (inline, blocks)
- Colors (text and background)
- Links
- Equations

## Known Limitations

Some Notion features currently have limited support:

- **Toggle Blocks**: Basic support only. Nested toggles and complex content within toggles may not render correctly.
- **Synced Blocks**: Limited support. Content is preserved but syncing behavior is not fully implemented.
- **Tables**: Basic support for simple tables. Complex formatting and column headers may not render correctly.

We're actively working on improving support for these features. For the most up-to-date status, please check our issues page.

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## License

[MIT](LICENSE)
            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "python_notion_to_md",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": "Emre Coklar <emre.coklar@gmail.com>",
    "keywords": "api-client, converter, markdown, notion",
    "author": null,
    "author_email": "Emre Coklar <emre.coklar@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/96/d9/a211520d47a5b1f7978657fc1d19e8bfed528028f36cdaf8b328342d60b7/python_notion_to_md-0.1.6.tar.gz",
    "platform": null,
    "description": "# notion_to_md (Python)\n\nConvert Notion pages to clean, readable Markdown. Python port of [notion-to-md](https://github.com/souvikinator/notion-to-md).\n\n## Quick Start\n\n1. Install the package:\n```bash\npip install notion_to_md\n```\n\n2. Basic usage:\n```python\nfrom notion_client import AsyncClient\nfrom notion_to_md import NotionToMarkdown\n\nasync def convert_page(notion_token: str, page_id: str) -> str:\n    # Initialize clients\n    notion = AsyncClient(auth=notion_token)\n    n2m = NotionToMarkdown(notion_client=notion)\n    \n    # Convert page to markdown\n    md_blocks = await n2m.page_to_markdown(page_id)\n    md_string = await n2m.to_markdown_string(md_blocks)\n    \n    return md_string['parent']  # Returns the main page content\n\n# Usage\nresult = await convert_page(\"your-notion-token\", \"your-page-id\")\nprint(result)\n```\n\n## Features\n\n- \ud83c\udfaf Supports all common Notion blocks (text, lists, tables, code, etc.)\n- \ud83d\udcdd Preserves formatting (bold, italic, code, colors)\n- \ud83d\uddbc\ufe0f Handles images (with optional base64 conversion)\n- \ud83d\udcd1 Supports nested content (child pages, synced blocks)\n- \u26a1 Modern async/await API\n- \ud83d\udd01 Built-in error handling and API retry logic\n\n## Configuration\n\nControl the converter's behavior with configuration options:\n\n```python\nfrom notion_to_md import NotionToMarkdown, ConfigurationOptions\n\nn2m = NotionToMarkdown(\n    notion_client=notion,\n    config=ConfigurationOptions(\n        # Core Options\n        separate_child_page=False,  # True to split child pages into separate files\n        parse_child_pages=True,     # False to skip child pages entirely\n        \n        # Image Handling\n        convert_images_to_base64=False,  # True to embed images as base64\n        \n        # API Behavior\n        api_retry_attempts=3,          # Number of retries for failed API calls\n        api_rate_limit_delay=0.5,      # Delay between API calls\n        max_concurrent_requests=5,      # Max concurrent API requests\n        \n        # Debugging\n        debug_mode=False               # Enable detailed error tracking\n    )\n)\n```\n\n## Advanced Usage\n\n### 1. Handling Child Pages\n\n```python\n# Convert page with child pages as separate files\nmd_blocks = await n2m.page_to_markdown(page_id)\nmd_string = await n2m.to_markdown_string(md_blocks)\n\n# Main page content\nmain_content = md_string['parent']\n\n# Child pages (if separate_child_page=True)\nfor page_id, content in md_string.items():\n    if page_id != 'parent':\n        # Each child page content\n        print(f\"Child page {page_id}: {content}\")\n```\n\n### 2. Custom Block Transformers\n\nAdd custom handling for specific block types:\n\n```python\ndef custom_code_block(block):\n    \"\"\"Custom transformer for code blocks\"\"\"\n    if block[\"type\"] != \"code\":\n        return False  # Let default handler process it\n        \n    language = block[\"code\"].get(\"language\", \"\")\n    code = \"\".join(text[\"plain_text\"] for text in block[\"code\"].get(\"rich_text\", []))\n    return f\"```{language}\\n{code}\\n```\"\n\n# Register the transformer\nn2m.set_custom_transformer(\"code\", custom_code_block)\n```\n\n### 3. Error Handling and Debugging\n\nEnable debug mode for detailed error tracking:\n\n```python\nn2m = NotionToMarkdown(\n    notion_client=notion,\n    config=ConfigurationOptions(debug_mode=True)\n)\n\n# Convert your page\nmd_blocks = await n2m.page_to_markdown(page_id)\n\n# Get debug information\ndebug_info = n2m.get_debug_info()\nif debug_info:\n    print(f\"Success rate: {debug_info['success_rate']}\")\n    print(f\"Errors: {len(debug_info['errors'])}\")\n    print(f\"Unhandled types: {debug_info['unhandled_types']}\")\n```\n\n## Complete Example\n\nHere's a full example that exports a Notion page to a Markdown file with metadata:\n\n```python\nasync def export_notion_page(notion_token: str, page_id: str, output_file: str):\n    notion = AsyncClient(auth=notion_token)\n    n2m = NotionToMarkdown(notion_client=notion)\n    \n    try:\n        # Get page metadata\n        page = await notion.pages.retrieve(page_id=page_id)\n        title = page.get('properties', {}).get('title', {}).get('title', [{}])[0].get('plain_text', 'Untitled')\n        \n        # Convert to markdown\n        md_blocks = await n2m.page_to_markdown(page_id)\n        md_string = await n2m.to_markdown_string(md_blocks)\n        \n        # Add metadata\n        content = f\"\"\"---\ntitle: {title}\nnotion_url: {page.get('url')}\nlast_edited: {page.get('last_edited_time')}\n---\n\n{md_string['parent']}\"\"\"\n        \n        # Save to file\n        with open(output_file, 'w', encoding='utf-8') as f:\n            f.write(content)\n            \n        print(f\"\u2713 Exported: {title} -> {output_file}\")\n        \n    except Exception as e:\n        print(f\"Error: {str(e)}\")\n```\n\n## Supported Content\n\n### Block Types\n- Text (paragraphs, headings)\n- Lists (bulleted, numbered, to-do)\n- Media (images, videos, files)\n- Embeds (bookmarks, PDFs)\n- Structural (tables, columns, toggles)\n- Interactive (equations, code blocks)\n- Organizational (child pages, databases)\n\n### Text Formatting\n- Basic (bold, italic, strikethrough)\n- Code (inline, blocks)\n- Colors (text and background)\n- Links\n- Equations\n\n## Known Limitations\n\nSome Notion features currently have limited support:\n\n- **Toggle Blocks**: Basic support only. Nested toggles and complex content within toggles may not render correctly.\n- **Synced Blocks**: Limited support. Content is preserved but syncing behavior is not fully implemented.\n- **Tables**: Basic support for simple tables. Complex formatting and column headers may not render correctly.\n\nWe're actively working on improving support for these features. For the most up-to-date status, please check our issues page.\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n## License\n\n[MIT](LICENSE)",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Convert Notion pages to Markdown - Python port of notion-to-md",
    "version": "0.1.6",
    "project_urls": null,
    "split_keywords": [
        "api-client",
        " converter",
        " markdown",
        " notion"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "e54d206424881a2bef2a0bdab4b9728e2530c5fd0147199401940596cfc1243a",
                "md5": "5e95939a8aaf139507667d0dc048105d",
                "sha256": "03b91faa23cb8102ea16efa2f200130c45b90fdca55c7fbd8aa085cb52cae068"
            },
            "downloads": -1,
            "filename": "python_notion_to_md-0.1.6-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "5e95939a8aaf139507667d0dc048105d",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 19012,
            "upload_time": "2025-02-04T05:04:15",
            "upload_time_iso_8601": "2025-02-04T05:04:15.850725Z",
            "url": "https://files.pythonhosted.org/packages/e5/4d/206424881a2bef2a0bdab4b9728e2530c5fd0147199401940596cfc1243a/python_notion_to_md-0.1.6-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "96d9a211520d47a5b1f7978657fc1d19e8bfed528028f36cdaf8b328342d60b7",
                "md5": "ad5ec4b03d34a79971903cd01ffd0918",
                "sha256": "0c968a7d278139be115ccd1b152aace9e49669454c1029869fb6b31e415c22a6"
            },
            "downloads": -1,
            "filename": "python_notion_to_md-0.1.6.tar.gz",
            "has_sig": false,
            "md5_digest": "ad5ec4b03d34a79971903cd01ffd0918",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 19942,
            "upload_time": "2025-02-04T05:04:17",
            "upload_time_iso_8601": "2025-02-04T05:04:17.708139Z",
            "url": "https://files.pythonhosted.org/packages/96/d9/a211520d47a5b1f7978657fc1d19e8bfed528028f36cdaf8b328342d60b7/python_notion_to_md-0.1.6.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-02-04 05:04:17",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "lcname": "python_notion_to_md"
}
        
Elapsed time: 0.52635s