latex - hf-tikz 和 sphinx 打得不好

标签 latex python-sphinx tikz

我正在尝试为我的 sphinx 矩阵添加一些颜色。我正在使用 hf-tikz为它之前。但是,当我将它添加到 Sphinx 时,它会错误地呈现它。

我想要得到的结果是

enter image description here

我得到的结果是

enter image description here

这是我拥有的代码。

main.rst :

.. math::

    \left(\begin{array}{cc}
        \tikzmarkin[style red]{a}a\tikzmarkend{a}
      & \tikzmarkin[style green]{b}b\tikzmarkend{b} \\
        \tikzmarkin[style blue]{c}c\tikzmarkend{c}
      & \tikzmarkin[style orange]{d}d\tikzmarkend{d} \\
    \end{array}\right)
    \star
    \left(\begin{array}{cc}
        \tikzmarkin[style red]{w}w\tikzmarkend{w}
      & \tikzmarkin[style green]{x}x\tikzmarkend{x} \\
        \tikzmarkin[style blue]{y}y\tikzmarkend{y}
      & \tikzmarkin[style orange]{z}z\tikzmarkend{z} \\
    \end{array}\right)
    =
    \left(\begin{array}{cc}
        \tikzmarkin[hor=style red]{aw}{a\star w}\tikzmarkend{aw}
      & \tikzmarkin[hor=style green]{bx}b\star x\tikzmarkend{bx} \\
        \tikzmarkin[hor=style blue]{cy}c\star y\tikzmarkend{cy}
      & \tikzmarkin[hor=style orange]{dz}d\star z\tikzmarkend{dz} \\
    \end{array}\right)


conf.py

extensions = [
  'sphinx.ext.imgmath',
]

# Math configurations (https://tex.stackexchange.com/a/69770/51173)
imgmath_image_format = 'svg'
imgmath_use_preview = True
imgmath_latex_preamble = r'''
  \usepackage{xcolor}
  \usepackage[customcolors]{hf-tikz}
  \colorlet{myred}{red!50!purple!30}
  \colorlet{mygreen}{green!50!lime!60}
  \colorlet{myblue}{blue!50!white!50}
  \colorlet{myorange}{orange!80!red!60}
  \colorlet{mycyan}{cyan!90!blue!60}
  \colorlet{mymagenta}{magenta!90!red!60}
  \tikzset{
    style red/.style={
      set fill color=myred,
      set border color=white,
    },
    style green/.style={
      set fill color=mygreen,
      set border color=white,
    },
    style blue/.style={
      set fill color=myblue,
      set border color=white,
    },
    style orange/.style={
      set fill color=myorange,
      set border color=white,
    },
    style cyan/.style={
      set fill color=mycyan,
      set border color=white,
    },
    style magenta/.style={
      set fill color=mymagenta,
      set border color=white,
    },
    %
    hor/.style={
      above left offset={-0.15,0.31},
      below right offset={0.15,-0.125},
      #1
    },
    ver/.style={
      above left offset={-0.1,0.3},
      below right offset={0.15,-0.15},
      #1
    }
  }
'''

生成文件
# Minimal makefile for Sphinx documentation
#

# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS    ?=
SPHINXBUILD   ?= sphinx-build
SOURCEDIR     = source
BUILDDIR      = build

# Put it first so that "make" without argument is like "make help".
help:
    @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

.PHONY: help Makefile

# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
    @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

make.bat
@ECHO OFF

pushd %~dp0

REM Command file for Sphinx documentation

if "%SPHINXBUILD%" == "" (
    set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=source
set BUILDDIR=build

if "%1" == "" goto help

%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
    echo.
    echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
    echo.installed, then set the SPHINXBUILD environment variable to point
    echo.to the full path of the 'sphinx-build' executable. Alternatively you
    echo.may add the Sphinx directory to PATH.
    echo.
    echo.If you don't have Sphinx installed, grab it from
    echo.http://sphinx-doc.org/
    exit /b 1
)

%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end

:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%

:end
popd

编辑:添加了用于构建 rst 的 makefile

最佳答案

我想我找到了为什么会这样:问题出在 sphinx.ext.imgmath 扩展名 + hf-tikz 不适用于 DVI 文件。

在转换数学方程时,sphinx 创建一个非常基本的 Latex 文档,并使用 latexpdf 编译它转换成 DVI 文件。之后将文件转换为SVG,并将生成的svg文件复制到sphinx的_build目录。问题是 dvisvgm(由 imgmath 使用)无法转换 tikz 内容。另一种方法是使用扩展的 DVI,但这也不能很好地工作。

解决方案是将所有内容编译为 PDF,然后将该 pdf 转换为 SVG。这有点问题,我发现的唯一方法是使用 pdf2svg + pdfcrop .我最终修改了 imgmath.py进入自定义扩展。以下是我在 imgmath.py 中所做的更改.这些更改需要使用外部应用程序,因此我认为创建拉取请求没有任何好处(至少不是使用更具可扩展性的解决方案)。
imgmath.py的变化:

  • 创建新方法:

  • def convert_pdf_to_svg(pdfpath, builder):
        # type: (str, Builder) -> Tuple[str, int]
        """Convert DVI file to SVG image."""
        tempdir = ensure_tempdir(builder)
        filename = path.join(tempdir, 'math.svg')
    
        name = 'pdfcrop'
        command = [name, pdfpath, pdfpath]
        run_external_command(command, name)
    
        name = 'pdf2svg'
        command = [name, pdfpath, filename]
        run_external_command(command, name)
        return filename, None
    
  • compile_math函数,内部 try块,将 return 语句替换为以下

  • if builder.config.imgmath_pdf2svg:
      return path.join(tempdir, 'math.pdf')
    else:
      return path.join(tempdir, 'math.dvi')
    
  • render_math方法,在块标题 # .dvi -> .png/svg ,替换 try使用以下内容阻止
  • try:
        if image_format == 'png':
            imgpath, depth = convert_dvi_to_png(dvipath, self.builder)
        elif image_format == 'svg':
            if self.builder.config.imgmath_pdf2svg:
                imgpath, depth = convert_pdf_to_svg(dvipath, self.builder)
            else:
                imgpath, depth = convert_dvi_to_svg(dvipath, self.builder)
    except InvokeError:
        self.builder._imgmath_warned_image_translator = True  # type: ignore
        return None, None
    
  • 最后,在 imgmath.py 的最后添加一个新的配置条目:

  •     app.add_config_value('imgmath_pdf2svg', False, 'html')
    

    之后,你可以写在 conf.py 启用 tikz 图像。

    imgmath_image_format = 'svg'
    imgmath_latex = 'latexmk'
    imgmath_latex_args = ['-pdf']
    imgmath_pdf2svg = True  # Available only in the custom `imgmath.py`
    

    imgmath 的补丁延期。 包括一些其他的东西:)

    补丁去a -> b .

    --- a/imgmath.py
    +++ b/imgmath.py
    @@ -15,7 +15,7 @@
     import sys
     import tempfile
     from hashlib import sha1
    -from os import path
    +from os import path, symlink
     from subprocess import CalledProcessError, PIPE
     from typing import Any, Dict, List, Tuple
    
    @@ -157,6 +157,11 @@
         with open(filename, 'w', encoding='utf-8') as f:
             f.write(latex)
    
    +    for add_file in builder.config.imgmath_latex_additional_files:
    +        filename = path.join(tempdir, path.basename(add_file))
    +        if not path.exists(filename):
    +            symlink(path.join(builder.confdir, add_file), filename)
    +
         # build latex command; old versions of latex don't have the
         # --output-directory option, so we have to manually chdir to the
         # temp dir to run it.
    @@ -165,9 +170,15 @@
         command.extend(builder.config.imgmath_latex_args)
         command.append('math.tex')
    
    +    output_extension = 'dvi'
    +    if builder.config.imgmath_latex == 'xelatex':
    +        output_extension = 'xdv'
    +    if builder.config.imgmath_pdf2svg:
    +        output_extension = 'pdf'
    +
         try:
             subprocess.run(command, stdout=PIPE, stderr=PIPE, cwd=tempdir, check=True)
    -        return path.join(tempdir, 'math.dvi')
    +        return path.join(tempdir, 'math.' + output_extension)
         except OSError:
             logger.warning(__('LaTeX command %r cannot be run (needed for math '
                               'display), check the imgmath_latex setting'),
    @@ -177,7 +188,7 @@
             raise MathExtError('latex exited with error', exc.stderr, exc.stdout)
    
    
    -def convert_dvi_to_image(command: List[str], name: str) -> Tuple[bytes, bytes]:
    +def run_external_command(command: List[str], name: str) -> Tuple[bytes, bytes]:
         """Convert DVI file to specific image format."""
         try:
             ret = subprocess.run(command, stdout=PIPE, stderr=PIPE, check=True)
    @@ -203,7 +214,7 @@
             command.append('--depth')
         command.append(dvipath)
    
    -    stdout, stderr = convert_dvi_to_image(command, name)
    +    stdout, stderr = run_external_command(command, name)
    
         depth = None
         if builder.config.imgmath_use_preview:
    @@ -227,7 +238,7 @@
         command.extend(builder.config.imgmath_dvisvgm_args)
         command.append(dvipath)
    
    -    stdout, stderr = convert_dvi_to_image(command, name)
    +    stdout, stderr = run_external_command(command, name)
    
         depth = None
         if builder.config.imgmath_use_preview:
    @@ -239,6 +250,21 @@
                     break
    
         return filename, depth
    +
    +def convert_pdf_to_svg(pdfpath, builder):
    +    # type: (str, Builder) -> Tuple[str, int]
    +    """Convert DVI file to SVG image."""
    +    tempdir = ensure_tempdir(builder)
    +    filename = path.join(tempdir, 'math.svg')
    +
    +    name = 'pdfcrop'
    +    command = [name, pdfpath, pdfpath]
    +    run_external_command(command, name)
    +
    +    name = 'pdf2svg'
    +    command = [name, pdfpath, filename]
    +    run_external_command(command, name)
    +    return filename, None
    
    
     def render_math(self: HTMLTranslator, math: str) -> Tuple[str, int]:
    @@ -291,7 +317,10 @@
             if image_format == 'png':
                 imgpath, depth = convert_dvi_to_png(dvipath, self.builder)
             elif image_format == 'svg':
    -            imgpath, depth = convert_dvi_to_svg(dvipath, self.builder)
    +            if self.builder.config.imgmath_pdf2svg:
    +                imgpath, depth = convert_pdf_to_svg(dvipath, self.builder)
    +            else:
    +                imgpath, depth = convert_dvi_to_svg(dvipath, self.builder)
         except InvokeError:
             self.builder._imgmath_warned_image_translator = True  # type: ignore
             return None, None
    @@ -396,8 +425,10 @@
                              ['-gamma', '1.5', '-D', '110', '-bg', 'Transparent'],
                              'html')
         app.add_config_value('imgmath_dvisvgm_args', ['--no-fonts'], 'html')
    +    app.add_config_value('imgmath_pdf2svg', False, 'html')
         app.add_config_value('imgmath_latex_args', [], 'html')
         app.add_config_value('imgmath_latex_preamble', '', 'html')
    +    app.add_config_value('imgmath_latex_additional_files', [], 'html')
         app.add_config_value('imgmath_add_tooltips', True, 'html')
         app.add_config_value('imgmath_font_size', 12, 'html')
         app.connect('build-finished', cleanup_tempdir)
    

    关于latex - hf-tikz 和 sphinx 打得不好,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57127182/

    相关文章:

    latex - Julia 策划问题 : label overlap and LaTeXStings expansion

    latex - 在单个 LaTeX 表格单元格中添加自定义左间距

    latex - 如何在 LaTeX 中为段落编号?

    python - readthedocs 上的 nbsphinx 语法突出显示

    latex - Gnuplot 4.4 和 TikZ 的问题

    latex - 如何为 Texlive 和 Lyx 文档处理器安装 IOP(物理研究所)Latex 文档类(已提供答案)

    python - 我想用我的文档呈现一个类(这是一个类)的属性

    internationalization - 如何国际化 Sphinx (i18n)

    r - 在 rmarkdown 的 tikz 节点标签中使用项目符号列表

    latex - 将pdflatex与-output-directory一起使用时的Tikz外部化问题