1
0
Fork 0
forked from github/pelican
pelican-theme/pelican/rstdirectives.py
2023-10-29 22:18:29 +01:00

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)