html-latex-images
1 #!/usr/bin/env python 2 # vim: sts=4 sw=4 et 3 4 import os, shutil, sys, subprocess 5 import tempfile, hashlib 6 import lxml.etree as ET 7 8 tmpdir = None 9 10 cachedir = os.environ.get('HTML_LATEX_CACHE', './cache') 11 12 nsmap = {'xhtml':"http://www.w3.org/1999/xhtml"} 13 14 latex_header = r""" 15 \documentclass{article} 16 \usepackage[mathletters]{ucs} 17 \usepackage[utf8x]{inputenc} 18 %\usepackage[T2A]{fontenc} 19 %\usepackage[english,russian]{babel} 20 \usepackage{euscript} 21 \usepackage{type1cm} 22 \usepackage{amssymb} 23 \usepackage{amsmath} 24 \usepackage{ulem} 25 \usepackage{mathrsfs} 26 \begin{document} 27 \thispagestyle{empty} 28 """ 29 30 latex_footer = r""" 31 \end{document} 32 """ 33 34 latex_cmd = "latex -interaction nonstopmode ./file.tex".split() 35 dvipng_cmd = "dvipng -q -D 148 -T tight -pp 1 --noghostscript file.dvi -o file.png".split() 36 37 def build_img(fn, e, block=False): 38 txt = e.text.strip() 39 txt = txt.replace('>', '>').replace('<', '<').replace('&', '&') # XML escapes 40 txt = txt.replace('\\[', '[').replace('\\]', ']') # Asciidoc escapes 41 md5 = hashlib.md5(txt.encode('utf-8')).hexdigest() 42 img = md5 + ".png" 43 fullimg = os.path.join(cachedir, img) 44 if not os.path.exists(fullimg): 45 latex(txt, block) 46 os.rename(os.path.join(tmpdir, 'file.png'), fullimg) 47 shutil.copy2(fullimg, os.path.join(os.path.dirname(fn), img)) 48 node = ET.Element('img', attrib={'class':'latexmath'}, id=md5, src=img, title=txt) 49 e.getparent().replace(e, node) 50 return 1 51 52 def latex(txt, block=False): 53 if block: 54 if not txt.startswith('$$'): txt = '$$' + txt 55 if not txt.endswith('$$'): txt = txt + '$$' 56 else: 57 if txt[0] != '$': txt = '$' + txt 58 if txt[-1] != '$': txt = txt + '$' 59 60 fp = open(os.path.join(tmpdir, 'file.tex'), 'w') 61 fp.write(latex_header) 62 fp.write(txt.encode('utf-8') + '\n') 63 fp.write(latex_footer) 64 fp.close() 65 r = subprocess.call(latex_cmd, cwd=tmpdir) 66 if r: raise RuntimeError("Compilation failed") 67 r = subprocess.call(dvipng_cmd, cwd=tmpdir) 68 if r: raise RuntimeError("Compilation failed") 69 70 def substitute(f): 71 xml = ET.parse(open(f), ET.HTMLParser()) 72 images = 0 73 for e in xml.xpath('//span[@class="latexmath"]', namespaces=nsmap): 74 images += build_img(f, e, block=False) 75 for e in xml.xpath('//div[@class="latexmath"]', namespaces=nsmap): 76 images += build_img(f, e, block=True) 77 if not images: return 78 print "Added %d images" % images 79 fp = open(f + ".math", 'w') 80 fp.write(ET.tostring(xml, pretty_print=True, xml_declaration=False, encoding="utf-8")) 81 fp.close() 82 os.unlink(f) 83 #os.rename(f, f + ".pre-math") 84 os.rename(f + ".math", f) 85 86 tmpdir = tempfile.mkdtemp(dir=cachedir) 87 try: 88 for f in sys.argv[1:]: 89 substitute(f) 90 finally: 91 shutil.rmtree(tmpdir)