import re from typing import TYPE_CHECKING, Match, Optional, Pattern from ..helpers import PREVENT_BACKSLASH if TYPE_CHECKING: from ..core import BaseRenderer, InlineState from ..inline_parser import InlineParser from ..markdown import Markdown __all__ = ["strikethrough", "mark", "insert", "superscript", "subscript"] _STRIKE_END = re.compile(r"(?:" + PREVENT_BACKSLASH + r"\\~|[^\s~])~~(?!~)") _MARK_END = re.compile(r"(?:" + PREVENT_BACKSLASH + r"\\=|[^\s=])==(?!=)") _INSERT_END = re.compile(r"(?:" + PREVENT_BACKSLASH + r"\\\^|[^\s^])\^\^(?!\^)") SUPERSCRIPT_PATTERN = r"\^(?:" + PREVENT_BACKSLASH + r"\\\^|\S|\\ )+?\^" SUBSCRIPT_PATTERN = r"~(?:" + PREVENT_BACKSLASH + r"\\~|\S|\\ )+?~" def parse_strikethrough(inline: "InlineParser", m: Match[str], state: "InlineState") -> Optional[int]: return _parse_to_end(inline, m, state, "strikethrough", _STRIKE_END) def render_strikethrough(renderer: "BaseRenderer", text: str) -> str: return "" + text + "" def parse_mark(inline: "InlineParser", m: Match[str], state: "InlineState") -> Optional[int]: return _parse_to_end(inline, m, state, "mark", _MARK_END) def render_mark(renderer: "BaseRenderer", text: str) -> str: return "" + text + "" def parse_insert(inline: "InlineParser", m: Match[str], state: "InlineState") -> Optional[int]: return _parse_to_end(inline, m, state, "insert", _INSERT_END) def render_insert(renderer: "BaseRenderer", text: str) -> str: return "" + text + "" def parse_superscript(inline: "InlineParser", m: Match[str], state: "InlineState") -> int: return _parse_script(inline, m, state, "superscript") def render_superscript(renderer: "BaseRenderer", text: str) -> str: return "" + text + "" def parse_subscript(inline: "InlineParser", m: Match[str], state: "InlineState") -> int: return _parse_script(inline, m, state, "subscript") def render_subscript(renderer: "BaseRenderer", text: str) -> str: return "" + text + "" def _parse_to_end( inline: "InlineParser", m: Match[str], state: "InlineState", tok_type: str, end_pattern: Pattern[str], ) -> Optional[int]: pos = m.end() m1 = end_pattern.search(state.src, pos) if not m1: return None end_pos = m1.end() text = state.src[pos : end_pos - 2] new_state = state.copy() new_state.src = text children = inline.render(new_state) state.append_token({"type": tok_type, "children": children}) return end_pos def _parse_script(inline: "InlineParser", m: Match[str], state: "InlineState", tok_type: str) -> int: text = m.group(0) new_state = state.copy() new_state.src = text[1:-1].replace("\\ ", " ") children = inline.render(new_state) state.append_token({"type": tok_type, "children": children}) return m.end() def strikethrough(md: "Markdown") -> None: """A mistune plugin to support strikethrough. Spec defined by GitHub flavored Markdown and commonly used by many parsers: .. code-block:: text ~~This was mistaken text~~ It will be converted into HTML: .. code-block:: html This was mistaken text :param md: Markdown instance """ md.inline.register( "strikethrough", r"~~(?=[^\s~])", parse_strikethrough, before="link", ) if md.renderer and md.renderer.NAME == "html": md.renderer.register("strikethrough", render_strikethrough) def mark(md: "Markdown") -> None: """A mistune plugin to add ```` tag. Spec defined at https://facelessuser.github.io/pymdown-extensions/extensions/mark/: .. code-block:: text ==mark me== ==mark \\=\\= equal== :param md: Markdown instance """ md.inline.register( "mark", r"==(?=[^\s=])", parse_mark, before="link", ) if md.renderer and md.renderer.NAME == "html": md.renderer.register("mark", render_mark) def insert(md: "Markdown") -> None: """A mistune plugin to add ```` tag. Spec defined at https://facelessuser.github.io/pymdown-extensions/extensions/caret/#insert: .. code-block:: text ^^insert me^^ :param md: Markdown instance """ md.inline.register( "insert", r"\^\^(?=[^\s\^])", parse_insert, before="link", ) if md.renderer and md.renderer.NAME == "html": md.renderer.register("insert", render_insert) def superscript(md: "Markdown") -> None: """A mistune plugin to add ```` tag. Spec defined at https://pandoc.org/MANUAL.html#superscripts-and-subscripts: .. code-block:: text 2^10^ is 1024. :param md: Markdown instance """ md.inline.register("superscript", SUPERSCRIPT_PATTERN, parse_superscript, before="linebreak") if md.renderer and md.renderer.NAME == "html": md.renderer.register("superscript", render_superscript) def subscript(md: "Markdown") -> None: """A mistune plugin to add ```` tag. Spec defined at https://pandoc.org/MANUAL.html#superscripts-and-subscripts: .. code-block:: text H~2~O is a liquid. :param md: Markdown instance """ md.inline.register("subscript", SUBSCRIPT_PATTERN, parse_subscript, before="linebreak") if md.renderer and md.renderer.NAME == "html": md.renderer.register("subscript", render_subscript)