Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
executable file 1005 lines (834 sloc) 29.7 KB
#! /usr/bin/perl
# any user of this may alternately be interested in:
# http://lucatrevisan.wordpress.com/latex-to-wordpress/
#
# Why do I also have one?
#
# 1) I wrote this before learning about the above.
#
# 2) After I'd learned about this, mine already had support for
# multiple argument newcommand macro replacement, and I couldn't
# figure out how to do the same in python (and don't really want to do so).
#
# 3) I'd added in \cite and \ref support
#
# 4) It doesn't support all my personal macros (this has a subset of
# what I've got in my peeters_macros.tex). If you are using
# this script and are not Peeter you probably want to modify
# expandPeetersMathModeMacros to do just your own.
#
# 5) I've got some rudimentary wikipedia and 'physics forum' output modes
# in this script.
#
# TODO:
# implement a latex to latex mode, so that it does nothing but expand
# personal macros for standalone use without \include's.
#
# BUGS:
#------
# o) CITE expansion:
# introduces some
# spurious % characters in the output sometimes and I haven't debugged
# that yet.
# o) mathml mode:
# equation numbering requires that section headings be suppressed.
# o) mathml mode:
# eqnarray requires more than one equation line, and &= shows up as
# is otherwise. Not doing that in the original .tex is required.
# o) Have bugs expanding {\begin{bmatrix}...\end{bmatrix}}_{...} output
# (example: ~/math/nonga/hamiltonian.tex).
#
# [Since the mathml output (usable in blogger since it supports javascript)
# turns out to not be that great, I'm not likely to do any more for the
# mathml output mode.]
#
use strict ;
use warnings ;
use Getopt::Long;
my $filebase ;
my $showUsage = 0 ;
# output for LaTeXMathML.js or wordpress?
my $mathml = 0 ;
my $wordpress = 0 ;
# for use of LaTeXMathML.js in a standalone html file:
my $mathmlHtml = 0 ;
# for use with physics Forums.
my $pf = 0 ;
# stackexchange (physics and math)
my $se = 0 ;
# wikipedia output.
my $wiki = 0 ;
my $auxdebug = 0 ;
my $urlMessage ;
#$urlMessage = "Click here for a PDF of this sequence of posts with nicer formatting" ;
$urlMessage = "Click here for a PDF of this post with nicer formatting and figures if the post had any (especially if my latex to wordpress script has left FORMULA DOES NOT PARSE errors.)" ;
my $urlMessage2 = '' ;
# $urlMessage2 .= "Note that this PDF file is formatted in a wide-for-screen layout that is probably not good for printing." ;
my $r1 = qr/
( # start of capture buffer 1
{ # match an opening brace
(?:
[^{}]++ # one or more non braces, non backtracking
|
(?1) # found { or }, so recurse to capture buffer 1
)*
} # match a closing brace
) # end of capture buffer 1
/x;
my $r2 = qr/
( # start of capture buffer 1
{ # match an opening brace
(?:
[^{}]++ # one or more non braces, non backtracking
|
(?1) # found { or }, so recurse to capture buffer 1
)*
} # match a closing brace
) # end of capture buffer 1
( # start of capture buffer 2
{ # match an opening brace
(?:
[^{}]++ # one or more non braces, non backtracking
|
(?1) # found { or }, so recurse to capture buffer 2
)*
} # match a closing brace
) # end of capture buffer 2
/x;
my $r3 = qr/
( # start of capture buffer 1
{ # match an opening brace
(?:
[^{}]++ # one or more non braces, non backtracking
|
(?1) # found { or }, so recurse to capture buffer 1
)*
} # match a closing brace
) # end of capture buffer 1
( # start of capture buffer 2
{ # match an opening brace
(?:
[^{}]++ # one or more non braces, non backtracking
|
(?1) # found { or }, so recurse to capture buffer 2
)*
} # match a closing brace
) # end of capture buffer 2
( # start of capture buffer 3
{ # match an opening brace
(?:
[^{}]++ # one or more non braces, non backtracking
|
(?1) # found { or }, so recurse to capture buffer 3
)*
} # match a closing brace
) # end of capture buffer 3
/x;
GetOptions(
'mathml!' => \$mathml,
'wordpress!' => \$wordpress,
'pf!' => \$pf,
'se!' => \$se,
'wikipedia!' => \$wiki,
'html!' => \$mathmlHtml,
'file=s' => \$filebase,
'help!' => \$showUsage,
) ;
if ( $showUsage or (1 != ( $mathml + $wordpress + $mathmlHtml + $pf + $wiki + $se )) )
{
die "usage: tex2blog -f filenameWithoutTexSuffix {-pf | -se | -html | -mathml | -wordpress -wiki} [-help]"
}
if ( $mathmlHtml )
{
$mathml = 1 ;
}
# it is assumed that the .tex or .ltx file has been pdflatex'ed already generating a .aux file for the equation numbers.
my %equations = processAuxFile( "$filebase.aux" ) ;
my %refnumbers ;
my $keywords = '' ;
my $category = 'Math and Physics Learning' ;
# side effect. creates the %refnumbers hash.
my $bibString = processBib() ;
# most of the file can be treated as single lines but we need
# to handle \begin{align}, \begin{equation} ... as multiline
# patterns. For this reason, slurp in the whole file, then handle
# all these types of patterns first, then do the rest.
#
# first the slurp:
#
my $allInput = slurpLatex( $filebase ) ;
# pre-filter out all the latex comments.
$allInput =~ s/%.*//mg ;
# now do the tricky bits.
$allInput =~ s/
\\begin{
(?:equation|dmath|align|eqnarray)
(\**) # $1. Is this a numbered equation or not. '*' for no.
}
(.*?) # $2. The latex text including all whitespace (and the label)
\\end{
(?:equation|dmath|align|eqnarray)
\** # the matching * if any.
}
/processOneEquation(0, $1, $2)/sgemx ;
my $g_title = 'no title' ;
# side effect: sets $g_title
my $allOut = processRest( $allInput ) ;
my $head = generatePrologue( $g_title ) ;
generateEpilogueAndPrintIt( $head . $allOut ) ;
exit ;
my $g_EquationSeqNo = 1 ;
sub processOneEquation
{
my ($bInline, $suppressNumbers, $eq) = @_ ;
my $oeq = $eq ;
# if ( $bInline )
# {
# warn "inline: '$eq'\n" ;
# }
# $eq =~ s/%.*//mg ;
my $curEquationLabel = '' ;
my $eqnArray = "eqnarray" ;
# warn "s: $suppressNumbers ; eq: $eq\n" ;
if ( $eq =~ s/\\label{(eqn:.*?)}//s || $eq =~ s/\\label{(thm:.*?)}//s )
{
my $label = $1 ;
if ( $mathml )
{
$equations{$label} = $g_EquationSeqNo++ ;
}
elsif (!$wiki)
{
if ( !exists $equations{$label} )
{
warn "no equation number for '$label'\n" ;
foreach ( keys %equations )
{
print "eq: $_\n" ;
}
die "aborting!\n" ;
}
die "no equation number for '$label'\n" if ( !exists $equations{$label} ) ;
#$curEquationLabel = "\\quad\\quad\\quad($equations{$label})" ;
# spacing tip from the 'not so short latex guide'
$curEquationLabel = "\\hspace{\\stretch{1}}($equations{$label})" ;
}
die "s: $suppressNumbers ; no label for equation '$oeq'" if ( $suppressNumbers ne '' ) ;
}
else
{
$eqnArray .= '*' ;
die "expected * for non-labelled equation '$eq'" if ( $suppressNumbers ne '*' ) ;
}
$eq =~ s/\n//smg ;
$eq = expandPeetersMathModeMacros( $eq ) ;
# if ( $bInline )
# {
# warn "inline post: '$eq'\n" ;
# }
# strip trailing \\ at the end of the equation:
#$eq =~ s/ *\\\\ *$//g;
# use <latexSepLineStart> <latexSepLineEnd> so that this equation isn't processed again, In the final pass when everything is split by lines change these to '$' characters for final output.
if ( $bInline )
{
$eq = "<latexInlineStart>$eq<latexInlineEnd>" ;
}
else
{
if ( $mathml )
{
$eq = "<latexSepLineStart>\\begin{$eqnArray}$eq \\end{$eqnArray}<latexSepLineEnd>" ;
}
elsif ( $wordpress )
{
# sample output from latex2wp. centers things ... looks a bit nicer.
#<p align=center>$latex \displaystyle \forall g \in {\cal F}. g^2 = \eta \ \ \ \ \ (1)&fg=000000$</p>
# latex2wp used this, but I don't see a difference:
my $fgString = '' ;
# $fgString = "&fg=000000" ; # omit.
$eq = "<latexSepLineStart>\\begin{aligned}$eq\\end{aligned} $curEquationLabel$fgString<latexSepLineEnd>" ;
}
elsif ( $se )
{
$eq = "<latexSepLineStart>$eq<latexSepLineEnd>" ;
}
else # wiki, and pf
{
$eq = "<latexSepLineStart>\\begin{align}$eq\\end{align} $curEquationLabel<latexSepLineEnd>" ;
}
}
return $eq ;
}
sub processBib
{
my $bibOut = '' ;
my $haveBib = 1 ;
open my $fh, "<$filebase.bbl" or $haveBib = 0 ;
if ( $haveBib )
{
my $curNum = 1 ;
while (<$fh>)
{
chomp ;
s,\\begin{thebibliography}.*,<h1>References</h1>, ;
#\bibitem[Joot({\natexlab{a}})]{PJLorentzWave}
s/\\bibitem.*]{/\\bibitem{/ ;
if ( s/\\bibitem{(.*?)}// )
{
$bibOut .= "\n\n" ;
$refnumbers{$1} = $curNum ;
$bibOut .= "[$curNum] " ;
$curNum++ ;
}
else
{
next if (/Available from:/ or
/\\providecommand/ or
/\\expandafter/ or
0 ) ;
if ( /\\end{thebibliography}/ )
{
$bibOut =~ s,\\url{(.*?)},<a href="$1">$1</a>,;
$bibOut .= "\n" ;
last ;
}
s/~/ /g ;
s,{ *\\em\s+(.*?)},<em>$1</em>,g;
s,\\em *{(.*?)},<em>$1</em>,g ;
s,\\emph *{(.*?)},<em>$1</em>,g ;
s/\\newblock// ;
# \url can be split across lines, as in the following:
# \url{http://en.wikipedia.org/w/index.php?title=Relativistic_Doppler_effect&o%
#ldid=298724264}.
#
#In case it isn't do a first check here before stripping out {}'s
#
s,\\url{(.*?)},<a href="$1">$1</a>,sg;
s/{(.*?)}/$1/g ;
#die "'$_'\n" if /\\url/ ;
$bibOut .= "$_" ;
}
}
close $fh ;
}
return $bibOut ;
}
sub generatePrologue
{
my ($title) = @_ ;
my $prologue = '' ;
if ( $mathmlHtml )
{
$prologue .= qq(
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 //EN"
"http://www.w3.org/TR/REC-html40/strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>$title</title>
<script type="text/javascript" src="http://math.etsu.edu/LaTeXMathML/LaTeXMathML.js"></script>
<link rel="stylesheet" type="text/css" href="http://math.etsu.edu/LaTeXMathML/LaTeXMathML.standardarticle.css" />
</head>
) ;
}
if ( $mathml )
{
$prologue .= qq(<pre class="LaTeX"><div>\n) ;
}
if ( $wordpress )
{
# FIXME: Can I mine the tags of all my posts and re-insert them directly into my original docs?
$prologue .= "
[category $category]
[title $g_title]
[tags $keywords]
[status draft]
[nogallery]
" ;
}
return $prologue ;
}
sub generateEpilogueAndPrintIt
{
my ($outText) = @_ ;
$outText .= $bibString ;
$outText =~ s/[\r\l]+//smg ;
if ( $mathml )
{
$outText .= qq(\n</div></pre>) ;
}
if ( $mathmlHtml )
{
$outText .= qq(\n</body> </html>) ;
}
# if ( $wordpress )
# {
# $outText .= qq([end] This and anything else should be ignored.) ;
#
# $outText .= "# email $ENV{WORDPRESSEMAIL} -s autopost -a ..." ;
# }
print $outText ;
}
sub processAuxFile
{
my ($auxFileName) = @_ ;
my %eq ;
# in mathml mode, number sequentially only since the equation numbers are generated as a side effect of using \begin{eqnarray}
if ( !$mathml )
{
open my $fh, "<$auxFileName" or die "could not open '$auxFileName'\n" ;
while (<$fh>)
{
chomp ;
# with {equation}
#\newlabel{eqn:landauMechanicsCh1P3:10}{{1.1}{1}{Guts\relax }{equation.1.2.1}{}}
# with {dmath}
#\newlabel{eqn:landauMechanicsCh1P3:10}{{1.1}{1}{Guts\relax }{Answer.1}{}}
if ( /^\\newlabel{(.*?)}.*equation\.(.*?)}/ )
{
$eq{$1} = $2 ;
}
#elsif ( /^\\newlabel{(.*?)}{{((?:\d|\.)+)}.*Answer/ )
elsif ( /^\\newlabel{(.*?)}{{((?:\d|\.)+)}.*/ )
{
$eq{$1} = $2 ;
}
elsif ( $auxdebug )
{
warn "auxdebug: $_\n" ;
}
}
close $fh ;
}
#
# debug. turns out that equation labels don't work quite right when they
# are also in a \enumerate \item ... context.
#
if ( $auxdebug )
{
foreach (keys %eq)
{
warn "label: '$_'\n" ;
}
}
return %eq ;
}
sub slurpLatex
{
my $failedOpen = 0 ;
my $rawLatex = '' ;
open my $fh, "<$filebase.tex" or $failedOpen = 1 ;
if ( $failedOpen )
{
open $fh, "<$filebase.ltx" or die "could not open '$filebase.tex' nor '$filebase.ltx'\n" ;
}
while (<$fh>)
{
$rawLatex .= $_ ;
}
close $fh ;
return $rawLatex ;
}
sub processRest
{
my ($allOneLine) = @_ ;
my @allLines = split( /\n/, $allOneLine ) ;
my $latexInlineStart ;
my $latexInlineEnd ;
my $latexSepLineStart ;
my $latexSepLineEnd ;
my $bProcessingItemize = 0 ;
my $bProcessingEnumerate = 0 ;
if ( $se )
{
$latexInlineStart = '$' ;
$latexInlineEnd = '$' ;
$latexSepLineStart = '$$' ;
$latexSepLineEnd = '$$' ;
}
elsif ( $pf )
{
$latexInlineStart = '[itex]' ;
$latexInlineEnd = '[/itex]' ;
$latexSepLineStart = '[tex]' ;
$latexSepLineEnd = '[/tex]' ;
}
elsif ( $wiki )
{
$latexInlineStart = '<math>' ;
$latexInlineEnd = '</math>' ;
$latexSepLineStart = ":<math>\n" ;
$latexSepLineEnd = "\n</math>\n" ;
}
elsif ( $wordpress )
{
$latexInlineStart = '$latex ' ;
$latexInlineEnd = '$' ;
$latexSepLineStart = '<p align=center>$latex ' ;
$latexSepLineEnd = "\$</p>\n" ;
}
elsif ( $mathml )
{
$latexInlineStart = '$' ;
$latexInlineEnd = '$' ;
$latexSepLineStart = '<blockquote>$' ;
$latexSepLineEnd = "$</blockquote>\n" ;
}
# Lance is a cool dude
# Lance is really a cool dude
# Lance is super duper snooper cob dude
else
{
die ;
}
my $out = '' ;
foreach (@allLines)
{
if ( s/(?:\\newcommand{\\keywords}{(.*)}|\\keywords{(.*)})// )
{
$keywords = $1 ;
}
s,\\renewcommand{\\basename}{(.*?)},\\blogpage{http://peeterjoot.com/archives/math2016/$1.pdf}, ;
next if ( /\\documentclass/ or
/\\usepackage/ or
/\\newcommand/ or
/\\renewcommand/ or
/\\input/ or
/{subequations}/ or
/\\revisionInfo/ or
/\\gitRevisionInfo/ or
/\\bibliography/ or
/\\beginArtWithToc/ or
/\\EndArticle/ or
/\\shipoutAnswer/ or
/\\EndNoBibArticle/ or
/\\beginArtNoToc/ or
0 ) ;
# if ( s/\\keywords{(.*)}// )
# {
# $keywords = $1 ;
# }
if ( s/\\wordpresscategory{(.*)}// )
{
$category = $1 ;
}
if ( s/\\(?:title|generatetitle|chapter){(.*)}// )
{
$g_title = $1 ;
}
unless ( $mathml )
{
next if ( /\\begin{document}/ or
/\\end{document}/ or
/\\maketitle/ or
/\\tableofcontents/ or
/\\title/ or
/\\email/ or
/\\date/ or
/\\author/ or
0 ) ;
# s/\\chapter{(.*)}/$1/ ;
}
s/\\paragraph{(.*?)}/<b>$1<\/b>/g;
# avoiding underline since that looks like a hyperlink.
s/\\underline{(.*?)}/<i>$1<\/i>/g;
s/\\underlineAndIndex{(.*?)}/<i>$1<\/i>/g;
s/\\S\b/section/g;
# process inline math $$ delimited. Assume that it is all in one line.
s/\$(.*?)\$/processOneEquation(1, '*', $1)/eg ;
s/<latexSepLineStart>/$latexSepLineStart/g ;
s/<latexSepLineEnd>/$latexSepLineEnd/g ;
s/<latexInlineStart>/$latexInlineStart/g ;
s/<latexInlineEnd>/$latexInlineEnd/g ;
s/\\chapcite{(.*?)}/[$refnumbers{$1}]/g;
s/\\citep{(.*?)}/[$refnumbers{$1}]/g;
s/\\cite{(.*?)}/[$refnumbers{$1}]/g;
s,\\blogpage{(.*)},<a href="$1">[$urlMessage]</a>$urlMessage2,;
s/\\C{(.*?)}/$latexInlineStart\\mathbb{C}^{$1}$latexInlineEnd/g;
s/\\R{(.*?)}/$latexInlineStart\\mathbb{R}^{$1}$latexInlineEnd/g;
s/\\ref{(eqn:.*?)}/eq. $equations{$1}/g ;
s/\\ref{(fig:.*?)}/fig. $equations{$1}/g ;
s/\\cref{(fig:.*?)}/fig. $equations{$1}/g ;
s/\\eqnref{(eqn:.*?)}/eq. $equations{$1}/g ;
s/\\Eqnref{(eqn:.*?)}/Eq. $equations{$1}/g ;
s/\\autoref{(eqn:.*?)}/($equations{$1})/g ;
die "use eqnref not eqref" if ( /\\eqref/ ) ;
if ( $wiki )
{
s,\\section{(.*)},==$1==,;
s,\\subsection{(.*)},===$1===,;
s,\\subsubsection{(.*)},===$1===,;
}
else
{
# latexMathMl can do section's but this makes the equation number matching harder (since you get 1.1 1.2 ...)
# could deal with that by processing things section by section, and then within each section doing all the equations.
s,\\section{(.*)},<h1>$1</h1>,;
s,\\subsection{(.*)},<h2>$1</h2>,;
s,\\subsubsection{(.*)},<h3>$1</h3>,;
# \makeproblem{Pendulum with support moving in circle}{landauMechanics:ch1:pr1}
# \makeanswer{landauMechanics:ch1:pr1}
s,\\makeoproblem{(.*?)}{(.*?)}{(.*?)},<h2>Question: $1 ($3)</h2>,;
s,\\makeproblem{(.*?)}{(.*?)},<h2>Question: $1</h2>,;
s,\\makeanswer{.*?},<h2>Answer</h2>,;
s,\\makeexample{(.*?)},<h2>Example: $1</h2>,;
}
if ( s,\\begin{itemize},<ol>, )
{
$bProcessingItemize = 1 ;
}
elsif ( s,\\begin{enumerate},<ul>, )
{
$bProcessingEnumerate = 1 ;
}
elsif ( s,\\end{itemize},</ol>, )
{
$bProcessingItemize = 0 ;
}
elsif ( s,\\end{enumerate},</ul>, )
{
$bProcessingEnumerate = 0 ;
}
s,\\item,<li>, ;
s,\\youtubehref{(.*?)},\\href{http://youtu.be/$1}{http://youtu.be/$1},g ;
s,\\href{(.*?)}{(.*?)},<a href="$1">$2</a>,g ;
# remove any label's not associated with specific formulas
s/\\label{(.*?)}//g;
$out .= "$_\n" ;
$out =~ s,\\begin{lstlisting},<pre>, ;
$out =~ s,\\end{lstlisting},</pre>, ;
}
return $out ;
}
sub expandPeetersMathModeMacros
{
my $out = "@_" ;
$out =~ s/\\\\/\\\\ /g;
# $out =~ s/&=/=/g;
# convert some of my macros:
# special case this one. bivector.tex shows that there is trouble with this
# expansion.
#$out =~ s/\\inv{\\B(.)}/\\frac{1}{\\mathbf{$1}}/g;
$out =~ s/\\inv${r1}/\\frac{1}{$1}/g;
$out =~ s/\\largestIntLessThan${r1}/\\lfloor $1 \\rfloor/g;
#$out =~ s/\\Abs{(.*?)}/{\\left\\lvert{$1}\\right\\rvert}/g;
if ( $mathml )
{
# why \\left\lvert?
$out =~ s/\\Abs${r1}/\\left\\vert $1 \\right\\vert/g;
$out =~ s/\\abs${r1}/\\left\\vert $1 \\right\\vert/g;
}
else
{
$out =~ s/\\Abs${r1}/\\left\\lvert $1 \\right\\rvert/g;
$out =~ s/\\abs${r1}/\\left\\lvert $1 \\right\\rvert/g;
}
my $lrDepth = 1 ;
while ( $out =~ s/\\lr\b/\\lr$lrDepth/ )
{
$lrDepth++ ;
}
for ( my $dd = $lrDepth - 1 ; $dd != 0 ; $dd-- )
{
$out =~ s/\\lr$dd${r1}/\\left( $1 \\right)/g;
}
$out =~ s/\\biglr${r1}/\\Bigl( $1 \\Bigr)/g;
$out =~ s/\\setlr${r1}/\\left\\{ $1 \\right\\}/g;
$out =~ s/\\Norm${r1}/\\left\\lVert $1 \\right\\rVert/g;
$out =~ s/\\ketbra${r2}/\\ket{$1} \\bra{$2}/g;
$out =~ s/\\bra${r1}/{\\left\\langle $1 \\right\\rvert}/g;
$out =~ s/\\ket${r1}/{\\left\\lvert $1 \\right\\rangle}/g;
$out =~ s/\\gpgrade${r2}/{\\left\\langle{$1}\\right\\rangle}_{$2}/g;
$out =~ s/\\braket${r2}/\\left\\langle{$1} \\vert {$2}\\right\\rangle/g;
$out =~ s/\\Expectation${r1}/\\left\\langle{$1}\\right\\rangle/g;
# $out =~ s/\\gpgradezero{(.*?)}/\\left\\langle{$1}\\right\\rangle/g;
# $out =~ s/\\gpgradeone{(.*?)}/{\\left\\langle{$1}\\right\\rangle}_{1}/g;
# $out =~ s/\\gpgradetwo{(.*?)}/{\\left\\langle{$1}\\right\\rangle}_{2}/g;
# $out =~ s/\\gpgradethree{(.*?)}/{\\left\\langle{$1}\\right\\rangle}_{3}/g;
$out =~ s/\\gpgradezero${r1}/\\left\\langle{$1}\\right\\rangle/g;
$out =~ s/\\gpgradeone${r1}/{\\left\\langle{$1}\\right\\rangle}_{1}/g;
$out =~ s/\\gpgradetwo${r1}/{\\left\\langle{$1}\\right\\rangle}_{2}/g;
$out =~ s/\\gpgradethree${r1}/{\\left\\langle{$1}\\right\\rangle}_{3}/g;
$out =~ s/\\gpgradefour${r1}/{\\left\\langle{$1}\\right\\rangle}_{4}/g;
$out =~ s/\\rgrad/\\stackrel{ \\rightarrow }{\\grad}/g;
$out =~ s/\\lgrad/\\stackrel{ \\leftarrow }{\\grad}/g;
$out =~ s/\\lrgrad/\\stackrel{ \\leftrightarrow }{\\grad}/g;
$out =~ s/\\lpartial/\\stackrel{ \\leftarrow }{\\partial}/g;
$out =~ s/\\rpartial/\\stackrel{ \\rightarrow }{\\partial}/g;
$out =~ s/\\lrpartial/\\stackrel{ \\leftrightarrow }{\\partial}/g;
$out =~ s/\\rspacegrad/\\stackrel{ \\rightarrow }{\\spacegrad}/g;
$out =~ s/\\lspacegrad/\\stackrel{ \\leftarrow }{\\spacegrad}/g;
$out =~ s/\\qedmarker/\\qquad\\square/g ;
$out =~ s/\\rboldpartial/\\stackrel{ \\rightarrow }{\\boldpartial}/g ;
$out =~ s/\\lboldpartial/\\stackrel{ \\leftarrow }{\\boldpartial}/g ;
$out =~ s/\\boldpartial/\\boldsymbol{\\partial}/g ;
$out =~ s/\\BCB/\\boldsymbol{\\mathcal{B}}/g;
$out =~ s/\\EE/\\boldsymbol{\\mathcal{E}}/g;
$out =~ s/\\kcap/\\hat{\\Bk}/g;
$out =~ s/\\xcap/\\hat{\\Bx}/g;
$out =~ s/\\ncap/\\hat{\\Bn}/g;
$out =~ s/\\taucap/\\hat{\\Btau}/g;
$out =~ s/\\rhocap/\\hat{\\Brho}/g;
$out =~ s/\\barb/\\bar{b}/g;
$out =~ s/\\barz/\\bar{z}/g;
$out =~ s/\\barq/\\bar{q}/g;
$out =~ s/\\barA/\\bar{A}/g;
$out =~ s/\\barh/\\bar{h}/g;
$out =~ s/\\barmu/\\bar{\\mu}/g;
$out =~ s/\\psihat/\\hat{\\psi}/g;
$out =~ s/\\Bomega/\\boldsymbol{\\omega}/g;
$out =~ s/\\Bepsilon/\\boldsymbol{\\epsilon}/g;
$out =~ s/\\BOmega/\\boldsymbol{\\Omega}/g;
$out =~ s/\\Bmu/\\boldsymbol{\\mu}/g;
$out =~ s/\\Bphi/\\boldsymbol{\\phi}/g;
$out =~ s/\\Bnu/\\boldsymbol{\\nu}/g;
$out =~ s/\\Btau/\\boldsymbol{\\tau}/g;
$out =~ s/\\Bsigma/\\boldsymbol{\\sigma}/g;
$out =~ s/\\Balpha/\\boldsymbol{\\alpha}/g;
$out =~ s/\\Brho/\\boldsymbol{\\rho}/g;
$out =~ s/\\Bbeta/\\boldsymbol{\\beta}/g;
$out =~ s/\\Bkappa/\\boldsymbol{\\kappa}/g;
$out =~ s/\\BTheta/\\boldsymbol{\\Theta}/g;
$out =~ s/\\BXI/\\boldsymbol{\\xi}/g;
$out =~ s/\\BEta/\\boldsymbol{\\eta}/g;
$out =~ s/\\(.)cap/\\hat{\\B$1}/g;
$out =~ s/\\hat(\w)/\\hat{$1}/g;
$out =~ s/\\InvGamma/\\sqrt{1 - \\frac{\\Bv^2}{c^2}}/g;
$out =~ s/\\conjugateStar${r1}/{$1}^{*}/g;
$out =~ s/\\conj/{*}/g;
# $out =~ s/\\aconjcap/\\widehat{\\mathbf{a}^{*}}/g;
$out =~ s/\\aconjcap/\\widehat{\\Ba^{*}}/g;
# this messes up \Bigr and \Bigl
# $out =~ s/\\B(.)/\\mathbf{$1}/g;
#
# Add word boundary:
# $out =~ s/\\B(.)\b/\\mathbf{$1}/g;
# hmm. that doesn't handle \Ba_\Ba. underscore is probably a word character.
#
$out =~ s/\\B(.)(\b|_)/\\mathbf{$1}$2/g;
$out =~ s/\\LL/\\mathcal{L}/g;
$out =~ s/\\FF/\\mathcal{F}/g;
$out =~ s/\\cross/\\times/g;
$out =~ s/\\grad/\\nabla/g;
$out =~ s/\\spacegrad/\\boldsymbol{\\nabla}/g;
$out =~ s/\\delambertian/\\square/g;
$out =~ s,\\PDi${r2},{\\partial $2}/{\\partial $1},g ;
$out =~ s,\\PDc${r3},\\left({\\partial $2}/{\\partial $1}\\right)_{$3},g ;
$out =~ s/\\PD${r2}/\\frac{\\partial $2}{\\partial $1}/g ;
$out =~ s/\\PauliI/\\begin{bmatrix} 1 & 0 \\\\ 0 & 1 \\\\ \\end{bmatrix}/g;
$out =~ s/\\PauliX/\\begin{bmatrix} 0 & 1 \\\\ 1 & 0 \\\\ \\end{bmatrix}/g;
$out =~ s/\\PauliYNoI/\\begin{bmatrix} 0 & -1 \\\\ 1 & 0 \\\\ \\end{bmatrix}/g;
$out =~ s/\\PauliY/\\begin{bmatrix} 0 & -i \\\\ i & 0 \\\\ \\end{bmatrix}/g;
$out =~ s/\\PauliZ/\\begin{bmatrix} 1 & 0 \\\\ 0 & -1 \\\\ \\end{bmatrix}/g;
$out =~ s/\\Clifford{(.*?)}{(.*?)}/\\mathcal{C}_{\\{{$1},{$2}\\}}/g;
$out =~ s/\\scalarProduct{(.*?)}{(.*?)}/{$1} \\bullet {$2}/g;
# $out =~ s/\\antisymmetric{(.*?)}{(.*?)}/\\left[{$1},{$2}\\right]/g;
# $out =~ s/\\symmetric{(.*?)}{(.*?)}/\\left\\{{$1},{$2}\\right\\}/g;
# run twice?
$out =~ s/\\antisymmetric${r2}/\\left[$1,$2\\right]/g;
$out =~ s/\\symmetric${r2}/\\left\\{$1,$2\\right\\}/g;
$out =~ s/\\antisymmetric${r2}/\\left[$1,$2\\right]/g;
$out =~ s/\\symmetric${r2}/\\left\\{$1,$2\\right\\}/g;
$out =~ s/\\DETuvwijk{(.*?)}{(.*?)}{(.*?)}{(.*?)}{(.*?)}{(.*?)}/\\begin{vmatrix} {$1}_{$4} & {$1}_{$5} & {$1}_{$6} \\\\ {$2}_{$4} & {$2}_{$5} & {$2}_{$6} \\\\ {$3}_{$4} & {$3}_{$5} & {$3}_{$6} \\end{vmatrix}/g;
$out =~ s/\\traceB${r1}/\\tr\\left({$1}\\right)/g;
$out =~ s/\\trace${r1}/\\tr{$1}/g;
$out =~ s/\\Span/\\text{span}/g;
$out =~ s/\\sinc/\\text{sinc}/g;
$out =~ s/\\var\b/\\text{var}/g;
$out =~ s/\\ddtau${r1}/\\frac{d{$1}}{d\\tau}/g;
$out =~ s/\\ddt${r1}/\\frac{d{$1}}{dt}/g;
$out =~ s/\\ddx${r1}/\\frac{d{$1}}{dx}/g;
$out =~ s/\\ddrho${r1}/\\frac{d{$1}}{d\\rho}/g;
$out =~ s/\\dds${r1}/\\frac{d{$1}}{ds}/g;
$out =~ s/\\pslash/\\not{p}/g;
$out =~ s/\\aslash/\\not{a}/g;
$out =~ s/\\bslash/\\not{b}/g;
$out =~ s/\\Dslash/\\not{D}/g;
$out =~ s/\\Aslash/\\not{A}/g;
$out =~ s/\\partialslash/\\not{\\partial}/g;
# hack:
if ( $wordpress )
{
$out =~ s/\\cancel${r1}/\\not{$1}/g;
}
$out =~ s/\\PDSq${r2}/\\frac{\\partial^2 {$2}}{\\partial {$1}^2}/g;
$out =~ s/\\innerprod${r2}/{\\langle{$1}, {$2}\\rangle}/g;
$out =~ s/\\overbar${r1}/\\bar{$1}/g;
$out =~ s/\\expectation${r1}/\\left\\langle{$1}\\right\\rangle/g;
$out =~ s/\\tr/\\text{Tr}/g;
$out =~ s/\\RejName/\\text{Rej}/g;
$out =~ s/\\Proj/\\text{Proj}/g;
$out =~ s/\\Det/\\text{Det}/g;
$out =~ s/\\erfc/\\text{erfc}/g;
$out =~ s/\\erf/\\text{erf}/g;
$out =~ s/\\Rot/\\text{Rot}/g;
$out =~ s/\\Scalar/\\text{Scalar}/g;
$out =~ s/\\Real/\\text{Real}/g;
$out =~ s/\\Imag/\\text{Imag}/g;
$out =~ s/\\symmetricVecBladePauli{(.*?)}{(.*?)}{(.*?)}/\\left\\{{$1},\\left[{$2},{$3}\\right]\\right\\}/g;
$out =~ s/\\symmetricBladeVecPauli{(.*?)}{(.*?)}{(.*?)}/\\left\\{\\left[{$1},{$2}\\right],{$3}\\right\\}/g;
$out =~ s/\\(.)hat/\\hat{$1}/g;
$out =~ s/\\(.)dot\b/\\dot{$1}/g;
# hack, undo the above for \\cdot
$out =~ s/\\dot{c}/\\cdot/g ;
$out =~ s/\\thetadot/\\dot{\\theta}/g;
$out =~ s/\\psidot/\\dot{\\psi}/g;
$out =~ s/\\phidot/\\dot{\\phi}/g;
$out =~ s/\\xdot/\\dot{x}/g;
$out =~ s/\\qdot/\\dot{q}/g;
$out =~ s/\\rdot/\\dot{r}/g;
$out =~ s/\\pdot/\\dot{p}/g;
$out =~ s/\\vdot/\\dot{v}/g;
$out =~ s/\\color${r2}/$2/g;
# not a good replacement:
$out =~ s/\\dbar/d/g;
$out =~ s/\\directproduct/\\otimes/g;
$out =~ s/\\thetacap/\\hat{\\boldsymbol{\\theta}}/g;
$out =~ s/\\phicap/\\hat{\\boldsymbol{\\phi}}/g;
$out =~ s/\\psicap/\\hat{\\boldsymbol{\\psi}}/g;
$out =~ s/\\questionEquals/\\stackrel{?}{=}/g;
$out =~ s/\\T\b/\\text{T}/g;
$out =~ s/\\BOne/\\mathbf{1}/g;
# Can't use txfonts in wordpress.
if ( $wordpress )
{
# hack way:
#$out =~ s/\\ointclockwise/\\oint/g;
#
# http://tex.stackexchange.com/a/178584/15
#
$out =~ s/\\ointctrclockwise/\\mathop{\\rlap{\\ensuremath{\\mkern3.5mu\\circlearrowright}}\\int}/g ;
$out =~ s/\\ointclockwise/\\mathop{\\rlap{\\ensuremath{\\mkern3.5mu\\circlearrowleft}}\\int}/g ;
}
$out =~ s/\\Bzero/\\mathbf{0}/g;
$out =~ s/\\bcB/\\boldsymbol{\\mathcal{B}}/g;
$out =~ s/\\Hbar/\\hbar/g;
$out =~ s/\\Atan/\\arctan/g;
$out =~ s/\\myBoxed/\\boxed/g;
$out =~ s/\\kB/k_{\\mathrm{B}}/g;
$out =~ s/\\kF/k_{\\mathrm{F}}/g;
$out =~ s/\\EF/E_{\\mathrm{F}}/g;
$out =~ s/\\ZG/Z_{\\mathrm{G}}/g;
$out =~ s/\\CV/C_{\\mathrm{V}}/g;
$out =~ s/\\CP/C_{\\mathrm{P}}/g;
$out =~ s/\\gBose${r1}/g_{$1}(z)/g;
die "remove mathLabelBoxes manually" if ( $out =~ /mathLabelBox/ ) ;
$out =~ s/\\evalbar${r2}/{\\left.{$1}\\right\\vert}_{$2}/g ;
$out =~ s/\\evalrange${r3}/{\\left.{$1}\\right\\vert}_{$2}^{$3}/g ;
$out =~ s/\\evalnobar${r2}/{$1}_{$2}/g ;
$out =~ s/\\DETuvij{(.)}{(.)}{(.)}{(.)}/\\begin{vmatrix} $1_$3 & $1_$4 \\\\ $2_$3 & $2_$4 \\end{vmatrix}/g;
# need a general way of dealing with this. wordpress latex doesn't like it
# the multiply nested {{...}} content.
#
$out =~ s/{{\\mathbf{(.)}}/{\\mathbf{$1}/g;
# bivector.tex. multiple passes of this required: ??
$out =~ s/\\gpgradetwo${r1}/{\\left\\langle{$1}\\right\\rangle}_{2}/g;
if ( $mathml )
{
$out =~ s/\\text/\\textrm/g;
$out =~ s/\\lvert/\\left\\vert/g ;
$out =~ s/\\rvert/\\right\\vert/g ;
# hack. Not supported by the script. should use arrows over.
$out =~ s/\\boldsymbol//g ;
}
return $out ;
}