How to make lstlisting work with tex4ht in table with fixed column width?

I am generating a table with fixed width with p specifications. In one column I need to put some text which is meant to be verbatim and can be few lines long so it will have to also automatically wrap in the column since it is p.

verbatim environment do not work. They do not wrap to fit column width. I tried also putting them in minipage of same width as the column. but still it did not wrap. So I gave up on using verbatim for this.

The only thing that worked well is to use listings. Now the text will wrap to fit column width and it is verbatim in some sense.

The only problem left to solve is to make this work with tex4ht.

It does not wrap in HTML and the whole listing content show on one line making the table very wide even for HTML. If I remove the listing environment, then it will wrap ofcourse, but then the text is no longer verbatim. it is an ordinary text, which will cause problems.

Even though I made sure I am using p and also using p-width option with make4ht.

How to make listing work in tex4ht the same as with PDF? The text has to be either vebratim or listing since its content can have characters which will cause trouble otherwise.

Here is a MWE.

\documentclass[12pt]{book}
\usepackage{longtable}
\usepackage{fancyvrb}
\usepackage{listings}
\lstset{
basicstyle=\footnotesize,
breaklines=true
}
\begin{document}
\begin{tabular}[c]{|p{0.4in}|p{0.4in}|p{0.4in}|p{2.2in}|p{2.2in}|}\hline
1&66&203&-2 (exception)\newline
\begin{lstlisting}
Exception raised: RuntimeError >> ECL says: THROW: The catch RAT-ERR is undefined.
\end{lstlisting}
& 1 (pass) \\\hline
\end{tabular}
\end{document}


This all works ok in pdf.

Compiled to HTML gives

   make4ht -a debug foo.tex "htm,p-width"


So it did not wrap.

I looked at other related questions and I see no solution to using listing like this inside table with tex4ht and keeping column width fixed.

tex4ht: How to create fixed width table columns

using mathml in htlatex makes it lose the table p-width specification in generated html

Any workaround?

Using TL 2021

Update

I tried the solution given, but for larger example it does not seem to wrap. I still get very wide columns in HTML. Here is another example to show.

\documentclass[11pt]{article}
\usepackage{longtable}
\usepackage{listings}
\lstset{
basicstyle=\footnotesize,
breaklines=true
}
\begin{document}

