Automatically choose renderer according to Accept header.

This commit is contained in:
Julien Palard 2023-04-21 11:01:45 +02:00
parent a2dad29337
commit bc75975da3
Signed by: mdk
GPG Key ID: 0EFC1AC1006886F8
6 changed files with 60 additions and 79 deletions

View File

@ -1,22 +0,0 @@
from django.template import RequestContext
from django.http import HttpResponse
from django.template import loader
from pygments import highlight
from pygments.lexers import get_lexer_by_name
from pygments.formatters import HtmlFormatter
def render_pygments(request, paste, data):
"""Renders Pygments template."""
lexer = get_lexer_by_name(paste.language.slug)
formatter = HtmlFormatter(style="emacs")
highlighted_content = highlight(paste.content, lexer, formatter)
data["paste"] = paste
data["highlighted"] = highlighted_content
rendered = loader.render_to_string("paste/show-pygments.html", data, request)
return HttpResponse(rendered)
def render_raw(request, paste, data):
"""Renders RAW content."""
return HttpResponse(paste.content, content_type="text/plain")

View File

@ -8,7 +8,7 @@ Et Paf.
Ce « pastebin-like » ne peut être utilisé qu'en ligne de commande, soit avec <tt>curl</tt> : Ce « pastebin-like » ne peut être utilisé qu'en ligne de commande, soit avec <tt>curl</tt> :
<div class="highlight"><pre><span></span>curl {{ absolute_index_url }} <span class="o">-F</span>python<span class="o">=</span>@hello.py <div class="highlight"><pre><span></span>curl {{ request.build_absolute_uri }} <span class="o">-F</span>python<span class="o">=</span>@hello.py
</pre></div> </pre></div>
<p>Le nom, entre <tt>-F</tt> et <tt>=</tt> sert à choisir la coloration syntaxique.</p> <p>Le nom, entre <tt>-F</tt> et <tt>=</tt> sert à choisir la coloration syntaxique.</p>
@ -17,13 +17,13 @@ Ce « pastebin-like » ne peut être utilisé qu'en ligne de commande, soit av
<div class="highlight"><pre><span></span>pafpy<span class="o">()</span> <div class="highlight"><pre><span></span>pafpy<span class="o">()</span>
<span class="o">{</span> <span class="o">{</span>
curl {{absolute_index_url}} -F<span class="s2">&quot;</span><span class="si">${</span><span class="nv">1</span><span class="p">##*.</span><span class="si">}</span><span class="s2">=@</span><span class="nv">$1</span><span class="s2">&quot;</span> curl {{request.build_absolute_uri}} -F<span class="s2">&quot;</span><span class="si">${</span><span class="nv">1</span><span class="p">##*.</span><span class="si">}</span><span class="s2">=@</span><span class="nv">$1</span><span class="s2">&quot;</span>
<span class="o">}</span> <span class="o">}</span>
</pre></div> </pre></div>
Demo : Demo :
<div class="highlight"><pre><span></span>$ pafpy test.py <div class="highlight"><pre><span></span>$ pafpy test.py
{{absolute_index_url}}D91F1CA {{request.build_absolute_uri}}D91F1CA
</pre></div> </pre></div>
{% endblock %} {% endblock %}

View File

@ -1,6 +1,6 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block extrastyle %} {% block extrastyle %}
<link href="/static/css//pasteque.css" rel="stylesheet"> <link href="/static/css/pasteque.css" rel="stylesheet">
{% endblock %} {% endblock %}
{% block title %}{{ slug }}{% endblock %} {% block title %}{{ slug }}{% endblock %}

View File

@ -7,7 +7,5 @@ from webtools import settings
urlpatterns = [ urlpatterns = [
path("", views.index, name="index"), path("", views.index, name="index"),
path("static/<path>", serve, {"document_root": settings.STATIC_ROOT}), path("static/<path>", serve, {"document_root": settings.STATIC_ROOT}),
path("paste/<slug:slug>/<renderer>", views.show, name="paste"),
path("paste/<slug:slug>", views.show, name="paste"),
path("<slug>", views.show, name="short_paste"), path("<slug>", views.show, name="short_paste"),
] ]

