Skip to content

Instantly share code, notes, and snippets.

@josch
Forked from EnigmaCurry/latex.py
Created June 4, 2011 05:08
Show Gist options
  • Save josch/1007600 to your computer and use it in GitHub Desktop.
Save josch/1007600 to your computer and use it in GitHub Desktop.
A LaTeX filter for blogofile
"""
Render TeX blocks to png
This is a Blogofile filter. Place it in your _filters directory.
"""
import tempfile
import subprocess
import shutil
import shlex
import os
import re
import hashlib
import blogofile_bf as bf
html_escape_table = {"&": "&amp;",'"': "&quot;","'": "&apos;",">": "&gt;","<": "&lt;"}
html_escape = lambda text: "".join(html_escape_table.get(c,c) for c in text)
tex_template = r"""
\documentclass[12pt]{article}
\usepackage{ucs}
\usepackage[utf8x]{inputenc}
\usepackage{amsmath}
\usepackage{amsthm}
\usepackage{amssymb}
\pagestyle{empty}
\begin{document}
$%s$
\end{document}
"""
latex_block_re = re.compile(r"\s\$\$latex\s(.*?)\s\$", re.DOTALL)
def render_tex_to_png(latex_block, png_location):
"""Render a TeX formatted string to an image file
Depends on 'latex' and 'dvipng' binaries on the system path
"""
#Create a temporary directory and go into it
tmp_dir = tempfile.mkdtemp()
previous_dir = os.getcwd()
os.chdir(tmp_dir)
tex_f = open(os.path.join(tmp_dir,"source.tex"),"w")
tex_f.write((tex_template % latex_block))
tex_f.close()
try:
#Generate the .dvi
p = subprocess.Popen(shlex.split(
'latex -interaction=nonstopmode source.tex'),
stdout=subprocess.PIPE)
p.wait()
#Generate the .ps
try:
p = subprocess.Popen(shlex.split(
'dvipng -bg Transparent -gamma 1.5 -D 120 -T tight'
' --strict source.dvi -o rendered.png'),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
p.wait()
except:
p = subprocess.Popen(shlex.split('dvips source.dvi'),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
p.wait()
#Generate the .png
p = subprocess.Popen(shlex.split(
'convert -density 120 -trim -transparent'
' "#FFFFFF" source.ps rendered.png'),stdout=subprocess.PIPE)
p.wait()
#Copy the .png to the png_location
os.chdir(previous_dir)
shutil.copyfile(os.path.join(tmp_dir,"rendered.png"),png_location)
finally:
#Go back to the original directory and clean up the temp files
os.chdir(previous_dir)
shutil.rmtree(tmp_dir)
def render_latex_blocks(src, cache_dir="_tmp", site_images_dir="images"):
"""Render a document with LaTeX blocks
1) Extract all the $$latex blocks
2) Render each TeX block to an image to the cache
3) Copy the (pre)rendered image from the cache to the _site dir
4) Replace the $$latex blocks with <img> tags
"""
img_substitutions = {}
for m in latex_block_re.finditer(src):
tex_expr = m.groups()[0]
fn = hashlib.md5(tex_expr).hexdigest()+".png"
png_cached = os.path.join(cache_dir,fn)
site_png_dir = bf.util.path_join("_site",bf.util.fs_site_path_helper(
site_images_dir))
site_png = bf.util.path_join(site_png_dir,fn)
#only render the image if the image is not already cached
if(not os.path.isfile(png_cached)):
bf.util.mkdir(cache_dir)
bf.filter.logger.info("Rendering LaTeX: "+tex_expr)
render_tex_to_png(tex_expr,png_cached)
#copy the rendered image to the site dir
bf.util.mkdir(site_png_dir)
shutil.copyfile(png_cached,site_png)
#record the $$latex block and it's replacement <img> tag
img_substitutions[m.group()] = "<img alt=\"%s\" src=\"%s%s\">" % \
(html_escape(tex_expr), bf.config.site.url,
bf.util.site_path_helper(site_images_dir,fn))
#Make the <img> tag replacements in a single pass
p = re.compile('|'.join(map(re.escape, img_substitutions)))
return p.sub(lambda x: img_substitutions[x.group(0)], src)
def run(src):
return render_latex_blocks(src)
---
categories: Category 1, Category 2
date: 2009/07/24 16:20:00
title: Sample LaTeX post
filter: latex, markdown
tags: test, blogofile, cool-stuff
author: Ryan
---
This is a sample post with TeX blocks.
This is a TeX block:
$$latex
y = \int_0^\infty \gamma^2 \cos(x) dx $ this is after the block.
This is an inline Tex block: $$latex \cos(x) $ and this is after.
This is two seperate inline Tex blocks: $$latex \sin(x) $ and then $$latex \tan(x) $ and this is after.
This is a mistyped TeX block because I didn't terminate it properly. $$latex \tan(x)$ and this text is rendered too because I didn't put a space before the dollar sign $
This is a broken TeX block because I didn't put a space before it$$latex \tan(x) $
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment