forked from github/pelican
92 lines
2.9 KiB
Python
92 lines
2.9 KiB
Python
import re
|
|
|
|
from docutils import nodes, utils
|
|
from docutils.parsers.rst import Directive, directives, roles
|
|
|
|
from pygments import highlight
|
|
from pygments.formatters import HtmlFormatter
|
|
from pygments.lexers import TextLexer, get_lexer_by_name
|
|
|
|
import pelican.settings as pys
|
|
|
|
|
|
class Pygments(Directive):
|
|
"""Source code syntax highlighting."""
|
|
|
|
required_arguments = 1
|
|
optional_arguments = 0
|
|
final_argument_whitespace = True
|
|
option_spec = {
|
|
"anchorlinenos": directives.flag,
|
|
"classprefix": directives.unchanged,
|
|
"hl_lines": directives.unchanged,
|
|
"lineanchors": directives.unchanged,
|
|
"linenos": directives.unchanged,
|
|
"linenospecial": directives.nonnegative_int,
|
|
"linenostart": directives.nonnegative_int,
|
|
"linenostep": directives.nonnegative_int,
|
|
"lineseparator": directives.unchanged,
|
|
"linespans": directives.unchanged,
|
|
"nobackground": directives.flag,
|
|
"nowrap": directives.flag,
|
|
"tagsfile": directives.unchanged,
|
|
"tagurlformat": directives.unchanged,
|
|
}
|
|
has_content = True
|
|
|
|
def run(self):
|
|
self.assert_has_content()
|
|
try:
|
|
lexer = get_lexer_by_name(self.arguments[0])
|
|
except ValueError:
|
|
# no lexer found - use the text one instead of an exception
|
|
lexer = TextLexer()
|
|
|
|
# Fetch the defaults
|
|
if pys.PYGMENTS_RST_OPTIONS is not None:
|
|
for k, v in pys.PYGMENTS_RST_OPTIONS.items():
|
|
# Locally set options overrides the defaults
|
|
if k not in self.options:
|
|
self.options[k] = v
|
|
|
|
if "linenos" in self.options and self.options["linenos"] not in (
|
|
"table",
|
|
"inline",
|
|
):
|
|
if self.options["linenos"] == "none":
|
|
self.options.pop("linenos")
|
|
else:
|
|
self.options["linenos"] = "table"
|
|
|
|
for flag in ("nowrap", "nobackground", "anchorlinenos"):
|
|
if flag in self.options:
|
|
self.options[flag] = True
|
|
|
|
# noclasses should already default to False, but just in case...
|
|
formatter = HtmlFormatter(noclasses=False, **self.options)
|
|
parsed = highlight("\n".join(self.content), lexer, formatter)
|
|
return [nodes.raw("", parsed, format="html")]
|
|
|
|
|
|
directives.register_directive("code-block", Pygments)
|
|
directives.register_directive("sourcecode", Pygments)
|
|
|
|
|
|
_abbr_re = re.compile(r"\((.*)\)$", re.DOTALL)
|
|
|
|
|
|
class abbreviation(nodes.Inline, nodes.TextElement):
|
|
pass
|
|
|
|
|
|
def abbr_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
|
|
text = utils.unescape(text)
|
|
m = _abbr_re.search(text)
|
|
if m is None:
|
|
return [abbreviation(text, text)], []
|
|
abbr = text[: m.start()].strip()
|
|
expl = m.group(1)
|
|
return [abbreviation(abbr, abbr, explanation=expl)], []
|
|
|
|
|
|
roles.register_local_role("abbr", abbr_role)
|