I was trying to do the same thing, and found this post. But... even though my book doesn't have fancy mathematical formulas, I thought what I developed could be of use to future generation of Latex book writers who are frustrated by HTML conversion.
I really needed to convert my Latex book to HTML. Having had experience with writing my own plain-text to HTML converters for some personal project software, and server side programming, I wrote this PHP script, that solves the problem for simple Latex documents using Regular Expressions.
By simple, I mean, only converts the following items:
- Images with "Figure" caption (automatic Figure N inserted)
- Converts
begin{lstlisting}...end{lstlisting}
to <code>...</code>
- Accurately converts
\textbf
, \textit
and \texttt
, so long as you follow the rule of nesting italics inside bolds (and not the other way around) to <b>
, <i>
and <span style = "font-family: Courier; font-weight: bold; color: #FF4500">
respectively. Change the color if need to.
\section
to <H1>
\subsection
to <H2>
\subsubsection
to <H3>
- Note,
\begin{figure}
will be converted to <img src = ""/>
The last item (7) requires additional attention. You must replicate your image folder elsewhere, and tweak the PHP script to point to it. In this example it is set to http://localhost/
it is assumed that you have some base image folder for entire manuscript. Make sure it exists somewhere and specify it in this part of the script.
One idea is... if possible, you can convert your mathematical formulas to images, use those images in your Latex document, and you should have no problem with the conversion using this script. Unfortunately, HTML doesn't really support math too well, at least at this time. Good luck!
It also does some other silly clean-up tweaking, like converting <p></p> to space, just to make sure there are no HTML redundancies.
The script is surprisingly simple. All glory to Regular Expressions.
It is also flexible - If you encounter errors, tweak it to your own heart desire. But be warned - it is quite important to perform some replacements in the exact order they appear in the script. Otherwise, you might break it.
Run following PHP script on your localhost, and make sure source.tex
is your Latex manuscript and that it resides in the same folder from which you are running the script:
<?php
chdir(dirname(__FILE__));
$file = file_get_contents("source.tex");
$figure_counter = 1;
$all_codes = array();
// Replace code
$file = preg_replace('/.lstset(.*)/', '', $file); // replace code block
$file = preg_replace('/.begin{lstlisting}(.*)/', '<code>', $file); // replace code block
$file = preg_replace('/.end{lstlisting}/', '</code>', $file); // replace code block
// Replace all <code>....</code> with CODE0, CODE1, CODE2, ... etc.
// It's best to do code clean up before any thing else
// Clean up < brackets inside <code> blocks, memorize all codes for later re-insertion,
function callback($matches) { global $all_codes; $M = str_replace(">", ">", str_replace(">","<",$matches[0])); $C = count($all_codes); $all_codes[$C] = $M; return "\n\nCODE".$C."\n\n"; }
$file = preg_replace_callback('/<code>(\r|\n|.*?)<\/code>/s', 'callback', $file);
// order is important here -- must convert TTT first, before BF AND IT
$file = preg_replace_callback('/.texttt{(.*?)}/', 'callbackT', $file); // mono text
// convert text styles
$file = preg_replace('/.textbf{(.*?)}/', '<b>$1</b>', $file); // bold text
$file = preg_replace('/.textit{(.*?)}/', '<i>$1</i>', $file); // italic text
function callbackT($matches) { return '<span style = "font-family:Courier; font-weight: bold; color: #FF4500">' . str_replace(">", ">", str_replace("<","<",substr($matches[0],8,-1))) . '</span>'; }
// convert sections to headers
$file = preg_replace('/.section{(.*?)}/', '<h1>$1</h1>', $file); // H1
$file = preg_replace('/.subsection{(.*?)}/', '<h2>$1</h2>', $file); // H2
$file = preg_replace('/.subsubsection{(.*?)}/', '<h3>$1</h3>', $file); // H3
// Replace images
$file = preg_replace('/.begin{figure}(.*)/', '', $file); // replace images
$file = preg_replace('/.end{figure}(.*)/', '', $file); // replace images
$file = preg_replace('/ .centering/', '', $file); // replace images
function callback1($matches) { global $figure_counter; return "<p>Figure " . ($figure_counter++) . ": " . substr($matches[0], 10, -1) . "</p>"; }
$file = preg_replace_callback('/ .caption{(.*?)}/', 'callback1', $file); // replace images
$file = preg_replace('/ .includegraphics(.*?){"\.\.(.*?)"}/', '<p><img src = "http://localhost/$2.png"></p>', $file); // replace images
$file = preg_replace('/ .label{(.*?)}/', '', $file); // replace images
// Insert paragraphs
$file = preg_replace('/(.*?)\r\n\r\n/', "\n<p>$1</p>\n", $file);
// just in case
$file = preg_replace('/<p><p>/', "<p>" . "\n", $file);
$file = preg_replace('/<\/p><\/p>/', "</p>" . "\n", $file);
$file = preg_replace('/<p>\nFigure/', "<p>Figure", $file);
$file = preg_replace('/<p>Figure\n/', "<p>Figure", $file);
// As the last step, reinsert codes, to avoid messing them up by previous replacements
for ($i = 0; $i < count($all_codes); $i++)
$file = preg_replace('/CODE'.$i.'/', $all_codes[$i], $file);
// Not sure why this is still the case but it is..
$file = preg_replace('/\n<p><\/code><\/p>/', "</code>", $file);
$style = "<style>body {background:white !important; color: black !important;} code { border: 1px solid gray; padding: 4px; } img { margin: 0 auto; position: relative; display: block; text-align: center; width: 75%; max-width: 500px; }</style>";
/* Print out the book in HTML! */
print "<body>" . $style . "\n" . $file . "</body>";
?>