Skip to content

Instantly share code, notes, and snippets.

@farleyknight
Created November 22, 2008 03:30
Show Gist options
  • Save farleyknight/27736 to your computer and use it in GitHub Desktop.
Save farleyknight/27736 to your computer and use it in GitHub Desktop.
Latex server. Pass equations, get pngs
# Usage:
# ruby latex_server.rb
#
# Try: <img src="http://localhost:4567/\cos \frac{\pi}{2} = 0">
# Get: A nice looking png of: cos(pi/2) = 0
#
# Bug1: Ellipses (...) don't work. Probably the way urls are parsed
# by sinatra. Use \ldots
# Bug2: Question marks don't work. Definitely due to the way urls
# are parsed by any web library. Use \qmark
# Bug3: Commas dont work.. Not sure if they are necessary or
# what to replace them with..?
#
#
require 'tempfile'
require 'pathname'
require 'fileutils'
require 'digest/sha1'
FileUtils.mkdir_p File.dirname(__FILE__) + "/public" unless File.exists? "public"
def latex_doc(cmd)
puts "cmd is #{cmd}"
%Q{
\\documentclass[10pt]{article}
\\special{papersize=3in,5in}
\\usepackage[utf8]{inputenc}
\\pagestyle{empty}
\\newcommand{\\qmark}{?}
\\begin{document}
$$#{cmd}$$
\\end{document}
}
end
def tmp(path)
Dir.tmpdir + "/" + path
end
def target_public_path(cmd, opts = {})
@realpath ||= Pathname.new(File.dirname(__FILE__)).realpath.to_s
(@realpath + "/public/") + Digest::SHA1.hexdigest(cmd + opts.inspect) + ".png"
end
def latex2png(cmd, opts = {})
return target_public_path(cmd, opts) if File.exists? target_public_path(cmd, opts)
f = nil
Tempfile.open("tmp.tex") do |f|
f.write latex_doc(cmd)
end
Dir.chdir Dir.tmpdir do
png_path = dvipng(tex2dvi(f.path), opts)
puts "Copying #{png_path} to #{target_public_path(cmd)}"
FileUtils.cp png_path, target_public_path(cmd, opts)
end
target_public_path(cmd, opts)
end
def tex2dvi(tex_path)
result = `latex -interaction=nonstopmode #{tex_path}`
(dvi_path = result.scan(/Output written on ([\w\.]+)/).first.first) rescue raise "No file match: #{result}"
dvi_path
end
def dvipng(dvi_path, opts = {})
png_path = dvi_path.split(".").first + ".png"
system("dvipng -D #{opts[:res]} -T tight #{dvi_path} -o #{png_path}")
png_path
end
require 'rubygems'
require 'sinatra'
# set_option :port, 8765
get '/:equation' do
send_file latex2png(params[:equation], :res => 150), :type => "image/png", :disposition => 'inline'
end
get '/:resolution/:equation' do
send_file latex2png(params[:equation], :res => params[:resolution]), :type => "image/png", :disposition => 'inline'
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment