99from enum import Enum
1010from importlib import resources
1111from pathlib import Path
12- from typing import Any , Callable , Dict , Generator , List , Optional , Type , Union
12+ from typing import Any , Callable , Dict , List , Optional , Type , Union
1313
1414import click
1515import cv2
1616import pptx
1717from click import Context , Parameter
18+ from jinja2 import Template
1819from lxml import etree
1920from PIL import Image
2021from pydantic import (
2930from pydantic_core import CoreSchema , core_schema
3031from tqdm import tqdm
3132
32- from . import data
33+ from . import templates
3334from .commons import folder_path_option , verbosity_option
3435from .config import PresentationConfig
3536from .logger import logger
3637from .present import get_scenes_presentation_config
3738
38- DATA_URI_FIX = r"""
39- // Fix found by @t-fritsch on GitHub
40- // see: https://github.com/hakimel/reveal.js/discussions/3362#discussioncomment-6651475.
41- function fixBase64VideoBackground(event) {
42- // event.previousSlide, event.currentSlide, event.indexh, event.indexv
43- if (event.currentSlide.getAttribute('data-background-video')) {
44- const background = Reveal.getSlideBackground(event.indexh, event.indexv),
45- video = background.querySelector('video'),
46- sources = video.querySelectorAll('source');
47-
48- sources.forEach((source, i) => {
49- const src = source.getAttribute('src');
50- if(src.match(/^data:video.*;base64$/)){
51- const nextSrc = sources[i+1]?.getAttribute('src');
52- video.setAttribute('src', `${src},${nextSrc}`);
53- }
54- });
55- }
56- }
57- Reveal.on( 'ready', fixBase64VideoBackground );
58- Reveal.on( 'slidechanged', fixBase64VideoBackground );
59- """
60-
6139
6240def open_with_default (file : Path ) -> None :
6341 system = platform .system ()
@@ -86,7 +64,7 @@ def validate_config_option(
8664 return config
8765
8866
89- def data_uri (file : Path ) -> str :
67+ def file_to_data_uri (file : Path ) -> str :
9068 """
9169 Reads a video and returns the corresponding data-uri.
9270 """
@@ -363,39 +341,15 @@ class RevealJS(Converter):
363341 title : str = "Manim Slides"
364342 model_config = ConfigDict (use_enum_values = True , extra = "forbid" )
365343
366- def get_sections_iter (self , assets_dir : Path ) -> Generator [str , None , None ]:
367- """Generates a sequence of sections, one per slide, that will be included into the html template."""
368- for presentation_config in self .presentation_configs :
369- for slide_config in presentation_config .slides :
370- file = slide_config .file
371-
372- logger .debug (f"Writing video section with file { file } " )
373-
374- if self .data_uri :
375- file = data_uri (file )
376- else :
377- file = assets_dir / file .name
378-
379- # TODO: document this
380- # Videos are muted because, otherwise, the first slide never plays correctly.
381- # This is due to a restriction in playing audio without the user doing anything.
382- # Later, this might be useful to only mute the first video, or to make it optional.
383- # Read more about this:
384- # https://developer.mozilla.org/en-US/docs/Web/Media/Autoplay_guide#autoplay_and_autoplay_blocking
385- if slide_config .loop :
386- yield f'<section data-background-size={ self .background_size .value } data-background-color="{ presentation_config .background_color } " data-background-video="{ file } " data-background-video-muted data-background-video-loop></section>'
387- else :
388- yield f'<section data-background-size={ self .background_size .value } data-background-color="{ presentation_config .background_color } " data-background-video="{ file } " data-background-video-muted></section>'
389-
390344 def load_template (self ) -> str :
391345 """Returns the RevealJS HTML template as a string."""
392346 if isinstance (self .template , Path ):
393347 return self .template .read_text ()
394348
395349 if sys .version_info < (3 , 9 ):
396- return resources .read_text (data , "revealjs_template .html" )
350+ return resources .read_text (templates , "revealjs .html" )
397351
398- return resources .files (data ).joinpath ("revealjs_template .html" ).read_text ()
352+ return resources .files (templates ).joinpath ("revealjs .html" ).read_text ()
399353
400354 def open (self , file : Path ) -> bool :
401355 return webbrowser .open (file .absolute ().as_uri ())
@@ -422,17 +376,13 @@ def convert_to(self, dest: Path) -> None:
422376 presentation_config .copy_to (full_assets_dir )
423377
424378 with open (dest , "w" ) as f :
425- sections = "" . join (self .get_sections_iter ( assets_dir ))
379+ revealjs_template = Template (self .load_template ( ))
426380
427- revealjs_template = self .load_template ()
428-
429- if self .data_uri :
430- data_uri_fix = DATA_URI_FIX
431- else :
432- data_uri_fix = ""
381+ options = self .dict ()
382+ options ["assets_dir" ] = assets_dir
433383
434- content = revealjs_template .format (
435- sections = sections , data_uri_fix = data_uri_fix , ** self . dict ()
384+ content = revealjs_template .render (
385+ file_to_data_uri = file_to_data_uri , ** options
436386 )
437387
438388 f .write (content )
0 commit comments