mirror of
https://github.com/jeertmans/manim-slides.git
synced 2025-08-06 14:19:52 +08:00
chore(convert): use Jinja2 for templating (#271)
* chore(convert): use Jinja2 for templating Use Jinja2 templating for more customizable rendering * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix(deps): jinja2 is no more optional --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
@ -49,6 +49,10 @@ In an effort to better document changes, this CHANGELOG document is now created.
|
|||||||
List of changes: `CONTINUE` to `NEXT`, `BACK` to `PREVIOUS`, and
|
List of changes: `CONTINUE` to `NEXT`, `BACK` to `PREVIOUS`, and
|
||||||
`REWIND` to `REPLAY`.
|
`REWIND` to `REPLAY`.
|
||||||
[#243](https://github.com/jeertmans/manim-slides/pull/243)
|
[#243](https://github.com/jeertmans/manim-slides/pull/243)
|
||||||
|
- Conversion to HTML now uses Jinja2 templating. The template file has
|
||||||
|
been modified accordingly, and old templates will not work anymore.
|
||||||
|
This is a **breaking change**.
|
||||||
|
[#271](https://github.com/jeertmans/manim-slides/pull/271)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
@ -9,12 +9,13 @@ from base64 import b64encode
|
|||||||
from enum import Enum
|
from enum import Enum
|
||||||
from importlib import resources
|
from importlib import resources
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Callable, Dict, Generator, List, Optional, Type, Union
|
from typing import Any, Callable, Dict, List, Optional, Type, Union
|
||||||
|
|
||||||
import click
|
import click
|
||||||
import cv2
|
import cv2
|
||||||
import pptx
|
import pptx
|
||||||
from click import Context, Parameter
|
from click import Context, Parameter
|
||||||
|
from jinja2 import Template
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from pydantic import (
|
from pydantic import (
|
||||||
@ -29,35 +30,12 @@ from pydantic import (
|
|||||||
from pydantic_core import CoreSchema, core_schema
|
from pydantic_core import CoreSchema, core_schema
|
||||||
from tqdm import tqdm
|
from tqdm import tqdm
|
||||||
|
|
||||||
from . import data
|
from . import templates
|
||||||
from .commons import folder_path_option, verbosity_option
|
from .commons import folder_path_option, verbosity_option
|
||||||
from .config import PresentationConfig
|
from .config import PresentationConfig
|
||||||
from .logger import logger
|
from .logger import logger
|
||||||
from .present import get_scenes_presentation_config
|
from .present import get_scenes_presentation_config
|
||||||
|
|
||||||
DATA_URI_FIX = r"""
|
|
||||||
// Fix found by @t-fritsch on GitHub
|
|
||||||
// see: https://github.com/hakimel/reveal.js/discussions/3362#discussioncomment-6651475.
|
|
||||||
function fixBase64VideoBackground(event) {
|
|
||||||
// event.previousSlide, event.currentSlide, event.indexh, event.indexv
|
|
||||||
if (event.currentSlide.getAttribute('data-background-video')) {
|
|
||||||
const background = Reveal.getSlideBackground(event.indexh, event.indexv),
|
|
||||||
video = background.querySelector('video'),
|
|
||||||
sources = video.querySelectorAll('source');
|
|
||||||
|
|
||||||
sources.forEach((source, i) => {
|
|
||||||
const src = source.getAttribute('src');
|
|
||||||
if(src.match(/^data:video.*;base64$/)){
|
|
||||||
const nextSrc = sources[i+1]?.getAttribute('src');
|
|
||||||
video.setAttribute('src', `${src},${nextSrc}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reveal.on( 'ready', fixBase64VideoBackground );
|
|
||||||
Reveal.on( 'slidechanged', fixBase64VideoBackground );
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def open_with_default(file: Path) -> None:
|
def open_with_default(file: Path) -> None:
|
||||||
system = platform.system()
|
system = platform.system()
|
||||||
@ -86,7 +64,7 @@ def validate_config_option(
|
|||||||
return config
|
return config
|
||||||
|
|
||||||
|
|
||||||
def data_uri(file: Path) -> str:
|
def file_to_data_uri(file: Path) -> str:
|
||||||
"""
|
"""
|
||||||
Reads a video and returns the corresponding data-uri.
|
Reads a video and returns the corresponding data-uri.
|
||||||
"""
|
"""
|
||||||
@ -363,39 +341,15 @@ class RevealJS(Converter):
|
|||||||
title: str = "Manim Slides"
|
title: str = "Manim Slides"
|
||||||
model_config = ConfigDict(use_enum_values=True, extra="forbid")
|
model_config = ConfigDict(use_enum_values=True, extra="forbid")
|
||||||
|
|
||||||
def get_sections_iter(self, assets_dir: Path) -> Generator[str, None, None]:
|
|
||||||
"""Generates a sequence of sections, one per slide, that will be included into the html template."""
|
|
||||||
for presentation_config in self.presentation_configs:
|
|
||||||
for slide_config in presentation_config.slides:
|
|
||||||
file = slide_config.file
|
|
||||||
|
|
||||||
logger.debug(f"Writing video section with file {file}")
|
|
||||||
|
|
||||||
if self.data_uri:
|
|
||||||
file = data_uri(file)
|
|
||||||
else:
|
|
||||||
file = assets_dir / file.name
|
|
||||||
|
|
||||||
# TODO: document this
|
|
||||||
# Videos are muted because, otherwise, the first slide never plays correctly.
|
|
||||||
# This is due to a restriction in playing audio without the user doing anything.
|
|
||||||
# Later, this might be useful to only mute the first video, or to make it optional.
|
|
||||||
# Read more about this:
|
|
||||||
# https://developer.mozilla.org/en-US/docs/Web/Media/Autoplay_guide#autoplay_and_autoplay_blocking
|
|
||||||
if slide_config.loop:
|
|
||||||
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>'
|
|
||||||
else:
|
|
||||||
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>'
|
|
||||||
|
|
||||||
def load_template(self) -> str:
|
def load_template(self) -> str:
|
||||||
"""Returns the RevealJS HTML template as a string."""
|
"""Returns the RevealJS HTML template as a string."""
|
||||||
if isinstance(self.template, Path):
|
if isinstance(self.template, Path):
|
||||||
return self.template.read_text()
|
return self.template.read_text()
|
||||||
|
|
||||||
if sys.version_info < (3, 9):
|
if sys.version_info < (3, 9):
|
||||||
return resources.read_text(data, "revealjs_template.html")
|
return resources.read_text(templates, "revealjs.html")
|
||||||
|
|
||||||
return resources.files(data).joinpath("revealjs_template.html").read_text()
|
return resources.files(templates).joinpath("revealjs.html").read_text()
|
||||||
|
|
||||||
def open(self, file: Path) -> bool:
|
def open(self, file: Path) -> bool:
|
||||||
return webbrowser.open(file.absolute().as_uri())
|
return webbrowser.open(file.absolute().as_uri())
|
||||||
@ -422,17 +376,13 @@ class RevealJS(Converter):
|
|||||||
presentation_config.copy_to(full_assets_dir)
|
presentation_config.copy_to(full_assets_dir)
|
||||||
|
|
||||||
with open(dest, "w") as f:
|
with open(dest, "w") as f:
|
||||||
sections = "".join(self.get_sections_iter(assets_dir))
|
revealjs_template = Template(self.load_template())
|
||||||
|
|
||||||
revealjs_template = self.load_template()
|
options = self.dict()
|
||||||
|
options["assets_dir"] = assets_dir
|
||||||
|
|
||||||
if self.data_uri:
|
content = revealjs_template.render(
|
||||||
data_uri_fix = DATA_URI_FIX
|
file_to_data_uri=file_to_data_uri, **options
|
||||||
else:
|
|
||||||
data_uri_fix = ""
|
|
||||||
|
|
||||||
content = revealjs_template.format(
|
|
||||||
sections=sections, data_uri_fix=data_uri_fix, **self.dict()
|
|
||||||
)
|
)
|
||||||
|
|
||||||
f.write(content)
|
f.write(content)
|
||||||
|
@ -1,290 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
|
||||||
|
|
||||||
<title>{title}</title>
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/{reveal_version}/reveal.min.css">
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/{reveal_version}/theme/{reveal_theme}.min.css">
|
|
||||||
|
|
||||||
<!-- Theme used for syntax highlighting of code -->
|
|
||||||
<!-- <link rel="stylesheet" href="lib/css/zenburn.css"> -->
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.13.1/styles/zenburn.min.css">
|
|
||||||
|
|
||||||
<!-- <link rel="stylesheet" href="index.css"> -->
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div class="reveal">
|
|
||||||
<div class="slides">
|
|
||||||
{sections}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/{reveal_version}/reveal.min.js"></script>
|
|
||||||
|
|
||||||
<!-- To include plugins, see: https://revealjs.com/plugins/ -->
|
|
||||||
|
|
||||||
<!-- <script src="index.js"></script> -->
|
|
||||||
<script>
|
|
||||||
Reveal.initialize({{
|
|
||||||
// The "normal" size of the presentation, aspect ratio will
|
|
||||||
// be preserved when the presentation is scaled to fit different
|
|
||||||
// resolutions. Can be specified using percentage units.
|
|
||||||
width: {width},
|
|
||||||
height: {height},
|
|
||||||
|
|
||||||
// Factor of the display size that should remain empty around
|
|
||||||
// the content
|
|
||||||
margin: {margin},
|
|
||||||
|
|
||||||
// Bounds for smallest/largest possible scale to apply to content
|
|
||||||
minScale: {min_scale},
|
|
||||||
maxScale: {max_scale},
|
|
||||||
|
|
||||||
// Display presentation control arrows
|
|
||||||
controls: {controls},
|
|
||||||
|
|
||||||
// Help the user learn the controls by providing hints, for example by
|
|
||||||
// bouncing the down arrow when they first encounter a vertical slide
|
|
||||||
controlsTutorial: {controls_tutorial},
|
|
||||||
|
|
||||||
// Determines where controls appear, "edges" or "bottom-right"
|
|
||||||
controlsLayout: {controls_layout},
|
|
||||||
|
|
||||||
// Visibility rule for backwards navigation arrows; "faded", "hidden"
|
|
||||||
// or "visible"
|
|
||||||
controlsBackArrows: {controls_back_arrows},
|
|
||||||
|
|
||||||
// Display a presentation progress bar
|
|
||||||
progress: {progress},
|
|
||||||
|
|
||||||
// Display the page number of the current slide
|
|
||||||
// - true: Show slide number
|
|
||||||
// - false: Hide slide number
|
|
||||||
//
|
|
||||||
// Can optionally be set as a string that specifies the number formatting:
|
|
||||||
// - "h.v": Horizontal . vertical slide number (default)
|
|
||||||
// - "h/v": Horizontal / vertical slide number
|
|
||||||
// - "c": Flattened slide number
|
|
||||||
// - "c/t": Flattened slide number / total slides
|
|
||||||
//
|
|
||||||
// Alternatively, you can provide a function that returns the slide
|
|
||||||
// number for the current slide. The function should take in a slide
|
|
||||||
// object and return an array with one string [slideNumber] or
|
|
||||||
// three strings [n1,delimiter,n2]. See #formatSlideNumber().
|
|
||||||
slideNumber: {slide_number},
|
|
||||||
|
|
||||||
// Can be used to limit the contexts in which the slide number appears
|
|
||||||
// - "all": Always show the slide number
|
|
||||||
// - "print": Only when printing to PDF
|
|
||||||
// - "speaker": Only in the speaker view
|
|
||||||
showSlideNumber: {show_slide_number},
|
|
||||||
|
|
||||||
// Use 1 based indexing for # links to match slide number (default is zero
|
|
||||||
// based)
|
|
||||||
hashOneBasedIndex: {hash_one_based_index},
|
|
||||||
|
|
||||||
// Add the current slide number to the URL hash so that reloading the
|
|
||||||
// page/copying the URL will return you to the same slide
|
|
||||||
hash: {hash},
|
|
||||||
|
|
||||||
// Flags if we should monitor the hash and change slides accordingly
|
|
||||||
respondToHashChanges: {respond_to_hash_changes},
|
|
||||||
|
|
||||||
// Push each slide change to the browser history. Implies `hash: true`
|
|
||||||
history: {history},
|
|
||||||
|
|
||||||
// Enable keyboard shortcuts for navigation
|
|
||||||
keyboard: {keyboard},
|
|
||||||
|
|
||||||
// Optional function that blocks keyboard events when retuning false
|
|
||||||
//
|
|
||||||
// If you set this to 'focused', we will only capture keyboard events
|
|
||||||
// for embedded decks when they are in focus
|
|
||||||
keyboardCondition: {keyboard_condition},
|
|
||||||
|
|
||||||
// Disables the default reveal.js slide layout (scaling and centering)
|
|
||||||
// so that you can use custom CSS layout
|
|
||||||
disableLayout: {disable_layout},
|
|
||||||
|
|
||||||
// Enable the slide overview mode
|
|
||||||
overview: {overview},
|
|
||||||
|
|
||||||
// Vertical centering of slides
|
|
||||||
center: {center},
|
|
||||||
|
|
||||||
// Enables touch navigation on devices with touch input
|
|
||||||
touch: {touch},
|
|
||||||
|
|
||||||
// Loop the presentation
|
|
||||||
loop: {loop},
|
|
||||||
|
|
||||||
// Change the presentation direction to be RTL
|
|
||||||
rtl: {rtl},
|
|
||||||
|
|
||||||
// Changes the behavior of our navigation directions.
|
|
||||||
//
|
|
||||||
// "default"
|
|
||||||
// Left/right arrow keys step between horizontal slides, up/down
|
|
||||||
// arrow keys step between vertical slides. Space key steps through
|
|
||||||
// all slides (both horizontal and vertical).
|
|
||||||
//
|
|
||||||
// "linear"
|
|
||||||
// Removes the up/down arrows. Left/right arrows step through all
|
|
||||||
// slides (both horizontal and vertical).
|
|
||||||
//
|
|
||||||
// "grid"
|
|
||||||
// When this is enabled, stepping left/right from a vertical stack
|
|
||||||
// to an adjacent vertical stack will land you at the same vertical
|
|
||||||
// index.
|
|
||||||
//
|
|
||||||
// Consider a deck with six slides ordered in two vertical stacks:
|
|
||||||
// 1.1 2.1
|
|
||||||
// 1.2 2.2
|
|
||||||
// 1.3 2.3
|
|
||||||
//
|
|
||||||
// If you're on slide 1.3 and navigate right, you will normally move
|
|
||||||
// from 1.3 -> 2.1. If "grid" is used, the same navigation takes you
|
|
||||||
// from 1.3 -> 2.3.
|
|
||||||
navigationMode: {navigation_mode},
|
|
||||||
|
|
||||||
// Randomizes the order of slides each time the presentation loads
|
|
||||||
shuffle: {shuffle},
|
|
||||||
|
|
||||||
// Turns fragments on and off globally
|
|
||||||
fragments: {fragments},
|
|
||||||
|
|
||||||
// Flags whether to include the current fragment in the URL,
|
|
||||||
// so that reloading brings you to the same fragment position
|
|
||||||
fragmentInURL: {fragment_in_url},
|
|
||||||
|
|
||||||
// Flags if the presentation is running in an embedded mode,
|
|
||||||
// i.e. contained within a limited portion of the screen
|
|
||||||
embedded: {embedded},
|
|
||||||
|
|
||||||
// Flags if we should show a help overlay when the question-mark
|
|
||||||
// key is pressed
|
|
||||||
help: {help},
|
|
||||||
|
|
||||||
// Flags if it should be possible to pause the presentation (blackout)
|
|
||||||
pause: {pause},
|
|
||||||
|
|
||||||
// Flags if speaker notes should be visible to all viewers
|
|
||||||
showNotes: {show_notes},
|
|
||||||
|
|
||||||
// Global override for autolaying embedded media (video/audio/iframe)
|
|
||||||
// - null: Media will only autoplay if data-autoplay is present
|
|
||||||
// - true: All media will autoplay, regardless of individual setting
|
|
||||||
// - false: No media will autoplay, regardless of individual setting
|
|
||||||
autoPlayMedia: {auto_play_media},
|
|
||||||
|
|
||||||
// Global override for preloading lazy-loaded iframes
|
|
||||||
// - null: Iframes with data-src AND data-preload will be loaded when within
|
|
||||||
// the viewDistance, iframes with only data-src will be loaded when visible
|
|
||||||
// - true: All iframes with data-src will be loaded when within the viewDistance
|
|
||||||
// - false: All iframes with data-src will be loaded only when visible
|
|
||||||
preloadIframes: {preload_iframes},
|
|
||||||
|
|
||||||
// Can be used to globally disable auto-animation
|
|
||||||
autoAnimate: {auto_animate},
|
|
||||||
|
|
||||||
// Optionally provide a custom element matcher that will be
|
|
||||||
// used to dictate which elements we can animate between.
|
|
||||||
autoAnimateMatcher: {auto_animate_matcher},
|
|
||||||
|
|
||||||
// Default settings for our auto-animate transitions, can be
|
|
||||||
// overridden per-slide or per-element via data arguments
|
|
||||||
autoAnimateEasing: {auto_animate_easing},
|
|
||||||
autoAnimateDuration: {auto_animate_duration},
|
|
||||||
autoAnimateUnmatched: {auto_animate_unmatched},
|
|
||||||
|
|
||||||
// CSS properties that can be auto-animated. Position & scale
|
|
||||||
// is matched separately so there's no need to include styles
|
|
||||||
// like top/right/bottom/left, width/height or margin.
|
|
||||||
autoAnimateStyles: {auto_animate_styles},
|
|
||||||
|
|
||||||
// Controls automatic progression to the next slide
|
|
||||||
// - 0: Auto-sliding only happens if the data-autoslide HTML attribute
|
|
||||||
// is present on the current slide or fragment
|
|
||||||
// - 1+: All slides will progress automatically at the given interval
|
|
||||||
// - false: No auto-sliding, even if data-autoslide is present
|
|
||||||
autoSlide: {auto_slide},
|
|
||||||
|
|
||||||
// Stop auto-sliding after user input
|
|
||||||
autoSlideStoppable: {auto_slide_stoppable},
|
|
||||||
|
|
||||||
// Use this method for navigation when auto-sliding (defaults to navigateNext)
|
|
||||||
autoSlideMethod: {auto_slide_method},
|
|
||||||
|
|
||||||
// Specify the average time in seconds that you think you will spend
|
|
||||||
// presenting each slide. This is used to show a pacing timer in the
|
|
||||||
// speaker view
|
|
||||||
defaultTiming: {default_timing},
|
|
||||||
|
|
||||||
// Enable slide navigation via mouse wheel
|
|
||||||
mouseWheel: {mouse_wheel},
|
|
||||||
|
|
||||||
// Opens links in an iframe preview overlay
|
|
||||||
// Add `data-preview-link` and `data-preview-link="false"` to customise each link
|
|
||||||
// individually
|
|
||||||
previewLinks: {preview_links},
|
|
||||||
|
|
||||||
// Exposes the reveal.js API through window.postMessage
|
|
||||||
postMessage: {post_message},
|
|
||||||
|
|
||||||
// Dispatches all reveal.js events to the parent window through postMessage
|
|
||||||
postMessageEvents: {post_message_events},
|
|
||||||
|
|
||||||
// Focuses body when page changes visibility to ensure keyboard shortcuts work
|
|
||||||
focusBodyOnPageVisibilityChange: {focus_body_on_page_visibility_change},
|
|
||||||
|
|
||||||
// Transition style
|
|
||||||
transition: {transition}, // none/fade/slide/convex/concave/zoom
|
|
||||||
|
|
||||||
// Transition speed
|
|
||||||
transitionSpeed: {transition_speed}, // default/fast/slow
|
|
||||||
|
|
||||||
// Transition style for full page slide backgrounds
|
|
||||||
backgroundTransition: {background_transition}, // none/fade/slide/convex/concave/zoom
|
|
||||||
|
|
||||||
// The maximum number of pages a single slide can expand onto when printing
|
|
||||||
// to PDF, unlimited by default
|
|
||||||
pdfMaxPagesPerSlide: {pdf_max_pages_per_slide},
|
|
||||||
|
|
||||||
// Prints each fragment on a separate slide
|
|
||||||
pdfSeparateFragments: {pdf_separate_fragments},
|
|
||||||
|
|
||||||
// Offset used to reduce the height of content within exported PDF pages.
|
|
||||||
// This exists to account for environment differences based on how you
|
|
||||||
// print to PDF. CLI printing options, like phantomjs and wkpdf, can end
|
|
||||||
// on precisely the total height of the document whereas in-browser
|
|
||||||
// printing has to end one pixel before.
|
|
||||||
pdfPageHeightOffset: {pdf_page_height_offset},
|
|
||||||
|
|
||||||
// Number of slides away from the current that are visible
|
|
||||||
viewDistance: {view_distance},
|
|
||||||
|
|
||||||
// Number of slides away from the current that are visible on mobile
|
|
||||||
// devices. It is advisable to set this to a lower number than
|
|
||||||
// viewDistance in order to save resources.
|
|
||||||
mobileViewDistance: {mobile_view_distance},
|
|
||||||
|
|
||||||
// The display mode that will be used to show slides
|
|
||||||
display: {display},
|
|
||||||
|
|
||||||
// Hide cursor if inactive
|
|
||||||
hideInactiveCursor: {hide_inactive_cursor},
|
|
||||||
|
|
||||||
// Time before the cursor is hidden (in ms)
|
|
||||||
hideCursorTime: {hide_cursor_time}
|
|
||||||
}});
|
|
||||||
|
|
||||||
{data_uri_fix}
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
329
manim_slides/templates/revealjs.html
Normal file
329
manim_slides/templates/revealjs.html
Normal file
@ -0,0 +1,329 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||||
|
|
||||||
|
<title>{{ title }}</title>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/{{ reveal_version }}/reveal.min.css">
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/{{ reveal_version }}/theme/{{ reveal_theme }}.min.css">
|
||||||
|
|
||||||
|
<!-- Theme used for syntax highlighting of code -->
|
||||||
|
<!-- <link rel="stylesheet" href="lib/css/zenburn.css"> -->
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.13.1/styles/zenburn.min.css">
|
||||||
|
|
||||||
|
<!-- <link rel="stylesheet" href="index.css"> -->
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="reveal">
|
||||||
|
<div class="slides">
|
||||||
|
{%- for presentation_config in presentation_configs -%}
|
||||||
|
{% set outer_loop = loop %}
|
||||||
|
{%- for slide_config in presentation_config.slides -%}
|
||||||
|
{%- if data_uri -%}
|
||||||
|
{% set file = file_to_data_uri(slide_config.file) %}
|
||||||
|
{%- else -%}
|
||||||
|
{% set file = assets_dir / slide_config.file.name %}
|
||||||
|
{%- endif -%}
|
||||||
|
<section
|
||||||
|
data-background-size={{ background_size }}
|
||||||
|
data-background-color="{{ presentation_config.background_color }}"
|
||||||
|
data-background-video="{{ file }}"
|
||||||
|
{% if loop.index == 1 and outer_loop.index == 1 -%}
|
||||||
|
data-background-video-muted
|
||||||
|
{%- endif -%}
|
||||||
|
{% if slide_config.loop -%}
|
||||||
|
data-background-video-loop
|
||||||
|
{%- endif -%}>
|
||||||
|
</section>
|
||||||
|
{%- endfor -%}
|
||||||
|
{%- endfor -%}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/{{ reveal_version }}/reveal.min.js"></script>
|
||||||
|
|
||||||
|
<!-- To include plugins, see: https://revealjs.com/plugins/ -->
|
||||||
|
|
||||||
|
<!-- <script src="index.js"></script> -->
|
||||||
|
<script>
|
||||||
|
Reveal.initialize({
|
||||||
|
// The "normal" size of the presentation, aspect ratio will
|
||||||
|
// be preserved when the presentation is scaled to fit different
|
||||||
|
// resolutions. Can be specified using percentage units.
|
||||||
|
width: {{ width }},
|
||||||
|
height: {{ height }},
|
||||||
|
|
||||||
|
// Factor of the display size that should remain empty around
|
||||||
|
// the content
|
||||||
|
margin: {{ margin }},
|
||||||
|
|
||||||
|
// Bounds for smallest/largest possible scale to apply to content
|
||||||
|
minScale: {{ min_scale }},
|
||||||
|
maxScale: {{ max_scale }},
|
||||||
|
|
||||||
|
// Display presentation control arrows
|
||||||
|
controls: {{ controls }},
|
||||||
|
|
||||||
|
// Help the user learn the controls by providing hints, for example by
|
||||||
|
// bouncing the down arrow when they first encounter a vertical slide
|
||||||
|
controlsTutorial: {{ controls_tutorial }},
|
||||||
|
|
||||||
|
// Determines where controls appear, "edges" or "bottom-right"
|
||||||
|
controlsLayout: {{ controls_layout }},
|
||||||
|
|
||||||
|
// Visibility rule for backwards navigation arrows; "faded", "hidden"
|
||||||
|
// or "visible"
|
||||||
|
controlsBackArrows: {{ controls_back_arrows }},
|
||||||
|
|
||||||
|
// Display a presentation progress bar
|
||||||
|
progress: {{ progress }},
|
||||||
|
|
||||||
|
// Display the page number of the current slide
|
||||||
|
// - true: Show slide number
|
||||||
|
// - false: Hide slide number
|
||||||
|
//
|
||||||
|
// Can optionally be set as a string that specifies the number formatting:
|
||||||
|
// - "h.v": Horizontal . vertical slide number (default)
|
||||||
|
// - "h/v": Horizontal / vertical slide number
|
||||||
|
// - "c": Flattened slide number
|
||||||
|
// - "c/t": Flattened slide number / total slides
|
||||||
|
//
|
||||||
|
// Alternatively, you can provide a function that returns the slide
|
||||||
|
// number for the current slide. The function should take in a slide
|
||||||
|
// object and return an array with one string [slideNumber] or
|
||||||
|
// three strings [n1,delimiter,n2]. See #formatSlideNumber().
|
||||||
|
slideNumber: {{ slide_number }},
|
||||||
|
|
||||||
|
// Can be used to limit the contexts in which the slide number appears
|
||||||
|
// - "all": Always show the slide number
|
||||||
|
// - "print": Only when printing to PDF
|
||||||
|
// - "speaker": Only in the speaker view
|
||||||
|
showSlideNumber: {{ show_slide_number }},
|
||||||
|
|
||||||
|
// Use 1 based indexing for # links to match slide number (default is zero
|
||||||
|
// based)
|
||||||
|
hashOneBasedIndex: {{ hash_one_based_index }},
|
||||||
|
|
||||||
|
// Add the current slide number to the URL hash so that reloading the
|
||||||
|
// page/copying the URL will return you to the same slide
|
||||||
|
hash: {{ hash }},
|
||||||
|
|
||||||
|
// Flags if we should monitor the hash and change slides accordingly
|
||||||
|
respondToHashChanges: {{ respond_to_hash_changes }},
|
||||||
|
|
||||||
|
// Push each slide change to the browser history. Implies `hash: true`
|
||||||
|
history: {{ history }},
|
||||||
|
|
||||||
|
// Enable keyboard shortcuts for navigation
|
||||||
|
keyboard: {{ keyboard }},
|
||||||
|
|
||||||
|
// Optional function that blocks keyboard events when retuning false
|
||||||
|
//
|
||||||
|
// If you set this to 'focused', we will only capture keyboard events
|
||||||
|
// for embedded decks when they are in focus
|
||||||
|
keyboardCondition: {{ keyboard_condition }},
|
||||||
|
|
||||||
|
// Disables the default reveal.js slide layout (scaling and centering)
|
||||||
|
// so that you can use custom CSS layout
|
||||||
|
disableLayout: {{ disable_layout }},
|
||||||
|
|
||||||
|
// Enable the slide overview mode
|
||||||
|
overview: {{ overview }},
|
||||||
|
|
||||||
|
// Vertical centering of slides
|
||||||
|
center: {{ center }},
|
||||||
|
|
||||||
|
// Enables touch navigation on devices with touch input
|
||||||
|
touch: {{ touch }},
|
||||||
|
|
||||||
|
// Loop the presentation
|
||||||
|
loop: {{ loop }},
|
||||||
|
|
||||||
|
// Change the presentation direction to be RTL
|
||||||
|
rtl: {{ rtl }},
|
||||||
|
|
||||||
|
// Changes the behavior of our navigation directions.
|
||||||
|
//
|
||||||
|
// "default"
|
||||||
|
// Left/right arrow keys step between horizontal slides, up/down
|
||||||
|
// arrow keys step between vertical slides. Space key steps through
|
||||||
|
// all slides (both horizontal and vertical).
|
||||||
|
//
|
||||||
|
// "linear"
|
||||||
|
// Removes the up/down arrows. Left/right arrows step through all
|
||||||
|
// slides (both horizontal and vertical).
|
||||||
|
//
|
||||||
|
// "grid"
|
||||||
|
// When this is enabled, stepping left/right from a vertical stack
|
||||||
|
// to an adjacent vertical stack will land you at the same vertical
|
||||||
|
// index.
|
||||||
|
//
|
||||||
|
// Consider a deck with six slides ordered in two vertical stacks:
|
||||||
|
// 1.1 2.1
|
||||||
|
// 1.2 2.2
|
||||||
|
// 1.3 2.3
|
||||||
|
//
|
||||||
|
// If you're on slide 1.3 and navigate right, you will normally move
|
||||||
|
// from 1.3 -> 2.1. If "grid" is used, the same navigation takes you
|
||||||
|
// from 1.3 -> 2.3.
|
||||||
|
navigationMode: {{ navigation_mode }},
|
||||||
|
|
||||||
|
// Randomizes the order of slides each time the presentation loads
|
||||||
|
shuffle: {{ shuffle }},
|
||||||
|
|
||||||
|
// Turns fragments on and off globally
|
||||||
|
fragments: {{ fragments }},
|
||||||
|
|
||||||
|
// Flags whether to include the current fragment in the URL,
|
||||||
|
// so that reloading brings you to the same fragment position
|
||||||
|
fragmentInURL: {{ fragment_in_url }},
|
||||||
|
|
||||||
|
// Flags if the presentation is running in an embedded mode,
|
||||||
|
// i.e. contained within a limited portion of the screen
|
||||||
|
embedded: {{ embedded }},
|
||||||
|
|
||||||
|
// Flags if we should show a help overlay when the question-mark
|
||||||
|
// key is pressed
|
||||||
|
help: {{ help }},
|
||||||
|
|
||||||
|
// Flags if it should be possible to pause the presentation (blackout)
|
||||||
|
pause: {{ pause }},
|
||||||
|
|
||||||
|
// Flags if speaker notes should be visible to all viewers
|
||||||
|
showNotes: {{ show_notes }},
|
||||||
|
|
||||||
|
// Global override for autolaying embedded media (video/audio/iframe)
|
||||||
|
// - null: Media will only autoplay if data-autoplay is present
|
||||||
|
// - true: All media will autoplay, regardless of individual setting
|
||||||
|
// - false: No media will autoplay, regardless of individual setting
|
||||||
|
autoPlayMedia: {{ auto_play_media }},
|
||||||
|
|
||||||
|
// Global override for preloading lazy-loaded iframes
|
||||||
|
// - null: Iframes with data-src AND data-preload will be loaded when within
|
||||||
|
// the viewDistance, iframes with only data-src will be loaded when visible
|
||||||
|
// - true: All iframes with data-src will be loaded when within the viewDistance
|
||||||
|
// - false: All iframes with data-src will be loaded only when visible
|
||||||
|
preloadIframes: {{ preload_iframes }},
|
||||||
|
|
||||||
|
// Can be used to globally disable auto-animation
|
||||||
|
autoAnimate: {{ auto_animate }},
|
||||||
|
|
||||||
|
// Optionally provide a custom element matcher that will be
|
||||||
|
// used to dictate which elements we can animate between.
|
||||||
|
autoAnimateMatcher: {{ auto_animate_matcher }},
|
||||||
|
|
||||||
|
// Default settings for our auto-animate transitions, can be
|
||||||
|
// overridden per-slide or per-element via data arguments
|
||||||
|
autoAnimateEasing: {{ auto_animate_easing }},
|
||||||
|
autoAnimateDuration: {{ auto_animate_duration }},
|
||||||
|
autoAnimateUnmatched: {{ auto_animate_unmatched }},
|
||||||
|
|
||||||
|
// CSS properties that can be auto-animated. Position & scale
|
||||||
|
// is matched separately so there's no need to include styles
|
||||||
|
// like top/right/bottom/left, width/height or margin.
|
||||||
|
autoAnimateStyles: {{ auto_animate_styles }},
|
||||||
|
|
||||||
|
// Controls automatic progression to the next slide
|
||||||
|
// - 0: Auto-sliding only happens if the data-autoslide HTML attribute
|
||||||
|
// is present on the current slide or fragment
|
||||||
|
// - 1+: All slides will progress automatically at the given interval
|
||||||
|
// - false: No auto-sliding, even if data-autoslide is present
|
||||||
|
autoSlide: {{ auto_slide }},
|
||||||
|
|
||||||
|
// Stop auto-sliding after user input
|
||||||
|
autoSlideStoppable: {{ auto_slide_stoppable }},
|
||||||
|
|
||||||
|
// Use this method for navigation when auto-sliding (defaults to navigateNext)
|
||||||
|
autoSlideMethod: {{ auto_slide_method }},
|
||||||
|
|
||||||
|
// Specify the average time in seconds that you think you will spend
|
||||||
|
// presenting each slide. This is used to show a pacing timer in the
|
||||||
|
// speaker view
|
||||||
|
defaultTiming: {{ default_timing }},
|
||||||
|
|
||||||
|
// Enable slide navigation via mouse wheel
|
||||||
|
mouseWheel: {{ mouse_wheel }},
|
||||||
|
|
||||||
|
// Opens links in an iframe preview overlay
|
||||||
|
// Add `data-preview-link` and `data-preview-link="false"` to customise each link
|
||||||
|
// individually
|
||||||
|
previewLinks: {{ preview_links }},
|
||||||
|
|
||||||
|
// Exposes the reveal.js API through window.postMessage
|
||||||
|
postMessage: {{ post_message }},
|
||||||
|
|
||||||
|
// Dispatches all reveal.js events to the parent window through postMessage
|
||||||
|
postMessageEvents: {{ post_message_events }},
|
||||||
|
|
||||||
|
// Focuses body when page changes visibility to ensure keyboard shortcuts work
|
||||||
|
focusBodyOnPageVisibilityChange: {{ focus_body_on_page_visibility_change }},
|
||||||
|
|
||||||
|
// Transition style
|
||||||
|
transition: {{ transition }}, // none/fade/slide/convex/concave/zoom
|
||||||
|
|
||||||
|
// Transition speed
|
||||||
|
transitionSpeed: {{ transition_speed }}, // default/fast/slow
|
||||||
|
|
||||||
|
// Transition style for full page slide backgrounds
|
||||||
|
backgroundTransition: {{ background_transition }}, // none/fade/slide/convex/concave/zoom
|
||||||
|
|
||||||
|
// The maximum number of pages a single slide can expand onto when printing
|
||||||
|
// to PDF, unlimited by default
|
||||||
|
pdfMaxPagesPerSlide: {{ pdf_max_pages_per_slide }},
|
||||||
|
|
||||||
|
// Prints each fragment on a separate slide
|
||||||
|
pdfSeparateFragments: {{ pdf_separate_fragments }},
|
||||||
|
|
||||||
|
// Offset used to reduce the height of content within exported PDF pages.
|
||||||
|
// This exists to account for environment differences based on how you
|
||||||
|
// print to PDF. CLI printing options, like phantomjs and wkpdf, can end
|
||||||
|
// on precisely the total height of the document whereas in-browser
|
||||||
|
// printing has to end one pixel before.
|
||||||
|
pdfPageHeightOffset: {{ pdf_page_height_offset }},
|
||||||
|
|
||||||
|
// Number of slides away from the current that are visible
|
||||||
|
viewDistance: {{ view_distance }},
|
||||||
|
|
||||||
|
// Number of slides away from the current that are visible on mobile
|
||||||
|
// devices. It is advisable to set this to a lower number than
|
||||||
|
// viewDistance in order to save resources.
|
||||||
|
mobileViewDistance: {{ mobile_view_distance }},
|
||||||
|
|
||||||
|
// The display mode that will be used to show slides
|
||||||
|
display: {{ display }},
|
||||||
|
|
||||||
|
// Hide cursor if inactive
|
||||||
|
hideInactiveCursor: {{ hide_inactive_cursor }},
|
||||||
|
|
||||||
|
// Time before the cursor is hidden (in ms)
|
||||||
|
hideCursorTime: {{ hide_cursor_time }}
|
||||||
|
});
|
||||||
|
|
||||||
|
{% if data_uri %}
|
||||||
|
// Fix found by @t-fritsch on GitHub
|
||||||
|
// see: https://github.com/hakimel/reveal.js/discussions/3362#discussioncomment-6651475.
|
||||||
|
function fixBase64VideoBackground(event) {
|
||||||
|
// event.previousSlide, event.currentSlide, event.indexh, event.indexv
|
||||||
|
if (event.currentSlide.getAttribute('data-background-video')) {
|
||||||
|
const background = Reveal.getSlideBackground(event.indexh, event.indexv),
|
||||||
|
video = background.querySelector('video'),
|
||||||
|
sources = video.querySelectorAll('source');
|
||||||
|
|
||||||
|
sources.forEach((source, i) => {
|
||||||
|
const src = source.getAttribute('src');
|
||||||
|
if(src.match(/^data:video.*;base64$/)) {
|
||||||
|
const nextSrc = sources[i+1]?.getAttribute('src');
|
||||||
|
video.setAttribute('src', `${src},${nextSrc}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reveal.on( 'ready', fixBase64VideoBackground );
|
||||||
|
Reveal.on( 'slidechanged', fixBase64VideoBackground );
|
||||||
|
{% endif %}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
1125
poetry.lock
generated
1125
poetry.lock
generated
File diff suppressed because it is too large
Load Diff
@ -50,7 +50,7 @@ click = "^8.1.3"
|
|||||||
click-default-group = "^1.2.2"
|
click-default-group = "^1.2.2"
|
||||||
docutils = {version = "^0.20.1", optional = true}
|
docutils = {version = "^0.20.1", optional = true}
|
||||||
ipython = {version = ">=8.12.2", optional = true}
|
ipython = {version = ">=8.12.2", optional = true}
|
||||||
jinja2 = {version = "^3.1.2", optional = true}
|
jinja2 = "^3.1.2"
|
||||||
lxml = "^4.9.2"
|
lxml = "^4.9.2"
|
||||||
manim = {version = "^0.17.3", optional = true}
|
manim = {version = "^0.17.3", optional = true}
|
||||||
manimgl = {version = "^1.6.1", optional = true}
|
manimgl = {version = "^1.6.1", optional = true}
|
||||||
@ -71,7 +71,7 @@ tqdm = "^4.64.1"
|
|||||||
magic = ["manim", "ipython"]
|
magic = ["manim", "ipython"]
|
||||||
manim = ["manim"]
|
manim = ["manim"]
|
||||||
manimgl = ["manimgl"]
|
manimgl = ["manimgl"]
|
||||||
sphinx-directive = ["docutils", "jinja2", "manim"]
|
sphinx-directive = ["docutils", "manim"]
|
||||||
|
|
||||||
[tool.poetry.group.dev]
|
[tool.poetry.group.dev]
|
||||||
optional = true
|
optional = true
|
||||||
|
Reference in New Issue
Block a user