<div dir="ltr"><div class="gmail_default" style="font-family:verdana,sans-serif;color:#000000">Hi Simon and Jan</div><div class="gmail_default" style="font-family:verdana,sans-serif;color:#000000"><br></div><div class="gmail_default" style="font-family:verdana,sans-serif;color:#000000">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.</div><div class="gmail_default" style="font-family:verdana,sans-serif;color:#000000"><br></div><div class="gmail_default" style="font-family:verdana,sans-serif;color:#000000">Best</div><div class="gmail_default" style="font-family:verdana,sans-serif;color:#000000"><br></div><div class="gmail_default" style="font-family:verdana,sans-serif;color:#000000">Fabien</div></div><br><div class="gmail_quote gmail_quote_container"><div dir="ltr" class="gmail_attr">On Mon, 10 Feb 2025 at 16:42, Simon Dominik Fink <<a href="mailto:sfink@ac.tuwien.ac.at">sfink@ac.tuwien.ac.at</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">> <br>
Hey Fabian,<br>
<br>
I currently have a bachelor student working on a tool that translates<br>
ipe objects to manim objects and that should allow to mostly faithfully<br>
render ipe slides to video via manim or to HTML via manim-slides +<br>
reveal.js. This should allow creating animations for all ipe-drawn<br>
objects and also all the other fancy things manim can do.<br>
Instead of statically doing the translation from ipe as a one-shot<br>
process that makes it hard to edit your ipe file once you started<br>
adding animations in manim, the idea is to have an ipe file and some<br>
annotating python file with the manim animations side-by-side and only<br>
do the translation at render time, so you can edit both files<br>
simultaneously.<br>
While I cannot share a public link just yet, the thesis should be<br>
handed in by the end of this month and I hope to be able to share more<br>
information shortly thereafter.<br>
<br>
Cheers,<br>
Niko from TU Wien<br>
<br>
> > Date: Sun, 9 Feb 2025 15:47:14 +0200<br>
> > From: Fabien Lafont <<a href="mailto:lafont.fabien@gmail.com" target="_blank">lafont.fabien@gmail.com</a>><br>
> > To: Ipe-discuss <<a href="mailto:ipe-discuss@lists.science.uu.nl" target="_blank">ipe-discuss@lists.science.uu.nl</a>><br>
> > Subject: [Ipe-discuss] Ipe presentation to reveal.js<br>
> > Message-ID:<br>
> > <CAC9H_cgx9R=CJx22ZqOjP5K0Hb_HLKxq7-<br>
> > <a href="mailto:Ay19c7u%2B1Ury5f0Q@mail.gmail.com" target="_blank">Ay19c7u+1Ury5f0Q@mail.gmail.com</a>><br>
> > Content-Type: text/plain; charset="utf-8"<br>
> > <br>
> > Hello everyone,<br>
> > <br>
> > I have been using IPE to make my presentation for many years now<br>
> > but I find<br>
> > it sometimes a bit limited when I want to include videos (or<br>
> > background<br>
> > animations made with manim:<br>
> > <a href="https://docs.manim.community/en/stable/tutorials/quickstart.html" rel="noreferrer" target="_blank">https://docs.manim.community/en/stable/tutorials/quickstart.html</a>).<br>
> > I<br>
> > therefore tried to switch to reveal.js paired with quarto (<br>
> > <a href="https://quarto.org/docs/presentations/revealjs/" rel="noreferrer" target="_blank">https://quarto.org/docs/presentations/revealjs/</a>).<br>
> > On the positive side it looks really good and it is pretty easy to<br>
> > create<br>
> > basic slides but, as often with such a solution, it is very rigid<br>
> > when it<br>
> > comes to add drawings or plots.<br>
> > <br>
> > I did, with a lot of help from chatGPT, a small script to convert<br>
> > slides<br>
> > made with IPE to svg images that are then loaded in a quarto file.<br>
> > It is<br>
> > working ok but I wanted to know if other people did similar things<br>
> > here and<br>
> > probably in a better way I did. For example now I save each slide<br>
> > separately in a SVG format which is a bit stupid when often each of<br>
> > these<br>
> > slides have 90% similar content.<br>
> > <br>
> > Here is my code:<br>
> > <br>
> > import os<br>
> > import subprocess<br>
> > import xml.etree.ElementTree as ET<br>
> > <br>
> > # ==============================<br>
> > # ? User Configuration ?<br>
> > # ==============================<br>
> > <br>
> > # Path to your Ipe presentation file (.ipe)<br>
> > IPE_FILE = "your_presentation.ipe" # Change this to your actual<br>
> > file<br>
> > <br>
> > # Output folder for generated SVGs and markdown<br>
> > OUTPUT_FOLDER = "output"<br>
> > <br>
> > # Name of the output Quarto markdown file<br>
> > MARKDOWN_FILE = "slides.qmd"<br>
> > <br>
> > # Path to the Ipe rendering tool (iperender)<br>
> > IPE_RENDER_PATH = "C:/path/to/iperender.exe" # Change this to your<br>
> > actual<br>
> > iperender path<br>
> > <br>
> > # ==============================<br>
> > # ? Script Execution Begins<br>
> > # ==============================<br>
> > <br>
> > # Step 1: Verify the IPE file exists<br>
> > if not os.path.exists(IPE_FILE):<br>
> > print(f"? ERROR: IPE file not found: {IPE_FILE}")<br>
> > exit(1)<br>
> > <br>
> > # Step 2: Create output directory<br>
> > os.makedirs(OUTPUT_FOLDER, exist_ok=True)<br>
> > <br>
> > # Step 3: Parse the IPE XML file to get pages (slides) and their<br>
> > views<br>
> > print(f"? Extracting pages and views from {IPE_FILE}...")<br>
> > <br>
> > tree = ET.parse(IPE_FILE)<br>
> > root = tree.getroot()<br>
> > <br>
> > slide_views = [] # List to store all slide titles and their views<br>
> > <br>
> > for page_idx, page in enumerate(root.findall(".//page"), start=1):<br>
> > # Get the slide title (default: "Slide X")<br>
> > title_element = page.find("title")<br>
> > slide_title = title_element.text.strip() if title_element is<br>
> > not None<br>
> > else f"Slide {page_idx}"<br>
> > <br>
> > views = []<br>
> > for view_idx, view in enumerate(page.findall("view"), start=1):<br>
> > layers = view.attrib.get("layers", "").split()<br>
> > if layers:<br>
> > views.append((view_idx, layers))<br>
> > <br>
> > if views:<br>
> > slide_views.append((slide_title, page_idx, views))<br>
> > <br>
> > print(f"? Found {len(slide_views)} slides with views.")<br>
> > <br>
> > # Step 4: Render each view of each slide<br>
> > svg_files = []<br>
> > <br>
> > for slide_title, page_idx, views in slide_views:<br>
> > for view_idx, (view_number, layers) in enumerate(views,<br>
> > start=1):<br>
> > output_svg = os.path.join(OUTPUT_FOLDER,<br>
> > f"{slide_title.replace('<br>
> > ', '_')}_view_{view_idx}.svg")<br>
> > output_svg = output_svg.replace("\\", "/") # Ensure cross-<br>
> > platform<br>
> > compatibility<br>
> > <br>
> > print(f"? Rendering {slide_title} (Page {page_idx}, View<br>
> > {view_idx}) -> {output_svg}...")<br>
> > <br>
> > # Render the slide view directly from the IPE file<br>
> > render_cmd = [IPE_RENDER_PATH, "-svg", "-page",<br>
> > str(page_idx),<br>
> > "-view", str(view_number), IPE_FILE, output_svg]<br>
> > result = subprocess.run(render_cmd, capture_output=True,<br>
> > text=True)<br>
> > <br>
> > if result.returncode != 0 or not<br>
> > os.path.exists(output_svg):<br>
> > print(f"? ERROR: Failed to render {slide_title} (Page<br>
> > {page_idx}, View {view_idx}). Message:\n{result.stderr}")<br>
> > continue<br>
> > <br>
> > svg_files.append((slide_title, output_svg))<br>
> > <br>
> > # Step 5: Check if any SVGs were generated<br>
> > if not svg_files:<br>
> > print("? ERROR: No slides generated. Check iperender and<br>
> > views.")<br>
> > exit(1)<br>
> > <br>
> > print(f"? Generated {len(svg_files)} slides.")<br>
> > <br>
> > # Step 6: Generate Quarto/Reveal.js Markdown file with the "clean"<br>
> > theme<br>
> > with open(MARKDOWN_FILE, "w") as f:<br>
> > f.write(<br>
> > """---<br>
> > title: "My Presentation"<br>
> > format: revealjs<br>
> > revealjs:<br>
> > theme: [default, clean] # Using the "clean" theme for better<br>
> > styling<br>
> > transition: fade<br>
> > slideNumber: true<br>
> > chalkboard: true<br>
> > previewLinks: true<br>
> > highlightStyle: github<br>
> > ---<br>
> > """<br>
> > )<br>
> > <br>
> > for slide_title, svg in svg_files:<br>
> > svg = svg.replace("\\", "/") # Ensure paths are cross-<br>
> > platform<br>
> > f.write(f"## {slide_title}\n\n") # Each view appears as a<br>
> > separate<br>
> > slide with the same title<br>
> > f.write(f"{{width=100%}}\n\n")<br>
> > <br>
> > print(f"\n? Quarto/Reveal.js presentation generated:<br>
> > {MARKDOWN_FILE}")<br>
> > -------------- next part --------------<br>
> > An HTML attachment was scrubbed...<br>
> > URL:<br>
> > <<a href="https://mailman.science.uu.nl/pipermail/ipe-discuss/attachments/20" rel="noreferrer" target="_blank">https://mailman.science.uu.nl/pipermail/ipe-discuss/attachments/20</a><br>
> > 250209/9edb6a0a/attachment-0001.html><br>
<br>
</blockquote></div>