Skip to content

Commit dc58d49

Browse files
feat(cli): automatically detect conversion format from DEST (#325)
* feat(cli): automatically detect conversion format from DEST As titled * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix(cli): fix and add tests * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix(ci): ? * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent f898dd3 commit dc58d49

10 files changed

+348
-4
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2323
[#320](https://github.com/jeertmans/manim-slides/pull/320)
2424
- Added the speaker notes option.
2525
[#322](https://github.com/jeertmans/manim-slides/pull/322)
26+
- Added `auto` option for conversion format, which is the default.
27+
This is somewhat a **breaking change**, but changes to the CLI
28+
API are not considered to be very important.
29+
[#325](https://github.com/jeertmans/manim-slides/pull/325)
2630

2731
(v5.1-modified)=
2832
### Modified

manim_slides/convert.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -626,10 +626,11 @@ def callback(ctx: Context, param: Parameter, value: bool) -> None:
626626
@click.argument("dest", type=click.Path(dir_okay=False, path_type=Path))
627627
@click.option(
628628
"--to",
629-
type=click.Choice(["html", "pdf", "pptx"], case_sensitive=False),
630-
default="html",
629+
type=click.Choice(["auto", "html", "pdf", "pptx"], case_sensitive=False),
630+
metavar="FORMAT",
631+
default="auto",
631632
show_default=True,
632-
help="Set the conversion format to use.",
633+
help="Set the conversion format to use. Use 'auto' to detect format from DEST.",
633634
)
634635
@click.option(
635636
"--open",
@@ -670,7 +671,19 @@ def convert(
670671
presentation_configs = get_scenes_presentation_config(scenes, folder)
671672

672673
try:
673-
converter = Converter.from_string(to)(
674+
if to == "auto":
675+
fmt = dest.suffix[1:].lower()
676+
try:
677+
cls = Converter.from_string(fmt)
678+
except KeyError:
679+
logger.warn(
680+
f"Could not guess conversion format from {dest!s}, defaulting to HTML."
681+
)
682+
cls = RevealJS
683+
else:
684+
cls = Converter.from_string(to)
685+
686+
converter = cls(
674687
presentation_configs=presentation_configs,
675688
template=template,
676689
**config_options,

test.html

Lines changed: 305 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,305 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
6+
7+
<title>Manim Slides</title>
8+
9+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/4.6.1/reveal.min.css">
10+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/4.6.1/theme/black.min.css">
11+
12+
<!-- Theme used for syntax highlighting of code -->
13+
<!-- <link rel="stylesheet" href="lib/css/zenburn.css"> -->
14+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.13.1/styles/zenburn.min.css">
15+
16+
<!-- <link rel="stylesheet" href="index.css"> -->
17+
</head>
18+
19+
<body>
20+
<div class="reveal">
21+
<div class="slides"><section
22+
data-background-size='contain'
23+
data-background-color="black"
24+
data-background-video="test_assets/666c4d3666df4cdb49aaba030b166948270194eee96f1a10eedf33ef7d3c9a7b.mp4"
25+
data-background-video-muted>
26+
27+
</section><section
28+
data-background-size='contain'
29+
data-background-color="black"
30+
data-background-video="test_assets/49d7b9453bdd459c0f7582859468b845a0abd7fd15637246ec1914c5c21ee33a.mp4"
31+
data-background-video-loop>
32+
33+
</section><section
34+
data-background-size='contain'
35+
data-background-color="black"
36+
data-background-video="test_assets/72568c120827bbf8c69201ee416c5bab6f875f1600889d2ee765346bb576887d.mp4"
37+
>
38+
39+
</section></div>
40+
</div>
41+
42+
<script src="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/4.6.1/reveal.min.js"></script>
43+
44+
<!-- To include plugins, see: https://revealjs.com/plugins/ -->
45+
46+
<!-- <script src="index.js"></script> -->
47+
<script>
48+
Reveal.initialize({
49+
50+
// The "normal" size of the presentation, aspect ratio will
51+
// be preserved when the presentation is scaled to fit different
52+
// resolutions. Can be specified using percentage units.
53+
width: '100%',
54+
height: '100%',
55+
56+
// Factor of the display size that should remain empty around
57+
// the content
58+
margin: 0.04,
59+
60+
// Bounds for smallest/largest possible scale to apply to content
61+
minScale: 0.2,
62+
maxScale: 2.0,
63+
64+
// Display presentation control arrows
65+
controls: false,
66+
67+
// Help the user learn the controls by providing hints, for example by
68+
// bouncing the down arrow when they first encounter a vertical slide
69+
controlsTutorial: true,
70+
71+
// Determines where controls appear, "edges" or "bottom-right"
72+
controlsLayout: 'bottom-right',
73+
74+
// Visibility rule for backwards navigation arrows; "faded", "hidden"
75+
// or "visible"
76+
controlsBackArrows: 'faded',
77+
78+
// Display a presentation progress bar
79+
progress: false,
80+
81+
// Display the page number of the current slide
82+
// - true: Show slide number
83+
// - false: Hide slide number
84+
//
85+
// Can optionally be set as a string that specifies the number formatting:
86+
// - "h.v": Horizontal . vertical slide number (default)
87+
// - "h/v": Horizontal / vertical slide number
88+
// - "c": Flattened slide number
89+
// - "c/t": Flattened slide number / total slides
90+
//
91+
// Alternatively, you can provide a function that returns the slide
92+
// number for the current slide. The function should take in a slide
93+
// object and return an array with one string [slideNumber] or
94+
// three strings [n1,delimiter,n2]. See #formatSlideNumber().
95+
slideNumber: false,
96+
97+
// Can be used to limit the contexts in which the slide number appears
98+
// - "all": Always show the slide number
99+
// - "print": Only when printing to PDF
100+
// - "speaker": Only in the speaker view
101+
showSlideNumber: 'all',
102+
103+
// Use 1 based indexing for # links to match slide number (default is zero
104+
// based)
105+
hashOneBasedIndex: false,
106+
107+
// Add the current slide number to the URL hash so that reloading the
108+
// page/copying the URL will return you to the same slide
109+
hash: false,
110+
111+
// Flags if we should monitor the hash and change slides accordingly
112+
respondToHashChanges: false,
113+
114+
// Push each slide change to the browser history. Implies `hash: true`
115+
history: false,
116+
117+
// Enable keyboard shortcuts for navigation
118+
keyboard: true,
119+
120+
// Optional function that blocks keyboard events when retuning false
121+
//
122+
// If you set this to 'focused', we will only capture keyboard events
123+
// for embedded decks when they are in focus
124+
keyboardCondition: null,
125+
126+
// Disables the default reveal.js slide layout (scaling and centering)
127+
// so that you can use custom CSS layout
128+
disableLayout: false,
129+
130+
// Enable the slide overview mode
131+
overview: true,
132+
133+
// Vertical centering of slides
134+
center: true,
135+
136+
// Enables touch navigation on devices with touch input
137+
touch: true,
138+
139+
// Loop the presentation
140+
loop: false,
141+
142+
// Change the presentation direction to be RTL
143+
rtl: false,
144+
145+
// Changes the behavior of our navigation directions.
146+
//
147+
// "default"
148+
// Left/right arrow keys step between horizontal slides, up/down
149+
// arrow keys step between vertical slides. Space key steps through
150+
// all slides (both horizontal and vertical).
151+
//
152+
// "linear"
153+
// Removes the up/down arrows. Left/right arrows step through all
154+
// slides (both horizontal and vertical).
155+
//
156+
// "grid"
157+
// When this is enabled, stepping left/right from a vertical stack
158+
// to an adjacent vertical stack will land you at the same vertical
159+
// index.
160+
//
161+
// Consider a deck with six slides ordered in two vertical stacks:
162+
// 1.1 2.1
163+
// 1.2 2.2
164+
// 1.3 2.3
165+
//
166+
// If you're on slide 1.3 and navigate right, you will normally move
167+
// from 1.3 -> 2.1. If "grid" is used, the same navigation takes you
168+
// from 1.3 -> 2.3.
169+
navigationMode: 'default',
170+
171+
// Randomizes the order of slides each time the presentation loads
172+
shuffle: false,
173+
174+
// Turns fragments on and off globally
175+
fragments: true,
176+
177+
// Flags whether to include the current fragment in the URL,
178+
// so that reloading brings you to the same fragment position
179+
fragmentInURL: true,
180+
181+
// Flags if the presentation is running in an embedded mode,
182+
// i.e. contained within a limited portion of the screen
183+
embedded: false,
184+
185+
// Flags if we should show a help overlay when the question-mark
186+
// key is pressed
187+
help: true,
188+
189+
// Flags if it should be possible to pause the presentation (blackout)
190+
pause: true,
191+
192+
// Flags if speaker notes should be visible to all viewers
193+
showNotes: false,
194+
195+
// Global override for autolaying embedded media (video/audio/iframe)
196+
// - null: Media will only autoplay if data-autoplay is present
197+
// - true: All media will autoplay, regardless of individual setting
198+
// - false: No media will autoplay, regardless of individual setting
199+
autoPlayMedia: null,
200+
201+
// Global override for preloading lazy-loaded iframes
202+
// - null: Iframes with data-src AND data-preload will be loaded when within
203+
// the viewDistance, iframes with only data-src will be loaded when visible
204+
// - true: All iframes with data-src will be loaded when within the viewDistance
205+
// - false: All iframes with data-src will be loaded only when visible
206+
preloadIframes: null,
207+
208+
// Can be used to globally disable auto-animation
209+
autoAnimate: true,
210+
211+
// Optionally provide a custom element matcher that will be
212+
// used to dictate which elements we can animate between.
213+
autoAnimateMatcher: null,
214+
215+
// Default settings for our auto-animate transitions, can be
216+
// overridden per-slide or per-element via data arguments
217+
autoAnimateEasing: 'ease',
218+
autoAnimateDuration: 1.0,
219+
autoAnimateUnmatched: true,
220+
221+
// CSS properties that can be auto-animated. Position & scale
222+
// is matched separately so there's no need to include styles
223+
// like top/right/bottom/left, width/height or margin.
224+
autoAnimateStyles: ['opacity', 'color', 'background-color', 'padding', 'font-size', 'line-height', 'letter-spacing', 'border-width', 'border-color', 'border-radius', 'outline', 'outline-offset'],
225+
226+
// Controls automatic progression to the next slide
227+
// - 0: Auto-sliding only happens if the data-autoslide HTML attribute
228+
// is present on the current slide or fragment
229+
// - 1+: All slides will progress automatically at the given interval
230+
// - false: No auto-sliding, even if data-autoslide is present
231+
autoSlide: 0,
232+
233+
// Stop auto-sliding after user input
234+
autoSlideStoppable: true,
235+
236+
// Use this method for navigation when auto-sliding (defaults to navigateNext)
237+
autoSlideMethod: null,
238+
239+
// Specify the average time in seconds that you think you will spend
240+
// presenting each slide. This is used to show a pacing timer in the
241+
// speaker view
242+
defaultTiming: null,
243+
244+
// Enable slide navigation via mouse wheel
245+
mouseWheel: false,
246+
247+
// Opens links in an iframe preview overlay
248+
// Add `data-preview-link` and `data-preview-link="false"` to customise each link
249+
// individually
250+
previewLinks: false,
251+
252+
// Exposes the reveal.js API through window.postMessage
253+
postMessage: true,
254+
255+
// Dispatches all reveal.js events to the parent window through postMessage
256+
postMessageEvents: false,
257+
258+
// Focuses body when page changes visibility to ensure keyboard shortcuts work
259+
focusBodyOnPageVisibilityChange: true,
260+
261+
// Transition style
262+
transition: 'none', // none/fade/slide/convex/concave/zoom
263+
264+
// Transition speed
265+
transitionSpeed: 'default', // default/fast/slow
266+
267+
// Transition style for full page slide backgrounds
268+
backgroundTransition: 'none', // none/fade/slide/convex/concave/zoom
269+
270+
// The maximum number of pages a single slide can expand onto when printing
271+
// to PDF, unlimited by default
272+
pdfMaxPagesPerSlide: Number.POSITIVE_INFINITY,
273+
274+
// Prints each fragment on a separate slide
275+
pdfSeparateFragments: true,
276+
277+
// Offset used to reduce the height of content within exported PDF pages.
278+
// This exists to account for environment differences based on how you
279+
// print to PDF. CLI printing options, like phantomjs and wkpdf, can end
280+
// on precisely the total height of the document whereas in-browser
281+
// printing has to end one pixel before.
282+
pdfPageHeightOffset: -1,
283+
284+
// Number of slides away from the current that are visible
285+
viewDistance: 3,
286+
287+
// Number of slides away from the current that are visible on mobile
288+
// devices. It is advisable to set this to a lower number than
289+
// viewDistance in order to save resources.
290+
mobileViewDistance: 2,
291+
292+
// The display mode that will be used to show slides
293+
display: 'block',
294+
295+
// Hide cursor if inactive
296+
hideInactiveCursor: true,
297+
298+
// Time before the cursor is hidden (in ms)
299+
hideCursorTime: 5000
300+
});
301+
302+
303+
</script>
304+
</body>
305+
</html>
Binary file not shown.
Binary file not shown.
Binary file not shown.

tests/test_main.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,28 @@ def test_convert(slides_folder: Path, extension: str) -> None:
6464
assert results.exit_code == 0
6565

6666

67+
@pytest.mark.parametrize(
68+
("extension", "expected_log"),
69+
[("html", ""), ("pdf", ""), ("pptx", ""), ("ppt", "WARNING")],
70+
)
71+
def test_convert_auto(slides_folder: Path, extension: str, expected_log: str) -> None:
72+
runner = CliRunner()
73+
74+
with runner.isolated_filesystem():
75+
results = runner.invoke(
76+
cli,
77+
[
78+
"convert",
79+
"BasicSlide",
80+
f"basic_example.{extension}",
81+
"--folder",
82+
str(slides_folder),
83+
],
84+
)
85+
86+
assert results.exit_code == 0, expected_log in results.output
87+
88+
6789
def test_init() -> None:
6890
runner = CliRunner()
6991

0 commit comments

Comments
 (0)