Include MATLAB code listing compiled into HTML with correct colors

htmllistingsMATLABmatlab-prettifiertex4ht

I am compiling a LaTeX file my_document.tex into an HTML page my_document.html using htlatex with the following command:

htlatex my_document.tex "xhtml,mathml-" " -cmozhtf"

I have a MATLAB code file main.m that I want to include in my_document.html with formatting that matches the MATLAB editor. When compiling with pdflatex, I use the following:

\documentclass{article}

\usepackage{listings}
\usepackage[numbered]{matlab-prettifier}

\lstset{
    style=Matlab-editor
}

\begin{document}
    \lstinputlisting{main.m}
\end{document}

Compiling the above code with htlatex, however, creates output that is black-and-white. Our current approach is to use m2tex to translate the .m file into a .tex file, but this makes the process of updating the HTML files more complicated because it adds a step, so I'm trying to find a way to simplify the process. I've included one approach as an answer, below, but am looking for other suggestions.

EDIT: Here is an example MATLAB file, main.m:

% This is a comment
var = "this is a string";

for i = 1:5
    doThing(i)
end

disp this_is_some_text

function doThing(i)
    fprintf('Number %d\n', i)
end

In the MATLAB code editor, main.m looks like the following screenshot, so the goal is to make the HTML output match this as well:

the appearance of main.m in the MATLAB code editor

Best Answer

Working with colors is a bit complicated with TeX4ht. Stuff like \textcolor works, but colors that are set by \color cannot be supported out of the box. You need to add some HTML tags with color information yourself.

For listings, we can use hooks provided by the package to insert some elements around each keyword. We can get the current color and insert CSS instructions.

Try this configuration file, config.cfg:

\Preamble{xhtml}
\makeatletter

\lst@AddToHook{OutputBox}{%
% get current color in the CSS form
\extractcolorspec{.}\html@color%
\expandafter\convertcolorspec\html@color{HTML}\html@color%
\HCode{<span style="color:\#\html@color">}}% init

\lst@AddToHook{PostOutput}{\HCode{</span>}}%
\begin{document}
\EndPreamble

In the OutputBox hook, we define the \html@color macro. It holds the current color suitable for CSS thanks to \extractcolorspec and \convertcolorspec commands. We insert it to the HTML output thanks to \lst@AddToHook{PostOutput}{\HCode{</span>}} command. In the PostOutput hook, we insert the closing </span> tag.

Here is a MWE:

\documentclass{article}
\usepackage{xcolor}

\usepackage{listings}
\usepackage[numbered]{matlab-prettifier}


\lstset{
    style=Matlab-editor
}


\begin{document}

Listings environment:

\begin{lstlisting}
function y = f(x)
    % comment
    y = x^2
    disp('1hll')
    [t, x] = ode45(@f, [0, 1], 0)
end
\end{lstlisting}

Included mathlab:

    \lstinputlisting{main.m}
\end{document}

Compile using (don't use htlatex, it is deprecated):

make4ht -c config.cfg -m draft my_document.tex

This is the result:

enter image description here

One last thing. I've found a bug in the configuration file for the Color package, color.4ht. It prevents the correct conversion of colors. Here is the correct version:

% color.4ht (2022-02-01-17:18), generated from tex4ht-4ht.tex
% Copyright 1997-2009 Eitan M. Gurari
% Copyright 2009-2022 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 2022-02-01-17:18}

\expandafter\ifx \csname color:def\endcsname\relax
    \let\color:def\def
\else  \expandafter\endinput\fi
\let\:temp\begingroup
\HLet\color@setgroup\:temp
\def\HColor{\:warning{\string\Hcode{...}{...} is deprecated; Use
   \string\Configure{HColor}{...}{...}}\Configure{HColor}}
