Commit f3e996a5 authored by Dave Kliczbor's avatar Dave Kliczbor
Browse files

Added feature: Choose between LaTeX and Wiki/reStructuredText Syntax

parent 39d5d838
...@@ -2,12 +2,16 @@ ...@@ -2,12 +2,16 @@
# -*- encoding: utf8 -*- # -*- encoding: utf8 -*-
from flask import Flask, flash, session, redirect, url_for, escape, request, Response, Markup from flask import Flask, flash, session, redirect, url_for, escape, request, Response, Markup
import sys, os, os.path, glob import sys
import os
import os.path
import glob
from genshi.template import TemplateLoader from genshi.template import TemplateLoader
from genshi.template.text import NewTextTemplate from genshi.template.text import NewTextTemplate
from flaskext.genshi import Genshi, render_response from flaskext.genshi import Genshi, render_response
from werkzeug.utils import secure_filename from werkzeug.utils import secure_filename
from collections import defaultdict from collections import defaultdict
from docutils.core import publish_parts
import warnings import warnings
import shutil import shutil
import subprocess import subprocess
...@@ -24,6 +28,7 @@ app.secret_key = config.app_secret ...@@ -24,6 +28,7 @@ app.secret_key = config.app_secret
genshi = Genshi(app) genshi = Genshi(app)
genshi.extensions['html'] = 'html5' genshi.extensions['html'] = 'html5'
def check_output(*popenargs, **kwargs): def check_output(*popenargs, **kwargs):
# Copied from py2.7s subprocess module # Copied from py2.7s subprocess module
r"""Run command with arguments and return its output as a byte string. r"""Run command with arguments and return its output as a byte string.
...@@ -58,205 +63,238 @@ def check_output(*popenargs, **kwargs): ...@@ -58,205 +63,238 @@ def check_output(*popenargs, **kwargs):
#raise Exception(output) #raise Exception(output)
return output return output
def allowed_file(filename): def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1] in config.allowed_extensions return '.' in filename and filename.rsplit('.', 1)[1] in config.allowed_extensions
@app.route('/') @app.route('/')
def index(**kwargs): def index(**kwargs):
data = defaultdict(str) data = defaultdict(str)
data.update(**kwargs) data.update(**kwargs)
filelist = glob.glob(config.datadir + '/*.schild') filelist = glob.glob(config.datadir + '/*.schild')
data['files'] = [ unicode(os.path.basename(f)) for f in sorted(filelist) ] data['files'] = [unicode(os.path.basename(f)) for f in sorted(filelist)]
return render_response('index.html', data) return render_response('index.html', data)
@app.route('/edit') @app.route('/edit')
def edit(**kwargs): def edit(**kwargs):
data = defaultdict(str) data = defaultdict(str)
data.update(**kwargs) data.update(**kwargs)
imagelist = glob.glob(config.imagedir + '/*.png') imagelist = glob.glob(config.imagedir + '/*.png')
data['images'] = [ os.path.basename(f) for f in imagelist ] data['images'] = [os.path.basename(f) for f in imagelist]
templatelist = glob.glob(config.textemplatedir + '/*.tex') templatelist = glob.glob(config.textemplatedir + '/*.tex')
data['templates'] = [ unicode(os.path.basename(f)) for f in sorted(templatelist) ] data['templates'] = [unicode(os.path.basename(f))
return render_response('edit.html', data) for f in sorted(templatelist)]
return render_response('edit.html', data)
@app.route('/edit/<filename>') @app.route('/edit/<filename>')
def edit_one(filename): def edit_one(filename):
with open(os.path.join(config.datadir, filename), 'r') as infile: with open(os.path.join(config.datadir, filename), 'r') as infile:
formdata = json.load(infile) formdata = defaultdict(str, json.load(infile))
return edit(form=formdata) if len(formdata['markup']) < 1:
formdata['markup'] = 'latex'
return edit(form=formdata)
def run_pdflatex(context, outputfilename, overwrite=True): def run_pdflatex(context, outputfilename, overwrite=True):
if not context.has_key('textemplate'): if not context.has_key('textemplate'):
context['textemplate'] = "text-image-quer.tex" context['textemplate'] = "text-image-quer.tex"
genshitex = TemplateLoader([config.textemplatedir]) genshitex = TemplateLoader([config.textemplatedir])
template = genshitex.load(context['textemplate'], cls=NewTextTemplate, encoding='utf8') template = genshitex.load(
if not overwrite and os.path.isfile(outputfilename) and os.path.getmtime(template.filepath) < os.path.getmtime(outputfilename): context['textemplate'], cls=NewTextTemplate, encoding='utf8')
return if not overwrite and os.path.isfile(outputfilename) and os.path.getmtime(template.filepath) < os.path.getmtime(outputfilename):
tmpdir = tempfile.mkdtemp(dir=config.tmpdir) return
if context.has_key('img') and context['img'] and context['img'] != '__none': print(str(context))
if context['markup'] == 'rst':
context['text'] = publish_parts(context['text'], writer_name='latex')['body']
context['headline'] = publish_parts(context['headline'], writer_name='latex')['body']
tmpdir = tempfile.mkdtemp(dir=config.tmpdir)
if context.has_key('img') and context['img'] and context['img'] != '__none':
try:
shutil.copy(os.path.join(config.imagedir, context[
'img']), os.path.join(tmpdir, context['img']))
except:
raise IOError("COULD NOT COPY")
else:
# print "MEH No image"
pass
tmptexfile = os.path.join(tmpdir, 'output.tex')
tmppdffile = os.path.join(tmpdir, 'output.pdf')
with open(tmptexfile, 'w') as texfile:
texfile.write(template.generate(form=context).render(encoding='utf8'))
cwd = os.getcwd()
os.chdir(tmpdir)
os.symlink(config.texsupportdir, os.path.join(tmpdir, 'support'))
try: try:
shutil.copy(os.path.join(config.imagedir, context['img']), os.path.join(tmpdir, context['img'])) texlog = check_output(
except: ['pdflatex', '--halt-on-error', tmptexfile], stderr=STDOUT)
raise IOError("COULD NOT COPY") except CalledProcessError as e:
else: if overwrite:
#print "MEH No image" flash(Markup("<p>PDFLaTeX Output:</p><pre>%s</pre>" % e.output), 'log')
pass raise SyntaxWarning("PDFLaTeX bailed out")
tmptexfile = os.path.join(tmpdir, 'output.tex') finally:
tmppdffile = os.path.join(tmpdir, 'output.pdf') os.chdir(cwd)
with open(tmptexfile, 'w') as texfile:
texfile.write(template.generate(form = context).render(encoding='utf8'))
cwd = os.getcwd()
os.chdir(tmpdir)
os.symlink(config.texsupportdir, os.path.join(tmpdir, 'support'))
try:
texlog = check_output(['pdflatex', '--halt-on-error', tmptexfile], stderr=STDOUT)
except CalledProcessError as e:
if overwrite: if overwrite:
flash(Markup("<p>PDFLaTeX Output:</p><pre>%s</pre>" % e.output), 'log') flash(Markup("<p>PDFLaTeX Output:</p><pre>%s</pre>" % texlog), 'log')
raise SyntaxWarning("PDFLaTeX bailed out") shutil.copy(tmppdffile, outputfilename)
finally: shutil.rmtree(tmpdir)
os.chdir(cwd)
if overwrite:
flash(Markup("<p>PDFLaTeX Output:</p><pre>%s</pre>" % texlog), 'log')
shutil.copy(tmppdffile, outputfilename)
shutil.rmtree(tmpdir)
def save_and_convert_image_upload(inputname): def save_and_convert_image_upload(inputname):
file = request.files[inputname] file = request.files[inputname]
if file: if file:
if not allowed_file(file.filename): if not allowed_file(file.filename):
raise UserWarning("Uploaded image is not in the list of allowed file types.") raise UserWarning(
filename = os.path.join(config.uploaddir, secure_filename(file.filename)) "Uploaded image is not in the list of allowed file types.")
file.save(filename) filename = os.path.join(
img = PythonMagick.Image(filename) config.uploaddir, secure_filename(file.filename))
imgname = os.path.splitext(secure_filename(file.filename))[0].replace('.', '_') + '.png' file.save(filename)
savedfilename = os.path.join(config.imagedir, imgname) img = PythonMagick.Image(filename)
img.write(savedfilename) imgname = os.path.splitext(secure_filename(file.filename))[
os.remove(filename) 0].replace('.', '_') + '.png'
return imgname savedfilename = os.path.join(config.imagedir, imgname)
return None img.write(savedfilename)
os.remove(filename)
return imgname
return None
@app.route('/create', methods=['POST']) @app.route('/create', methods=['POST'])
def create(): def create():
if request.method == 'POST': if request.method == 'POST':
formdata = request.form.to_dict(flat=True) formdata = defaultdict(str, request.form.to_dict(flat=True))
for a in ('headline', 'text'): for a in ('headline', 'text'):
formdata[a] = unicode(formdata[a]) formdata[a] = unicode(formdata[a])
try: try:
imgpath = save_and_convert_image_upload('imgupload') imgpath = save_and_convert_image_upload('imgupload')
if imgpath is not None: if imgpath is not None:
formdata['img'] = imgpath formdata['img'] = imgpath
outfilename = secure_filename(formdata['headline'][:16])+str(hash(formdata['headline']+formdata['text']+os.path.splitext(formdata['textemplate'])[0]+os.path.splitext(formdata['img'])[0]))+'.schild' outfilename = secure_filename(formdata['headline'][:16]) + str(hash(formdata['headline'] + formdata[
outpdfname = outfilename + '.pdf' 'text'] + os.path.splitext(formdata['textemplate'])[0] + os.path.splitext(formdata['img'])[0])) + '.schild'
formdata['pdfname'] = outpdfname outpdfname = outfilename + '.pdf'
run_pdflatex(formdata, os.path.join(config.pdfdir, outpdfname)) formdata['pdfname'] = outpdfname
with open(os.path.join(config.datadir, outfilename), 'w') as outfile: with open(os.path.join(config.datadir, outfilename), 'w') as outfile:
json.dump(formdata, outfile) json.dump(formdata, outfile)
flash(Markup(u"""PDF created and data saved. You might create another one. Here's a preview. Click to print.<br/> run_pdflatex(formdata, os.path.join(config.pdfdir, outpdfname))
flash(Markup(u"""PDF created and data saved. You might create another one. Here's a preview. Click to print.<br/>
<a href="%s"><img src="%s"/></a>""" % <a href="%s"><img src="%s"/></a>""" %
(url_for('schild', filename=outfilename), url_for('pdfthumbnail', pdfname=outpdfname, maxgeometry=200)) (url_for('schild', filename=outfilename), url_for(
)) 'pdfthumbnail', pdfname=outpdfname, maxgeometry=200))
except Exception as e: ))
flash(u"Could not create pdf or save data: %s" % str(e), 'error') except Exception as e:
flash(u"Could not create pdf or save data: %s" % str(e), 'error')
data = {'form': formdata}
imagelist = glob.glob(config.imagedir + '/*.png')
data['images'] = [os.path.basename(f) for f in imagelist]
templatelist = glob.glob(config.textemplatedir + '/*.tex')
data['templates'] = [os.path.basename(f) for f in sorted(templatelist)]
return redirect(url_for('edit_one', filename=outfilename))
flash("No POST data. You've been redirected to the edit page.", 'warning')
return redirect(url_for('edit'))
data = {'form': formdata }
imagelist = glob.glob(config.imagedir + '/*.png')
data['images'] = [ os.path.basename(f) for f in imagelist ]
templatelist = glob.glob(config.textemplatedir + '/*.tex')
data['templates'] = [ os.path.basename(f) for f in sorted(templatelist) ]
return render_response('edit.html', data)
flash("No POST data. You've been redirected to the edit page.", 'warning')
return redirect(url_for('edit'))
@app.route('/schild/<filename>') @app.route('/schild/<filename>')
def schild(filename): def schild(filename):
return render_response('schild.html', {'filename':filename, 'printer':[ unicode(f) for f in sorted(config.printers.keys()) ]}) return render_response('schild.html', {'filename': filename, 'printer': [unicode(f) for f in sorted(config.printers.keys())]})
@app.route('/printout', methods=['POST']) @app.route('/printout', methods=['POST'])
def printout(): def printout():
filename = os.path.join(config.pdfdir, secure_filename(request.form['filename'])) filename = os.path.join(
printer = config.printers[request.form['printer']] config.pdfdir, secure_filename(request.form['filename']))
copies = int(request.form['copies']) or 0 printer = config.printers[request.form['printer']]
if copies > 0 and copies <= 6: copies = int(request.form['copies']) or 0
try: if copies > 0 and copies <= 6:
lprout = check_output(['lpr', '-H', str(config.printserver), '-P', str(printer), '-#', str(copies)] + config.lproptions + [filename], stderr=STDOUT) try:
flash(u'Schild wurde zum Drucker geschickt!') lprout = check_output(['lpr', '-H', str(config.printserver), '-P', str(
except CalledProcessError as e: printer), '-#', str(copies)] + config.lproptions + [filename], stderr=STDOUT)
flash(Markup("<p>Could not print:</p><pre>%s</pre>" % e.output), 'error') flash(u'Schild wurde zum Drucker geschickt!')
else: except CalledProcessError as e:
flash(u'Ungültige Anzahl Kopien!') flash(Markup("<p>Could not print:</p><pre>%s</pre>" % e.output), 'error')
return redirect(url_for('index')) else:
flash(u'Ungültige Anzahl Kopien!')
return redirect(url_for('index'))
@app.route('/delete', methods=['POST']) @app.route('/delete', methods=['POST'])
def delete(): def delete():
filename = secure_filename(request.form['filename']) filename = secure_filename(request.form['filename'])
try: try:
os.unlink(os.path.join(config.datadir, filename)) os.unlink(os.path.join(config.datadir, filename))
for f in glob.glob(os.path.join(config.pdfdir, filename + '.pdf*')): for f in glob.glob(os.path.join(config.pdfdir, filename + '.pdf*')):
os.unlink(f) os.unlink(f)
flash(u"Schild %s wurde gelöscht" % filename) flash(u"Schild %s wurde gelöscht" % filename)
return redirect(url_for('index')) return redirect(url_for('index'))
except: except:
flash(u"Schild %s konnte nicht gelöscht werden." % filename, 'error') flash(u"Schild %s konnte nicht gelöscht werden." % filename, 'error')
return redirect(url_for('schild', filename=filename)) return redirect(url_for('schild', filename=filename))
@app.route('/image/<imgname>') @app.route('/image/<imgname>')
def image(imgname): def image(imgname):
imgpath = os.path.join(config.imagedir, secure_filename(imgname)) imgpath = os.path.join(config.imagedir, secure_filename(imgname))
#print(imgpath) # print(imgpath)
if os.path.exists(imgpath): if os.path.exists(imgpath):
with open(imgpath, 'r') as imgfile: with open(imgpath, 'r') as imgfile:
return Response(imgfile.read(), mimetype="image/png") return Response(imgfile.read(), mimetype="image/png")
else: else:
return "Meh" #redirect(url_for('index')) return "Meh" # redirect(url_for('index'))
def make_thumb(filename, maxgeometry): def make_thumb(filename, maxgeometry):
thumbpath = filename + '.' + str(maxgeometry) thumbpath = filename + '.' + str(maxgeometry)
if not os.path.exists(thumbpath) or os.path.getmtime(filename) > os.path.getmtime(thumbpath): if not os.path.exists(thumbpath) or os.path.getmtime(filename) > os.path.getmtime(thumbpath):
img = PythonMagick.Image(str(filename)) img = PythonMagick.Image(str(filename))
img.transform("%sx%s" % (maxgeometry,maxgeometry)) img.transform("%sx%s" % (maxgeometry, maxgeometry))
img.quality(90) img.quality(90)
img.write(str("png:%s" % thumbpath)) img.write(str("png:%s" % thumbpath))
return thumbpath return thumbpath
@app.route('/thumbnail/<imgname>/<int:maxgeometry>') @app.route('/thumbnail/<imgname>/<int:maxgeometry>')
def thumbnail(imgname, maxgeometry): def thumbnail(imgname, maxgeometry):
imgpath = os.path.join(config.imagedir, secure_filename(imgname)) imgpath = os.path.join(config.imagedir, secure_filename(imgname))
thumbpath = make_thumb(imgpath, maxgeometry) thumbpath = make_thumb(imgpath, maxgeometry)
with open(thumbpath, 'r') as imgfile: with open(thumbpath, 'r') as imgfile:
return Response(imgfile.read(), mimetype="image/png") return Response(imgfile.read(), mimetype="image/png")
@app.route('/pdfthumb/<pdfname>/<int:maxgeometry>') @app.route('/pdfthumb/<pdfname>/<int:maxgeometry>')
def pdfthumbnail(pdfname, maxgeometry): def pdfthumbnail(pdfname, maxgeometry):
pdfpath = os.path.join(config.pdfdir, secure_filename(pdfname)) pdfpath = os.path.join(config.pdfdir, secure_filename(pdfname))
thumbpath = make_thumb(pdfpath, maxgeometry) thumbpath = make_thumb(pdfpath, maxgeometry)
with open(thumbpath, 'r') as imgfile: with open(thumbpath, 'r') as imgfile:
return Response(imgfile.read(), mimetype="image/png") return Response(imgfile.read(), mimetype="image/png")
@app.route('/tplthumb/<tplname>/<int:maxgeometry>') @app.route('/tplthumb/<tplname>/<int:maxgeometry>')
def tplthumbnail(tplname, maxgeometry): def tplthumbnail(tplname, maxgeometry):
pdfpath = os.path.join(config.cachedir, secure_filename(tplname)+'.pdf') pdfpath = os.path.join(config.cachedir, secure_filename(tplname) + '.pdf')
try: try:
run_pdflatex( run_pdflatex(
{ 'textemplate' : secure_filename(tplname), {'textemplate': secure_filename(tplname),
'img' : 'pictograms-nps-misc-camera.png', 'img': 'pictograms-nps-misc-camera.png',
'headline' : u'Überschrift', 'headline': u'Überschrift',
'text' : u'Dies ist der Text, der in der UI als Text bezeichnet ist.', 'text': u'Dies ist der Text, der in der UI als Text bezeichnet ist.',
}, pdfpath, overwrite=False }, pdfpath, overwrite=False
) )
except Exception as e: except Exception as e:
return str(e) return str(e)
else: else:
thumbpath = make_thumb(pdfpath, maxgeometry) thumbpath = make_thumb(pdfpath, maxgeometry)
with open(thumbpath, 'r') as imgfile: with open(thumbpath, 'r') as imgfile:
return Response(imgfile.read(), mimetype="image/png") return Response(imgfile.read(), mimetype="image/png")
@app.route('/pdfdownload/<pdfname>') @app.route('/pdfdownload/<pdfname>')
def pdfdownload(pdfname): def pdfdownload(pdfname):
pdfpath = os.path.join(config.pdfdir, secure_filename(pdfname)) pdfpath = os.path.join(config.pdfdir, secure_filename(pdfname))
with open(pdfpath, 'r') as pdffile: with open(pdfpath, 'r') as pdffile:
return Response(pdffile.read(), mimetype="application/pdf") return Response(pdffile.read(), mimetype="application/pdf")
if __name__ == '__main__': if __name__ == '__main__':
app.debug = True app.debug = True
app.run(host=config.listen, port=config.port) app.run(host=config.listen, port=config.port)
...@@ -23,6 +23,9 @@ body > a { ...@@ -23,6 +23,9 @@ body > a {
img.bigpreview { img.bigpreview {
width: 100%; width: 100%;
} }
.box {
width: 95%;
}
} }
body > *, form > * { body > *, form > * {
display: block; display: block;
...@@ -133,3 +136,10 @@ textarea { ...@@ -133,3 +136,10 @@ textarea {
margin: 0.3em 0; margin: 0.3em 0;
background: #eee linear-gradient(to bottom, #fff 0%,#eee 0.5em,#eee 92%,#e6e6e6 100%); background: #eee linear-gradient(to bottom, #fff 0%,#eee 0.5em,#eee 92%,#e6e6e6 100%);
} }
label {
line-height: 1.8em;
}
.box label+select {
height: initial;
float: right;
}
\ No newline at end of file
...@@ -44,6 +44,18 @@ ...@@ -44,6 +44,18 @@
</div> </div>
<div class="box"> <div class="box">
<label for="form:text">Text</label> <label for="form:text">Text</label>
<select name="markup">
<py:choose>
<py:when test="not defined('form') or form.markup == 'rst' or form.markup == ''">
<option value="latex">LaTeX</option>
<option value="rst" selected="True">Wiki (reStructuredText)</option>
</py:when>
<py:when test="defined('form') and form.markup == 'latex'">
<option value="latex" selected="True">LaTeX</option>
<option value="rst">Wiki (reStructuredText)</option>
</py:when>
</py:choose>
</select>
<textarea name="text" id="form:text" cols="35" rows="5"><py:if test="defined('form')">${form.text}</py:if></textarea> <textarea name="text" id="form:text" cols="35" rows="5"><py:if test="defined('form')">${form.text}</py:if></textarea>
</div><br/> </div><br/>
<div class="box"> <div class="box">
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment