4:copyright: Copyright 2019 by Taler Systems SA
11from pathlib
import Path
13from docutils
import nodes
14from typing
import List, Optional, Iterable, Dict, Tuple
15from typing
import cast
17from pygments.lexers
import get_lexer_by_name
18from pygments.filter
import Filter
19from pygments.token import Literal, Text, Operator, Keyword, Name, Number
22from pygments.lexer
import RegexLexer, bygroups, include
23from pygments.formatters
import HtmlFormatter
25from docutils
import nodes
26from docutils.nodes
import Element, Node
28from sphinx.roles
import XRefRole
29from sphinx.domains
import Domain, ObjType, Index
30from sphinx.directives
import directives
31from sphinx.util.docutils
import SphinxDirective
32from sphinx.util.nodes
import make_refnode
33from sphinx.util
import logging
34from sphinx.highlighting
import PygmentsBridge
35from sphinx.builders.html
import StandaloneHTMLBuilder
36from sphinx.pygments_styles
import SphinxStyle
38logger = logging.getLogger(__name__)
43 Directive for a code block
with special highlighting
or line numbering
48 required_arguments = 1
49 optional_arguments = 0
50 final_argument_whitespace =
False
52 "force": directives.flag,
53 "linenos": directives.flag,
56 "emphasize-lines": directives.unchanged_required,
57 "caption": directives.unchanged_required,
58 "class": directives.class_option,
61 def run(self) -> List[Node]:
62 document = self.state.document
63 code =
"\n".join(self.content)
64 location = self.state_machine.get_source_and_line(self.lineno)
66 linespec = self.options.
get(
"emphasize-lines")
69 nlines = len(self.content)
70 hl_lines = parselinenos(linespec, nlines)
71 if any(i >= nlines
for i
in hl_lines):
73 __(
"line number spec is out of range(1-%d): %r")
74 % (nlines, self.options[
"emphasize-lines"]),
78 hl_lines = [x + 1
for x
in hl_lines
if x < nlines]
79 except ValueError
as err:
80 return [document.reporter.warning(err, line=self.lineno)]
84 if "dedent" in self.options:
85 location = self.state_machine.get_source_and_line(self.lineno)
86 lines = code.split(
"\n")
87 lines = dedent_lines(lines, self.options[
"dedent"], location=location)
88 code =
"\n".join(lines)
90 literal = nodes.literal_block(code, code)
91 if "linenos" in self.options
or "lineno-start" in self.options:
92 literal[
"linenos"] =
True
93 literal[
"classes"] += self.options.
get(
"class", [])
94 literal[
"force"] =
"force" in self.options
95 literal[
"language"] =
"tsref"
96 extra_args = literal[
"highlight_args"] = {}
97 if hl_lines
is not None:
98 extra_args[
"hl_lines"] = hl_lines
99 if "lineno-start" in self.options:
100 extra_args[
"linenostart"] = self.options[
"lineno-start"]
101 self.set_source_info(literal)
103 caption = self.options.
get(
"caption")
106 literal = container_wrapper(self, literal, caption)
107 except ValueError
as exc:
108 return [document.reporter.warning(exc, line=self.lineno)]
110 tsid =
"tsref-type-" + self.arguments[0]
111 literal[
"ids"].append(tsid)
113 tsname = self.arguments[0]
114 ts = self.env.get_domain(
"ts")
115 ts.add_object(
"type", tsname, self.env.docname, tsid)
121 """TypeScript domain."""
127 "def": TypeScriptDefinition,
132 lowercase=
False, warn_dangling=
True, innernodeclass=nodes.inline
136 dangling_warnings = {
137 "type":
"undefined TypeScript type: %(target)s",
140 def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode):
144 logger.warn(
"type {}/{} not found".format(typ, target))
147 anchor =
"tsref-type-{}".format(str(target))
148 title = typ.upper() +
" " + target
149 return make_refnode(builder, fromdocname, info[0], anchor, contnode, title)
152 """Resolve the pending_xref *node* with the given *target*.
154 The reference comes from an
"any" or similar role, which means that Sphinx
157 For now sphinxcontrib-httpdomain doesn't resolve any xref nodes.
160 list of tuples ``(
'domain:role', newnode)``, where ``
'domain:role'``
161 is the name of a role that could have created the same reference,
169 anchor =
"tsref-type-{}".format(str(target))
170 title =
"TYPE" +
" " + target
171 node = make_refnode(builder, fromdocname, info[0], anchor, contnode, title)
172 ret.append((
"ts:type", node))
176 def objects(self) -> Dict[Tuple[str, str], Tuple[str, str]]:
177 return self.data.setdefault(
181 def add_object(self, objtype: str, name: str, docname: str, labelid: str) ->
None:
187 For `TypeScript <https://www.typescriptlang.org/>`_ source code.
193 mimetypes = [
"text/x-typescript"]
197 "commentsandwhitespace": [
200 (
r"//.*?\n", Comment.Single),
201 (
r"/\*.*?\*/", Comment.Multiline),
203 "slashstartsregex": [
204 include(
"commentsandwhitespace"),
206 r"/(\\.|[^[/\\\n]|\[(\\.|[^\]\\\n])*])+/" r"([gim]+\b|\B)",
210 (
r"(?=/)", Text, (
"#pop",
"badregex")),
213 "badregex": [(
r"\n", Text,
"#pop")],
215 (
r"[a-zA-Z0-9_?.$]+", Keyword.Type),
218 (
r"\n", Text,
"#pop"),
219 (
r";", Text,
"#pop"),
223 (
r"^(?=\s|/|<!--)", Text,
"slashstartsregex"),
224 include(
"commentsandwhitespace"),
226 r"\+\+|--|~|&&|\?|:|\|\||\\(?=\n)|"
227 r"(<<|>>>?|==?|!=?|[-<>+*%&\|\^/])=?",
231 (
r"[{(\[;,]", Punctuation,
"slashstartsregex"),
232 (
r"[})\].]", Punctuation),
234 r"(for|in|while|do|break|return|continue|switch|case|default|if|else|"
235 r"throw|try|catch|finally|new|delete|typeof|instanceof|void|"
241 r"(var|let|const|with|function)\b",
246 r"(abstract|boolean|byte|char|class|const|debugger|double|enum|export|"
247 r"extends|final|float|goto|implements|import|int|interface|long|native|"
248 r"package|private|protected|public|short|static|super|synchronized|throws|"
249 r"transient|volatile)\b",
252 (
r"(true|false|null|NaN|Infinity|undefined)\b", Keyword.Constant),
254 r"(Array|Boolean|Date|Error|Function|Math|netscape|"
255 r"Number|Object|Packages|RegExp|String|sun|decodeURI|"
256 r"decodeURIComponent|encodeURI|encodeURIComponent|"
257 r"Error|eval|isFinite|isNaN|parseFloat|parseInt|document|this|"
263 r"\b(module)(\s*)(\s*[a-zA-Z0-9_?.$][\w?.$]*)(\s*)",
264 bygroups(Keyword.Reserved, Text, Name.Other, Text),
268 (
r"\b(string|bool|number)\b", Keyword.Type),
270 (
r"\b(constructor|declare|interface|as|AS)\b", Keyword.Reserved),
273 r"(super)(\s*)\(([a-zA-Z0-9,_?.$\s]+\s*)\)",
274 bygroups(Keyword.Reserved, Text),
278 (
r"([a-zA-Z_?.$][\w?.$]*)\(\) \{", Name.Other,
"slashstartsregex"),
281 r"([a-zA-Z0-9_?.$][\w?.$]*)(\s*:\s*)",
282 bygroups(Name.Other, Text),
287 r"\b(type)(\s*)([a-zA-Z0-9_?.$]+)(\s*)(=)(\s*)",
288 bygroups(Keyword.Reserved, Text, Name.Other, Text, Operator, Text),
291 (
r"[$a-zA-Z_][a-zA-Z0-9_]*", Name.Other),
292 (
r"[0-9][0-9]*\.[0-9]+([eE][0-9]+)?[fd]?", Number.Float),
293 (
r"0x[0-9a-fA-F]+", Number.Hex),
294 (
r"[0-9]+", Number.Integer),
295 (
r'"(\\\\|\\"|[^"])*"', String.Double),
296 (
r"'(\\\\|\\'|[^'])*'", String.Single),
310 Filter.__init__(self, **options)
314 for m
in re.finditer(literal_reg, value):
315 pre = value[last : m.start()]
327 for ttype, value
in stream:
328 if ttype
in Token.Keyword.Type:
333 elif ttype
in Token.Comment:
335 for m
in re.finditer(link_reg, value):
336 pre = value[last : m.start()]
361_escape_html_table = {
372 super(LinkingHtmlFormatter, self).
__init__(**kwargs)
381 return '<span style="font-weight: bolder">%s</span>' % (value,)
385 "{}:{}: code block contains xref to '{}' with unsupported trailing underscore".format(
391 if xref.startswith(
'"'):
393 if re.match(
"^[0-9]+$", xref)
is not None:
410 if self.
_bridge.docname
is None:
414 content = caption
if caption
is not None else value
415 ts = self.
_builder.env.get_domain(
"ts")
416 r1 = ts.objects.get((
"type", xref),
None)
424 '<a style="color:inherit;text-decoration:underline" href="%s">%s</a>'
428 std = self.
_builder.env.get_domain(
"std")
429 r2 = std.labels.get(xref.lower(),
None)
437 '<a style="color:inherit;text-decoration:underline" href="%s">%s</a>'
440 r3 = std.anonlabels.get(xref.lower(),
None)
448 '<a style="color:inherit;text-decoration:underline" href="%s">%s</a>'
453 "{}:{}: code block contains unresolved xref '{}'".format(
461 cls = self._get_css_class(tok)
463 if cls
is None or cls ==
"":
465 return '<span class="%s">%s</span>' % (cls, value)
469 Just format the tokens, without any wrapping tags.
470 Yield individual lines.
472 lsep = self.lineseparator
473 escape_table = _escape_html_table
476 for ttype, value
in tokensource:
479 parts = value.translate(escape_table).split(
"\n")
484 elif len(parts) == 1:
486 line += self.
_fmt_fmt(parts[0], ttype)
488 line += self.
_fmt_fmt(parts[0], ttype)
490 for part
in parts[1:-1]:
491 yield 1, self.
_fmt_fmt(part, ttype) + lsep
492 line = self.
_fmt_fmt(parts[-1], ttype)
503 "style": SphinxStyle,
514 self, source, lang, opts=None, force=False, location=None, **kwargs
516 if isinstance(location, tuple):
517 docname, line = location
521 elif isinstance(location, Element):
522 self.
line = location.line
523 self.
path = location.source
525 return super().
highlight_block(source, lang, opts, force, location, **kwargs)
532 if self.config.pygments_style
is not None:
533 style = self.config.pygments_style
535 style = self.theme.get_confstr(
"theme",
"pygments_style",
"none")
543 if not hasattr(tok,
"kv"):
545 return tok.kv.get(key)
549 new_tok = _TokenType(tok)
551 new_tok.subtypes = set(tok.subtypes)
552 new_tok.parent = tok.parent
558 e = token_props.get(tokid)
560 e = token_props[tokid] = (tok, {})
567 e = token_props.get(tokid)
574link_reg = re.compile(
r"(?<!`)`([^`<]+)\s*(?:<([^>]+)>)?\s*`_?")
575literal_reg = re.compile(
r"``([^`]+)``")
581 def __init__(self, **options):
582 super().__init__(**options)
585 app.add_lexer(
"tsref", TsrefLexer)
586 app.add_domain(TypeScriptDomain)
587 app.add_builder(MyHtmlBuilder)
def __init__(self, app, **options)
def _filter_one_literal(self, ttype, value)
def filter(self, lexer, stream)
def __init__(self, **kwargs)
def _fmt(self, value, tok)
def _get_value(self, value, tok)
def _format_lines(self, tokensource)
def init_highlighter(self)
def __init__(self, builder, trim_doctest_flags)
def highlight_block(self, source, lang, opts=None, force=False, location=None, **kwargs)
def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode)
def resolve_any_xref(self, env, fromdocname, builder, target, node, contnode)
Dict[Tuple[str, str], Tuple[str, str]] objects(self)
None add_object(self, str objtype, str name, str docname, str labelid)
static int get
Get DID Documement for DID Flag.
static struct GNUNET_IDENTITY_Handle * id
Handle to IDENTITY.
def get_annotation(tok, key)
def tok_setprop(tok, key, value)
def tok_getprop(tok, key)