El resaltado de sintaxis de Django causa problemas de escape de caracteres
Pregunta
He estado trabajando en mi propio blog basado en django (como todos, lo sé) para mejorar mi python, y pensé que agregar algo de resaltado de sintaxis sería bastante bueno. Observé algunos fragmentos y decidí combinar algunos y escribir mi propio filtro de plantilla de resaltado de sintaxis usando Beautiful Soup and Pygments. Se ve así:
from django import template
from BeautifulSoup import BeautifulSoup
import pygments
import pygments.lexers as lexers
import pygments.formatters as formatters
register = template.Library()
@register.filter(name='pygmentize')
def pygmentize(value):
try:
formatter = formatters.HtmlFormatter(style='trac')
tree = BeautifulSoup(value)
for code in tree.findAll('code'):
if not code['class']: code['class'] = 'text'
lexer = lexers.get_lexer_by_name(code['class'])
new_content = pygments.highlight(code.contents[0], lexer, formatter)
new_content += u"<style>%s</style>" % formatter.get_style_defs('.highlight')
code.replaceWith ( "%s\n" % new_content )
content = str(tree)
return content
except KeyError:
return value
Busca un bloque de código como este y resalta y publicita los estilos relevantes:
<code class="python">
print "Hello World"
</code>
Todo esto funcionaba bien hasta que un bloque de código que estaba incluido tenía algo de HTML. Ahora, conozco todo el html que necesito, así que escribo las publicaciones de mi blog directamente en él y, cuando renderizo en la plantilla, marco el cuerpo de la publicación como seguro:
{{ post.body|pygmentize|safe }}
Este enfoque da como resultado que cualquier html en un bloque de código simplemente se represente como html (es decir, no se muestra). He estado jugando con el uso de la función de escape django en el código extraído del cuerpo por mi filtro, pero parece que nunca puedo hacerlo bien. Creo que mi comprensión del contenido que se escapa no es lo suficientemente completa. También he intentado escribir la versión escapada en el cuerpo de la publicación (por ejemplo, & Lt;), pero solo sale como texto.
¿Cuál es la mejor manera de marcar el html para su visualización? ¿Voy a hacer todo esto mal?
Gracias.
Solución
Finalmente encontré algo de tiempo para resolverlo. Cuando una sopa hermosa tira del contenido y contiene una etiqueta, la etiqueta aparece como un subnodo de una lista. Esta línea es la culpable:
new_content = pygments.highlight(code.contents[0], lexer, formatter)
El [0] corta la otra parte del código, no se decodifica incorrectamente. Pobre error manchado de mi parte. Esa línea debe ser reemplazada por:
new_content = pygments.highlight(code.decodeContents(), lexer, formatter)
Las lecciones aquí son para asegurarse de saber cuál es el problema y saber cómo funcionan sus bibliotecas.