\begin{longtable}[c]{|p{0.4in}|p{0.4in}|p{0.4in}|p{2.2in}|p{2.2in}|}\hline
1&5&193&0 (not solved)& 1 (pass) \\
2&10&466&0 (not solved)& 1 (pass) \\
39&33&320&-2 (exception)\newline
\begin{lstlisting}
Exception raised: TypeError >> An error occurred running a Giac command:INPUT:sage2:=int(sage0,sageVARx):;OUTPUT:Warning, integration of abs or sign assumes constant sign by intervals (correct if the argument is real):Check [abs(t_
\end{lstlisting}
& 1 (pass) \\
40&33&841&0 (not solved)& 1 (pass) \\
45&33&1954&-2 (exception)\newline
\begin{lstlisting}
Exception raised: TypeError >> An error occurred running a Giac command:INPUT:sage2:=int(sage0,sageVARx):;OUTPUT:index.cc index_m i_lex_is_greater Error: Bad Argument Value
\end{lstlisting}
& 1 (pass) \\ \hline
\end{longtable}

\end{document}


Compiled using

 make4ht -a debug -c a.cfg foo.tex "htm,mathjax,p-width"


Where a.cfg is

\Preamble{xhtml}
\Css{table .lstlisting{ white-space: pre-wrap; }}
\begin{document}
\EndPreamble


gives using Brave browser the following

Which is the same as before. So pre-wrap; had no effect.

On FireFox browser it does a little better

And on Chrome browser it gives same as Brave. And on Edge browser also same as Brave. So FireFox browser did the best job. But in all cases it does not wrap as in PDF. I needed the columns to be same width and for the verbatim text to wrap. May be this is not possible?

Compare to the PDF

Update

Found a way to do this in HTML directly. So now just need to figure how to translate this into tex4ht .cfg. This is how to it in HTML.

<!DOCTYPE html>
<html lang='en-US' xml:lang='en-US'>
<meta charset='utf-8' />
<style>
td { border: 1px solid #000; padding: 5px; max-width: 2.3in;  white-space: wrap; overflow: hidden;}

pre {
overflow-x: auto;
white-space: pre-wrap;
white-space: -moz-pre-wrap;
white-space: -pre-wrap;
white-space: -o-pre-wrap;
word-wrap: break-word;
}

</style>
<table>
<tr>
<td> 1</td>
<td> 5</td>
<td> 193</td>
<td> 0 (not solved)</td>
<td> 1 (pass)</td>
</tr>
<tr>
<td> 1</td>
<td> 5</td>
<td> 193</td>
<td> -2 (exception) <pre>Exception raised: TypeError >> An error occurred running a Giac command:INPUT:sage2:=int(sage0,sageVARx):;OUTPUT:Warning, integration of abs or sign assumes constant sign by intervals (correct if the argument is real):Check [abs(t_ </pre> </td>
<td> 1 (pass)</td>
</tr>
<tr>
<td> 1</td>
<td> 5</td>
<td> 193</td>
<td> -2 (exception) <pre>Exception raised: TypeError >> An error occurred running a Giac command:INPUT:sage2:=int(sage0,sageVARx):;OUTPUT:Warning, integration of abs or sign assumes constant sign by intervals (correct if the argument is real):Check [abs(t_ </pre> </td>
<td> -2 (exception) <pre>Exception raised: TypeError >> An error occurred running a Giac command:INPUT:sage2:=int(sage0,sageVARx):;OUTPUT:Warning, integration of abs or sign assumes constant sign by intervals (correct if the argument is real):Check [abs(t_ </pre> </td>
</tr>
</table>
</body>
</html>


Which gives

Which is what I want. Fixed width table with verbatim wrapped also.

Update March 15, 2022

I found small problem with the solution given. When addition \caption it no longer works!

Here is MWE

\documentclass[12pt]{article}
\usepackage{longtable}
\usepackage{listings}
\lstset{
basicstyle=\footnotesize,
breaklines=true
}

\begin{document}

\begin{longtable}[c]{|p{0.4in}|p{0.4in}|p{0.4in}|p{2.2in}|p{2.2in}|}\hline
\# &test file \#&integral \#&Giac 1.7.0 via sagemath 9.5&Giac 1.7.0 via sagemath 9.3 \\ \hline
39&33&320&-2 (exception)
\begin{lstlisting}
Exception raised: TypeError >> An error occurred running a Giac command:INPUT:sage2:=int(sage0,sageVARx):;OUTPUT:Warning, integration of abs or sign assumes constant sign by intervals (correct if the argument is real):Check [abs(t_
\end{lstlisting}
& 1 (pass) \\ \hline
\end{longtable}

\begin{longtable}[c]{|p{0.4in}|p{0.4in}|p{0.4in}|p{2.2in}|p{2.2in}|}\hline
\caption{Summary of regression test}\\
39&33&320&-2 (exception)
\begin{lstlisting}
Exception raised: TypeError >> An error occurred running a Giac command:INPUT:sage2:=int(sage0,sageVARx):;OUTPUT:Warning, integration of abs or sign assumes constant sign by intervals (correct if the argument is real):Check [abs(t_
\end{lstlisting}
& 1 (pass)\\ \hline
\end{longtable}

\end{document}


The above is compiled with

make4ht -a debug -c mycfg.cfg foo.tex "htm,mathjax,p-width"


Where mycfg.cfg is

\Preamble{xhtml}
\Css{table .lstlisting{
white-space: pre-wrap;
word-break: break-all;
}}

\makeatletter
% use normal space in listings
\def\lst@outputspace{\HCode{ }}
\Css{.lstlisting .label{margin-right:0em; }}
\makeatother

\begin{document}
\EndPreamble


Gives the HTML

The second table above lost the column width due to adding \caption Is there a workaround this?

Update March 24, 2022

I found a small problem with the proposed solution. It adds an extra newline in the generated listing in the web page. This newline is not present in the input. This seems to be due to using white-space: pre-wrap; but this is need to force the wrapping for column width.

Can this wrapping to column width be done without introducing extra new lines? Here is MWE

\documentclass[12pt]{book}
\usepackage{longtable}
\usepackage{listings}
\lstset{
basicstyle=\ttfamily\small,
breaklines=true
}
\begin{document}
\begin{tabular}[c]{|p{0.4in}|p{0.4in}|p{0.4in}|p{2.2in}|p{2.2in}|}\hline
1&66&203&-2 (exception)\newline
\begin{lstlisting}
Exception raised: RuntimeError >> ECL says: THROW: The catch RAT-ERR is undefined.
second line
third line
\end{lstlisting}
& 1 (pass) \\\hline
\end{tabular}
\end{document}


Compiled using

make4ht  -ulm default -a debug -c ./nma_mathjax.cfg foo2.tex "mathjax,htm"


Where nma_mathjax.cfg is exactly the one given in the answer below. Here it is again:

\Preamble{xhtml,p-width}

\Css{table .lstlisting{
white-space: pre-wrap;
word-break: break-all;
}}

\makeatletter
% use normal space in listings
\def\lst@outputspace{\HCode{ }}
\Css{.lstlisting .label{margin-right:0em; }}
\makeatother

\begin{document}
\EndPreamble


The HTML shows the lone lines do wrap correctly, but there are new lines added:

Edit:

here is a full config file with recent changes in Listings. They will be available only in TL 2022:

\Preamble{xhtml}

%%%%%%%%%%%%%%%%%%%%%%
%thanks to michal.h21

\makeatletter
\catcode\:=11
\bgroup%
% handle backround color and border in listings
\ifx\lst@fillcolor\@empty\else%
\lst@fillcolor%
\extractcolorspec{.}\html@fillcolor%
\expandafter\convertcolorspec\html@fillcolor{HTML}\html@fillcolor%
\Css{\#listing-\listingN{background-color:\#\html@fillcolor;}}%
\fi%
\ifx\lst@rulecolor\@empty\else%
\lst@rulecolor%
\extractcolorspec{.}\html@rulecolor%
\expandafter\convertcolorspec\html@rulecolor{HTML}\html@rulecolor%
\Css{\#listing-\listingN{border: 1px solid \#\html@rulecolor;}}%
\fi%
\egroup%
}

\ConfigureEnv{lstlisting}
{\ifvmode \IgnorePar\fi \EndP
\HCode{<!--l. \the\inputlineno-->}%
\gdef\start:LstLn{%
\HCode{<pre class="lstlisting" id="listing-\listingN">}%
\gdef\start:LstLn{\HCode{\Hnewline}}}
\bgroup%
% we put the closing </div> here in order to support floating listings
% https://tex.stackexchange.com/a/615703/2891
\pend:def\lst@DeInit{\ifvmode\IgnorePar\fi\EndP\HCode{</pre>}}%
\Configure{listings}
{{\everypar{}\leavevmode}}
{{\everypar{}\leavevmode}}
{\start:LstLn \HCode{<span class="label">}}
{\HCode{</span>}}%
}
{\egroup\par}
{} {}
\Css{pre.lstlisting, pre.lstinputlisting{font-family: monospace,monospace; white-space: pre-wrap;
margin-top:0.5em; margin-bottom:0.5em;
}}

\Configure{lstinputlisting}
{\ifvmode \IgnorePar\fi \EndP
\HCode{<!--l. \the\inputlineno-->}%
\HCode{<pre class="lstinputlisting" id="listing-\listingN">}%
\bgroup\ttfamily%\special{t4ht@(}%
\Configure{listings}%
{{\everypar{}\leavevmode}}%
{{\everypar{}\leavevmode}}%
{\HCode{\Hnewline<span class="label">}}%
{\HCode{</span>}}%
}
{%\special{t4ht@)}
\egroup%
\ifvmode \IgnorePar\fi \EndP  \HCode{</pre>}\par}%
\Css{}
\makeatother
\catcode\:=12
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%see https://tex.stackexchange.com/questions/634005/how-to-make-lstlisting-work-with-tex4ht-in-table-with-fixed-column-width
%to support listlisting in table so it wraps. added Feb 16, 2022

\Css{table .lstlisting{
white-space: pre-wrap;
word-break: break-all;
}}
\makeatletter
% use normal space in listings
\def\lst@outputspace{\HCode{ }}
\Css{.lstlisting .label{margin-right:0em; }}
\makeatother

\begin{document}
\EndPreamble


I've found that TeX4ht used non breaking spaces in listings, which prevented line breaking. You also need to declare some CSS to enable line breaking in listings:

\Preamble{xhtml}
\Css{table .lstlisting{
white-space: pre-wrap;
word-break: break-all;
}}

\makeatletter
% use normal space in listings
\def\lst@outputspace{\HCode{ }}
\Css{.lstlisting .label{margin-right:0em; }}
\makeatother

\begin{document}
\EndPreamble


• Thanks, this is better. But why is the columns width in HTML still not the same as in PDF? Since the 4th and 5th columns are supposed to be 2.2 inch wide each. I know in HTML itself, it is possible to have the widths fixed. Feb 16 at 15:49
• @Nasser the witdths are set correctly, it is just that the browser decides where to break line. I don't think that this is something what can be fixed :/ Feb 16 at 17:47
• Thanks. I posted another example now. This had no effect at all on a larger example. This is a problem. I know in HTML itself it is possible to have fixed width columns. I've seen plenty of examples. But the wrapping is a problem. Then I have to find another way to format this not using table which will be hard. Feb 16 at 17:53
• You are right. I tried 4 browsers, and Firefox does best job. But sill columns are not same width. But I am sure this can be when using Direct coding in HTML? Feb 16 at 18:00
• @Nasser I think that I've found the solution. Feb 16 at 21:24