mirror of
https://github.com/jeertmans/manim-slides.git
synced 2025-05-17 18:55:53 +08:00
feat(lib): Sphinx directive can now read files (#261)
* feat(lib): Sphinx directive can now read files You can optionally read a file instead of the Sphinx directive's content * fix(lib): rst syntax and docs * [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>
This commit is contained in:
16
.github/workflows/pages.yml
vendored
16
.github/workflows/pages.yml
vendored
@ -56,18 +56,8 @@ jobs:
|
|||||||
id: cache-media-restore
|
id: cache-media-restore
|
||||||
uses: actions/cache/restore@v3
|
uses: actions/cache/restore@v3
|
||||||
with:
|
with:
|
||||||
path: media
|
path: docs/media
|
||||||
key: ${{ runner.os }}-media
|
key: ${{ runner.os }}-docs-media
|
||||||
- name: Build animations
|
|
||||||
run: |
|
|
||||||
poetry run manim example.py ConvertExample BasicExample ThreeDExample
|
|
||||||
- name: Convert animations to HTML slides
|
|
||||||
run: |
|
|
||||||
poetry run manim-slides convert -v DEBUG ConvertExample docs/source/_static/slides.html -ccontrols=true
|
|
||||||
poetry run manim-slides convert -v DEBUG BasicExample docs/source/_static/basic_example.html -ccontrols=true
|
|
||||||
poetry run manim-slides convert -v DEBUG ThreeDExample docs/source/_static/three_d_example.html -ccontrols=true
|
|
||||||
- name: Show docs/source/_static/ dir content (video only)
|
|
||||||
run: tree -L 3 docs/source/_static/ -P '*.mp4'
|
|
||||||
- name: Clear cache
|
- name: Clear cache
|
||||||
run: |
|
run: |
|
||||||
gh extension install actions/gh-actions-cache
|
gh extension install actions/gh-actions-cache
|
||||||
@ -78,7 +68,7 @@ jobs:
|
|||||||
id: cache-media-save
|
id: cache-media-save
|
||||||
uses: actions/cache/save@v3
|
uses: actions/cache/save@v3
|
||||||
with:
|
with:
|
||||||
path: media
|
path: docs/media
|
||||||
key: ${{ steps.cache-media-restore.outputs.cache-primary-key }}
|
key: ${{ steps.cache-media-restore.outputs.cache-primary-key }}
|
||||||
- name: Build docs
|
- name: Build docs
|
||||||
run: cd docs && poetry run make html
|
run: cd docs && poetry run make html
|
||||||
|
@ -25,6 +25,9 @@ In an effort to better document changes, this CHANGELOG document is now created.
|
|||||||
- Added a full screen key binding (defaults to <kbd>F</kbd>) in the
|
- Added a full screen key binding (defaults to <kbd>F</kbd>) in the
|
||||||
presenter.
|
presenter.
|
||||||
[#243](https://github.com/jeertmans/manim-slides/pull/243)
|
[#243](https://github.com/jeertmans/manim-slides/pull/243)
|
||||||
|
- Added support for including code from a file in Manim Slides
|
||||||
|
Sphinx directive.
|
||||||
|
[#261](https://github.com/jeertmans/manim-slides/pull/261)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
@ -28,11 +28,11 @@ In a [very few steps](./quickstart), you can create slides and present them eith
|
|||||||
|
|
||||||
Slide through the demo below to get a quick glimpse on what you can do with Manim Slides.
|
Slide through the demo below to get a quick glimpse on what you can do with Manim Slides.
|
||||||
|
|
||||||
|
```{eval-rst}
|
||||||
<!-- From: https://faq.dailymotion.com/hc/en-us/articles/360022841393-How-to-preserve-the-player-aspect-ratio-on-a-responsive-page -->
|
.. manim-slides:: ../../example.py:ConvertExample
|
||||||
|
:hide_source:
|
||||||
<div style="position:relative;padding-bottom:56.25%;"> <iframe style="width:100%;height:100%;position:absolute;left:0px;top:0px;" frameborder="0" width="100%" height="100%" allowfullscreen allow="autoplay" src="_static/slides.html"></iframe></div>
|
:quality: high
|
||||||
|
```
|
||||||
|
|
||||||
```{toctree}
|
```{toctree}
|
||||||
:hidden:
|
:hidden:
|
||||||
|
@ -29,9 +29,11 @@ where `-ccontrols=true` indicates that we want to display the blue navigation ar
|
|||||||
|
|
||||||
Basic example from quickstart.
|
Basic example from quickstart.
|
||||||
|
|
||||||
<div style="position:relative;padding-bottom:56.25%;"> <iframe style="width:100%;height:100%;position:absolute;left:0px;top:0px;" frameborder="0" width="100%" height="100%" allowfullscreen allow="autoplay" src="../_static/basic_example.html"></iframe></div>
|
|
||||||
|
|
||||||
```{eval-rst}
|
```{eval-rst}
|
||||||
|
.. manim-slides: ../../../example.py:BasicExample
|
||||||
|
:hide_source:
|
||||||
|
:quality: high
|
||||||
|
|
||||||
.. literalinclude:: ../../../example.py
|
.. literalinclude:: ../../../example.py
|
||||||
:language: python
|
:language: python
|
||||||
:linenos:
|
:linenos:
|
||||||
@ -42,11 +44,13 @@ Basic example from quickstart.
|
|||||||
|
|
||||||
Example using 3D camera. As Manim and ManimGL handle 3D differently, definitions are slightly different.
|
Example using 3D camera. As Manim and ManimGL handle 3D differently, definitions are slightly different.
|
||||||
|
|
||||||
<div style="position:relative;padding-bottom:56.25%;"> <iframe style="width:100%;height:100%;position:absolute;left:0px;top:0px;" frameborder="0" width="100%" height="100%" allowfullscreen allow="autoplay" src="../_static/three_d_example.html"></iframe></div>
|
|
||||||
|
|
||||||
### With Manim
|
### With Manim
|
||||||
|
|
||||||
```{eval-rst}
|
```{eval-rst}
|
||||||
|
.. manim-slides: ../../../example.py:ThreeDExample
|
||||||
|
:hide_source:
|
||||||
|
:quality: high
|
||||||
|
|
||||||
.. literalinclude:: ../../../example.py
|
.. literalinclude:: ../../../example.py
|
||||||
:language: python
|
:language: python
|
||||||
:linenos:
|
:linenos:
|
||||||
@ -120,9 +124,11 @@ directly write the `construct` method in the body of `MovingCameraSlide`.
|
|||||||
|
|
||||||
A more advanced example is `ConvertExample`, which is used as demo slide and tutorial.
|
A more advanced example is `ConvertExample`, which is used as demo slide and tutorial.
|
||||||
|
|
||||||
<div style="position:relative;padding-bottom:56.25%;"> <iframe style="width:100%;height:100%;position:absolute;left:0px;top:0px;" frameborder="0" width="100%" height="100%" allowfullscreen allow="autoplay" src="../_static/slides.html"></iframe></div>
|
|
||||||
|
|
||||||
```{eval-rst}
|
```{eval-rst}
|
||||||
|
.. manim-slides: ../../../example.py:ConvertExample
|
||||||
|
:hide_source:
|
||||||
|
:quality: high
|
||||||
|
|
||||||
.. literalinclude:: ../../../example.py
|
.. literalinclude:: ../../../example.py
|
||||||
:language: python
|
:language: python
|
||||||
:linenos:
|
:linenos:
|
||||||
|
@ -70,16 +70,29 @@ render scenes that are defined within doctests, for example::
|
|||||||
... def construct(self):
|
... def construct(self):
|
||||||
... self.play(Create(dot))
|
... self.play(Create(dot))
|
||||||
|
|
||||||
|
A third application is to render scenes from another specific file::
|
||||||
|
|
||||||
|
.. manim-slides:: file.py:FileExample
|
||||||
|
:hide_source:
|
||||||
|
:quality: high
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
The code will be executed with the current working directory
|
||||||
|
being the same as the one containing the source file. This being said,
|
||||||
|
you should probably not include examples that rely on external files, since
|
||||||
|
relative paths risk to be broken.
|
||||||
|
|
||||||
Options
|
Options
|
||||||
-------
|
-------
|
||||||
|
|
||||||
Options can be passed as follows::
|
Options can be passed as follows::
|
||||||
|
|
||||||
.. manim-slides:: <Class name>
|
.. manim-slides:: <file>:<Class name>
|
||||||
:<option name>: <value>
|
:<option name>: <value>
|
||||||
|
|
||||||
The following configuration options are supported by the
|
The following configuration options are supported by the
|
||||||
directive:
|
directive::
|
||||||
|
|
||||||
hide_source
|
hide_source
|
||||||
If this flag is present without argument,
|
If this flag is present without argument,
|
||||||
@ -110,6 +123,7 @@ import re
|
|||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from timeit import timeit
|
from timeit import timeit
|
||||||
|
from typing import Tuple
|
||||||
|
|
||||||
import jinja2
|
import jinja2
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
@ -211,7 +225,17 @@ class ManimSlidesDirective(Directive):
|
|||||||
|
|
||||||
global classnamedict
|
global classnamedict
|
||||||
|
|
||||||
clsname = self.arguments[0]
|
def split_file_cls(arg: str) -> Tuple[Path, str]:
|
||||||
|
if ":" in arg:
|
||||||
|
file, cls = arg.split(":", maxsplit=1)
|
||||||
|
_, file = self.state.document.settings.env.relfn2path(file)
|
||||||
|
return Path(file), cls
|
||||||
|
else:
|
||||||
|
return None, arg
|
||||||
|
|
||||||
|
arguments = [split_file_cls(arg) for arg in self.arguments]
|
||||||
|
|
||||||
|
clsname = arguments[0][1]
|
||||||
if clsname not in classnamedict:
|
if clsname not in classnamedict:
|
||||||
classnamedict[clsname] = 1
|
classnamedict[clsname] = 1
|
||||||
else:
|
else:
|
||||||
@ -271,20 +295,24 @@ class ManimSlidesDirective(Directive):
|
|||||||
"output_file": output_file,
|
"output_file": output_file,
|
||||||
}
|
}
|
||||||
|
|
||||||
user_code = self.content
|
if file := arguments[0][0]:
|
||||||
|
user_code = file.absolute().read_text().splitlines()
|
||||||
|
else:
|
||||||
|
user_code = self.content
|
||||||
|
|
||||||
if user_code[0].startswith(">>> "): # check whether block comes from doctest
|
if user_code[0].startswith(">>> "): # check whether block comes from doctest
|
||||||
user_code = [
|
user_code = [
|
||||||
line[4:] for line in user_code if line.startswith((">>> ", "... "))
|
line[4:] for line in user_code if line.startswith((">>> ", "... "))
|
||||||
]
|
]
|
||||||
|
|
||||||
code = [
|
code = [
|
||||||
"from manim import *",
|
|
||||||
*user_code,
|
*user_code,
|
||||||
f"{clsname}().render()",
|
f"{clsname}().render()",
|
||||||
]
|
]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with tempconfig(example_config):
|
with tempconfig(example_config):
|
||||||
|
print(f"Rendering {clsname}...")
|
||||||
run_time = timeit(lambda: exec("\n".join(code), globals()), number=1)
|
run_time = timeit(lambda: exec("\n".join(code), globals()), number=1)
|
||||||
video_dir = config.get_dir("video_dir")
|
video_dir = config.get_dir("video_dir")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -306,9 +334,6 @@ class ManimSlidesDirective(Directive):
|
|||||||
RevealJS(presentation_configs=presentation_configs, controls="true").convert_to(
|
RevealJS(presentation_configs=presentation_configs, controls="true").convert_to(
|
||||||
destfile
|
destfile
|
||||||
)
|
)
|
||||||
# shutil.copyfile(filesrc, destfile)
|
|
||||||
|
|
||||||
print("CLASS NAME:", clsname)
|
|
||||||
|
|
||||||
rendered_template = jinja2.Template(TEMPLATE).render(
|
rendered_template = jinja2.Template(TEMPLATE).render(
|
||||||
clsname=clsname,
|
clsname=clsname,
|
||||||
@ -400,6 +425,7 @@ TEMPLATE = r"""
|
|||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
|
<!-- From: https://faq.dailymotion.com/hc/en-us/articles/360022841393-How-to-preserve-the-player-aspect-ratio-on-a-responsive-page -->
|
||||||
|
|
||||||
<div style="position:relative;padding-bottom:56.25%;">
|
<div style="position:relative;padding-bottom:56.25%;">
|
||||||
<iframe
|
<iframe
|
||||||
|
Reference in New Issue
Block a user