We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Error message redirecting to missing documentation
Hi. I am working with manim for the first time and I encountered this:
```
Manim Community v0.17.2

sh: 1: dvisvgm: not found
<traceback>
ValueError: Your installation does not support converting .dvi files to SVG. Consider updating dvisvgm to at least version 2.4. If this does not solve the problem, please
refer to our troubleshooting guide at: https://docs.manim.community/en/stable/installation/troubleshooting.html
```
I tried to follow this link but it's 404. I did some investigation through git and the commit 48747a74d932cc36394c1b7a69994b51855be359 removed this page.

References to this dead page can be found in https://github.com/ManimCommunity/manim/blob/main/.github/ISSUE_TEMPLATE/installation_issue.md?plain=1#L14 and https://github.com/ManimCommunity/manim/blob/main/manim/utils/tex_file_writing.py#L247

I am new to manim so I don't feel confident making a PR to fix this. There could be more 404 links present, I'm only reporting the one I came across.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `manim/utils/tex_file_writing.py`
Content:
```
1 """Interface for writing, compiling, and converting ``.tex`` files.
2 
3 .. SEEALSO::
4 
5     :mod:`.mobject.svg.tex_mobject`
6 
7 """
8 
9 from __future__ import annotations
10 
11 import hashlib
12 import os
13 import re
14 import unicodedata
15 from pathlib import Path
16 
17 from manim.utils.tex import TexTemplate
18 
19 from .. import config, logger
20 
21 
22 def tex_hash(expression):
23     id_str = str(expression)
24     hasher = hashlib.sha256()
25     hasher.update(id_str.encode())
26     # Truncating at 16 bytes for cleanliness
27     return hasher.hexdigest()[:16]
28 
29 
30 def tex_to_svg_file(
31     expression: str,
32     environment: str | None = None,
33     tex_template: TexTemplate | None = None,
34 ):
35     """Takes a tex expression and returns the svg version of the compiled tex
36 
37     Parameters
38     ----------
39     expression
40         String containing the TeX expression to be rendered, e.g. ``\\sqrt{2}`` or ``foo``
41     environment
42         The string containing the environment in which the expression should be typeset, e.g. ``align*``
43     tex_template
44         Template class used to typesetting. If not set, use default template set via `config["tex_template"]`
45 
46     Returns
47     -------
48     :class:`Path`
49         Path to generated SVG file.
50     """
51     if tex_template is None:
52         tex_template = config["tex_template"]
53     tex_file = generate_tex_file(expression, environment, tex_template)
54     dvi_file = compile_tex(
55         tex_file,
56         tex_template.tex_compiler,
57         tex_template.output_format,
58     )
59     return convert_to_svg(dvi_file, tex_template.output_format)
60 
61 
62 def generate_tex_file(
63     expression: str,
64     environment: str | None = None,
65     tex_template: TexTemplate | None = None,
66 ):
67     """Takes a tex expression (and an optional tex environment),
68     and returns a fully formed tex file ready for compilation.
69 
70     Parameters
71     ----------
72     expression
73         String containing the TeX expression to be rendered, e.g. ``\\sqrt{2}`` or ``foo``
74     environment
75         The string containing the environment in which the expression should be typeset, e.g. ``align*``
76     tex_template
77         Template class used to typesetting. If not set, use default template set via `config["tex_template"]`
78 
79     Returns
80     -------
81     :class:`Path`
82         Path to generated TeX file
83     """
84     if tex_template is None:
85         tex_template = config["tex_template"]
86     if environment is not None:
87         output = tex_template.get_texcode_for_expression_in_env(expression, environment)
88     else:
89         output = tex_template.get_texcode_for_expression(expression)
90 
91     tex_dir = config.get_dir("tex_dir")
92     if not tex_dir.exists():
93         tex_dir.mkdir()
94 
95     result = tex_dir / (tex_hash(output) + ".tex")
96     if not result.exists():
97         logger.info(
98             "Writing %(expression)s to %(path)s",
99             {"expression": expression, "path": f"{result}"},
100         )
101         result.write_text(output, encoding="utf-8")
102     return result
103 
104 
105 def tex_compilation_command(
106     tex_compiler: str, output_format: str, tex_file: Path, tex_dir: Path
107 ) -> str:
108     """Prepares the tex compilation command with all necessary cli flags
109 
110     Parameters
111     ----------
112     tex_compiler
113         String containing the compiler to be used, e.g. ``pdflatex`` or ``lualatex``
114     output_format
115         String containing the output format generated by the compiler, e.g. ``.dvi`` or ``.pdf``
116     tex_file
117         File name of TeX file to be typeset.
118     tex_dir
119         Path to the directory where compiler output will be stored.
120 
121     Returns
122     -------
123     :class:`str`
124         Compilation command according to given parameters
125     """
126     if tex_compiler in {"latex", "pdflatex", "luatex", "lualatex"}:
127         commands = [
128             tex_compiler,
129             "-interaction=batchmode",
130             f'-output-format="{output_format[1:]}"',
131             "-halt-on-error",
132             f'-output-directory="{tex_dir.as_posix()}"',
133             f'"{tex_file.as_posix()}"',
134             ">",
135             os.devnull,
136         ]
137     elif tex_compiler == "xelatex":
138         if output_format == ".xdv":
139             outflag = "-no-pdf"
140         elif output_format == ".pdf":
141             outflag = ""
142         else:
143             raise ValueError("xelatex output is either pdf or xdv")
144         commands = [
145             "xelatex",
146             outflag,
147             "-interaction=batchmode",
148             "-halt-on-error",
149             f'-output-directory="{tex_dir.as_posix()}"',
150             f'"{tex_file.as_posix()}"',
151             ">",
152             os.devnull,
153         ]
154     else:
155         raise ValueError(f"Tex compiler {tex_compiler} unknown.")
156     return " ".join(commands)
157 
158 
159 def insight_inputenc_error(matching):
160     code_point = chr(int(matching[1], 16))
161     name = unicodedata.name(code_point)
162     yield f"TexTemplate does not support character '{name}' (U+{matching[1]})."
163     yield "See the documentation for manim.mobject.svg.tex_mobject for details on using a custom TexTemplate."
164 
165 
166 def insight_package_not_found_error(matching):
167     yield f"You do not have package {matching[1]} installed."
168     yield f"Install {matching[1]} it using your LaTeX package manager, or check for typos."
169 
170 
171 def compile_tex(tex_file: Path, tex_compiler: str, output_format: str) -> Path:
172     """Compiles a tex_file into a .dvi or a .xdv or a .pdf
173 
174     Parameters
175     ----------
176     tex_file
177         File name of TeX file to be typeset.
178     tex_compiler
179         String containing the compiler to be used, e.g. ``pdflatex`` or ``lualatex``
180     output_format
181         String containing the output format generated by the compiler, e.g. ``.dvi`` or ``.pdf``
182 
183     Returns
184     -------
185     :class:`Path`
186         Path to generated output file in desired format (DVI, XDV or PDF).
187     """
188     result = tex_file.with_suffix(output_format)
189     tex_dir = config.get_dir("tex_dir")
190     if not result.exists():
191         command = tex_compilation_command(
192             tex_compiler,
193             output_format,
194             tex_file,
195             tex_dir,
196         )
197         exit_code = os.system(command)
198         if exit_code != 0:
199             log_file = tex_file.with_suffix(".log")
200             print_all_tex_errors(log_file, tex_compiler, tex_file)
201             raise ValueError(
202                 f"{tex_compiler} error converting to"
203                 f" {output_format[1:]}. See log output above or"
204                 f" the log file: {log_file}",
205             )
206     return result
207 
208 
209 def convert_to_svg(dvi_file: Path, extension: str, page: int = 1):
210     """Converts a .dvi, .xdv, or .pdf file into an svg using dvisvgm.
211 
212     Parameters
213     ----------
214     dvi_file
215         File name of the input file to be converted.
216     extension
217         String containing the file extension and thus indicating the file type, e.g. ``.dvi`` or ``.pdf``
218     page
219         Page to be converted if input file is multi-page.
220 
221     Returns
222     -------
223     :class:`Path`
224         Path to generated SVG file.
225     """
226     result = dvi_file.with_suffix(".svg")
227     if not result.exists():
228         commands = [
229             "dvisvgm",
230             "--pdf" if extension == ".pdf" else "",
231             "-p " + str(page),
232             f'"{dvi_file.as_posix()}"',
233             "-n",
234             "-v 0",
235             "-o " + f'"{result.as_posix()}"',
236             ">",
237             os.devnull,
238         ]
239         os.system(" ".join(commands))
240 
241     # if the file does not exist now, this means conversion failed
242     if not result.exists():
243         raise ValueError(
244             f"Your installation does not support converting {dvi_file.suffix} files to SVG."
245             f" Consider updating dvisvgm to at least version 2.4."
246             f" If this does not solve the problem, please refer to our troubleshooting guide at:"
247             f" https://docs.manim.community/en/stable/installation/troubleshooting.html",
248         )
249 
250     return result
251 
252 
253 def print_all_tex_errors(log_file: Path, tex_compiler: str, tex_file: Path) -> None:
254     if not log_file.exists():
255         raise RuntimeError(
256             f"{tex_compiler} failed but did not produce a log file. "
257             "Check your LaTeX installation.",
258         )
259     with log_file.open(encoding="utf-8") as f:
260         tex_compilation_log = f.readlines()
261     error_indices = [
262         index for index, line in enumerate(tex_compilation_log) if line.startswith("!")
263     ]
264     if error_indices:
265         with tex_file.open() as f:
266             tex = f.readlines()
267         for error_index in error_indices:
268             print_tex_error(tex_compilation_log, error_index, tex)
269 
270 
271 LATEX_ERROR_INSIGHTS = [
272     (
273         r"inputenc Error: Unicode character (?:.*) \(U\+([0-9a-fA-F]+)\)",
274         insight_inputenc_error,
275     ),
276     (
277         r"LaTeX Error: File `(.*?[clsty])' not found",
278         insight_package_not_found_error,
279     ),
280 ]
281 
282 
283 def print_tex_error(tex_compilation_log, error_start_index, tex_source):
284     logger.error(
285         f"LaTeX compilation error: {tex_compilation_log[error_start_index][2:]}",
286     )
287 
288     # TeX errors eventually contain a line beginning 'l.xxx` where xxx is the line number that caused the compilation
289     # failure. This code finds the next such line after the error current error message
290     line_of_tex_error = (
291         int(
292             [
293                 log_line
294                 for log_line in tex_compilation_log[error_start_index:]
295                 if log_line.startswith("l.")
296             ][0]
297             .split(" ")[0]
298             .split(".")[1],
299         )
300         - 1
301     )
302     # our tex error may be on a line outside our user input because of post-processing
303     if line_of_tex_error >= len(tex_source):
304         return None
305 
306     context = ["Context of error: \n"]
307     if line_of_tex_error < 3:
308         context += tex_source[: line_of_tex_error + 3]
309         context[-4] = "-> " + context[-4]
310     elif line_of_tex_error > len(tex_source) - 3:
311         context += tex_source[line_of_tex_error - 1 :]
312         context[1] = "-> " + context[1]
313     else:
314         context += tex_source[line_of_tex_error - 3 : line_of_tex_error + 3]
315         context[-4] = "-> " + context[-4]
316 
317     context = "".join(context)
318     logger.error(context)
319 
320     for insights in LATEX_ERROR_INSIGHTS:
321         prob, get_insight = insights
322         matching = re.search(
323             prob,
324             "".join(tex_compilation_log[error_start_index])[2:],
325         )
326         if matching is not None:
327             for insight in get_insight(matching):
328                 logger.info(insight)
329
```
--- 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/manim/utils/tex_file_writing.py b/manim/utils/tex_file_writing.py
--- a/manim/utils/tex_file_writing.py
+++ b/manim/utils/tex_file_writing.py
@@ -244,7 +244,8 @@
             f"Your installation does not support converting {dvi_file.suffix} files to SVG."
             f" Consider updating dvisvgm to at least version 2.4."
             f" If this does not solve the problem, please refer to our troubleshooting guide at:"
-            f" https://docs.manim.community/en/stable/installation/troubleshooting.html",
+            f" https://docs.manim.community/en/stable/faq/general.html#my-installation-"
+            f"does-not-support-converting-pdf-to-svg-help",
         )
 
     return result

{"golden_diff": "diff --git a/manim/utils/tex_file_writing.py b/manim/utils/tex_file_writing.py\n--- a/manim/utils/tex_file_writing.py\n+++ b/manim/utils/tex_file_writing.py\n@@ -244,7 +244,8 @@\n             f\"Your installation does not support converting {dvi_file.suffix} files to SVG.\"\n             f\" Consider updating dvisvgm to at least version 2.4.\"\n             f\" If this does not solve the problem, please refer to our troubleshooting guide at:\"\n-            f\" https://docs.manim.community/en/stable/installation/troubleshooting.html\",\n+            f\" https://docs.manim.community/en/stable/faq/general.html#my-installation-\"\n+            f\"does-not-support-converting-pdf-to-svg-help\",\n         )\n \n     return result\n", "issue": "Error message redirecting to missing documentation\nHi. I am working with manim for the first time and I encountered this:\r\n```\r\nManim Community v0.17.2\r\n\r\nsh: 1: dvisvgm: not found\r\n<traceback>\r\nValueError: Your installation does not support converting .dvi files to SVG. Consider updating dvisvgm to at least version 2.4. If this does not solve the problem, please\r\nrefer to our troubleshooting guide at: https://docs.manim.community/en/stable/installation/troubleshooting.html\r\n```\r\nI tried to follow this link but it's 404. I did some investigation through git and the commit 48747a74d932cc36394c1b7a69994b51855be359 removed this page.\r\n\r\nReferences to this dead page can be found in https://github.com/ManimCommunity/manim/blob/main/.github/ISSUE_TEMPLATE/installation_issue.md?plain=1#L14 and https://github.com/ManimCommunity/manim/blob/main/manim/utils/tex_file_writing.py#L247\r\n\r\nI am new to manim so I don't feel confident making a PR to fix this. There could be more 404 links present, I'm only reporting the one I came across.\n", "before_files": [{"content": "\"\"\"Interface for writing, compiling, and converting ``.tex`` files.\n\n.. SEEALSO::\n\n    :mod:`.mobject.svg.tex_mobject`\n\n\"\"\"\n\nfrom __future__ import annotations\n\nimport hashlib\nimport os\nimport re\nimport unicodedata\nfrom pathlib import Path\n\nfrom manim.utils.tex import TexTemplate\n\nfrom .. import config, logger\n\n\ndef tex_hash(expression):\n    id_str = str(expression)\n    hasher = hashlib.sha256()\n    hasher.update(id_str.encode())\n    # Truncating at 16 bytes for cleanliness\n    return hasher.hexdigest()[:16]\n\n\ndef tex_to_svg_file(\n    expression: str,\n    environment: str | None = None,\n    tex_template: TexTemplate | None = None,\n):\n    \"\"\"Takes a tex expression and returns the svg version of the compiled tex\n\n    Parameters\n    ----------\n    expression\n        String containing the TeX expression to be rendered, e.g. ``\\\\sqrt{2}`` or ``foo``\n    environment\n        The string containing the environment in which the expression should be typeset, e.g. ``align*``\n    tex_template\n        Template class used to typesetting. If not set, use default template set via `config[\"tex_template\"]`\n\n    Returns\n    -------\n    :class:`Path`\n        Path to generated SVG file.\n    \"\"\"\n    if tex_template is None:\n        tex_template = config[\"tex_template\"]\n    tex_file = generate_tex_file(expression, environment, tex_template)\n    dvi_file = compile_tex(\n        tex_file,\n        tex_template.tex_compiler,\n        tex_template.output_format,\n    )\n    return convert_to_svg(dvi_file, tex_template.output_format)\n\n\ndef generate_tex_file(\n    expression: str,\n    environment: str | None = None,\n    tex_template: TexTemplate | None = None,\n):\n    \"\"\"Takes a tex expression (and an optional tex environment),\n    and returns a fully formed tex file ready for compilation.\n\n    Parameters\n    ----------\n    expression\n        String containing the TeX expression to be rendered, e.g. ``\\\\sqrt{2}`` or ``foo``\n    environment\n        The string containing the environment in which the expression should be typeset, e.g. ``align*``\n    tex_template\n        Template class used to typesetting. If not set, use default template set via `config[\"tex_template\"]`\n\n    Returns\n    -------\n    :class:`Path`\n        Path to generated TeX file\n    \"\"\"\n    if tex_template is None:\n        tex_template = config[\"tex_template\"]\n    if environment is not None:\n        output = tex_template.get_texcode_for_expression_in_env(expression, environment)\n    else:\n        output = tex_template.get_texcode_for_expression(expression)\n\n    tex_dir = config.get_dir(\"tex_dir\")\n    if not tex_dir.exists():\n        tex_dir.mkdir()\n\n    result = tex_dir / (tex_hash(output) + \".tex\")\n    if not result.exists():\n        logger.info(\n            \"Writing %(expression)s to %(path)s\",\n            {\"expression\": expression, \"path\": f\"{result}\"},\n        )\n        result.write_text(output, encoding=\"utf-8\")\n    return result\n\n\ndef tex_compilation_command(\n    tex_compiler: str, output_format: str, tex_file: Path, tex_dir: Path\n) -> str:\n    \"\"\"Prepares the tex compilation command with all necessary cli flags\n\n    Parameters\n    ----------\n    tex_compiler\n        String containing the compiler to be used, e.g. ``pdflatex`` or ``lualatex``\n    output_format\n        String containing the output format generated by the compiler, e.g. ``.dvi`` or ``.pdf``\n    tex_file\n        File name of TeX file to be typeset.\n    tex_dir\n        Path to the directory where compiler output will be stored.\n\n    Returns\n    -------\n    :class:`str`\n        Compilation command according to given parameters\n    \"\"\"\n    if tex_compiler in {\"latex\", \"pdflatex\", \"luatex\", \"lualatex\"}:\n        commands = [\n            tex_compiler,\n            \"-interaction=batchmode\",\n            f'-output-format=\"{output_format[1:]}\"',\n            \"-halt-on-error\",\n            f'-output-directory=\"{tex_dir.as_posix()}\"',\n            f'\"{tex_file.as_posix()}\"',\n            \">\",\n            os.devnull,\n        ]\n    elif tex_compiler == \"xelatex\":\n        if output_format == \".xdv\":\n            outflag = \"-no-pdf\"\n        elif output_format == \".pdf\":\n            outflag = \"\"\n        else:\n            raise ValueError(\"xelatex output is either pdf or xdv\")\n        commands = [\n            \"xelatex\",\n            outflag,\n            \"-interaction=batchmode\",\n            \"-halt-on-error\",\n            f'-output-directory=\"{tex_dir.as_posix()}\"',\n            f'\"{tex_file.as_posix()}\"',\n            \">\",\n            os.devnull,\n        ]\n    else:\n        raise ValueError(f\"Tex compiler {tex_compiler} unknown.\")\n    return \" \".join(commands)\n\n\ndef insight_inputenc_error(matching):\n    code_point = chr(int(matching[1], 16))\n    name = unicodedata.name(code_point)\n    yield f\"TexTemplate does not support character '{name}' (U+{matching[1]}).\"\n    yield \"See the documentation for manim.mobject.svg.tex_mobject for details on using a custom TexTemplate.\"\n\n\ndef insight_package_not_found_error(matching):\n    yield f\"You do not have package {matching[1]} installed.\"\n    yield f\"Install {matching[1]} it using your LaTeX package manager, or check for typos.\"\n\n\ndef compile_tex(tex_file: Path, tex_compiler: str, output_format: str) -> Path:\n    \"\"\"Compiles a tex_file into a .dvi or a .xdv or a .pdf\n\n    Parameters\n    ----------\n    tex_file\n        File name of TeX file to be typeset.\n    tex_compiler\n        String containing the compiler to be used, e.g. ``pdflatex`` or ``lualatex``\n    output_format\n        String containing the output format generated by the compiler, e.g. ``.dvi`` or ``.pdf``\n\n    Returns\n    -------\n    :class:`Path`\n        Path to generated output file in desired format (DVI, XDV or PDF).\n    \"\"\"\n    result = tex_file.with_suffix(output_format)\n    tex_dir = config.get_dir(\"tex_dir\")\n    if not result.exists():\n        command = tex_compilation_command(\n            tex_compiler,\n            output_format,\n            tex_file,\n            tex_dir,\n        )\n        exit_code = os.system(command)\n        if exit_code != 0:\n            log_file = tex_file.with_suffix(\".log\")\n            print_all_tex_errors(log_file, tex_compiler, tex_file)\n            raise ValueError(\n                f\"{tex_compiler} error converting to\"\n                f\" {output_format[1:]}. See log output above or\"\n                f\" the log file: {log_file}\",\n            )\n    return result\n\n\ndef convert_to_svg(dvi_file: Path, extension: str, page: int = 1):\n    \"\"\"Converts a .dvi, .xdv, or .pdf file into an svg using dvisvgm.\n\n    Parameters\n    ----------\n    dvi_file\n        File name of the input file to be converted.\n    extension\n        String containing the file extension and thus indicating the file type, e.g. ``.dvi`` or ``.pdf``\n    page\n        Page to be converted if input file is multi-page.\n\n    Returns\n    -------\n    :class:`Path`\n        Path to generated SVG file.\n    \"\"\"\n    result = dvi_file.with_suffix(\".svg\")\n    if not result.exists():\n        commands = [\n            \"dvisvgm\",\n            \"--pdf\" if extension == \".pdf\" else \"\",\n            \"-p \" + str(page),\n            f'\"{dvi_file.as_posix()}\"',\n            \"-n\",\n            \"-v 0\",\n            \"-o \" + f'\"{result.as_posix()}\"',\n            \">\",\n            os.devnull,\n        ]\n        os.system(\" \".join(commands))\n\n    # if the file does not exist now, this means conversion failed\n    if not result.exists():\n        raise ValueError(\n            f\"Your installation does not support converting {dvi_file.suffix} files to SVG.\"\n            f\" Consider updating dvisvgm to at least version 2.4.\"\n            f\" If this does not solve the problem, please refer to our troubleshooting guide at:\"\n            f\" https://docs.manim.community/en/stable/installation/troubleshooting.html\",\n        )\n\n    return result\n\n\ndef print_all_tex_errors(log_file: Path, tex_compiler: str, tex_file: Path) -> None:\n    if not log_file.exists():\n        raise RuntimeError(\n            f\"{tex_compiler} failed but did not produce a log file. \"\n            \"Check your LaTeX installation.\",\n        )\n    with log_file.open(encoding=\"utf-8\") as f:\n        tex_compilation_log = f.readlines()\n    error_indices = [\n        index for index, line in enumerate(tex_compilation_log) if line.startswith(\"!\")\n    ]\n    if error_indices:\n        with tex_file.open() as f:\n            tex = f.readlines()\n        for error_index in error_indices:\n            print_tex_error(tex_compilation_log, error_index, tex)\n\n\nLATEX_ERROR_INSIGHTS = [\n    (\n        r\"inputenc Error: Unicode character (?:.*) \\(U\\+([0-9a-fA-F]+)\\)\",\n        insight_inputenc_error,\n    ),\n    (\n        r\"LaTeX Error: File `(.*?[clsty])' not found\",\n        insight_package_not_found_error,\n    ),\n]\n\n\ndef print_tex_error(tex_compilation_log, error_start_index, tex_source):\n    logger.error(\n        f\"LaTeX compilation error: {tex_compilation_log[error_start_index][2:]}\",\n    )\n\n    # TeX errors eventually contain a line beginning 'l.xxx` where xxx is the line number that caused the compilation\n    # failure. This code finds the next such line after the error current error message\n    line_of_tex_error = (\n        int(\n            [\n                log_line\n                for log_line in tex_compilation_log[error_start_index:]\n                if log_line.startswith(\"l.\")\n            ][0]\n            .split(\" \")[0]\n            .split(\".\")[1],\n        )\n        - 1\n    )\n    # our tex error may be on a line outside our user input because of post-processing\n    if line_of_tex_error >= len(tex_source):\n        return None\n\n    context = [\"Context of error: \\n\"]\n    if line_of_tex_error < 3:\n        context += tex_source[: line_of_tex_error + 3]\n        context[-4] = \"-> \" + context[-4]\n    elif line_of_tex_error > len(tex_source) - 3:\n        context += tex_source[line_of_tex_error - 1 :]\n        context[1] = \"-> \" + context[1]\n    else:\n        context += tex_source[line_of_tex_error - 3 : line_of_tex_error + 3]\n        context[-4] = \"-> \" + context[-4]\n\n    context = \"\".join(context)\n    logger.error(context)\n\n    for insights in LATEX_ERROR_INSIGHTS:\n        prob, get_insight = insights\n        matching = re.search(\n            prob,\n            \"\".join(tex_compilation_log[error_start_index])[2:],\n        )\n        if matching is not None:\n            for insight in get_insight(matching):\n                logger.info(insight)\n", "path": "manim/utils/tex_file_writing.py"}], "after_files": [{"content": "\"\"\"Interface for writing, compiling, and converting ``.tex`` files.\n\n.. SEEALSO::\n\n    :mod:`.mobject.svg.tex_mobject`\n\n\"\"\"\n\nfrom __future__ import annotations\n\nimport hashlib\nimport os\nimport re\nimport unicodedata\nfrom pathlib import Path\n\nfrom manim.utils.tex import TexTemplate\n\nfrom .. import config, logger\n\n\ndef tex_hash(expression):\n    id_str = str(expression)\n    hasher = hashlib.sha256()\n    hasher.update(id_str.encode())\n    # Truncating at 16 bytes for cleanliness\n    return hasher.hexdigest()[:16]\n\n\ndef tex_to_svg_file(\n    expression: str,\n    environment: str | None = None,\n    tex_template: TexTemplate | None = None,\n):\n    \"\"\"Takes a tex expression and returns the svg version of the compiled tex\n\n    Parameters\n    ----------\n    expression\n        String containing the TeX expression to be rendered, e.g. ``\\\\sqrt{2}`` or ``foo``\n    environment\n        The string containing the environment in which the expression should be typeset, e.g. ``align*``\n    tex_template\n        Template class used to typesetting. If not set, use default template set via `config[\"tex_template\"]`\n\n    Returns\n    -------\n    :class:`Path`\n        Path to generated SVG file.\n    \"\"\"\n    if tex_template is None:\n        tex_template = config[\"tex_template\"]\n    tex_file = generate_tex_file(expression, environment, tex_template)\n    dvi_file = compile_tex(\n        tex_file,\n        tex_template.tex_compiler,\n        tex_template.output_format,\n    )\n    return convert_to_svg(dvi_file, tex_template.output_format)\n\n\ndef generate_tex_file(\n    expression: str,\n    environment: str | None = None,\n    tex_template: TexTemplate | None = None,\n):\n    \"\"\"Takes a tex expression (and an optional tex environment),\n    and returns a fully formed tex file ready for compilation.\n\n    Parameters\n    ----------\n    expression\n        String containing the TeX expression to be rendered, e.g. ``\\\\sqrt{2}`` or ``foo``\n    environment\n        The string containing the environment in which the expression should be typeset, e.g. ``align*``\n    tex_template\n        Template class used to typesetting. If not set, use default template set via `config[\"tex_template\"]`\n\n    Returns\n    -------\n    :class:`Path`\n        Path to generated TeX file\n    \"\"\"\n    if tex_template is None:\n        tex_template = config[\"tex_template\"]\n    if environment is not None:\n        output = tex_template.get_texcode_for_expression_in_env(expression, environment)\n    else:\n        output = tex_template.get_texcode_for_expression(expression)\n\n    tex_dir = config.get_dir(\"tex_dir\")\n    if not tex_dir.exists():\n        tex_dir.mkdir()\n\n    result = tex_dir / (tex_hash(output) + \".tex\")\n    if not result.exists():\n        logger.info(\n            \"Writing %(expression)s to %(path)s\",\n            {\"expression\": expression, \"path\": f\"{result}\"},\n        )\n        result.write_text(output, encoding=\"utf-8\")\n    return result\n\n\ndef tex_compilation_command(\n    tex_compiler: str, output_format: str, tex_file: Path, tex_dir: Path\n) -> str:\n    \"\"\"Prepares the tex compilation command with all necessary cli flags\n\n    Parameters\n    ----------\n    tex_compiler\n        String containing the compiler to be used, e.g. ``pdflatex`` or ``lualatex``\n    output_format\n        String containing the output format generated by the compiler, e.g. ``.dvi`` or ``.pdf``\n    tex_file\n        File name of TeX file to be typeset.\n    tex_dir\n        Path to the directory where compiler output will be stored.\n\n    Returns\n    -------\n    :class:`str`\n        Compilation command according to given parameters\n    \"\"\"\n    if tex_compiler in {\"latex\", \"pdflatex\", \"luatex\", \"lualatex\"}:\n        commands = [\n            tex_compiler,\n            \"-interaction=batchmode\",\n            f'-output-format=\"{output_format[1:]}\"',\n            \"-halt-on-error\",\n            f'-output-directory=\"{tex_dir.as_posix()}\"',\n            f'\"{tex_file.as_posix()}\"',\n            \">\",\n            os.devnull,\n        ]\n    elif tex_compiler == \"xelatex\":\n        if output_format == \".xdv\":\n            outflag = \"-no-pdf\"\n        elif output_format == \".pdf\":\n            outflag = \"\"\n        else:\n            raise ValueError(\"xelatex output is either pdf or xdv\")\n        commands = [\n            \"xelatex\",\n            outflag,\n            \"-interaction=batchmode\",\n            \"-halt-on-error\",\n            f'-output-directory=\"{tex_dir.as_posix()}\"',\n            f'\"{tex_file.as_posix()}\"',\n            \">\",\n            os.devnull,\n        ]\n    else:\n        raise ValueError(f\"Tex compiler {tex_compiler} unknown.\")\n    return \" \".join(commands)\n\n\ndef insight_inputenc_error(matching):\n    code_point = chr(int(matching[1], 16))\n    name = unicodedata.name(code_point)\n    yield f\"TexTemplate does not support character '{name}' (U+{matching[1]}).\"\n    yield \"See the documentation for manim.mobject.svg.tex_mobject for details on using a custom TexTemplate.\"\n\n\ndef insight_package_not_found_error(matching):\n    yield f\"You do not have package {matching[1]} installed.\"\n    yield f\"Install {matching[1]} it using your LaTeX package manager, or check for typos.\"\n\n\ndef compile_tex(tex_file: Path, tex_compiler: str, output_format: str) -> Path:\n    \"\"\"Compiles a tex_file into a .dvi or a .xdv or a .pdf\n\n    Parameters\n    ----------\n    tex_file\n        File name of TeX file to be typeset.\n    tex_compiler\n        String containing the compiler to be used, e.g. ``pdflatex`` or ``lualatex``\n    output_format\n        String containing the output format generated by the compiler, e.g. ``.dvi`` or ``.pdf``\n\n    Returns\n    -------\n    :class:`Path`\n        Path to generated output file in desired format (DVI, XDV or PDF).\n    \"\"\"\n    result = tex_file.with_suffix(output_format)\n    tex_dir = config.get_dir(\"tex_dir\")\n    if not result.exists():\n        command = tex_compilation_command(\n            tex_compiler,\n            output_format,\n            tex_file,\n            tex_dir,\n        )\n        exit_code = os.system(command)\n        if exit_code != 0:\n            log_file = tex_file.with_suffix(\".log\")\n            print_all_tex_errors(log_file, tex_compiler, tex_file)\n            raise ValueError(\n                f\"{tex_compiler} error converting to\"\n                f\" {output_format[1:]}. See log output above or\"\n                f\" the log file: {log_file}\",\n            )\n    return result\n\n\ndef convert_to_svg(dvi_file: Path, extension: str, page: int = 1):\n    \"\"\"Converts a .dvi, .xdv, or .pdf file into an svg using dvisvgm.\n\n    Parameters\n    ----------\n    dvi_file\n        File name of the input file to be converted.\n    extension\n        String containing the file extension and thus indicating the file type, e.g. ``.dvi`` or ``.pdf``\n    page\n        Page to be converted if input file is multi-page.\n\n    Returns\n    -------\n    :class:`Path`\n        Path to generated SVG file.\n    \"\"\"\n    result = dvi_file.with_suffix(\".svg\")\n    if not result.exists():\n        commands = [\n            \"dvisvgm\",\n            \"--pdf\" if extension == \".pdf\" else \"\",\n            \"-p \" + str(page),\n            f'\"{dvi_file.as_posix()}\"',\n            \"-n\",\n            \"-v 0\",\n            \"-o \" + f'\"{result.as_posix()}\"',\n            \">\",\n            os.devnull,\n        ]\n        os.system(\" \".join(commands))\n\n    # if the file does not exist now, this means conversion failed\n    if not result.exists():\n        raise ValueError(\n            f\"Your installation does not support converting {dvi_file.suffix} files to SVG.\"\n            f\" Consider updating dvisvgm to at least version 2.4.\"\n            f\" If this does not solve the problem, please refer to our troubleshooting guide at:\"\n            f\" https://docs.manim.community/en/stable/faq/general.html#my-installation-\"\n            f\"does-not-support-converting-pdf-to-svg-help\",\n        )\n\n    return result\n\n\ndef print_all_tex_errors(log_file: Path, tex_compiler: str, tex_file: Path) -> None:\n    if not log_file.exists():\n        raise RuntimeError(\n            f\"{tex_compiler} failed but did not produce a log file. \"\n            \"Check your LaTeX installation.\",\n        )\n    with log_file.open(encoding=\"utf-8\") as f:\n        tex_compilation_log = f.readlines()\n    error_indices = [\n        index for index, line in enumerate(tex_compilation_log) if line.startswith(\"!\")\n    ]\n    if error_indices:\n        with tex_file.open() as f:\n            tex = f.readlines()\n        for error_index in error_indices:\n            print_tex_error(tex_compilation_log, error_index, tex)\n\n\nLATEX_ERROR_INSIGHTS = [\n    (\n        r\"inputenc Error: Unicode character (?:.*) \\(U\\+([0-9a-fA-F]+)\\)\",\n        insight_inputenc_error,\n    ),\n    (\n        r\"LaTeX Error: File `(.*?[clsty])' not found\",\n        insight_package_not_found_error,\n    ),\n]\n\n\ndef print_tex_error(tex_compilation_log, error_start_index, tex_source):\n    logger.error(\n        f\"LaTeX compilation error: {tex_compilation_log[error_start_index][2:]}\",\n    )\n\n    # TeX errors eventually contain a line beginning 'l.xxx` where xxx is the line number that caused the compilation\n    # failure. This code finds the next such line after the error current error message\n    line_of_tex_error = (\n        int(\n            [\n                log_line\n                for log_line in tex_compilation_log[error_start_index:]\n                if log_line.startswith(\"l.\")\n            ][0]\n            .split(\" \")[0]\n            .split(\".\")[1],\n        )\n        - 1\n    )\n    # our tex error may be on a line outside our user input because of post-processing\n    if line_of_tex_error >= len(tex_source):\n        return None\n\n    context = [\"Context of error: \\n\"]\n    if line_of_tex_error < 3:\n        context += tex_source[: line_of_tex_error + 3]\n        context[-4] = \"-> \" + context[-4]\n    elif line_of_tex_error > len(tex_source) - 3:\n        context += tex_source[line_of_tex_error - 1 :]\n        context[1] = \"-> \" + context[1]\n    else:\n        context += tex_source[line_of_tex_error - 3 : line_of_tex_error + 3]\n        context[-4] = \"-> \" + context[-4]\n\n    context = \"\".join(context)\n    logger.error(context)\n\n    for insights in LATEX_ERROR_INSIGHTS:\n        prob, get_insight = insights\n        matching = re.search(\n            prob,\n            \"\".join(tex_compilation_log[error_start_index])[2:],\n        )\n        if matching is not None:\n            for insight in get_insight(matching):\n                logger.info(insight)\n", "path": "manim/utils/tex_file_writing.py"}]}