feat(cli): feally featured RevealJS template (#80)

* feat(cli): feally featured RevealJS template

This adds an option for every possible RevealJS option. Error messages are also improved.

RevealJS version is bumped to latest (4.4.0).

* feat(cli): add primitive support for arbitrary JS functions

* fix(cli): some typos / issues in template

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix(lib): pickling issue

* fix(lib): ignore typing error due to __reduce_ex__

* feat(cli): add template selection, fixes first slide bug, and rm stuff

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
Jérome Eertmans
2022-12-07 16:27:23 +01:00
committed by GitHub
parent a82ca81dc5
commit c0c73ad4d4
4 changed files with 537 additions and 176 deletions

View File

@ -48,7 +48,7 @@ jobs:
- name: Build animation and convert it into HTML slides - name: Build animation and convert it into HTML slides
run: | run: |
poetry run manim example.py ConvertExample poetry run manim example.py ConvertExample
poetry run manim-slides convert ConvertExample docs/source/_static/slides.html -cembedded=true -ccontrols=true poetry run manim-slides convert ConvertExample docs/source/_static/slides.html -ccontrols=true
- name: Build docs - name: Build docs
run: cd docs && make html run: cd docs && make html
- name: Upload artifact - name: Upload artifact

4
.gitignore vendored
View File

@ -23,3 +23,7 @@ docs/build/
docs/source/_static/slides_assets/ docs/source/_static/slides_assets/
docs/source/_static/slides.html docs/source/_static/slides.html
slides_assets/
slides.html

View File

@ -1,12 +1,12 @@
import os import os
import webbrowser import webbrowser
from enum import Enum from enum import Enum
from typing import Any, Callable, Dict, Generator, List, Type from typing import Any, Callable, Dict, Generator, List, Optional, Type, Union
import click import click
import pkg_resources import pkg_resources
from click import Context, Parameter from click import Context, Parameter
from pydantic import BaseModel from pydantic import BaseModel, PositiveInt, ValidationError
from .commons import folder_path_option, verbosity_option from .commons import folder_path_option, verbosity_option
from .config import PresentationConfig from .config import PresentationConfig
@ -34,14 +34,21 @@ def validate_config_option(
class Converter(BaseModel): # type: ignore class Converter(BaseModel): # type: ignore
presentation_configs: List[PresentationConfig] = [] presentation_configs: List[PresentationConfig] = []
assets_dir: str = "{basename}_assets" assets_dir: str = "{basename}_assets"
template: Optional[str] = None
def convert_to(self, dest: str) -> None: def convert_to(self, dest: str) -> None:
"""Converts self, i.e., a list of presentations, into a given format.""" """Converts self, i.e., a list of presentations, into a given format."""
raise NotImplementedError raise NotImplementedError
def load_template(self) -> str:
"""Returns the template as a string.
An empty string is returned if no template is used."""
return ""
def open(self, file: str) -> bool: def open(self, file: str) -> bool:
"""Opens a file, generated with converter, using appropriate application.""" """Opens a file, generated with converter, using appropriate application."""
return webbrowser.open(file) raise NotImplementedError
@classmethod @classmethod
def from_string(cls, s: str) -> Type["Converter"]: def from_string(cls, s: str) -> Type["Converter"]:
@ -51,11 +58,126 @@ class Converter(BaseModel): # type: ignore
}[s] }[s]
class JSBool(str, Enum): class Str(str):
"""A simple string, but quoted when needed."""
# This fixes pickling issue on Python 3.8
__reduce_ex__ = str.__reduce_ex__
def __str__(self) -> str:
"""Ensures that the string is correctly quoted."""
if self in ["true", "false", "null"]:
return super().__str__()
else:
return f"'{super().__str__()}'"
Function = str # Basically, anything
class JsTrue(str, Enum):
true = "true"
class JsFalse(str, Enum):
false = "false"
class JsBool(Str, Enum): # type: ignore
true = "true" true = "true"
false = "false" false = "false"
class JsNull(Str, Enum): # type: ignore
null = "null"
class ControlsLayout(Str, Enum): # type: ignore
edges = "edges"
bottom_right = "bottom-right"
class ControlsBackArrows(Str, Enum): # type: ignore
faded = "faded"
hidden = "hidden"
visibly = "visibly"
class SlideNumber(Str, Enum): # type: ignore
true = "true"
false = "false"
hdotv = "h.v"
handv = "h/v"
c = "c"
candt = "c/t"
class ShowSlideNumber(Str, Enum): # type: ignore
all = "all"
print = "print"
speaker = "speaker"
class KeyboardCondition(Str, Enum): # type: ignore
null = "null"
focused = "focused"
class NavigationMode(Str, Enum): # type: ignore
default = "default"
linear = "linear"
grid = "grid"
class AutoPlayMedia(Str, Enum): # type: ignore
null = "null"
true = "true"
false = "false"
PreloadIframes = AutoPlayMedia
class AutoAnimateMatcher(Str, Enum): # type: ignore
null = "null"
class AutoAnimateEasing(Str, Enum): # type: ignore
ease = "ease"
AutoSlide = Union[PositiveInt, JsFalse]
class AutoSlideMethod(Str, Enum): # type: ignore
null = "null"
MouseWheel = Union[JsNull, float]
class Transition(Str, Enum): # type: ignore
none = "none"
fade = "fade"
slide = "slide"
convex = "convex"
concave = "concave"
zoom = "zoom"
class TransitionSpeed(Str, Enum): # type: ignore
default = "default"
fast = "fast"
slow = "slow"
BackgroundTransition = Transition
class Display(Str, Enum): # type: ignore
block = "block"
class RevealTheme(str, Enum): class RevealTheme(str, Enum):
black = "black" black = "black"
white = "white" white = "white"
@ -71,21 +193,90 @@ class RevealTheme(str, Enum):
class RevealJS(Converter): class RevealJS(Converter):
background_color: str = "black" # Presentation size options from RevealJS
controls: JSBool = JSBool.false width: Union[Str, int] = Str("100%")
embedded: JSBool = JSBool.false height: Union[Str, int] = Str("100%")
fragments: JSBool = JSBool.false margin: float = 0.04
height: str = "100%" min_scale: float = 0.2
loop: JSBool = JSBool.false max_scale: float = 2.0
progress: JSBool = JSBool.false # Configuration options from RevealJS
reveal_version: str = "3.7.0" controls: JsBool = JsBool.false
controls_tutorial: JsBool = JsBool.true
controls_layout: ControlsLayout = ControlsLayout.bottom_right
controls_back_arrows: ControlsBackArrows = ControlsBackArrows.faded
progress: JsBool = JsBool.false
slide_number: SlideNumber = SlideNumber.false
show_slide_number: Union[ShowSlideNumber, Function] = ShowSlideNumber.all
hash_one_based_index: JsBool = JsBool.false
hash: JsBool = JsBool.false
respond_to_hash_changes: JsBool = JsBool.false
history: JsBool = JsBool.false
keyboard: JsBool = JsBool.true
keyboard_condition: Union[KeyboardCondition, Function] = KeyboardCondition.null
disable_layout: JsBool = JsBool.false
overview: JsBool = JsBool.true
center: JsBool = JsBool.true
touch: JsBool = JsBool.true
loop: JsBool = JsBool.false
rtl: JsBool = JsBool.false
navigation_mode: NavigationMode = NavigationMode.default
shuffle: JsBool = JsBool.false
fragments: JsBool = JsBool.true
fragment_in_url: JsBool = JsBool.true
embedded: JsBool = JsBool.false
help: JsBool = JsBool.true
pause: JsBool = JsBool.true
show_notes: JsBool = JsBool.false
auto_play_media: AutoPlayMedia = AutoPlayMedia.null
preload_iframes: PreloadIframes = PreloadIframes.null
auto_animate: JsBool = JsBool.true
auto_animate_matcher: Union[AutoAnimateMatcher, Function] = AutoAnimateMatcher.null
auto_animate_easing: AutoAnimateEasing = AutoAnimateEasing.ease
auto_animate_duration: float = 1.0
auto_animate_unmatched: JsBool = JsBool.true
auto_animate_styles: List[str] = [
"opacity",
"color",
"background-color",
"padding",
"font-size",
"line-height",
"letter-spacing",
"border-width",
"border-color",
"border-radius",
"outline",
"outline-offset",
]
auto_slide: AutoSlide = 0
auto_slide_stoppable: JsBool = JsBool.true
auto_slide_method: Union[AutoSlideMethod, Function] = AutoSlideMethod.null
default_timing: Union[JsNull, int] = JsNull.null
mouse_wheel: JsBool = JsBool.false
preview_links: JsBool = JsBool.false
post_message: JsBool = JsBool.true
post_message_events: JsBool = JsBool.false
focus_body_on_page_visibility_change: JsBool = JsBool.true
transition: Transition = Transition.none
transition_speed: TransitionSpeed = TransitionSpeed.default
background_transition: BackgroundTransition = BackgroundTransition.none
pdf_max_pages_per_slide: Union[int, str] = "Number.POSITIVE_INFINITY"
pdf_separate_fragments: JsBool = JsBool.true
pdf_page_height_offset: int = -1
view_distance: int = 3
mobile_view_distance: int = 2
display: Display = Display.block
hide_inactive_cursor: JsBool = JsBool.true
hide_cursor_time: int = 5000
# Add. options
background_color: str = "black" # TODO: use pydantic.color.Color
reveal_version: str = "4.4.0"
reveal_theme: RevealTheme = RevealTheme.black reveal_theme: RevealTheme = RevealTheme.black
shuffle: JSBool = JSBool.false
title: str = "Manim Slides" title: str = "Manim Slides"
width: str = "100%"
class Config: class Config:
use_enum_values = True use_enum_values = True
extra = "forbid"
def get_sections_iter(self) -> Generator[str, None, None]: def get_sections_iter(self) -> Generator[str, None, None]:
"""Generates a sequence of sections, one per slide, that will be included into the html template.""" """Generates a sequence of sections, one per slide, that will be included into the html template."""
@ -94,17 +285,27 @@ class RevealJS(Converter):
file = presentation_config.files[slide_config.start_animation] file = presentation_config.files[slide_config.start_animation]
file = os.path.join(self.assets_dir, os.path.basename(file)) file = os.path.join(self.assets_dir, os.path.basename(file))
# 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.
if slide_config.is_loop(): if slide_config.is_loop():
yield f'<section data-background-video="{file}" data-background-video-loop></section>' yield f'<section data-background-video="{file}" data-background-video-muted data-background-video-loop></section>'
else: else:
yield f'<section data-background-video="{file}"></section>' yield f'<section 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, str):
with open(self.template, "r") as f:
return f.read()
return pkg_resources.resource_string( return pkg_resources.resource_string(
__name__, "data/revealjs_template.html" __name__, "data/revealjs_template.html"
).decode() ).decode()
def open(self, file: str) -> bool:
return webbrowser.open(file)
def convert_to(self, dest: str) -> None: def convert_to(self, dest: str) -> None:
"""Converts this configuration into a RevealJS HTML presentation, saved to DEST.""" """Converts this configuration into a RevealJS HTML presentation, saved to DEST."""
dirname = os.path.dirname(dest) dirname = os.path.dirname(dest)
@ -138,19 +339,13 @@ def show_config_options(function: Callable[..., Any]) -> Callable[..., Any]:
if not value or ctx.resilient_parsing: if not value or ctx.resilient_parsing:
return return
to = ctx.params.get("to") to = ctx.params.get("to", "html")
if to: converter = Converter.from_string(to)(presentation_configs=[])
converter = Converter.from_string(to)(scenes=[]) for key, value in converter.dict().items():
for key, value in converter.dict().items(): click.echo(f"{key}: {repr(value)}")
click.echo(f"{key}: {repr(value)}")
ctx.exit() ctx.exit()
else:
raise click.UsageError(
"Using --show-config option requires to first specify --to option."
)
return click.option( return click.option(
"--show-config", "--show-config",
@ -163,6 +358,35 @@ def show_config_options(function: Callable[..., Any]) -> Callable[..., Any]:
)(function) )(function)
def show_template_option(function: Callable[..., Any]) -> Callable[..., Any]:
"""Wraps a function to add a `--show-template` option."""
def callback(ctx: Context, param: Parameter, value: bool) -> None:
if not value or ctx.resilient_parsing:
return
to = ctx.params.get("to", "html")
template = ctx.params.get("template", None)
converter = Converter.from_string(to)(
presentation_configs=[], template=template
)
click.echo(converter.load_template())
ctx.exit()
return click.option(
"--show-template",
is_flag=True,
help="Show the template (currently) used for a given conversion format and exit.",
default=None,
expose_value=False,
show_envvar=True,
callback=callback,
)(function)
@click.command() @click.command()
@click.argument("scenes", nargs=-1) @click.argument("scenes", nargs=-1)
@folder_path_option @folder_path_option
@ -187,8 +411,16 @@ def show_config_options(function: Callable[..., Any]) -> Callable[..., Any]:
"config_options", "config_options",
multiple=True, multiple=True,
callback=validate_config_option, callback=validate_config_option,
help="Configuration options passed to the converter. E.g., pass `-cbackground_color=red` to set the background color to red (if supported).", help="Configuration options passed to the converter. E.g., pass `-cshow_number=true` to display slide numbers.",
) )
@click.option(
"--use-template",
"template",
metavar="FILE",
type=click.Path(exists=True, dir_okay=False),
help="Use the template given by FILE instead of default one. To echo the default template, use `--show-template`.",
)
@show_template_option
@show_config_options @show_config_options
@verbosity_option @verbosity_option
def convert( def convert(
@ -199,6 +431,7 @@ def convert(
open_result: bool, open_result: bool,
force: bool, force: bool,
config_options: Dict[str, str], config_options: Dict[str, str],
template: Optional[str],
) -> None: ) -> None:
""" """
Convert SCENE(s) into a given format and writes the result in DEST. Convert SCENE(s) into a given format and writes the result in DEST.
@ -206,11 +439,29 @@ def convert(
presentation_configs = get_scenes_presentation_config(scenes, folder) presentation_configs = get_scenes_presentation_config(scenes, folder)
converter = Converter.from_string(to)( try:
presentation_configs=presentation_configs, **config_options converter = Converter.from_string(to)(
) presentation_configs=presentation_configs,
template=template,
**config_options,
)
converter.convert_to(dest) converter.convert_to(dest)
if open_result: if open_result:
converter.open(dest) converter.open(dest)
except ValidationError as e:
errors = e.errors()
msg = [
f"{len(errors)} error(s) occured with configuration options for '{to}', see below."
]
for error in errors:
option = error["loc"][0]
_msg = error["msg"]
msg.append(f"Option '{option}': {_msg}")
raise click.UsageError("\n".join(msg))

View File

@ -1,185 +1,291 @@
<!doctype html> <!doctype html>
<html> <html>
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>{title}</title> <title>{title}</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reveal.js@{reveal_version}/css/reveal.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/{reveal_version}/reveal.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reveal.js@{reveal_version}/css/theme/{reveal_theme}.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 --> <!-- Theme used for syntax highlighting of code -->
<!-- <link rel="stylesheet" href="lib/css/zenburn.css"> --> <!-- <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="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.13.1/styles/zenburn.min.css">
<!-- Printing and PDF exports --> <!-- <link rel="stylesheet" href="index.css"> -->
<script> </head>
var link = document.createElement('link');
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = window.location.search.match(/print-pdf/gi) ? 'https://cdn.jsdelivr.net/npm/reveal.js@{reveal_version}/css/print/pdf.css' : 'https://cdn.jsdelivr.net/npm/reveal.js@{reveal_version}/css/print/paper.css';
document.getElementsByTagName('head')[0].appendChild(link);
</script>
<!-- <link rel="stylesheet" href="index.css"> -->
</head>
<body> <body>
<div class="reveal"> <div class="reveal">
<div class="slides"> <div class="slides">
{sections} {sections}
</div> </div>
</div> </div>
<!--<script src="lib/js/head.min.js"></script>--> <script src="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/{reveal_version}/reveal.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/headjs@1.0.3/dist/1.0.0/head.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/reveal.js@{reveal_version}/js/reveal.min.js"></script>
<!-- <script src="index.js"></script> --> <!-- To include plugins, see: https://revealjs.com/plugins/ -->
<script>
// More info about config & dependencies:
// - https://github.com/hakimel/reveal.js#configuration
// - https://github.com/hakimel/reveal.js#dependencies
Reveal.initialize({{
// Display controls in the bottom right corner
controls: {controls},
width: '{width}', <!-- <script src="index.js"></script> -->
height: '{height}', <script>
Reveal.initialize({{
// Display a presentation progress bar // The "normal" size of the presentation, aspect ratio will
progress: {progress}, // be preserved when the presentation is scaled to fit different
// resolutions. Can be specified using percentage units.
width: {width},
height: {height},
// Set default timing of 2 minutes per slide // Factor of the display size that should remain empty around
defaultTiming: 120, // the content
margin: {margin},
// Display the page number of the current slide // Bounds for smallest/largest possible scale to apply to content
slideNumber: true, minScale: {min_scale},
maxScale: {max_scale},
// Push each slide change to the browser history // Display presentation control arrows
history: false, controls: {controls},
// Enable keyboard shortcuts for navigation // Help the user learn the controls by providing hints, for example by
keyboard: true, // bouncing the down arrow when they first encounter a vertical slide
controlsTutorial: {controls_tutorial},
// Enable the slide overview mode // Determines where controls appear, "edges" or "bottom-right"
overview: true, controlsLayout: {controls_layout},
// Vertical centering of slides // Visibility rule for backwards navigation arrows; "faded", "hidden"
center: true, // or "visible"
controlsBackArrows: {controls_back_arrows},
// Enables touch navigation on devices with touch input // Display a presentation progress bar
touch: true, progress: {progress},
// Loop the presentation // Display the page number of the current slide
loop: {loop}, // - 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},
// Change the presentation direction to be RTL // Can be used to limit the contexts in which the slide number appears
rtl: false, // - "all": Always show the slide number
// - "print": Only when printing to PDF
// - "speaker": Only in the speaker view
showSlideNumber: {show_slide_number},
// Randomizes the order of slides each time the presentation loads // Use 1 based indexing for # links to match slide number (default is zero
shuffle: {shuffle}, // based)
hashOneBasedIndex: {hash_one_based_index},
// Turns fragments on and off globally // Add the current slide number to the URL hash so that reloading the
fragments: {fragments}, // page/copying the URL will return you to the same slide
hash: {hash},
// Flags if the presentation is running in an embedded mode, // Flags if we should monitor the hash and change slides accordingly
// i.e. contained within a limited portion of the screen respondToHashChanges: {respond_to_hash_changes},
embedded: {embedded},
// Flags if we should show a help overlay when the questionmark // Push each slide change to the browser history. Implies `hash: true`
// key is pressed history: {history},
help: true,
// Flags if speaker notes should be visible to all viewers // Enable keyboard shortcuts for navigation
showNotes: false, keyboard: {keyboard},
// Global override for autolaying embedded media (video/audio/iframe) // Optional function that blocks keyboard events when retuning false
// - null: Media will only autoplay if data-autoplay is present //
// - true: All media will autoplay, regardless of individual setting // If you set this to 'focused', we will only capture keyboard events
// - false: No media will autoplay, regardless of individual setting // for embedded decks when they are in focus
autoPlayMedia: null, keyboardCondition: {keyboard_condition},
// Number of milliseconds between automatically proceeding to the // Disables the default reveal.js slide layout (scaling and centering)
// next slide, disabled when set to 0, this value can be overwritten // so that you can use custom CSS layout
// by using a data-autoslide attribute on your slides disableLayout: {disable_layout},
autoSlide: 0,
// Stop auto-sliding after user input // Enable the slide overview mode
autoSlideStoppable: true, overview: {overview},
// Use this method for navigation when auto-sliding // Vertical centering of slides
autoSlideMethod: Reveal.navigateNext, center: {center},
// Enable slide navigation via mouse wheel // Enables touch navigation on devices with touch input
mouseWheel: false, touch: {touch},
// Hides the address bar on mobile devices // Loop the presentation
hideAddressBar: true, loop: {loop},
// Opens links in an iframe preview overlay // Change the presentation direction to be RTL
previewLinks: true, rtl: {rtl},
// Transition style // Changes the behavior of our navigation directions.
transition: 'none', // none/fade/slide/convex/concave/zoom //
// "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},
// Transition speed // Randomizes the order of slides each time the presentation loads
transitionSpeed: 'default', // default/fast/slow shuffle: {shuffle},
// Transition style for full page slide backgrounds // Turns fragments on and off globally
backgroundTransition: 'none', // none/fade/slide/convex/concave/zoom fragments: {fragments},
// Number of slides away from the current that are visible // Flags whether to include the current fragment in the URL,
viewDistance: 3, // so that reloading brings you to the same fragment position
fragmentInURL: {fragment_in_url},
// Parallax background image // Flags if the presentation is running in an embedded mode,
parallaxBackgroundImage: '', // e.g. "'https://s3.amazonaws.com/hakim-static/reveal-js/reveal-parallax-1.jpg'" // i.e. contained within a limited portion of the screen
embedded: {embedded},
// Parallax background size // Flags if we should show a help overlay when the question-mark
parallaxBackgroundSize: '', // CSS syntax, e.g. "2100px 900px" // key is pressed
help: {help},
// Number of pixels to move the parallax background per slide // Flags if it should be possible to pause the presentation (blackout)
// - Calculated automatically unless specified pause: {pause},
// - Set to 0 to disable movement along an axis
parallaxBackgroundHorizontal: null, // Flags if speaker notes should be visible to all viewers
parallaxBackgroundVertical: null, 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}
// The display mode that will be used to show slides }});
display: 'block', </script>
</body>
/*
multiplex: {{
// Example values. To generate your own, see the socket.io server instructions.
secret: '13652805320794272084', // Obtained from the socket.io server. Gives this (the master) control of the presentation
id: '1ea875674b17ca76', // Obtained from socket.io server
url: 'https://reveal-js-multiplex-ccjbegmaii.now.sh' // Location of socket.io server
}},
*/
dependencies: [
{{ src: 'https://cdn.jsdelivr.net/npm/reveal.js@{reveal_version}/plugin/markdown/marked.js' }},
{{ src: 'https://cdn.jsdelivr.net/npm/reveal.js@{reveal_version}/plugin/markdown/markdown.js' }},
{{ src: 'https://cdn.jsdelivr.net/npm/reveal.js@{reveal_version}/plugin/notes/notes.js', async: true }},
{{ src: 'https://cdn.jsdelivr.net/npm/reveal.js@{reveal_version}/plugin/highlight/highlight.js', async: true, callback: function () {{ hljs.initHighlightingOnLoad(); }} }},
//{{ src: '//cdn.socket.io/socket.io-1.3.5.js', async: true }},
//{{ src: 'plugin/multiplex/master.js', async: true }},
// and if you want speaker notes
{{ src: 'https://cdn.jsdelivr.net/npm/reveal.js@{reveal_version}/plugin/notes-server/client.js', async: true }}
],
markdown: {{
// renderer: myrenderer,
smartypants: true
}}
}});
Reveal.configure({{
// PDF Configurations
pdfMaxPagesPerSlide: 1
}});
</script>
</body>
</html> </html>