[Ipe-discuss] Ipe presentation to reveal.js
Fabien Lafont
lafont.fabien at gmail.com
Mon Feb 10 16:30:40 CET 2025
Hi Simon and Jan
Thanks both of us for your answers. I will try your approach Jan. Also
Simon your project sounds really cool! Please let us know when your student
defends his thesis if you can share the code with us.
Best
Fabien
On Mon, 10 Feb 2025 at 16:42, Simon Dominik Fink <sfink at ac.tuwien.ac.at>
wrote:
> >
> Hey Fabian,
>
> I currently have a bachelor student working on a tool that translates
> ipe objects to manim objects and that should allow to mostly faithfully
> render ipe slides to video via manim or to HTML via manim-slides +
> reveal.js. This should allow creating animations for all ipe-drawn
> objects and also all the other fancy things manim can do.
> Instead of statically doing the translation from ipe as a one-shot
> process that makes it hard to edit your ipe file once you started
> adding animations in manim, the idea is to have an ipe file and some
> annotating python file with the manim animations side-by-side and only
> do the translation at render time, so you can edit both files
> simultaneously.
> While I cannot share a public link just yet, the thesis should be
> handed in by the end of this month and I hope to be able to share more
> information shortly thereafter.
>
> Cheers,
> Niko from TU Wien
>
> > > Date: Sun, 9 Feb 2025 15:47:14 +0200
> > > From: Fabien Lafont <lafont.fabien at gmail.com>
> > > To: Ipe-discuss <ipe-discuss at lists.science.uu.nl>
> > > Subject: [Ipe-discuss] Ipe presentation to reveal.js
> > > Message-ID:
> > > <CAC9H_cgx9R=CJx22ZqOjP5K0Hb_HLKxq7-
> > > Ay19c7u+1Ury5f0Q at mail.gmail.com>
> > > Content-Type: text/plain; charset="utf-8"
> > >
> > > 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/20
> > > 250209/9edb6a0a/attachment-0001.html>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.science.uu.nl/pipermail/ipe-discuss/attachments/20250210/c6a2d445/attachment-0001.html>
More information about the Ipe-discuss
mailing list