We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Latex and Sphinx are not yet functioning together.
This example is working on sphinx:
```
.. manim:: DotScene1
    :quality: low
    :save_last_frame:

        class DotScene1(Scene):
            def construct(self):
                dot = Dot().set_color(GREEN)
                self.add(dot)
                self.wait(1)
```
However, when I have something tex related, it throws an error:
```
.. manim:: TextExample
    :quality: medium
    :save_last_frame:
    
    class TextExample(Scene):
        def construct(self):
            t = TextMobject("Hello World")
            self.add(t)
```
> Exception occurred:
  File "/home/k/projects/manim-community/manim/utils/tex_file_writing.py", line 32, in generate_tex_file
    with open(result, "w", encoding="utf-8") as outfile:
FileNotFoundError: [Errno 2] No such file or directory: 'media/Tex/7d1ec941f0e30957.tex'
The full traceback has been saved in /tmp/sphinx-err-4zdxhjgt.log, if you want to report the issue to the developers.
Please also report this if it was a user error, so that a better error message can be provided next time.
A bug report can be filed in the tracker at <https://github.com/sphinx-doc/sphinx/issues>. Thanks!
make: *** [Makefile:26: html] Error 2

A similar error message comes e.g. for this example:
```
.. manim:: Plot1
    :quality: medium
    :save_last_frame:

    class Plot1(GraphScene):
       def construct(self):
           self.setup_axes()
           my_func = lambda x: np.sin(x)
           func_graph=self.get_graph(my_func)
           self.add(func_graph)
```

