import datetime import random from flask import Blueprint, current_app, render_template, request, session, redirect, url_for, abort try: import markdown has_markdown = True except ImportError: has_markdown = False import pygments from pygments import highlight from pygments.lexers import get_all_lexers, get_lexer_by_name from pygments.formatters import HtmlFormatter from . import db app = Blueprint('pastepy', __name__) base62_alphabet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' class PasteError(Exception): pass class UnknownSyntaxError(PasteError): pass class CustomHtmlFormatter(HtmlFormatter): def wrap(self, source, outfile): yield 0, '
'
line = 1
for i, t in source:
if i == 1:
yield i, '{}'.format(line, t)
line += 1
else:
yield i, t
yield 0, '
'
def init_lexers():
all_lexers = dict([(x[0], x[1][0] if x[1] else x[0]) for x in get_all_lexers()])
lexers = []
removed = []
for cat, ls in current_app.config['CATEGORIES']:
for l in ls:
removed.append(l)
lexers.append((cat, [(x, all_lexers[x]) for x in ls if x in all_lexers]))
for l in removed:
try:
del all_lexers[l]
except KeyError:
pass
rendered = []
if has_markdown:
rendered.append(('Rendered markdown', 'md-render'))
if len(rendered):
lexers.append(('Rendered', rendered))
lexers.append(('Others' if current_app.config['CATEGORIES'] else 'Syntax', sorted(all_lexers.items(), key = lambda l: l[0].lower())))
current_app.config['LEXERS'] = lexers
current_app.config['FORMATTER'] = CustomHtmlFormatter(linenos='table', lineanchors='line', anchorlinenos=True)
init_lexers()
@app.route('/')
@app.route('/paste')
def paste():
context = {
'title': 'New paste',
}
return render_template('paste.html', **context)
def get_formatted(syntax, text):
if syntax == 'md-render' and has_markdown:
text = markdown.markdown(text, extensions=current_app.config['MARKDOWN_EXTENSIONS'])
lexername = 'Rendered markdown'
else:
try:
lex = get_lexer_by_name(syntax or 'text')
except pygments.util.ClassNotFound:
raise UnknownSyntaxError(syntax)
lexername = lex.name
text = highlight(text, lex, current_app.config['FORMATTER'])
return (lexername, text)
def add_paste():
nick = request.form.get('nick')
syntax = request.form.get('syntax')
title = request.form.get('title')
text = request.form.get('text').replace('\r', '')
with db.session_scope() as db_session:
paste_hash = ''.join(random.choice(base62_alphabet) for x in range(5))
paste = db.Paste(paste_hash, nick, datetime.datetime.utcnow(), syntax, title, text, request.remote_addr)
db_session.add(paste)
if 'remember_me' in request.form:
session['nick'] = nick
else:
session.pop('nick', None)
if 'remember_syntax' in request.form:
session['syntax'] = syntax
else:
session.pop('syntax', None)
return redirect(url_for('.view_paste', paste_hash=paste_hash))
def render_preview():
try:
lexername, text = get_formatted(request.form['syntax'], request.form['text'])
except UnknownSyntaxError:
abort(500, 'Could not find lexer "{}".'.format(request.form['syntax']))
nick = request.form['nick'] or 'Anonymous'
title = request.form['title'] or 'Untitled'
return render_template('view.html',
title='Preview',
hash=None,
nick=nick,
date='{} UTC'.format(datetime.datetime.utcnow().ctime()),
syntax=lexername,
pastetitle=title,
text=text,
rendered=(lexername or '').startswith('Rendered '),
)
@app.route('/paste', methods=['POST'])
def post_paste():
if request.form['type'] == 'Preview':
return render_preview()
if request.form['type'] == 'Paste':
return add_paste()
abort(404)
@app.route('/view/