# -*- coding: utf-8 -*-
"""
###################
Pygments Formatters
###################
Modified Pygments formatters.
"""
from __future__ import print_function
import os
import os.path
from pygments.token import Token
from pygments.formatters.html import HtmlFormatter, _escape_html_table
from django.core.validators import URLValidator, ValidationError
url_validator = URLValidator()
class HtmlLinkifyFormatter(HtmlFormatter):
"""Add anchor tags to hyperlinks in code."""
def _format_lines(self, tokensource):
"""
Just format the tokens, without any wrapping tags.
Yield individual lines.
"""
nocls = self.noclasses
lsep = self.lineseparator
# for <span style=""> lookup only
getcls = self.ttype2class.get
c2s = self.class2style
escape_table = _escape_html_table
tagsfile = self.tagsfile
lspan = ''
line = []
for ttype, value in tokensource:
if nocls:
cclass = getcls(ttype)
while cclass is None:
ttype = ttype.parent
cclass = getcls(ttype)
cspan = cclass and '<span style="%s">' % c2s[cclass][0] or ''
else:
cls = self._get_css_classes(ttype)
cspan = cls and '<span class="%s">' % cls or ''
parts = value.translate(escape_table).split('\n')
# ================================================================
# MODIFIED
# ================================================================
# Make URLs clickable
# ====================
#
# Converts valid urls to::
#
# <a href="{{ url }}">
# "<span class="hyperlink">{{ url }}</span>"
# </a>
#
if ttype == Token.Literal.String.Double:
v = value.strip('"')
try:
url_validator(v)
parts = [('<a href=\'%s\'>'
'"<span class="hyperlink">%s</span>"'
'</a>') % (v, v.translate(escape_table))]
except ValidationError:
pass
# ================================================================
if tagsfile and ttype in Token.Name:
filename, linenumber = self._lookup_ctag(value)
if linenumber:
base, filename = os.path.split(filename)
if base:
base += '/'
filename, extension = os.path.splitext(filename)
url = self.tagurlformat % {'path': base, 'fname': filename,
'fext': extension}
parts[0] = "<a href=\"%s#%s-%d\">%s" % \
(url, self.lineanchors, linenumber, parts[0])
parts[-1] = parts[-1] + "</a>"
# for all but the last line
for part in parts[:-1]:
if line:
# print(line)
if lspan != cspan:
line.extend(((lspan and '</span>'), cspan, part,
(cspan and '</span>'), lsep))
else: # both are the same
line.extend((part, (lspan and '</span>'), lsep))
# out = 1, ''.join(line)
yield 1, ''.join(line)
line = []
elif part:
yield 1, ''.join((cspan, part, (cspan and '</span>'),
lsep))
else:
yield 1, lsep
# for the last line
if line and parts[-1]:
if lspan != cspan:
line.extend(((lspan and '</span>'), cspan, parts[-1]))
lspan = cspan
else:
line.append(parts[-1])
elif parts[-1]:
line = [cspan, parts[-1]]
lspan = cspan
# else we neither have to open a new span nor set lspan
if line:
line.extend(((lspan and '</span>'), lsep))
yield 1, ''.join(line)