--- 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 
25         >>> dot = Dot(color=RED)
26         >>> dot.color
27         <Color #fc6255>
28         >>> class DirectiveDoctestExample(Scene):
29         ...     def construct(self):
30         ...         self.play(ShowCreation(dot))
31 
32 
33 Options
34 -------
35 
36 Options can be passed as follows::
37 
38     .. manim:: <Class name>
39         :<option name>: <value>
40 
41 The following configuration options are supported by the
42 directive:
43 
44     display_source
45         If this flag is present without argument,
46         the source code is displayed above the rendered video.
47 
48     quality : {'low', 'medium', 'high', 'fourk'}
49         Controls render quality of the video, in analogy to
50         the corresponding command line flags.
51 
52     save_as_gif
53         If this flag is present without argument,
54         the scene is rendered as a gif.
55 
56     save_last_frame
57         If this flag is present without argument,
58         an image representing the last frame of the scene will
59         be rendered and displayed, instead of a video.
60 
61 """
62 from docutils.parsers.rst import directives, Directive
63 from docutils.parsers.rst.directives.images import Image
64 
65 import jinja2
66 import os
67 from os.path import relpath
68 
69 import shutil
70 
71 classnamedict = {}
72 
73 
74 class ManimDirective(Directive):
75     r"""The ``.. manim::`` directive.
76 
77     See the module docstring for documentation.
78     """
79     has_content = True
80     required_arguments = 1
81     optional_arguments = 0
82     option_spec = {
83         "display_source": bool,
84         "quality": lambda arg: directives.choice(
85             arg, ("low", "medium", "high", "fourk")
86         ),
87         "save_as_gif": bool,
88         "save_last_frame": bool,
89     }
90     final_argument_whitespace = True
91 
92     def run(self):
93         from manim import config
94 
95         global classnamedict
96 
97         clsname = self.arguments[0]
98         if clsname not in classnamedict:
99             classnamedict[clsname] = 1
100         else:
101             classnamedict[clsname] += 1
102 
103         display_source = "display_source" in self.options
104         save_as_gif = "save_as_gif" in self.options
105         save_last_frame = "save_last_frame" in self.options
106         assert not (save_as_gif and save_last_frame)
107 
108         frame_rate = config["frame_rate"]
109         pixel_height = config["pixel_height"]
110         pixel_width = config["pixel_width"]
111 
112         if "quality" in self.options:
113             quality = self.options["quality"]
114             if quality == "low":
115                 pixel_height = 480
116                 pixel_width = 854
117                 frame_rate = 15
118             elif quality == "medium":
119                 pixel_height = 720
120                 pixel_width = 1280
121                 frame_rate = 30
122             elif quality == "high":
123                 pixel_height = 1440
124                 pixel_width = 2560
125                 frame_rate = 60
126             elif quality == "fourk":
127                 pixel_height = 2160
128                 pixel_width = 3840
129                 frame_rate = 60
130 
131         qualitydir = f"{pixel_height}p{frame_rate}"
132 
133         state_machine = self.state_machine
134         document = state_machine.document
135 
136         source_file_name = document.attributes["source"]
137         source_rel_name = relpath(source_file_name, setup.confdir)
138         source_rel_dir = os.path.dirname(source_rel_name)
139         while source_rel_dir.startswith(os.path.sep):
140             source_rel_dir = source_rel_dir[1:]
141 
142         dest_dir = os.path.abspath(
143             os.path.join(setup.app.builder.outdir, source_rel_dir)
144         )
145         if not os.path.exists(dest_dir):
146             os.makedirs(dest_dir)
147 
148         source_block = [
149             ".. code-block:: python",
150             "",
151             *["    " + line for line in self.content],
152         ]
153         source_block = "\n".join(source_block)
154 
155         media_dir = os.path.join("source", "media")
156         images_dir = os.path.join(media_dir, "images")
157         video_dir = os.path.join(media_dir, "videos")
158         output_file = f"{clsname}-{classnamedict[clsname]}"
159 
160         file_writer_config_code = [
161             f'config["frame_rate"] = {frame_rate}',
162             f'config["pixel_height"] = {pixel_height}',
163             f'config["pixel_width"] = {pixel_width}',
164             f'file_writer_config["media_dir"] = "{media_dir}"',
165             f'file_writer_config["images_dir"] = "{images_dir}"',
166             f'file_writer_config["video_dir"] = "{video_dir}"',
167             f'file_writer_config["save_last_frame"] = {save_last_frame}',
168             f'file_writer_config["save_as_gif"] = {save_as_gif}',
169             f'file_writer_config["output_file"] = "{output_file}"',
170         ]
171 
172         user_code = self.content
173         if user_code[0].startswith(">>> "):  # check whether block comes from doctest
174             user_code = [
175                 line[4:] for line in user_code if line.startswith((">>> ", "... "))
176             ]
177 
178         code = [
179             "from manim import *",
180             *file_writer_config_code,
181             *user_code,
182             f"{clsname}()",
183         ]
184         exec("\n".join(code), globals())
185 
186         # copy video file to output directory
187         if not (save_as_gif or save_last_frame):
188             filename = f"{output_file}.mp4"
189             filesrc = os.path.join(video_dir, qualitydir, filename)
190             destfile = os.path.join(dest_dir, filename)
191             shutil.copyfile(filesrc, destfile)
192         elif save_as_gif:
193             filename = f"{output_file}.gif"
194             filesrc = os.path.join(video_dir, qualitydir, filename)
195         elif save_last_frame:
196             filename = f"{output_file}.png"
197             filesrc = os.path.join(images_dir, filename)
198         else:
199             raise ValueError("Invalid combination of render flags received.")
200 
201         rendered_template = jinja2.Template(TEMPLATE).render(
202             display_source=display_source,
203             filesrc=filesrc[6:],
204             output_file=output_file,
205             save_last_frame=save_last_frame,
206             save_as_gif=save_as_gif,
207             source_block=source_block,
208         )
209         state_machine.insert_input(
210             rendered_template.split("\n"), source=document.attributes["source"]
211         )
212 
213         return []
214 
215 
216 def setup(app):
217     import manim
218 
219     setup.app = app
220     setup.config = app.config
221     setup.confdir = app.confdir
222     app.add_directive("manim", ManimDirective)
223 
224     metadata = {"parallel_read_safe": False, "parallel_write_safe": True}
225     return metadata
226 
227 
228 TEMPLATE = r"""
229 {% if display_source %}
230 .. raw:: html
231 
232     <div class="manim-example">
233 
234 {{ source_block }}
235 {% endif %}
236 
237 {% if not (save_as_gif or save_last_frame) %}
238 .. raw:: html
239 
240     <video class="manim-video" controls loop autoplay src="./{{ output_file }}.mp4"></video>
241 {% elif save_as_gif %}
242 .. image:: {{ filesrc }}
243     :align: center
244 {% elif save_last_frame %}
245 .. image:: {{ filesrc }}
246     :align: center
247 {% endif %}
248 
249 {% if display_source %}
250 .. raw:: html
251 
252     </div>
253 {% endif %}
254 """
255
```
--- 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
@@ -152,8 +152,18 @@
         ]
         source_block = "\n".join(source_block)
 
-        media_dir = os.path.join("source", "media")
+        media_dir = os.path.join(setup.confdir, "media")
+        if not os.path.exists(media_dir):
+            os.mkdir(media_dir)
         images_dir = os.path.join(media_dir, "images")
+        if not os.path.exists(images_dir):
+            os.mkdir(images_dir)
+        tex_dir = os.path.join(media_dir, "tex")
+        if not os.path.exists(tex_dir):
+            os.mkdir(tex_dir)
+        text_dir = os.path.join(media_dir, "text")
+        if not os.path.exists(text_dir):
+            os.mkdir(text_dir)
         video_dir = os.path.join(media_dir, "videos")
         output_file = f"{clsname}-{classnamedict[clsname]}"
 
@@ -163,6 +173,8 @@
             f'config["pixel_width"] = {pixel_width}',
             f'file_writer_config["media_dir"] = "{media_dir}"',
             f'file_writer_config["images_dir"] = "{images_dir}"',
+            f'file_writer_config["tex_dir"] = "{tex_dir}"',
+            f'file_writer_config["text_dir"] = "{text_dir}"',
             f'file_writer_config["video_dir"] = "{video_dir}"',
             f'file_writer_config["save_last_frame"] = {save_last_frame}',
             f'file_writer_config["save_as_gif"] = {save_as_gif}',
@@ -200,7 +212,7 @@
 
         rendered_template = jinja2.Template(TEMPLATE).render(
             display_source=display_source,
-            filesrc=filesrc[6:],
+            filesrc_rel=os.path.relpath(filesrc, setup.confdir),
             output_file=output_file,
             save_last_frame=save_last_frame,
             save_as_gif=save_as_gif,
@@ -239,10 +251,10 @@
 
     <video class="manim-video" controls loop autoplay src="./{{ output_file }}.mp4"></video>
 {% elif save_as_gif %}
-.. image:: {{ filesrc }}
+.. image:: /{{ filesrc_rel }}
     :align: center
 {% elif save_last_frame %}
-.. image:: {{ filesrc }}
+.. image:: /{{ filesrc_rel }}
     :align: center
 {% endif %}

{"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@@ -152,8 +152,18 @@\n         ]\n         source_block = \"\\n\".join(source_block)\n \n-        media_dir = os.path.join(\"source\", \"media\")\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@@ -163,6 +173,8 @@\n             f'config[\"pixel_width\"] = {pixel_width}',\n             f'file_writer_config[\"media_dir\"] = \"{media_dir}\"',\n             f'file_writer_config[\"images_dir\"] = \"{images_dir}\"',\n+            f'file_writer_config[\"tex_dir\"] = \"{tex_dir}\"',\n+            f'file_writer_config[\"text_dir\"] = \"{text_dir}\"',\n             f'file_writer_config[\"video_dir\"] = \"{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@@ -200,7 +212,7 @@\n \n         rendered_template = jinja2.Template(TEMPLATE).render(\n             display_source=display_source,\n-            filesrc=filesrc[6:],\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@@ -239,10 +251,10 @@\n \n     <video class=\"manim-video\" controls loop autoplay src=\"./{{ output_file }}.mp4\"></video>\n {% elif save_as_gif %}\n-.. image:: {{ filesrc }}\n+.. image:: /{{ filesrc_rel }}\n     :align: center\n {% elif save_last_frame %}\n-.. image:: {{ filesrc }}\n+.. image:: /{{ filesrc_rel }}\n     :align: center\n {% endif %}\n", "issue": "Latex and Sphinx are not yet functioning together.\nThis example is working on sphinx:\r\n```\r\n.. manim:: DotScene1\r\n    :quality: low\r\n    :save_last_frame:\r\n\r\n        class DotScene1(Scene):\r\n            def construct(self):\r\n                dot = Dot().set_color(GREEN)\r\n                self.add(dot)\r\n                self.wait(1)\r\n```\r\nHowever, when I have something tex related, it throws an error:\r\n```\r\n.. manim:: TextExample\r\n    :quality: medium\r\n    :save_last_frame:\r\n    \r\n    class TextExample(Scene):\r\n        def construct(self):\r\n            t = TextMobject(\"Hello World\")\r\n            self.add(t)\r\n```\r\n> Exception occurred:\r\n  File \"/home/k/projects/manim-community/manim/utils/tex_file_writing.py\", line 32, in generate_tex_file\r\n    with open(result, \"w\", encoding=\"utf-8\") as outfile:\r\nFileNotFoundError: [Errno 2] No such file or directory: 'media/Tex/7d1ec941f0e30957.tex'\r\nThe full traceback has been saved in /tmp/sphinx-err-4zdxhjgt.log, if you want to report the issue to the developers.\r\nPlease also report this if it was a user error, so that a better error message can be provided next time.\r\nA bug report can be filed in the tracker at <https://github.com/sphinx-doc/sphinx/issues>. Thanks!\r\nmake: *** [Makefile:26: html] Error 2\r\n\r\nA similar error message comes e.g. for this example:\r\n```\r\n.. manim:: Plot1\r\n    :quality: medium\r\n    :save_last_frame:\r\n\r\n    class Plot1(GraphScene):\r\n       def construct(self):\r\n           self.setup_axes()\r\n           my_func = lambda x: np.sin(x)\r\n           func_graph=self.get_graph(my_func)\r\n           self.add(func_graph)\r\n```\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\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    display_source\n        If this flag is present without argument,\n        the source code is 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\"\"\"\nfrom docutils.parsers.rst import directives, Directive\nfrom docutils.parsers.rst.directives.images import Image\n\nimport jinja2\nimport os\nfrom os.path import relpath\n\nimport shutil\n\nclassnamedict = {}\n\n\nclass ManimDirective(Directive):\n    r\"\"\"The ``.. manim::`` directive.\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        \"display_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    }\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        display_source = \"display_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\n        frame_rate = config[\"frame_rate\"]\n        pixel_height = config[\"pixel_height\"]\n        pixel_width = config[\"pixel_width\"]\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(\"source\", \"media\")\n        images_dir = os.path.join(media_dir, \"images\")\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\"] = \"{media_dir}\"',\n            f'file_writer_config[\"images_dir\"] = \"{images_dir}\"',\n            f'file_writer_config[\"video_dir\"] = \"{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\"] = \"{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}()\",\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            display_source=display_source,\n            filesrc=filesrc[6:],\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        )\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 display_source %}\n.. raw:: html\n\n    <div class=\"manim-example\">\n\n{{ source_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 }}\n    :align: center\n{% elif save_last_frame %}\n.. image:: {{ filesrc }}\n    :align: center\n{% endif %}\n\n{% if display_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\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    display_source\n        If this flag is present without argument,\n        the source code is 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\"\"\"\nfrom docutils.parsers.rst import directives, Directive\nfrom docutils.parsers.rst.directives.images import Image\n\nimport jinja2\nimport os\nfrom os.path import relpath\n\nimport shutil\n\nclassnamedict = {}\n\n\nclass ManimDirective(Directive):\n    r\"\"\"The ``.. manim::`` directive.\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        \"display_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    }\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        display_source = \"display_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\n        frame_rate = config[\"frame_rate\"]\n        pixel_height = config[\"pixel_height\"]\n        pixel_width = config[\"pixel_width\"]\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\"] = \"{media_dir}\"',\n            f'file_writer_config[\"images_dir\"] = \"{images_dir}\"',\n            f'file_writer_config[\"tex_dir\"] = \"{tex_dir}\"',\n            f'file_writer_config[\"text_dir\"] = \"{text_dir}\"',\n            f'file_writer_config[\"video_dir\"] = \"{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\"] = \"{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}()\",\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            display_source=display_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        )\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 display_source %}\n.. raw:: html\n\n    <div class=\"manim-example\">\n\n{{ source_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 display_source %}\n.. raw:: html\n\n    </div>\n{% endif %}\n\"\"\"\n", "path": "docs/source/manim_directive.py"}]}