View File

@ -1,65 +1,72 @@
from . import renderers import json
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.template import RequestContext, loader
from django.urls import reverse from django.urls import reverse
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponseRedirect, HttpResponse
from django.views.decorators.csrf import csrf_exempt from django.views.decorators.csrf import csrf_exempt
from .models import Paste, Language from pygments import highlight
from .forms import PasteForm from pygments.formatters import HtmlFormatter
from pygments.lexers import get_lexer_by_name
from webtools import settings from webtools import settings
from paste.forms import PasteForm
from paste.models import Language, Paste
@csrf_exempt @csrf_exempt
def index(request): def index(request):
"""Displays form.""" """Displays form."""
data = {"menu": "index", "max_characters": settings.PASTE["max_characters"]} if request.method == "GET":
if request.method == "POST": return render(request, "paste/index.html")
paste = Paste() paste = Paste()
paste.choose_slug() paste.choose_slug()
if request.FILES: if request.FILES:
for language_name, any_file in request.FILES.items(): (language_name, the_file), *_ = request.FILES.items()
break language = Language.by_name(language_name)
language = Language.by_name(language_name) form = PasteForm(
form = PasteForm( {
{ "language": language.id,
"language": language.id, "content": the_file.read().decode(),
"content": any_file.read().decode(), },
}, instance=paste,
instance=paste,
)
else:
form = PasteForm(request.POST, instance=paste)
if not form.is_valid():
data["form"] = form
return render(request, "paste/index.html", data)
form.save() # Some logic added to overrided method, see forms.py
location = request.build_absolute_uri(
reverse("short_paste", kwargs={"slug": paste.slug})
) )
return HttpResponseRedirect( if not form.is_valid():
location, content=location + "\n", content_type="text/plain" return HttpResponse(json.dumps(form.errors, indent=4))
) form.save()
data["form"] = PasteForm( location = request.build_absolute_uri(
initial={ reverse("short_paste", kwargs={"slug": paste.slug})
"language": Language.by_name(settings.PASTE["default_language"]).id, )
} return HttpResponseRedirect(
location, content=location + "\n", content_type="text/plain"
) )
data["absolute_index_url"] = request.build_absolute_uri(reverse("index"))
return render(request, "paste/index.html", data)
def show(request, slug, renderer="pygments"): def show(request, slug):
"""Display paste.""" """Display paste."""
# Fetching object
paste = get_object_or_404(Paste, slug=slug) paste = get_object_or_404(Paste, slug=slug)
data = {"slug": slug}
# Handling expiration
# Before rendering actions
paste.incr_viewcount() paste.incr_viewcount()
# Handling rendering modes
if not renderer or renderer not in settings.PASTE["enabled_renderers"]: if "html" in request.headers["accept"]:
renderer = settings.PASTE["default_renderer"] render_method = render_pygments
data["current_renderer"] = renderer else:
data["renderers"] = settings.PASTE["enabled_renderers"] render_method = render_raw
render_method = getattr(renderers, "render_%s" % renderer) return render_method(request, paste, {"slug": slug})
return render_method(request, paste, data)
def render_pygments(request, paste, data):
"""Renders Pygments template."""
lexer = get_lexer_by_name(paste.language.slug)
formatter = HtmlFormatter(style="emacs")
highlighted_content = highlight(paste.content, lexer, formatter)
data["paste"] = paste
data["highlighted"] = highlighted_content
rendered = loader.render_to_string("paste/show-pygments.html", data, request)
return HttpResponse(rendered)
def render_raw(request, paste, data):
"""Renders RAW content."""
return HttpResponse(paste.content, content_type="text/plain")

View File

@ -92,8 +92,6 @@ INSTALLED_APPS = (
PASTE = { PASTE = {
"has_meta_table": False, "has_meta_table": False,
"enabled_renderers": ["pygments", "raw"],
"default_renderer": "pygments",
"max_characters": 100000, "max_characters": 100000,
"default_language": "Python", "default_language": "Python",
} }