[Ipe-discuss] Ipe presentation to reveal.js
Fabien Lafont
lafont.fabien at gmail.com
Sun Feb 9 14:47:14 CET 2025
Hello everyone,
I have been using IPE to make my presentation for many years now but I find
it sometimes a bit limited when I want to include videos (or background
animations made with manim:
https://docs.manim.community/en/stable/tutorials/quickstart.html). I
therefore tried to switch to reveal.js paired with quarto (
https://quarto.org/docs/presentations/revealjs/).
On the positive side it looks really good and it is pretty easy to create
basic slides but, as often with such a solution, it is very rigid when it
comes to add drawings or plots.
I did, with a lot of help from chatGPT, a small script to convert slides
made with IPE to svg images that are then loaded in a quarto file. It is
working ok but I wanted to know if other people did similar things here and
probably in a better way I did. For example now I save each slide
separately in a SVG format which is a bit stupid when often each of these
slides have 90% similar content.
Here is my code:
import os
import subprocess
import xml.etree.ElementTree as ET
# ==============================
# 🔹 User Configuration 🔹
# ==============================
# Path to your Ipe presentation file (.ipe)
IPE_FILE = "your_presentation.ipe" # Change this to your actual file
# Output folder for generated SVGs and markdown
OUTPUT_FOLDER = "output"
# Name of the output Quarto markdown file
MARKDOWN_FILE = "slides.qmd"
# Path to the Ipe rendering tool (iperender)
IPE_RENDER_PATH = "C:/path/to/iperender.exe" # Change this to your actual
iperender path
# ==============================
# ✅ Script Execution Begins
# ==============================
# Step 1: Verify the IPE file exists
if not os.path.exists(IPE_FILE):
print(f"❌ ERROR: IPE file not found: {IPE_FILE}")
exit(1)
# Step 2: Create output directory
os.makedirs(OUTPUT_FOLDER, exist_ok=True)
# Step 3: Parse the IPE XML file to get pages (slides) and their views
print(f"🔍 Extracting pages and views from {IPE_FILE}...")
tree = ET.parse(IPE_FILE)
root = tree.getroot()
slide_views = [] # List to store all slide titles and their views
for page_idx, page in enumerate(root.findall(".//page"), start=1):
# Get the slide title (default: "Slide X")
title_element = page.find("title")
slide_title = title_element.text.strip() if title_element is not None
else f"Slide {page_idx}"
views = []
for view_idx, view in enumerate(page.findall("view"), start=1):
layers = view.attrib.get("layers", "").split()
if layers:
views.append((view_idx, layers))
if views:
slide_views.append((slide_title, page_idx, views))
print(f"✅ Found {len(slide_views)} slides with views.")
# Step 4: Render each view of each slide
svg_files = []
for slide_title, page_idx, views in slide_views:
for view_idx, (view_number, layers) in enumerate(views, start=1):
output_svg = os.path.join(OUTPUT_FOLDER, f"{slide_title.replace('
', '_')}_view_{view_idx}.svg")
output_svg = output_svg.replace("\\", "/") # Ensure cross-platform
compatibility
print(f"🎨 Rendering {slide_title} (Page {page_idx}, View
{view_idx}) -> {output_svg}...")
# Render the slide view directly from the IPE file
render_cmd = [IPE_RENDER_PATH, "-svg", "-page", str(page_idx),
"-view", str(view_number), IPE_FILE, output_svg]
result = subprocess.run(render_cmd, capture_output=True, text=True)
if result.returncode != 0 or not os.path.exists(output_svg):
print(f"❌ ERROR: Failed to render {slide_title} (Page
{page_idx}, View {view_idx}). Message:\n{result.stderr}")
continue
svg_files.append((slide_title, output_svg))
# Step 5: Check if any SVGs were generated
if not svg_files:
print("❌ ERROR: No slides generated. Check iperender and views.")
exit(1)
print(f"✅ Generated {len(svg_files)} slides.")
# Step 6: Generate Quarto/Reveal.js Markdown file with the "clean" theme
with open(MARKDOWN_FILE, "w") as f:
f.write(
"""---
title: "My Presentation"
format: revealjs
revealjs:
theme: [default, clean] # Using the "clean" theme for better styling
transition: fade
slideNumber: true
chalkboard: true
previewLinks: true
highlightStyle: github
---
"""
)
for slide_title, svg in svg_files:
svg = svg.replace("\\", "/") # Ensure paths are cross-platform
f.write(f"## {slide_title}\n\n") # Each view appears as a separate
slide with the same title
f.write(f"{{width=100%}}\n\n")
print(f"\n✅ Quarto/Reveal.js presentation generated: {MARKDOWN_FILE}")
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.science.uu.nl/pipermail/ipe-discuss/attachments/20250209/9edb6a0a/attachment.html>
More information about the Ipe-discuss
mailing list