| 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 "<del>" + text + "</del>" |
|
|
|
|
| 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 "<mark>" + text + "</mark>" |
|
|
|
|
| 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 "<ins>" + text + "</ins>" |
|
|
|
|
| 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 "<sup>" + text + "</sup>" |
|
|
|
|
| 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 "<sub>" + text + "</sub>" |
|
|
|
|
| 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 |
| |
| <del>This was mistaken text</del> |
| |
| :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 ``<mark>`` 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 ``<ins>`` 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 ``<sup>`` 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 ``<sub>`` 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) |
|
|