Skip to main content

Write in Jupyter Notebooks. Publish anywhere.

Project description

nb2wb

Write in notebooks. Publish anywhere.

nb2wb turns notebook-native writing into paste-ready HTML for editors that do not understand Jupyter, Quarto, or LaTeX. Start from a notebook, a Markdown article, or a Quarto document, then target a neutral preview wrapper or a profile tuned for Substack, Medium, X Articles, LinkedIn, Dev.to, Hashnode, Ghost, or WordPress.

The project also ships a reverse scaffold. Use wb2nb or nb2wb.revert() to turn published HTML back into a Jupyter notebook when you need to recover prose, code blocks, and image-derived content.

Why People Reach for nb2wb

  • Render code cells as syntax-highlighted images so theme and spacing survive copy and paste.
  • Render display math as images and inline math as readable Unicode text.
  • Keep tables as native HTML or convert them to images when a platform editor is unreliable.
  • Wrap output for different publishing targets without rewriting article content.
  • Serve extracted images through --serve when editors reject embedded data URIs.
  • Reverse HTML posts back into notebook scaffolds, with OCR as an opt-in upgrade.
  • Apply safety limits and HTML/SVG sanitization by default for server-side use.

Supported Inputs

  • Jupyter notebooks: .ipynb
  • Quarto documents: .qmd
  • Markdown documents: .md
  • In-memory notebook payloads: dict / nbformat.NotebookNode
  • In-memory text payloads: raw strings or {"format": "...", "content": "..."}
  • Reverse conversion inputs: .html, .htm, and in-memory HTML payloads

Installation

Install the base package:

pip install nb2wb

Install extras only when you need them:

pip install "nb2wb[ocr]"     # local OCR for reverse conversion
pip install "nb2wb[openai]"  # OpenAI-backed OCR pipeline
pip install "nb2wb[gemini]"  # Google Gemini-backed OCR pipeline

For development:

git clone https://github.com/the-palindrome/nb2wb.git
cd nb2wb
pip install -e ".[dev]"

Quick Start

Convert a notebook to the default preview wrapper:

nb2wb notebook.ipynb

Target a platform profile:

nb2wb notebook.ipynb -t medium
nb2wb notebook.ipynb -t x
nb2wb notebook.ipynb -t linkedin

Use execution, raw mode, and wrapper overrides when you need them:

nb2wb report.qmd --execute
nb2wb report.ipynb --warnings
nb2wb report.ipynb --raw -o article_raw.html
nb2wb report.ipynb -t ghost --image-strategy embed --article-width 900
nb2wb report.ipynb --serve
nb2wb report.ipynb --verbose

Reverse an HTML article back into a notebook scaffold:

wb2nb article.html
wb2nb article.html -o recovered.ipynb
wb2nb article.html --ocr-pipeline local
OPENAI_API_KEY=... wb2nb article.html --ocr-pipeline openai --model your-model-name
GEMINI_API_KEY=... wb2nb article.html --ocr-pipeline gemini --model gemini-2.0-flash
GEMINI_API_KEY=... wb2nb article.html --ocr-pipeline gemini --model gemini-2.5-flash --verbose

Python API

nb2wb.convert() is content-only. Load files with helpers first, then pass the in-memory payload into the converter.

import nb2wb

payload = nb2wb.load_input_payload("notebook.ipynb")
html = nb2wb.convert(
    payload,
    target="substack",
    config={"latex": {"try_usetex": True}},
    verbose=True,
)

You can also enable package logging explicitly:

import nb2wb

nb2wb.configure_logging(verbose=True)

You can also pass text or notebook payloads directly:

import nb2wb

html = nb2wb.convert(
    {
        "format": "md",
        "content": "# Shipping Notes\n\n`nb2wb` handles this in memory.",
    },
    target="medium",
    raw_mode=True,
)

Reverse conversion follows the same pattern:

import nb2wb

payload = nb2wb.load_html_payload("article.html")
notebook = nb2wb.revert(payload)

Add OCR only when you want image-derived notebook cells:

from nb2wb.ocr.openai import OpenAIOCRPipeline

ocr_notebook = nb2wb.revert(
    payload,
    ocr_pipeline=OpenAIOCRPipeline(model="your-model-name"),
)

Examples

The examples/ directory now covers forward conversion, reverse conversion, API usage, Markdown directives, Quarto {output} chunks, visibility tags, rich HTML/SVG outputs, and target-specific publishing flows.

Useful entry points:

Security Model

nb2wb keeps the safe path on by default:

  • HTML and SVG fragments are sanitized.
  • CSS URLs are filtered.
  • Remote image fetching is SSRF-safe.
  • Local image handling blocks traversal and escape paths.
  • Notebook payloads are constrained by configurable size and workload limits.

Execution is different. If you enable --execute or execute=True, treat the notebook as untrusted code and isolate that runtime yourself.

Documentation

Development

Run the test suite:

pytest

Build docs locally:

pip install -e ".[docs]"
sphinx-build -b html docs docs/_build/html

The detailed test guide lives in tests/README.md.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nb2wb-0.3.1.tar.gz (92.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nb2wb-0.3.1-py3-none-any.whl (104.9 kB view details)

Uploaded Python 3

File details

Details for the file nb2wb-0.3.1.tar.gz.

File metadata

  • Download URL: nb2wb-0.3.1.tar.gz
  • Upload date:
  • Size: 92.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for nb2wb-0.3.1.tar.gz
Algorithm Hash digest
SHA256 62e8dfd5cb378ae829f23d9743fbe77f801622728af65d641410c2cdf93b41f5
MD5 5f5304f73f7a68f8e5d50daa416364ce
BLAKE2b-256 242f1ce4f1207f92f830515acf435adf30cf555e489c37cc488acb8154e8572b

See more details on using hashes here.

Provenance

The following attestation bundles were made for nb2wb-0.3.1.tar.gz:

Publisher: publish.yml on the-palindrome/nb2wb

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file nb2wb-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: nb2wb-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 104.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for nb2wb-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 e458d8a7ef59449e6cf95fdc677d567fe1119da1134c711babf8a95edfecb8b3
MD5 f48b9495aee4112303fdee0541f54429
BLAKE2b-256 8113138c4c7bcc9f1bfa46501271c79be693ddc18f6bb210e78690704eca043a

See more details on using hashes here.

Provenance

The following attestation bundles were made for nb2wb-0.3.1-py3-none-any.whl:

Publisher: publish.yml on the-palindrome/nb2wb

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page