"""
Replace Latex math mode/\\begin{}\\end{} blocks with html img tag
after rendering
$Id: ReplaceInlineLatex.py,v 1.11 2001/09/07 14:21:16 rsbowman Exp $
TODO:
use \\ref{shit} to make reference to equations. Convert \\ref{shit} to the
appropriate (number): add negative match to latexPattern for \\ref, do a
s/// after generating an equation with a \\label.
Separate vertical alignment characters & into a new
\\end{equation}\\begin{equation} and then render the separate images in
a table to acheive vertical alignment.
"""
import re, os
from DocumentTemplate.html_quote import html_quote
from util import fileNameFor, imagesPath, workingDir, getPngSize, runCommand, log
from string import strip, join, replace
# This will fail on nested blocks \begin{array} \begin{array}...\end{array} \end{array}
# It is necessary for this to be all one regex (unfortunately) so that we do
# not pick up equations inside \begin{latex}...\end{latex}, rather only the
# outer delimiters.
latexPattern = r'(?
Some or all expressions may not have rendered properly,
because Latex returned the following error:
%s
"""
reConsts = re.MULTILINE+re.DOTALL
def findLatexCode(text,
findLatex=re.compile(latexPattern,
reConsts).findall,
):
codeList = map(lambda x: x[0], findLatex(text))
return codeList
def replaceInlineLatex(body, charheightpx, alignfudge, resfudge, latexTemplate=None):
from latexWrapper import renderNonexistingImages
renumbered = re.compile(r'[ \t]*\\begin{ *(math|equation|eqnarray) *}')
reunnumbered = re.compile(r'[ \t]*(\\begin{ *((math|equation|eqnarray)\*|table|tabular|displaymath|array|latex) *}|\\\[)')
body = strip(body)
latexCodeList = findLatexCode(body)
newlatexCodeList = []
eqnum = 0
for code in latexCodeList:
if code[0]=='!':
# We need to identify if we're inside a '' block or an example:: block here.
newcode = re.compile('^!', re.MULTILINE).sub('', code)
# change the dollar sign so that the replace below does not hit
# this code again (in the case of the same code appearing twice,
# once escaped, once not)
#newcode = re.compile('\$', re.MULTILINE).sub('$', newcode, 2)
# prevent stx from mangling asterisks
#newcode = re.compile('\*', re.MULTILINE).sub('*', newcode)
# and this will hide \(\), \[\], \begin...\end, including any
# equations that may be hiding inside a \begin{latex}..\end{latex}
newcode = re.compile(r'\\\[', re.MULTILINE).sub('\\![', newcode)
#newcode = re.compile(r'\\', re.MULTILINE).sub('\', newcode)
body = replace(body, code, newcode, 1)
continue
else:
newlatexCodeList.append(code)
oldcode = code
renummatch = renumbered.match(code)
if renummatch:
eqnum = eqnum + 1
code = renumbered.sub('\\\\begin{\\1*}\n\\label{eq%d}' %(eqnum), code, 1)
kind = renummatch.group(1)
code = re.compile('\\\\end{ *%s *}' %(kind)).sub('\\\\end{%s*}' %(kind), code, 1)
code = renumbered.sub('\\\\begin{\\1*}\n\\label{eq%d}' %(eqnum), code, 1)
# FIXME we really shouldn't do this...it will recreate block equations with different numbers.
newlatexCodeList[newlatexCodeList.index(oldcode)] = code
# FIXME This will also replace any escaped code :(
body = replace(body, oldcode, code, 1)
errors = renderNonexistingImages(newlatexCodeList, charheightpx, alignfudge, resfudge,
latexTemplate=latexTemplate)
if not errors:
for code in newlatexCodeList:
labelmatch = re.compile('\\\\label{eq(\\d+)}').search(code, 1)
commentedcode = re.compile('^', re.MULTILINE).sub('!', html_quote(code))
# "--" inside a comment screws up browsers. But in LaTeX math mode "--" and "- -" are equivalent.
commentedcode = re.compile('--', re.MULTILINE).sub('- -', commentedcode)
if labelmatch:
eqnum = labelmatch.group(1)
imageTag = '' %(eqnum) \
+ '
| ' \
+ getImageFor(code, charheightpx) \
+ ' | (%s) |
' %(eqnum)
elif reunnumbered.match(code):
imageTag = '' \
+ '| ' \
+ getImageFor(code, charheightpx) \
+ ' | |
'
else:
imageTag = getImageFor(code, charheightpx)
body = replace(body, code, imageTag, 1)
# We try to match the > and < (or ^/$) from the preceeding and trailing tags,
# so as not to catch the alt="..." from a latex equation
# FIXME this is slow. Use something like perl's m/\G/g to iterate over (n)
for i in range(1,int(eqnum)+1):
body = re.compile(r'((?:>|^)(?:[^<]*\s|))\( *(?:[Ee][Qq]\.)?\s*(%d) *\)([^>]*(?:<|$))' %(i)).sub(r'\1(\2)\3', body)
else:
body = "" + body + "
" + errorMessage %(errors)
# Handle escaping of latex
body = re.compile(r'(?%s' %(preamble,
src,
imageUrl,
width,
height,
postamble)