aboutsummaryrefslogtreecommitdiffstats
path: root/bn_django
diff options
context:
space:
mode:
Diffstat (limited to 'bn_django')
-rw-r--r--bn_django/git_wiki/latex_directive.py129
-rw-r--r--bn_django/git_wiki/urls.py2
-rw-r--r--bn_django/git_wiki/views.py61
3 files changed, 183 insertions, 9 deletions
diff --git a/bn_django/git_wiki/latex_directive.py b/bn_django/git_wiki/latex_directive.py
new file mode 100644
index 0000000..823cc6a
--- /dev/null
+++ b/bn_django/git_wiki/latex_directive.py
@@ -0,0 +1,129 @@
+"""
+Implement latex directive.
+
+"""
+import os
+import shutil
+import sha
+import tempfile
+import subprocess
+
+from docutils import nodes
+from docutils.parsers.rst.directives import register_directive, flag
+from docutils.parsers.rst.roles import register_canonical_role
+
+from settings import *
+
+dorawtexstuff = False
+
+def latex_math(tex,centerize=False):
+ """ Process `tex` and produce image nodes. """
+ if not dorawtexstuff:
+ image_names = latex_snippet_to_png(tex)
+ the_nodes = []
+ alt = tex
+ styleclasses = ("equation",)
+ if tex[:2] =='$$':
+ centerize=True
+ if centerize:
+ styleclasses += ("centered-equ",)
+ for pageno, name in enumerate(image_names):
+ the_nodes.append(nodes.image(uri=name, alt=alt,
+ classes=styleclasses,))
+ alt = ''
+ return the_nodes
+ else:
+ return [nodes.raw(tex,tex,format='latex')]
+
+def latex_directive(name, arguments, options, content, lineno,
+ content_offset, block_text, state, state_machine):
+ """ Latex directive. """
+ tex = '\n'.join(content)
+ return latex_math(tex)
+latex_directive.content = True
+
+
+def latex_role(role, rawtext, text, lineno, inliner,
+ options={}, content=[]):
+ """ Latex role. """
+ i = rawtext.find('`')
+ tex = rawtext[i+1:-1]
+ return latex_math(tex,), []
+
+def register():
+ register_directive('latex', latex_directive)
+ register_canonical_role('latex', latex_role)
+ register_canonical_role('m', latex_role)
+
+def call_command_in_dir(app, args, targetdir):
+
+ cwd = os.getcwd()
+ try:
+ os.chdir(targetdir)
+ #print args
+ #print ' '.join(args)
+ p = subprocess.Popen(app + ' ' + ' '.join(args), shell=True)
+ sts = os.waitpid(p.pid, 0)
+
+ # FIXME -- should we raise an exception of status is non-zero?
+
+ finally:
+ # Restore working directory
+ os.chdir(cwd)
+
+latex_template = r'''
+\documentclass[12pt]{article}
+\pagestyle{empty}
+%(prologue)s
+\begin{document}
+%(raw)s
+\end{document}
+'''
+max_pages = 10
+MAX_RUN_TIME = 5 # seconds
+latex_name_template = 'latex2png_%s'
+latex = "latex"
+dvipng = "dvipng"
+latex_args = ("--interaction=nonstopmode", "%s.tex")
+dvipng_args = ("-q", "-bgTransparent", "-Ttight", "--noghostscript", "-l%s" % max_pages, "%s.dvi")
+
+def latex_snippet_to_png(inputtex, prologue=''):
+ """ Convert a latex snippet into a png. """
+ import shutil
+
+ tex = latex_template % { 'raw': inputtex, 'prologue': prologue }
+ namebase = latex_name_template % sha.new(tex).hexdigest()
+ dst = namebase + '%d.png'
+
+ tmpdir = tempfile.mkdtemp()
+ try:
+ data = open("%s/%s.tex" % (tmpdir, namebase), "w")
+ data.write(tex)
+ data.close()
+ args = list(latex_args)
+ args[-1] = args[-1] % namebase
+ res = call_command_in_dir(latex, args, tmpdir)
+ if not res is None:
+ # FIXME need to return some sort of error
+ return []
+ args = list(dvipng_args)
+ args[-1] = args[-1] % namebase
+ res = call_command_in_dir(dvipng, args, tmpdir)
+ if not res is None:
+ # FIXME need to return some sort of error
+ return []
+
+ page = 1
+ pagenames = []
+ while os.access("%s/%s%d.png" % (tmpdir, namebase, page), os.R_OK):
+ pagename = dst % page
+ shutil.copyfile("%s/%s%d.png" % (tmpdir, namebase, page),
+ EQU_FOLDER + pagename)
+ page += 1
+ pagenames.append(EQU_PREFIX + pagename)
+ finally:
+ # FIXME do some tidy up here
+ pass
+ shutil.rmtree(tmpdir)
+ return pagenames
+
diff --git a/bn_django/git_wiki/urls.py b/bn_django/git_wiki/urls.py
index 3489941..22f36a3 100644
--- a/bn_django/git_wiki/urls.py
+++ b/bn_django/git_wiki/urls.py
@@ -18,7 +18,7 @@ urlpatterns = patterns('bn_django.git_wiki.views',
(r'^commit/(?P<hash>[0-9a-z]{40})/$', 'view_commit',),
(r'^(?P<reqslug>[\w\-\_\/]*)/log/$', 'tree',),
(r'^(?P<reqslug>[\w\-\_\/]*)/edit/$', 'tree',),
- (r'^(?P<reqslug>[\w\-\_\/]*)/pdf/$', 'latexitem',),
+ (r'^(?P<reqslug>[\w\-\_\/]*)/pdf/$', 'pdfitem',),
(r'^(?P<reqslug>[\w\-\_\/]*)/raw/$', 'rawitem',),
(r'^(?P<reqslug>[\w\-\_\/]*)/latex/$', 'latexitem',),
(r'^(?P<reqslug>[\w\-\_\/]*\.png/?)$', 'figure',),
diff --git a/bn_django/git_wiki/views.py b/bn_django/git_wiki/views.py
index 2bfc034..6eff54b 100644
--- a/bn_django/git_wiki/views.py
+++ b/bn_django/git_wiki/views.py
@@ -50,7 +50,10 @@ def item(request, reqslug, blob=None):
i.update()
try:
- from docutils.core import publish_parts
+ from docutils.core import publish_parts,Publisher
+ import latex_directive
+ latex_directive.dorawtexstuff = False
+ latex_directive.register()
except ImportError:
if settings.DEBUG:
raise HttpResponseServerError(request)
@@ -72,12 +75,16 @@ def latexitem(request, reqslug, blob=None):
i.update()
try:
- from docutils.core import publish_parts
+ from docutils.core import publish_parts,Publisher
+ import latex_directive
+ latex_directive.dorawtexstuff = True
+ latex_directive.register()
except ImportError:
if settings.DEBUG:
raise HttpResponseServerError(request)
else:
- docutils_settings = getattr(settings, "GITWIKI_REST_SETTINGS", {})
+ docutils_settings = getattr(settings, "GITWIKI_REST_SETTINGS",
+ {'format':'latex'})
parts = publish_parts(source=i.contents, writer_name="latex", settings_overrides=docutils_settings)
hr = HttpResponse(mimetype="text/plain")
hr['Content-Disposition'] = 'filename=%s.tex' % reqslug
@@ -97,16 +104,54 @@ def pdfitem(request, reqslug, blob=None):
i.update()
try:
- from docutils.core import publish_parts
+ from docutils.core import publish_parts,Publisher
+ import latex_directive
+ latex_directive.dorawtexstuff = True
+ latex_directive.register()
+ import tempfile,re,os,shutil
except ImportError:
if settings.DEBUG:
raise HttpResponseServerError(request)
else:
- docutils_settings = getattr(settings, "GITWIKI_REST_SETTINGS", {})
+ docutils_settings = getattr(settings, "GITWIKI_REST_SETTINGS",
+ {'format':'latex'})
parts = publish_parts(source=i.contents, writer_name="latex", settings_overrides=docutils_settings)
- hr = HttpResponse(mimetype="text/plain")
- hr['Content-Disposition'] = 'filename=%s.tex' % reqslug
- hr.write(parts['whole'])
+ tmpdir = tempfile.mkdtemp()
+ pre = i.slug().split('/')
+ for fig in re.findall('\\includegraphics.*\{(.+)\}', parts['whole']):
+ if len(pre) > 1:
+ fig_blob = fromslug("%s/%s" % ('/'.join(pre[:-1])),fig)
+ else:
+ fig_blob = fromslug(fig)
+ # if might have to create subdirectories for figures
+ fig_pre = fig.split('/')
+ if len(fig_pre) > 1:
+ os.mkdir("%s/%s" % (tmpdir,'/'.join(fig_pre[:-1])))
+ fig_file = file(str("%s/%s" % (tmpdir,fig)),'wb')
+ fig_blob.update()
+ fig_file.write(fig_blob.contents)
+ fig_file.close()
+
+ hr = HttpResponse(mimetype="application/pdf")
+ #hr = HttpResponse()
+ hr['Content-Disposition'] = 'filename=%s.pdf' % reqslug
+ write_tex,pdf = os.popen2('rubber-pipe -qqq -d --into %s' % tmpdir)
+ write_tex.write(parts['whole'].replace('{\$}','$'))
+ write_tex.flush()
+ write_tex.close()
+ #hr.write(parts['whole'])
+ #pdf.flush()
+ for l in pdf.readlines():
+ hr.write(l)
+ try:
+ pdff = open("%s/rubtmp0.pdf" % tmpdir,'r')
+ for l in pdff.readlines():
+ hr.write(l)
+ pdff.close()
+ except:
+ pass
+ pdf.close()
+ shutil.rmtree(tmpdir)
return hr
def rawitem(request, reqslug, blob=None):