Tex4ht: using tikzexternalize still includes svg, not png

make4httex4httikz-external

I'm using make4ht to generate HTML from a .tex file which contains tikz images.

I use the tikzexternalize command together with code from Htlatex and Tikz creates sometimes incorrect svgs to ensure that the images are included as .png files in the HTML.

minimal working example

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{external}

\ifdefined\HCode
 % this part is activated with make4ht
 \tikzexternalize[mode=only graphics]
 \tikzset{png export/.style={
    /pgf/images/external info,
    /pgf/images/include external/.code={%
      \includegraphics{##1.png},
     },
   },
  png export,
 }
\else
 % this part is activated with pdflatex
 \tikzexternalize
 \tikzset{pdf export/.style={
    /pgf/images/external info,
    /pgf/images/include external/.code={%
      \includegraphics{##1.pdf},
     },
   },
  pdf export,
 }
\fi

\begin{document}
\begin{tikzpicture}
 \draw (0,0) -- (0,1) -- (1,1) -- (1,0) -- (0,0);
\end{tikzpicture}
\end{document}

compilation

I use the following command to produce myfile-figure0.pdf and then image magick to produce myfile-figure0.png:

pdflatex --shell-escape myfile
magick.exe myfile-figure0.pdf myfile-figure0.png

I then use

make4ht -m draft myfile.tex

to produce the following HTML

<!DOCTYPE html> 
<html lang='en-US' xml:lang='en-US'> 
<head><title></title> 
<meta charset='utf-8' /> 
<meta content='TeX4ht (https://tug.org/tex4ht/)' name='generator' /> 
<meta content='width=device-width,initial-scale=1' name='viewport' /> 
<link href='myfile.css' rel='stylesheet' type='text/css' /> 
<meta content='myfile.tex' name='src' /> 
</head><body>
<!-- l. 29 --><p class='noindent'><img alt=',
' src='myfile0x.svg' />
</p>
    
</body> 
</html>

the question

How can I configure my build process so that instead of

<img alt=',
' src='myfile0x.svg' />

I receive

<img alt=',
' src='myfile-figure0.png' />

for reference

I'm on texlive 2021 and make4ht version 0.3j. In texlive 2020 and before, I did not have this issue, and the settings that I have gave my desired output.

Perhaps my issue is related to the following snippet from myfile.log which I also did not receive in texlive 2020.

(\end occurred inside a group at level 1)

### simple group (level 1) entered at line 22 ({)
### bottom level

Best Answer

This is caused by the fact that TeX4ht now uses the pgfsys-dvisvgm4ht.def driver by default. It doesn't support the external library. Here is the version that fixes this issue:

% Copyright 2021 by Michal Hoftich
% Copyright 2006 by Till Tantau
%
% This file may be distributed and/or modified
%
% 1. under the LaTeX Project Public License and/or
% 2. under the GNU Public License.
%
% See the file doc/generic/pgf/licenses/LICENSE for more details.

\ProvidesFileRCS{pgfsys-dvisvgm4ht.def}

% Driver commands for tex4ht

%
% Load common pdf commands:
%

% we load the dvips driver by default. it doesn't support patterns and some other stuff,
% but it handles better nested images and some formatting. if you use patterns or if you
% have other issues with the default method, pass the "tikz-dvisvgm" option to make4ht. 
\ifdefined\ifOption
\ifOption{tikz+}{\input pgfsys-dvisvgm.def}{\input pgfsys-dvips.def}
\else
% load the dvips driver by default
\input pgfsys-dvips.def
\fi


\def\texfourht@tikz@begin{%
  \bgroup%
  \def\run@pict@cmd{}% insert the \Picture hooks only in the top nesting level
  \def\end@pict@cmd{}%
  \ifdefined\EndPicture\else% We are already inside command that uses \Picture
  \ifdefined\inside@pict@cmd\else% handle nested uses
  \ifdefined\tikzexternalize\else% Support externalize library
  \def\run@pict@cmd{\Picture*}%
  \def\end@pict@cmd{\EndPicture}%
  \fi\fi\fi%
  % command used to detect nesting
  \def\inside@pict@cmd{}%
  \csname a:tikzpicture\endcsname%
}

\def\texfourht@tikz@end{%
  \csname b:tikzpicture\endcsname%
  \egroup%
}

\AtBeginDocument{%
  \NewConfigure{tikzpicture}{2}%
  \catcode`\:=11%
  \Configure{tikzpicture}{%
    \protect\csname nested:math\endcsname% support display math
    \run@pict@cmd{}%
  }{\end@pict@cmd}
  % configure the output picture format to svg, as it will require dvisvgm
  % post processing. 
  \Configure{Picture}{.svg}%
  % insert tex4ht hooks around TikZ picture box
  \def\pgfsys@typesetpicturebox#1{%
    \texfourht@tikz@begin%
    \orig@pgfsys@typesetpicturebox{#1}%
    \texfourht@tikz@end%
  }
  %
  \ConfigureEnv{tikzpicture}{\texfourht@tikz@begin}{\texfourht@tikz@end}{}{}%
  \ConfigureEnv{pgfpicture}{\texfourht@tikz@begin}{\texfourht@tikz@end}{}{}%
  \catcode`\:=12%
}


% Make the code inserted by tex4ht configurable
% 


\let\orig@pgfsys@typesetpicturebox\pgfsys@typesetpicturebox
%\def\pgf@sys@postscript@header#1{{\special{! #1}}}


\endinput


%%% Local Variables:
%%% mode: latex
%%% End:

I've also found that you have one issue in your TeX file. You have spurious comma after \includegraphics command. It ends in the HTML code. This is a fixed version:

\documentclass{article}


\usepackage{tikz}
\usetikzlibrary{external}

\ifdefined\HCode
 % this part is activated with make4ht
 \tikzexternalize[mode=only graphics]
 \tikzset{png export/.style={
    /pgf/images/external info,
    /pgf/images/include external/.code={%
      \includegraphics{##1.png}
     },
   },
  png export,
 }
\else
 % this part is activated with pdflatex
 \tikzexternalize
 \tikzset{pdf export/.style={
    /pgf/images/external info,
    /pgf/images/include external/.code={%
      \includegraphics{##1.pdf},
     },
   },
  pdf export,
 }
\fi

\begin{document}
\begin{tikzpicture}
 \draw (0,0) -- (0,1) -- (1,1) -- (1,0) -- (0,0);
\end{tikzpicture}

\end{document}

Btw, TeX4ht has built-in support for the externalization library, it always requires the picture mode. The current version is somehow broken, but you can try this fix, tikz-hooks.4ht:

% tikz-hooks.4ht (2021-10-21-14:55), generated from tex4ht-4ht.tex
% Copyright 2021 TeX Users Group
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either
% version 1.3c of this license or (at your option) any
% later version. The latest version of this license is in
%   http://www.latex-project.org/lppl.txt
% and version 1.3c or later is part of all distributions
% of LaTeX version 2005/12/01 or later.
%
% This work has the LPPL maintenance status "maintained".
%
% The Current Maintainer of this work
% is the TeX4ht Project <http://tug.org/tex4ht>.
%
% If you modify this program, changing the
% version identification would be appreciated.
\immediate\write-1{version 2021-10-21-14:55}

\ifdefined\pgfsysdriver\else%
  \typeout{*****************************}
  \typeout{TeX4ht info: Using dvisvgm4ht TikZ driver. Put \detokenize{\def\pgfsysdriver{driver-name}} to your
  document before use of TikZ if you want to another driver. Use tikz+ option if your TikZ pictures use patterns.}%
  \def\pgfsysdriver{pgfsys-dvisvgm4ht.def}%
\fi%
\:AtEndOfPackage{%
\let\use:tikzlibrary\usetikzlibrary
\def\find:externalize#1external#2\@nil{%
  \ifdefined\tikzexternalize
    \let\tikz:externalize\tikzexternalize
    \renewcommand\tikzexternalize[1][]{\tikz:externalize[##1,mode=only graphics]}
    \tikzset{%
      tex4ht inc/.style={%
        /pgf/images/include external/.code={%
          \includegraphics[]{####1.pdf}%
        }%
      }%
    }%
    \tikzset{tex4ht inc}%
  \fi%
}
\append:defI\use@@tikzlibrary{\find:externalize##1external\@nil}%
}

You can then simplify your document:

\documentclass{article}


\usepackage{tikz}
\usetikzlibrary{external}

\tikzexternalize
\tikzset{pdf export/.style={
   /pgf/images/external info,
   /pgf/images/include external/.code={%
     \includegraphics{##1.pdf}
    },
  },
 pdf export,
}

\begin{document}
\begin{tikzpicture}
 \draw (0,0) -- (0,1) -- (1,1) -- (1,0) -- (0,0);
\end{tikzpicture}

\end{document}

And this is the result:

enter image description here

Related Question