def _render(self, tokens, idx, options, env): token = tokens[idx] info = unescapeAll(token.info).strip() if token.info else "" content = escapeHtml(token.content) block_name = "" if info: block_name = info.split()[0] return ("<pre><code" + (f' class="block-{block_name}" ' if block_name else "") + ">" + content + "</code></pre>\n")
def fence(self, tokens, idx, options, env): token = tokens[idx] # TODO : Later, add correct highlights for languages # info = unescapeAll(token.info).strip() if token.info else "" # langName = "" # if info: # langName = info.split()[0] highlighted = escapeHtml(token.content) if token.attrs: return pre(code(highlighted), **token.attr) else: return pre(code(highlighted))
def _render(self, tokens, options, env): """ Recursive function parsing each token into the right Dominate tag. """ pending_tags = [] pending_content = [[]] for t, token in enumerate(tokens): if token.type == "fence": # Special case pending_content[-1].append(self.fence(tokens, t, options, env)) elif token.tag != "": if not token.nesting: # Directly append to content c = [token.content] if token.content else [] tag = getattr(dominate.tags, token.tag) tag = tag( *c) if token.attrs is None else tag(*c, **token.attrs) pending_content[-1].append(tag) elif len(pending_tags) > 0 and pending_tags[ -1] == token.tag: # Closing tag t = pending_tags.pop() c = pending_content.pop() tag = getattr(dominate.tags, t) tag = tag(c) if token.attrs is None else tag( c, **token.attrs) pending_content[-1].append(tag) else: # Opening tag if token.tag == "p" and len( pending_tags) > 0 and pending_tags[-1] == "li": continue pending_tags.append(token.tag) pending_content.append([]) elif token.children is not None: assert len(token.children) > 0 pending_content[-1].extend( self._render(token.children, options, env)) else: if not token.hidden: pending_content[-1].append(escapeHtml(token.content)) assert len(pending_tags) == 0, pending_tags assert len(pending_content) == 1, pending_content return pending_content[-1]
def amsmath_plugin(md: MarkdownIt, *, renderer: Optional[Callable[[str], str]] = None): """Parses TeX math equations, without any surrounding delimiters, only for top-level `amsmath <https://ctan.org/pkg/amsmath>`__ environments: .. code-block:: latex \\begin{gather*} a_1=b_1+c_1\\\\ a_2=b_2+c_2-d_2+e_2 \\end{gather*} :param renderer: Function to render content, by default escapes HTML """ md.block.ruler.before( "blockquote", "amsmath", amsmath_block, { "alt": ["paragraph", "reference", "blockquote", "list", "footnote_def"] }, ) if renderer is None: _renderer = lambda content: escapeHtml(content) else: _renderer = renderer def render_amsmath_block(self, tokens, idx, options, env): content = _renderer(str(tokens[idx].content)) return f'<div class="math amsmath">\n{content}\n</div>\n' md.add_render_rule("amsmath", render_amsmath_block)
def render_autolink(self, token): refuri = target = escapeHtml(token.attrGet("href")) ref_node = nodes.reference(target, target, refuri=refuri) self.add_line_and_source_path(ref_node, token) self.current_node.append(ref_node)
def dollarmath_plugin( md: MarkdownIt, *, allow_labels: bool = True, allow_space: bool = True, allow_digits: bool = True, double_inline: bool = False, label_normalizer: Optional[Callable[[str], str]] = None, renderer: Optional[Callable[[str, Dict[str, Any]], str]] = None, label_renderer: Optional[Callable[[str], str]] = None, ) -> None: """Plugin for parsing dollar enclosed math, e.g. inline: ``$a=1$``, block: ``$$b=2$$`` This is an improved version of ``texmath``; it is more performant, and handles ``\\`` escaping properly and allows for more configuration. :param allow_labels: Capture math blocks with label suffix, e.g. ``$$a=1$$ (eq1)`` :param allow_space: Parse inline math when there is space after/before the opening/closing ``$``, e.g. ``$ a $`` :param allow_digits: Parse inline math when there is a digit before/after the opening/closing ``$``, e.g. ``1$`` or ``$2``. This is useful when also using currency. :param double_inline: Search for double-dollar math within inline contexts :param label_normalizer: Function to normalize the label, by default replaces whitespace with `-` :param renderer: Function to render content: `(str, {"display_mode": bool}) -> str`, by default escapes HTML :param label_renderer: Function to render labels, by default creates anchor """ if label_normalizer is None: label_normalizer = lambda label: re.sub(r"\s+", "-", label) md.inline.ruler.before( "escape", "math_inline", math_inline_dollar(allow_space, allow_digits, double_inline), ) md.block.ruler.before("fence", "math_block", math_block_dollar(allow_labels, label_normalizer)) # TODO the current render rules are really just for testing # would be good to allow "proper" math rendering, # e.g. https://github.com/roniemartinez/latex2mathml if renderer is None: _renderer = lambda content, _: escapeHtml(content) else: _renderer = renderer if label_renderer is None: _label_renderer = ( lambda label: f'<a href="#{label}" class="mathlabel" title="Permalink to this equation">¶</a>' # noqa: E501 ) else: _label_renderer = label_renderer def render_math_inline(self, tokens, idx, options, env) -> str: content = _renderer( str(tokens[idx].content).strip(), {"display_mode": False}) return f'<span class="math inline">{content}</span>' def render_math_inline_double(self, tokens, idx, options, env) -> str: content = _renderer( str(tokens[idx].content).strip(), {"display_mode": True}) return f'<div class="math inline">{content}</div>' def render_math_block(self, tokens, idx, options, env) -> str: content = _renderer( str(tokens[idx].content).strip(), {"display_mode": True}) return f'<div class="math block">\n{content}\n</div>\n' def render_math_block_label(self, tokens, idx, options, env) -> str: content = _renderer( str(tokens[idx].content).strip(), {"display_mode": True}) _id = tokens[idx].info label = _label_renderer(tokens[idx].info) return f'<div id="{_id}" class="math block">\n{label}\n{content}\n</div>\n' md.add_render_rule("math_inline", render_math_inline) md.add_render_rule("math_inline_double", render_math_inline_double) md.add_render_rule("math_block", render_math_block) md.add_render_rule("math_block_label", render_math_block_label)
def render_autolink(self, token: SyntaxTreeNode) -> None: refuri = target = escapeHtml(token.attrGet("href") or "") # type: ignore[arg-type] ref_node = nodes.reference(target, target, refuri=refuri) self.add_line_and_source_path(ref_node, token) self.current_node.append(ref_node)