\NewConfigure{HColor}[2]{\if !#1!\if!#2!\let\HColor\relax \else \edef\HColor{#2}\fi
\else
   \expandafter\edef\csname CLR:#1\endcsname{#2}\fi}
\def\:temp#1#2#3{%
  \@ifundefined{color@#2}%
    {\c@lor@error{model `#2'}}%
    {\@ifundefined{\string\color @#1}{}%
      {\PackageInfo{color}{Redefining color #1}}%
     \csname color@#2\expandafter\endcsname
         \csname\string\color @#1\endcsname{#3}}}
\ifx \definecolor\:temp
   \pend:defIII\definecolor{%
     \expandafter\ifx\csname HColor:##2\endcsname\relax\else
        \csname HColor:##2\endcsname ##3 //%
        \edef\:temp{{HColor}{##1}{\HColor}}%
        \expandafter\Configure\:temp
     \fi}
\fi

\NewConfigure{color}{1}
\def\:tempc#1#2#3{\protect\leavevmode{\protect\a:textcolor
      \color#1{#2}#3\protect\b:textcolor}}
\HLet\@textcolor=\:tempc
\NewConfigure{textcolor}{2}
   \def\pagecolor{%
  \begingroup \a:pagecolor
      \let\ignorespaces\endgroup
      \let\set@color\set@page@color
      \color}
\NewConfigure{pagecolor}{1}
\def\:tempa[#1]#2{\a:color{#1 #2}\o:@undeclaredcolor:[#1]{#2}}
\HLet\@undeclaredcolor\:tempa
\pend:defI\@declaredcolor{\a:color{##1}}
\NewConfigure{SetHColor}[2]{{%
   \expandafter\let\expandafter\:temp \csname CLR:#2\endcsname
   \ifx \:temp\relax
      \edef\:temp{#2 //}\expandafter\get:HColor\:temp
      \ifx \HColor\relax
          \expandafter\ifx \csname get!HColor\endcsname\relax \else
  \edef\:temp{#2!//}\expandafter\csname get!HColor\expandafter\endcsname\:temp
\fi
%
      \fi
   \else             \let\HColor=\:temp \fi
   \ifx \HColor\relax
      \:warning{missing \string\Configure{HColor}{#2}{...}
           (in LaTeX: \csname\string\color @#2\endcsname)}%
      \expandafter\global\expandafter\let\csname CLR:#2\endcsname\empty
    \else #1\fi }}
\def\get:HColor#1 #2//{%
  \if\relax#2\relax
  % \expandafter\ifx \csname HColor:#1\endcsname\relax
     \let\HColor=\relax
     \expandafter\ifx \csname\string\color @#1\endcsname \relax\else
   \expandafter\ifx \csname colortyp:\endcsname\relax \else
      \csname colortyp:\expandafter\expandafter\expandafter\endcsname
         \csname\string\color @#1\expandafter\endcsname
         \space . //%
\fi \fi
%
  \else
     \csname HColor:#1\endcsname #2 //%
  \fi
}
\def\c:HColor:gray:{\def\HColor:gray##1 ##2//}
\Configure{HColor:gray}{\Configure{HColor}{}{}}
\def\c:HColor:rgb:{\def\HColor:rgb##1,##2,##3 ##4//}
\Configure{HColor:rgb}{\Configure{HColor}{}{}}
\def\c:HColor:cmyk:{\def\HColor:cmyk##1,##2,##3,##4 ##5//}
\Configure{HColor:cmyk}{\Configure{HColor}{}{}}

\long\def\:temp#1#2#3{%
   \ifcolors@
      \def\:temp{#1}\def\:tempa{\relax}\ifx\:temp\:tempa
      \a:colorbox \else \a:fcolorbox \fi
   \fi
   {#1{\leavevmode #2{\set@color#3}}}%
   \ifcolors@
      \def\:temp{#1}\def\:tempa{\relax}\ifx\:temp\:tempa
      \b:colorbox \else \b:fcolorbox \fi
   \fi
}
\HLet\color@b@x\:temp
\NewConfigure{colorbox}{2}
\NewConfigure{fcolorbox}{2}

\Hinput{color}
\endinput
Related Question