We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Redesign manim-example blocks
At the very least the blocks should be easier to distinguish from each other.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `docs/source/manim_directive.py`
Content:
```
1 r"""
2 A directive for including Manim videos in a Sphinx document
3 ===========================================================
4 
5 When rendering the HTML documentation, the ``.. manim::`` directive
6 implemented here allows to include rendered videos.
7 
8 Its basic usage that allows processing **inline content**
9 looks as follows::
10 
11     .. manim:: MyScene
12 
13         class MyScene(Scene):
14             def construct(self):
15                 ...
16 
17 It is required to pass the name of the class representing the
18 scene to be rendered to the directive.
19 
20 As a second application, the directive can also be used to
21 render scenes that are defined within doctests, for example::
22 
23     .. manim:: DirectiveDoctestExample
24         :ref_classes: Dot
25 
26         >>> dot = Dot(color=RED)
27         >>> dot.color
28         <Color #fc6255>
29         >>> class DirectiveDoctestExample(Scene):
30         ...     def construct(self):
31         ...         self.play(ShowCreation(dot))
32 
33 
34 Options
35 -------
36 
37 Options can be passed as follows::
38 
39     .. manim:: <Class name>
40         :<option name>: <value>
41 
42 The following configuration options are supported by the
43 directive:
44 
45     hide_source
46         If this flag is present without argument,
47         the source code is not displayed above the rendered video.
48 
49     quality : {'low', 'medium', 'high', 'fourk'}
50         Controls render quality of the video, in analogy to
51         the corresponding command line flags.
52 
53     save_as_gif
54         If this flag is present without argument,
55         the scene is rendered as a gif.
56 
57     save_last_frame
58         If this flag is present without argument,
59         an image representing the last frame of the scene will
60         be rendered and displayed, instead of a video.
61 
62     ref_classes
63         A list of classes, separated by spaces, that is
64         rendered in a reference block after the source code.
65 
66     ref_functions
67         A list of functions and methods, separated by spaces,
68         that is rendered in a reference block after the source code.
69 
70 """
71 from docutils.parsers.rst import directives, Directive
72 
73 import jinja2
74 import os
75 from os.path import relpath
76 from typing import List
77 
78 import shutil
79 
80 classnamedict = {}
81 
82 
83 def process_name_list(option_input: str, reference_type: str) -> List[str]:
84     r"""Reformats a string of space separated class names
85     as a list of strings containing valid Sphinx references.
86 
87     TESTS
88     -----
89 
90     ::
91 
92         >>> process_name_list("Tex TexTemplate", "class")
93         [":class:`~.Tex`", ":class:`~.TexTemplate`"]
94         >>> process_name_list("Scene.play Mobject.rotate", "func")
95         [":func:`~.Scene.play`", ":func:`~.Mobject.rotate`"]
96     """
97     return [f":{reference_type}:`~.{name}`" for name in option_input.split()]
98 
99 
100 class ManimDirective(Directive):
101     r"""The manim directive, rendering videos while building
102     the documentation.
103 
104     See the module docstring for documentation.
105     """
106     has_content = True
107     required_arguments = 1
108     optional_arguments = 0
109     option_spec = {
110         "hide_source": bool,
111         "quality": lambda arg: directives.choice(
112             arg, ("low", "medium", "high", "fourk")
113         ),
114         "save_as_gif": bool,
115         "save_last_frame": bool,
116         "ref_classes": lambda arg: process_name_list(arg, "class"),
117         "ref_functions": lambda arg: process_name_list(arg, "func"),
118     }
119     final_argument_whitespace = True
120 
121     def run(self):
122         from manim import config
123 
124         global classnamedict
125 
126         clsname = self.arguments[0]
127         if clsname not in classnamedict:
128             classnamedict[clsname] = 1
129         else:
130             classnamedict[clsname] += 1
131 
132         hide_source = "hide_source" in self.options
133         save_as_gif = "save_as_gif" in self.options
134         save_last_frame = "save_last_frame" in self.options
135         assert not (save_as_gif and save_last_frame)
136         if "ref_classes" in self.options or "ref_functions" in self.options:
137             ref_classes = self.options.get("ref_classes", [])
138             ref_functions = self.options.get("ref_functions", [])
139             ref_content = ref_classes + ref_functions
140             ref_block = f"""
141 .. admonition:: Example References
142     :class: example-reference
143 
144     {' '.join(ref_content)}"""
145         else:
146             ref_block = ""
147 
148         frame_rate = 30
149         pixel_height = 480
150         pixel_width = 854
151 
152         if "quality" in self.options:
153             quality = self.options["quality"]
154             if quality == "low":
155                 pixel_height = 480
156                 pixel_width = 854
157                 frame_rate = 15
158             elif quality == "medium":
159                 pixel_height = 720
160                 pixel_width = 1280
161                 frame_rate = 30
162             elif quality == "high":
163                 pixel_height = 1440
164                 pixel_width = 2560
165                 frame_rate = 60
166             elif quality == "fourk":
167                 pixel_height = 2160
168                 pixel_width = 3840
169                 frame_rate = 60
170 
171         qualitydir = f"{pixel_height}p{frame_rate}"
172 
173         state_machine = self.state_machine
174         document = state_machine.document
175 
176         source_file_name = document.attributes["source"]
177         source_rel_name = relpath(source_file_name, setup.confdir)
178         source_rel_dir = os.path.dirname(source_rel_name)
179         while source_rel_dir.startswith(os.path.sep):
180             source_rel_dir = source_rel_dir[1:]
181 
182         dest_dir = os.path.abspath(
183             os.path.join(setup.app.builder.outdir, source_rel_dir)
184         )
185         if not os.path.exists(dest_dir):
186             os.makedirs(dest_dir)
187 
188         source_block = [
189             ".. code-block:: python",
190             "",
191             *["    " + line for line in self.content],
192         ]
193         source_block = "\n".join(source_block)
194 
195         media_dir = os.path.join(setup.confdir, "media")
196         if not os.path.exists(media_dir):
197             os.mkdir(media_dir)
198         images_dir = os.path.join(media_dir, "images")
199         if not os.path.exists(images_dir):
200             os.mkdir(images_dir)
201         tex_dir = os.path.join(media_dir, "tex")
202         if not os.path.exists(tex_dir):
203             os.mkdir(tex_dir)
204         text_dir = os.path.join(media_dir, "text")
205         if not os.path.exists(text_dir):
206             os.mkdir(text_dir)
207         video_dir = os.path.join(media_dir, "videos")
208         output_file = f"{clsname}-{classnamedict[clsname]}"
209 
210         file_writer_config_code = [
211             f'config["frame_rate"] = {frame_rate}',
212             f'config["pixel_height"] = {pixel_height}',
213             f'config["pixel_width"] = {pixel_width}',
214             f'file_writer_config["media_dir"] = r"{media_dir}"',
215             f'file_writer_config["images_dir"] = r"{images_dir}"',
216             f'file_writer_config["tex_dir"] = r"{tex_dir}"',
217             f'file_writer_config["text_dir"] = r"{text_dir}"',
218             f'file_writer_config["video_dir"] = r"{video_dir}"',
219             f'file_writer_config["save_last_frame"] = {save_last_frame}',
220             f'file_writer_config["save_as_gif"] = {save_as_gif}',
221             f'file_writer_config["output_file"] = r"{output_file}"',
222         ]
223 
224         user_code = self.content
225         if user_code[0].startswith(">>> "):  # check whether block comes from doctest
226             user_code = [
227                 line[4:] for line in user_code if line.startswith((">>> ", "... "))
228             ]
229 
230         code = [
231             "from manim import *",
232             *file_writer_config_code,
233             *user_code,
234             f"{clsname}().render()",
235         ]
236         exec("\n".join(code), globals())
237 
238         # copy video file to output directory
239         if not (save_as_gif or save_last_frame):
240             filename = f"{output_file}.mp4"
241             filesrc = os.path.join(video_dir, qualitydir, filename)
242             destfile = os.path.join(dest_dir, filename)
243             shutil.copyfile(filesrc, destfile)
244         elif save_as_gif:
245             filename = f"{output_file}.gif"
246             filesrc = os.path.join(video_dir, qualitydir, filename)
247         elif save_last_frame:
248             filename = f"{output_file}.png"
249             filesrc = os.path.join(images_dir, filename)
250         else:
251             raise ValueError("Invalid combination of render flags received.")
252 
253         rendered_template = jinja2.Template(TEMPLATE).render(
254             hide_source=hide_source,
255             filesrc_rel=os.path.relpath(filesrc, setup.confdir),
256             output_file=output_file,
257             save_last_frame=save_last_frame,
258             save_as_gif=save_as_gif,
259             source_block=source_block,
260             ref_block=ref_block,
261         )
262         state_machine.insert_input(
263             rendered_template.split("\n"), source=document.attributes["source"]
264         )
265 
266         return []
267 
268 
269 def setup(app):
270     import manim
271 
272     setup.app = app
273     setup.config = app.config
274     setup.confdir = app.confdir
275     app.add_directive("manim", ManimDirective)
276 
277     metadata = {"parallel_read_safe": False, "parallel_write_safe": True}
278     return metadata
279 
280 
281 TEMPLATE = r"""
282 {% if not hide_source %}
283 .. raw:: html
284 
285     <div class="manim-example">
286 
287 {{ source_block }}
288 {{ ref_block }}
289 {% endif %}
290 
291 {% if not (save_as_gif or save_last_frame) %}
292 .. raw:: html
293 
294     <video class="manim-video" controls loop autoplay src="./{{ output_file }}.mp4"></video>
295 {% elif save_as_gif %}
296 .. image:: /{{ filesrc_rel }}
297     :align: center
298 {% elif save_last_frame %}
299 .. image:: /{{ filesrc_rel }}
300     :align: center
301 {% endif %}
302 
303 {% if not hide_source %}
304 .. raw:: html
305 
306     </div>
307 {% endif %}
308 """
309
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/docs/source/manim_directive.py b/docs/source/manim_directive.py
--- a/docs/source/manim_directive.py
+++ b/docs/source/manim_directive.py
@@ -251,6 +251,7 @@
             raise ValueError("Invalid combination of render flags received.")
 
         rendered_template = jinja2.Template(TEMPLATE).render(
+            clsname=clsname,
             hide_source=hide_source,
             filesrc_rel=os.path.relpath(filesrc, setup.confdir),
             output_file=output_file,
@@ -284,8 +285,6 @@
 
     <div class="manim-example">
 
-{{ source_block }}
-{{ ref_block }}
 {% endif %}
 
 {% if not (save_as_gif or save_last_frame) %}
@@ -299,10 +298,16 @@
 .. image:: /{{ filesrc_rel }}
     :align: center
 {% endif %}
-
 {% if not hide_source %}
 .. raw:: html
 
-    </div>
+    <div class="example-header">{{ clsname }}</div>
+
+{{ source_block }}
+{{ ref_block }}
 {% endif %}
+
+.. raw:: html
+
+    </div>
 """

{"golden_diff": "diff --git a/docs/source/manim_directive.py b/docs/source/manim_directive.py\n--- a/docs/source/manim_directive.py\n+++ b/docs/source/manim_directive.py\n@@ -251,6 +251,7 @@\n             raise ValueError(\"Invalid combination of render flags received.\")\n \n         rendered_template = jinja2.Template(TEMPLATE).render(\n+            clsname=clsname,\n             hide_source=hide_source,\n             filesrc_rel=os.path.relpath(filesrc, setup.confdir),\n             output_file=output_file,\n@@ -284,8 +285,6 @@\n \n     <div class=\"manim-example\">\n \n-{{ source_block }}\n-{{ ref_block }}\n {% endif %}\n \n {% if not (save_as_gif or save_last_frame) %}\n@@ -299,10 +298,16 @@\n .. image:: /{{ filesrc_rel }}\n     :align: center\n {% endif %}\n-\n {% if not hide_source %}\n .. raw:: html\n \n-    </div>\n+    <div class=\"example-header\">{{ clsname }}</div>\n+\n+{{ source_block }}\n+{{ ref_block }}\n {% endif %}\n+\n+.. raw:: html\n+\n+    </div>\n \"\"\"\n", "issue": "Redesign manim-example blocks\nAt the very least the blocks should be easier to distinguish from each other.\n", "before_files": [{"content": "r\"\"\"\nA directive for including Manim videos in a Sphinx document\n===========================================================\n\nWhen rendering the HTML documentation, the ``.. manim::`` directive\nimplemented here allows to include rendered videos.\n\nIts basic usage that allows processing **inline content**\nlooks as follows::\n\n    .. manim:: MyScene\n\n        class MyScene(Scene):\n            def construct(self):\n                ...\n\nIt is required to pass the name of the class representing the\nscene to be rendered to the directive.\n\nAs a second application, the directive can also be used to\nrender scenes that are defined within doctests, for example::\n\n    .. manim:: DirectiveDoctestExample\n        :ref_classes: Dot\n\n        >>> dot = Dot(color=RED)\n        >>> dot.color\n        <Color #fc6255>\n        >>> class DirectiveDoctestExample(Scene):\n        ...     def construct(self):\n        ...         self.play(ShowCreation(dot))\n\n\nOptions\n-------\n\nOptions can be passed as follows::\n\n    .. manim:: <Class name>\n        :<option name>: <value>\n\nThe following configuration options are supported by the\ndirective:\n\n    hide_source\n        If this flag is present without argument,\n        the source code is not displayed above the rendered video.\n\n    quality : {'low', 'medium', 'high', 'fourk'}\n        Controls render quality of the video, in analogy to\n        the corresponding command line flags.\n\n    save_as_gif\n        If this flag is present without argument,\n        the scene is rendered as a gif.\n\n    save_last_frame\n        If this flag is present without argument,\n        an image representing the last frame of the scene will\n        be rendered and displayed, instead of a video.\n\n    ref_classes\n        A list of classes, separated by spaces, that is\n        rendered in a reference block after the source code.\n\n    ref_functions\n        A list of functions and methods, separated by spaces,\n        that is rendered in a reference block after the source code.\n\n\"\"\"\nfrom docutils.parsers.rst import directives, Directive\n\nimport jinja2\nimport os\nfrom os.path import relpath\nfrom typing import List\n\nimport shutil\n\nclassnamedict = {}\n\n\ndef process_name_list(option_input: str, reference_type: str) -> List[str]:\n    r\"\"\"Reformats a string of space separated class names\n    as a list of strings containing valid Sphinx references.\n\n    TESTS\n    -----\n\n    ::\n\n        >>> process_name_list(\"Tex TexTemplate\", \"class\")\n        [\":class:`~.Tex`\", \":class:`~.TexTemplate`\"]\n        >>> process_name_list(\"Scene.play Mobject.rotate\", \"func\")\n        [\":func:`~.Scene.play`\", \":func:`~.Mobject.rotate`\"]\n    \"\"\"\n    return [f\":{reference_type}:`~.{name}`\" for name in option_input.split()]\n\n\nclass ManimDirective(Directive):\n    r\"\"\"The manim directive, rendering videos while building\n    the documentation.\n\n    See the module docstring for documentation.\n    \"\"\"\n    has_content = True\n    required_arguments = 1\n    optional_arguments = 0\n    option_spec = {\n        \"hide_source\": bool,\n        \"quality\": lambda arg: directives.choice(\n            arg, (\"low\", \"medium\", \"high\", \"fourk\")\n        ),\n        \"save_as_gif\": bool,\n        \"save_last_frame\": bool,\n        \"ref_classes\": lambda arg: process_name_list(arg, \"class\"),\n        \"ref_functions\": lambda arg: process_name_list(arg, \"func\"),\n    }\n    final_argument_whitespace = True\n\n    def run(self):\n        from manim import config\n\n        global classnamedict\n\n        clsname = self.arguments[0]\n        if clsname not in classnamedict:\n            classnamedict[clsname] = 1\n        else:\n            classnamedict[clsname] += 1\n\n        hide_source = \"hide_source\" in self.options\n        save_as_gif = \"save_as_gif\" in self.options\n        save_last_frame = \"save_last_frame\" in self.options\n        assert not (save_as_gif and save_last_frame)\n        if \"ref_classes\" in self.options or \"ref_functions\" in self.options:\n            ref_classes = self.options.get(\"ref_classes\", [])\n            ref_functions = self.options.get(\"ref_functions\", [])\n            ref_content = ref_classes + ref_functions\n            ref_block = f\"\"\"\n.. admonition:: Example References\n    :class: example-reference\n\n    {' '.join(ref_content)}\"\"\"\n        else:\n            ref_block = \"\"\n\n        frame_rate = 30\n        pixel_height = 480\n        pixel_width = 854\n\n        if \"quality\" in self.options:\n            quality = self.options[\"quality\"]\n            if quality == \"low\":\n                pixel_height = 480\n                pixel_width = 854\n                frame_rate = 15\n            elif quality == \"medium\":\n                pixel_height = 720\n                pixel_width = 1280\n                frame_rate = 30\n            elif quality == \"high\":\n                pixel_height = 1440\n                pixel_width = 2560\n                frame_rate = 60\n            elif quality == \"fourk\":\n                pixel_height = 2160\n                pixel_width = 3840\n                frame_rate = 60\n\n        qualitydir = f\"{pixel_height}p{frame_rate}\"\n\n        state_machine = self.state_machine\n        document = state_machine.document\n\n        source_file_name = document.attributes[\"source\"]\n        source_rel_name = relpath(source_file_name, setup.confdir)\n        source_rel_dir = os.path.dirname(source_rel_name)\n        while source_rel_dir.startswith(os.path.sep):\n            source_rel_dir = source_rel_dir[1:]\n\n        dest_dir = os.path.abspath(\n            os.path.join(setup.app.builder.outdir, source_rel_dir)\n        )\n        if not os.path.exists(dest_dir):\n            os.makedirs(dest_dir)\n\n        source_block = [\n            \".. code-block:: python\",\n            \"\",\n            *[\"    \" + line for line in self.content],\n        ]\n        source_block = \"\\n\".join(source_block)\n\n        media_dir = os.path.join(setup.confdir, \"media\")\n        if not os.path.exists(media_dir):\n            os.mkdir(media_dir)\n        images_dir = os.path.join(media_dir, \"images\")\n        if not os.path.exists(images_dir):\n            os.mkdir(images_dir)\n        tex_dir = os.path.join(media_dir, \"tex\")\n        if not os.path.exists(tex_dir):\n            os.mkdir(tex_dir)\n        text_dir = os.path.join(media_dir, \"text\")\n        if not os.path.exists(text_dir):\n            os.mkdir(text_dir)\n        video_dir = os.path.join(media_dir, \"videos\")\n        output_file = f\"{clsname}-{classnamedict[clsname]}\"\n\n        file_writer_config_code = [\n            f'config[\"frame_rate\"] = {frame_rate}',\n            f'config[\"pixel_height\"] = {pixel_height}',\n            f'config[\"pixel_width\"] = {pixel_width}',\n            f'file_writer_config[\"media_dir\"] = r\"{media_dir}\"',\n            f'file_writer_config[\"images_dir\"] = r\"{images_dir}\"',\n            f'file_writer_config[\"tex_dir\"] = r\"{tex_dir}\"',\n            f'file_writer_config[\"text_dir\"] = r\"{text_dir}\"',\n            f'file_writer_config[\"video_dir\"] = r\"{video_dir}\"',\n            f'file_writer_config[\"save_last_frame\"] = {save_last_frame}',\n            f'file_writer_config[\"save_as_gif\"] = {save_as_gif}',\n            f'file_writer_config[\"output_file\"] = r\"{output_file}\"',\n        ]\n\n        user_code = self.content\n        if user_code[0].startswith(\">>> \"):  # check whether block comes from doctest\n            user_code = [\n                line[4:] for line in user_code if line.startswith((\">>> \", \"... \"))\n            ]\n\n        code = [\n            \"from manim import *\",\n            *file_writer_config_code,\n            *user_code,\n            f\"{clsname}().render()\",\n        ]\n        exec(\"\\n\".join(code), globals())\n\n        # copy video file to output directory\n        if not (save_as_gif or save_last_frame):\n            filename = f\"{output_file}.mp4\"\n            filesrc = os.path.join(video_dir, qualitydir, filename)\n            destfile = os.path.join(dest_dir, filename)\n            shutil.copyfile(filesrc, destfile)\n        elif save_as_gif:\n            filename = f\"{output_file}.gif\"\n            filesrc = os.path.join(video_dir, qualitydir, filename)\n        elif save_last_frame:\n            filename = f\"{output_file}.png\"\n            filesrc = os.path.join(images_dir, filename)\n        else:\n            raise ValueError(\"Invalid combination of render flags received.\")\n\n        rendered_template = jinja2.Template(TEMPLATE).render(\n            hide_source=hide_source,\n            filesrc_rel=os.path.relpath(filesrc, setup.confdir),\n            output_file=output_file,\n            save_last_frame=save_last_frame,\n            save_as_gif=save_as_gif,\n            source_block=source_block,\n            ref_block=ref_block,\n        )\n        state_machine.insert_input(\n            rendered_template.split(\"\\n\"), source=document.attributes[\"source\"]\n        )\n\n        return []\n\n\ndef setup(app):\n    import manim\n\n    setup.app = app\n    setup.config = app.config\n    setup.confdir = app.confdir\n    app.add_directive(\"manim\", ManimDirective)\n\n    metadata = {\"parallel_read_safe\": False, \"parallel_write_safe\": True}\n    return metadata\n\n\nTEMPLATE = r\"\"\"\n{% if not hide_source %}\n.. raw:: html\n\n    <div class=\"manim-example\">\n\n{{ source_block }}\n{{ ref_block }}\n{% endif %}\n\n{% if not (save_as_gif or save_last_frame) %}\n.. raw:: html\n\n    <video class=\"manim-video\" controls loop autoplay src=\"./{{ output_file }}.mp4\"></video>\n{% elif save_as_gif %}\n.. image:: /{{ filesrc_rel }}\n    :align: center\n{% elif save_last_frame %}\n.. image:: /{{ filesrc_rel }}\n    :align: center\n{% endif %}\n\n{% if not hide_source %}\n.. raw:: html\n\n    </div>\n{% endif %}\n\"\"\"\n", "path": "docs/source/manim_directive.py"}], "after_files": [{"content": "r\"\"\"\nA directive for including Manim videos in a Sphinx document\n===========================================================\n\nWhen rendering the HTML documentation, the ``.. manim::`` directive\nimplemented here allows to include rendered videos.\n\nIts basic usage that allows processing **inline content**\nlooks as follows::\n\n    .. manim:: MyScene\n\n        class MyScene(Scene):\n            def construct(self):\n                ...\n\nIt is required to pass the name of the class representing the\nscene to be rendered to the directive.\n\nAs a second application, the directive can also be used to\nrender scenes that are defined within doctests, for example::\n\n    .. manim:: DirectiveDoctestExample\n        :ref_classes: Dot\n\n        >>> dot = Dot(color=RED)\n        >>> dot.color\n        <Color #fc6255>\n        >>> class DirectiveDoctestExample(Scene):\n        ...     def construct(self):\n        ...         self.play(ShowCreation(dot))\n\n\nOptions\n-------\n\nOptions can be passed as follows::\n\n    .. manim:: <Class name>\n        :<option name>: <value>\n\nThe following configuration options are supported by the\ndirective:\n\n    hide_source\n        If this flag is present without argument,\n        the source code is not displayed above the rendered video.\n\n    quality : {'low', 'medium', 'high', 'fourk'}\n        Controls render quality of the video, in analogy to\n        the corresponding command line flags.\n\n    save_as_gif\n        If this flag is present without argument,\n        the scene is rendered as a gif.\n\n    save_last_frame\n        If this flag is present without argument,\n        an image representing the last frame of the scene will\n        be rendered and displayed, instead of a video.\n\n    ref_classes\n        A list of classes, separated by spaces, that is\n        rendered in a reference block after the source code.\n\n    ref_functions\n        A list of functions and methods, separated by spaces,\n        that is rendered in a reference block after the source code.\n\n\"\"\"\nfrom docutils.parsers.rst import directives, Directive\n\nimport jinja2\nimport os\nfrom os.path import relpath\nfrom typing import List\n\nimport shutil\n\nclassnamedict = {}\n\n\ndef process_name_list(option_input: str, reference_type: str) -> List[str]:\n    r\"\"\"Reformats a string of space separated class names\n    as a list of strings containing valid Sphinx references.\n\n    TESTS\n    -----\n\n    ::\n\n        >>> process_name_list(\"Tex TexTemplate\", \"class\")\n        [\":class:`~.Tex`\", \":class:`~.TexTemplate`\"]\n        >>> process_name_list(\"Scene.play Mobject.rotate\", \"func\")\n        [\":func:`~.Scene.play`\", \":func:`~.Mobject.rotate`\"]\n    \"\"\"\n    return [f\":{reference_type}:`~.{name}`\" for name in option_input.split()]\n\n\nclass ManimDirective(Directive):\n    r\"\"\"The manim directive, rendering videos while building\n    the documentation.\n\n    See the module docstring for documentation.\n    \"\"\"\n    has_content = True\n    required_arguments = 1\n    optional_arguments = 0\n    option_spec = {\n        \"hide_source\": bool,\n        \"quality\": lambda arg: directives.choice(\n            arg, (\"low\", \"medium\", \"high\", \"fourk\")\n        ),\n        \"save_as_gif\": bool,\n        \"save_last_frame\": bool,\n        \"ref_classes\": lambda arg: process_name_list(arg, \"class\"),\n        \"ref_functions\": lambda arg: process_name_list(arg, \"func\"),\n    }\n    final_argument_whitespace = True\n\n    def run(self):\n        from manim import config\n\n        global classnamedict\n\n        clsname = self.arguments[0]\n        if clsname not in classnamedict:\n            classnamedict[clsname] = 1\n        else:\n            classnamedict[clsname] += 1\n\n        hide_source = \"hide_source\" in self.options\n        save_as_gif = \"save_as_gif\" in self.options\n        save_last_frame = \"save_last_frame\" in self.options\n        assert not (save_as_gif and save_last_frame)\n        if \"ref_classes\" in self.options or \"ref_functions\" in self.options:\n            ref_classes = self.options.get(\"ref_classes\", [])\n            ref_functions = self.options.get(\"ref_functions\", [])\n            ref_content = ref_classes + ref_functions\n            ref_block = f\"\"\"\n.. admonition:: Example References\n    :class: example-reference\n\n    {' '.join(ref_content)}\"\"\"\n        else:\n            ref_block = \"\"\n\n        frame_rate = 30\n        pixel_height = 480\n        pixel_width = 854\n\n        if \"quality\" in self.options:\n            quality = self.options[\"quality\"]\n            if quality == \"low\":\n                pixel_height = 480\n                pixel_width = 854\n                frame_rate = 15\n            elif quality == \"medium\":\n                pixel_height = 720\n                pixel_width = 1280\n                frame_rate = 30\n            elif quality == \"high\":\n                pixel_height = 1440\n                pixel_width = 2560\n                frame_rate = 60\n            elif quality == \"fourk\":\n                pixel_height = 2160\n                pixel_width = 3840\n                frame_rate = 60\n\n        qualitydir = f\"{pixel_height}p{frame_rate}\"\n\n        state_machine = self.state_machine\n        document = state_machine.document\n\n        source_file_name = document.attributes[\"source\"]\n        source_rel_name = relpath(source_file_name, setup.confdir)\n        source_rel_dir = os.path.dirname(source_rel_name)\n        while source_rel_dir.startswith(os.path.sep):\n            source_rel_dir = source_rel_dir[1:]\n\n        dest_dir = os.path.abspath(\n            os.path.join(setup.app.builder.outdir, source_rel_dir)\n        )\n        if not os.path.exists(dest_dir):\n            os.makedirs(dest_dir)\n\n        source_block = [\n            \".. code-block:: python\",\n            \"\",\n            *[\"    \" + line for line in self.content],\n        ]\n        source_block = \"\\n\".join(source_block)\n\n        media_dir = os.path.join(setup.confdir, \"media\")\n        if not os.path.exists(media_dir):\n            os.mkdir(media_dir)\n        images_dir = os.path.join(media_dir, \"images\")\n        if not os.path.exists(images_dir):\n            os.mkdir(images_dir)\n        tex_dir = os.path.join(media_dir, \"tex\")\n        if not os.path.exists(tex_dir):\n            os.mkdir(tex_dir)\n        text_dir = os.path.join(media_dir, \"text\")\n        if not os.path.exists(text_dir):\n            os.mkdir(text_dir)\n        video_dir = os.path.join(media_dir, \"videos\")\n        output_file = f\"{clsname}-{classnamedict[clsname]}\"\n\n        file_writer_config_code = [\n            f'config[\"frame_rate\"] = {frame_rate}',\n            f'config[\"pixel_height\"] = {pixel_height}',\n            f'config[\"pixel_width\"] = {pixel_width}',\n            f'file_writer_config[\"media_dir\"] = r\"{media_dir}\"',\n            f'file_writer_config[\"images_dir\"] = r\"{images_dir}\"',\n            f'file_writer_config[\"tex_dir\"] = r\"{tex_dir}\"',\n            f'file_writer_config[\"text_dir\"] = r\"{text_dir}\"',\n            f'file_writer_config[\"video_dir\"] = r\"{video_dir}\"',\n            f'file_writer_config[\"save_last_frame\"] = {save_last_frame}',\n            f'file_writer_config[\"save_as_gif\"] = {save_as_gif}',\n            f'file_writer_config[\"output_file\"] = r\"{output_file}\"',\n        ]\n\n        user_code = self.content\n        if user_code[0].startswith(\">>> \"):  # check whether block comes from doctest\n            user_code = [\n                line[4:] for line in user_code if line.startswith((\">>> \", \"... \"))\n            ]\n\n        code = [\n            \"from manim import *\",\n            *file_writer_config_code,\n            *user_code,\n            f\"{clsname}().render()\",\n        ]\n        exec(\"\\n\".join(code), globals())\n\n        # copy video file to output directory\n        if not (save_as_gif or save_last_frame):\n            filename = f\"{output_file}.mp4\"\n            filesrc = os.path.join(video_dir, qualitydir, filename)\n            destfile = os.path.join(dest_dir, filename)\n            shutil.copyfile(filesrc, destfile)\n        elif save_as_gif:\n            filename = f\"{output_file}.gif\"\n            filesrc = os.path.join(video_dir, qualitydir, filename)\n        elif save_last_frame:\n            filename = f\"{output_file}.png\"\n            filesrc = os.path.join(images_dir, filename)\n        else:\n            raise ValueError(\"Invalid combination of render flags received.\")\n\n        rendered_template = jinja2.Template(TEMPLATE).render(\n            clsname=clsname,\n            hide_source=hide_source,\n            filesrc_rel=os.path.relpath(filesrc, setup.confdir),\n            output_file=output_file,\n            save_last_frame=save_last_frame,\n            save_as_gif=save_as_gif,\n            source_block=source_block,\n            ref_block=ref_block,\n        )\n        state_machine.insert_input(\n            rendered_template.split(\"\\n\"), source=document.attributes[\"source\"]\n        )\n\n        return []\n\n\ndef setup(app):\n    import manim\n\n    setup.app = app\n    setup.config = app.config\n    setup.confdir = app.confdir\n    app.add_directive(\"manim\", ManimDirective)\n\n    metadata = {\"parallel_read_safe\": False, \"parallel_write_safe\": True}\n    return metadata\n\n\nTEMPLATE = r\"\"\"\n{% if not hide_source %}\n.. raw:: html\n\n    <div class=\"manim-example\">\n\n{% endif %}\n\n{% if not (save_as_gif or save_last_frame) %}\n.. raw:: html\n\n    <video class=\"manim-video\" controls loop autoplay src=\"./{{ output_file }}.mp4\"></video>\n{% elif save_as_gif %}\n.. image:: /{{ filesrc_rel }}\n    :align: center\n{% elif save_last_frame %}\n.. image:: /{{ filesrc_rel }}\n    :align: center\n{% endif %}\n{% if not hide_source %}\n.. raw:: html\n\n    <div class=\"example-header\">{{ clsname }}</div>\n\n{{ source_block }}\n{{ ref_block }}\n{% endif %}\n\n.. raw:: html\n\n    </div>\n\"\"\"\n", "path": "docs/source/manim_directive.py"}]}