8

I'm trying to convert a Jupyter notebook that is using RISE to visualize the slides as a slideshow in the browser into a PDF file. The PDF file should have all pages in landscape mode and resemble the view in the browser. Of course, animations are not possible, but it should be possible to have fragments either combined in a single PDF slide or spread across multiple sort of "accumulating" slides (i.e. building upon their forerunner slides) .

I've been trying to create my own Jinja template that generates a LaTeX document utilizing the beamer document class, with not much success so far.

Do you know if there are any tools or templates or exporters or anything available that can help me with this process? Preferably automatically, like, utilizing nbconvert?

Hendrik Wiese
  • 2,010
  • 3
  • 22
  • 49

3 Answers3

11

Figured it out myself. Take these steps:

  1. launch jupyter nbconvert --to slides --post serve the_notebook.ipynb; the browser will open the node hosted the_notebook.slides.html
  2. replace the # after the the_notebook.slides.html in the browser URL with ?print-pdf so that the url looks most likely like http://127.0.0.1:8000/the_notebook.slides.html?print-pdf
  3. print to PDF file
Hendrik Wiese
  • 2,010
  • 3
  • 22
  • 49
2

Some time ago, I needed to programmatically convert Jupyter Notebook presentations to PDF slides. I did some research and you can use puppeteer to automate the process. You need a simple Python script for this:

import asyncio
import os
import tempfile

from subprocess import PIPE, Popen
from pyppeteer import launch

import concurrent.futures

async def html_to_pdf(html_file, pdf_file, pyppeteer_args=None):
    """Convert a HTML file to a PDF"""
    browser = await launch(
        handleSIGINT=False,
        handleSIGTERM=False,
        handleSIGHUP=False,
        headless=True,
        args=["--no-sandbox"],
    )

    page = await browser.newPage()
    await page.setViewport(dict(width=994, height=768))
    await page.emulateMedia("screen")

    await page.goto(f"file://{html_file}", {"waitUntil": ["networkidle2"]})

    page_margins = {
        "left": "20px",
        "right": "20px",
        "top": "30px",
        "bottom": "30px",
    }

    dimensions = await page.evaluate(
        """() => {
        return {
            width: document.body.scrollWidth,
            height: document.body.scrollHeight,
            offsetWidth: document.body.offsetWidth,
            offsetHeight: document.body.offsetHeight,
            deviceScaleFactor: window.devicePixelRatio,
        }
    }"""
    )
    width = dimensions["width"]
    height = dimensions["height"]

    await page.pdf(
        {
            "path": pdf_file,
            "format": "A4",
            "printBackground": True,
            "margin": page_margins,
        }
    )

    await browser.close()



if __name__ == "__main__":
    
    html_input_file = "/you/need/full/path/here/presentation.slides.html?print-pdf"
    pdf_output_file = "slides.pdf"

    pool = concurrent.futures.ThreadPoolExecutor()
    pool.submit(
        asyncio.run,
        html_to_pdf(
            html_input_file,
            pdf_output_file
        ),
    ).result()

The script accepts the HTML slides as input and produces the PDF slides as output. Please note that you need to provide full path for the HTML file. I wrote an article on how to convert notebook presentations to pdf slides. If you would like to apply styling, here is longer version of the script.

pplonski
  • 5,023
  • 1
  • 30
  • 34
0

I guess jupyter nbconvert --to pdf the_notebook.ipynb should work fine. You do need to install latex though.

Tejas Shetty
  • 685
  • 6
  • 30
  • 1
    This normally converts a notebook to a pdf, it doesn't create a pdf from the rendered RISE presentation, which cannot be done in a single step, but only through intermediate conversion >html>pdf for example as in the other answer. – Vincenzooo Aug 14 '21 at 17:37