Skip to content

jkitchin/ox-ipynb

Repository files navigation

ox-ipynb — Export Org-mode files to Jupyter Notebooks

Overview

ox-ipynb is an Org-mode exporter that converts org-mode files to Jupyter notebooks (.ipynb format). It provides a seamless workflow for authoring computational notebooks in Org-mode while maintaining compatibility with the Jupyter ecosystem.

Jupyter notebooks consist of two basic cell types: markdown cells (for text, math, images) and code cells (for executable code with results). This exporter intelligently parses org-mode content into these cell types, preserving formatting, structure, and executable code blocks.

Key Features:

  • Multiple language kernels: Python, R, Julia, Clojure
  • Rich markdown export: LaTeX math, tables, images, links
  • Table of contents generation
  • Citations (org-cite and org-ref)
  • Slideshow support (RISE)
  • Cell and notebook metadata control
  • Participant notebooks (strips solutions/hidden content)
  • Export variations (with/without results)

Installation

Requirements

  • Emacs 30+
  • Org-mode 9.7+
  • Jupyter (for viewing/running notebooks)

Basic Setup

  1. Clone or download this repository
  2. Add to your Emacs configuration:
(add-to-list 'load-path "/path/to/ox-ipynb")
(require 'ox-ipynb)
  1. The export menu will be available in any org-mode buffer via C-c C-e n

Quick Start

Basic Export Workflow

  1. Create an org-mode file with code blocks:
#+TITLE: My First Notebook
#+AUTHOR: Your Name

* Introduction

This is a markdown cell.

print("Hello, Jupyter!")
  1. Export using C-c C-e n o (export to notebook and open)

Export Options

The export menu (C-c C-e n) provides several options:

KeyCommandDescription
bExport to bufferView JSON in Emacs buffer
nExport to notebookSave as .ipynb file
oExport to notebook and openSave and open in Jupyter
pExport to participant notebookRemove solutions and hidden content
rExport without results and openStrip all code results before export
sExport to slides and openConvert to RISE slideshow

Supported Languages

ox-ipynb supports multiple Jupyter kernels. Specify the language in your code blocks:

Python

import numpy as np
print(np.array([1, 2, 3]))

Or use ipython as the language name (legacy support).

R

library(ggplot2)
summary(iris)

Requirements: R, IRkernel package, and R kernel registered with Jupyter.

Julia

using Statistics
mean([1, 2, 3, 4, 5])

Clojure

(map inc [1 2 3 4 5])

Requirements: Clojupyter kernel installed.

Specifying Language Explicitly

If the first code block doesn’t match your notebook language, use:

#+OX-IPYNB-LANGUAGE: jupyter-python

Adding New Languages

To add support for new languages, extend ox-ipynb-kernelspecs and ox-ipynb-language-infos variables. See the existing definitions in ox-ipynb.el as examples.

Core Features

Code Blocks and Results

Code blocks are exported as code cells. Results are automatically included:

x = [1, 2, 3, 4, 5]
sum(x)

#+RESULTS:
: 15

Controlling Export with :exports parameter

# This block won't appear in the notebook
secret_config = "hidden"

# This block shows code and results (default)
print("Visible output")

Options: code, results, both (default), none

Tables

Org-mode tables export as markdown tables:

| Name    | Score | Grade |
|---------+-------+-------|
| Alice   |    92 | A     |
| Bob     |    85 | B     |
| Charlie |    78 | C     |

Tables with headers and complex formatting are preserved correctly. Recent improvements (Issue #23) ensure proper markdown table structure.

Mathematics (LaTeX)

Inline math and display equations are supported:

The equation $E = mc^2$ is Einstein's mass-energy equivalence.

The integral is:
$$\int_{0}^{\infty} e^{-x^2} dx = \frac{\sqrt{\pi}}{2}$$

Special handling prevents dollar signs in tables from being interpreted as math (Issue #81387fd).

Images and Links

External Links

Visit [[https://jupyter.org][Jupyter Project]] for more information.

Internal Links

Cross-references between sections work:

See [[*Introduction][the introduction section]] for background.

Images

[[file:plot.png]]

Images are embedded as base64-encoded data for portability. Matplotlib plots generated in code cells are automatically captured.

Table of Contents

Enable automatic TOC generation:

#+OPTIONS: toc:t

Control depth:

#+OPTIONS: toc:2

The TOC is inserted as a markdown cell with clickable navigation links.

Citations and Bibliography

ox-ipynb supports two citation systems:

org-cite (Recommended)

Modern Org 9.5+ citation system:

#+BIBLIOGRAPHY: references.bib

According to [cite:@smith2020], the results show...

#+PRINT_BIBLIOGRAPHY:

Citations are formatted as “(Author et al. YEAR)” and the bibliography is generated automatically.

org-ref

Traditional org-ref package:

bibliography:references.bib

According to cite:smith2020, the results show...

Configuration required:

(setq ox-ipynb-preprocess-hook
      '((lambda () (org-ref-csl-preprocess-buffer 'html))))

See examples/07-citations-org-cite.org and examples/08-citations-org-ref.org.

Advanced Features

Cell Metadata

Add metadata to individual cells using #+attr_ipynb::

#+attr_ipynb: :tags ["important" "review"]
result = compute_critical_value()

This is preserved in the notebook JSON and can be used by Jupyter extensions.

Notebook-Level Metadata

Add custom metadata to the entire notebook:

#+OX-IPYNB-NOTEBOOK-METADATA: (rise . ((autolaunch . t) (scroll . t)))

Useful for slideshow settings (RISE), execution control, and extensions.

Keyword Metadata

Export specific org-mode keywords to notebook metadata:

#+OX-IPYNB-KEYWORD-METADATA: AUTHOR DATE DESCRIPTION
#+TITLE: My Notebook
#+AUTHOR: John Doe
#+DATE: 2025-01-15
#+DESCRIPTION: Analysis of experimental data

These keywords are stored in the notebook metadata’s org section.

Slideshows (RISE)

Create presentations using Jupyter RISE extension:

#+OX-IPYNB-NOTEBOOK-METADATA: (rise . ((autolaunch . t)))

* Title Slide
#+attr_ipynb: (slideshow . ((slide_type . slide)))

Introduction content

* Main Point
#+attr_ipynb: (slideshow . ((slide_type . slide)))

Main content

** Details
#+attr_ipynb: (slideshow . ((slide_type . subslide)))

Additional details

Slide types: slide, subslide, fragment, skip, notes

Helper function: M-x ox-ipynb-insert-slide inserts the attribute line interactively.

Participant Notebooks

Create student/participant versions by automatically removing solutions and instructor notes:

def calculate_mean(data):
    ### BEGIN SOLUTION
    return sum(data) / len(data)
    ### END SOLUTION
    pass  # Student implements here

Export with C-c C-e n p to strip:

  • ### BEGIN SOLUTION ... ### END SOLUTION regions
  • ### BEGIN HIDDEN ... ### END HIDDEN regions
  • Elements marked with #+attr_ipynb: :remove t

Export Without Results

Create clean notebooks without cluttering output:

Export with C-c C-e n r to remove all #+RESULTS: blocks before export. Useful for:

  • Sharing notebooks for others to run fresh
  • Version control (cleaner diffs)
  • Reducing file size

Export Tags

Control what content is exported:

Exclude Tags

#+EXCLUDE_TAGS: noexport private

* Public Section
This will be exported.

* Private Notes                                                   :private:
This section won't appear in the notebook.

Select Tags

#+SELECT_TAGS: publish

* Draft Section
Not exported (no tag).

* Published Analysis                                             :publish:
This will be exported.

Broken Links Handling

The exporter handles broken or special links gracefully:

#+OPTIONS: broken-links:mark

Options: nil (error), t (ignore), mark (mark as broken)

Particularly useful when using citation links or other special link types.

Noweb Expansion

Org-babel noweb references are expanded during export:

<<setup>>
<<analysis>>
<<visualization>>

Configuration

Preprocessing Hooks

Customize export behavior with hooks:

(setq ox-ipynb-preprocess-hook
      '(my-custom-processing-function))

Common uses:

  • Citation processing (org-ref-csl-preprocess-buffer)
  • Custom transformations
  • Cleanup operations

Built-in preprocessing functions:

  • ox-ipynb-preprocess-ignore - Remove :ignore: tagged headings
  • ox-ipynb-preprocess-babel-calls - Remove babel calls
  • ox-ipynb-remove-solution - Strip solution regions
  • ox-ipynb-remove-hidden - Strip hidden regions
  • ox-ipynb-remove-remove - Remove marked elements

Export File Name

Control the output filename:

Buffer-level

#+EXPORT_FILE_NAME: my-notebook.ipynb

Subtree-level

Use property drawers:

* My Section
:PROPERTIES:
:EXPORT_FILE_NAME: section-notebook.ipynb
:END:

Programmatic

(let ((export-file-name "custom-name.ipynb"))
  (ox-ipynb-export-to-ipynb-file))

Publishing

Integrate with org-publish:

(setq org-publish-project-alist
      '(("notebooks"
         :base-directory "~/org/notebooks/"
         :publishing-directory "~/public/notebooks/"
         :publishing-function ox-ipynb-publish-to-notebook)))

Examples

The examples/ directory contains comprehensive demonstrations:

ExampleFeature
01-basic.orgBasic export workflow
02-exclude-tags.orgTag-based filtering
03-broken-links.orgLink handling
04-tables.orgTable export
05-latex-math.orgMathematical expressions
06-links-images.orgLinks and images
07-citations-org-cite.orgCitations (org-cite)
08-citations-org-ref.orgCitations (org-ref)
09-toc-export.orgTable of contents
10-metadata-cells.orgCell metadata
11-slideshow.orgRISE slideshows
12-languages-r.orgR language support
13-noweb.orgNoweb expansion
14-participant.orgParticipant notebooks
15-no-results.orgExport without results
16-custom-notebook-metadata.orgNotebook metadata
17-diagram-exports-results.orgDiagram exports

See examples/README.org for detailed documentation.

Programmatic Usage

Batch Export

Export multiple org files:

(ox-ipynb-export-org-file-to-ipynb-file "notebook.org")

Works in Dired: mark files and run M-x ox-ipynb-export-org-file-to-ipynb-file

From Elisp

;; Export to buffer
(ox-ipynb-export-to-ipynb-buffer)

;; Export to file
(ox-ipynb-export-to-ipynb-file)

;; Export and open
(ox-ipynb-export-to-ipynb-file-and-open)

;; Export subtree
(ox-ipynb-export-to-ipynb-file nil t)

Troubleshooting

Common Issues

Export menu not visible

Ensure ox-ipynb is loaded: (require 'ox-ipynb)

Language not recognized

Add language to ox-ipynb-kernelspecs and ox-ipynb-language-infos. A warning message will indicate missing languages.

Images not displaying

  • Check file paths (relative paths work best)
  • Ensure images exist before export
  • Matplotlib plots should use plt.show()

Math not rendering

  • Jupyter requires MathJax (usually included)
  • Use $...$ for inline, $$...$$ for display math
  • Avoid dollar signs in non-math contexts

Citations not working

  • org-cite: Requires oc.el and bibliography file accessible
  • org-ref: Requires preprocessing hook configuration
  • Check .bib file paths are correct

Debugging

Enable verbose output:

(setq org-export-with-broken-links 'mark)

Check the *Messages* buffer for warnings and errors.

Recent Changes

Recent improvements (see git log for details):

  • 2025: Support for :exports parameter in source blocks
  • 2025: Fixed table export (removed extra horizontal rules)
  • 2025: Custom notebook-level metadata support
  • 2025: Clojure/Clojupyter language support
  • 2025: Warning when language not in kernelspecs
  • 2025: Comprehensive example suite added
  • 2025: Metadata preservation through intermediate export
  • 2025: TOC duplication fixes
  • 2025: Removed s.el and dash.el dependencies

See commit history for complete changelog.

Contributing

Contributions welcome! Please:

  1. Add tests/examples for new features
  2. Update this README
  3. Follow existing code style
  4. Submit pull requests to https://github.com/jkitchin/ox-ipynb

License

GPL v2 or later. See source file for details.

Links

About

org-mode exporter to Jupyter notebooks

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 10