Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
replacements.py128 linesDownload Raw Back to rules_core
1"""Simple typographic replacements2 3* ``(c)``, ``(C)`` → ©4* ``(tm)``, ``(TM)`` → ™5* ``(r)``, ``(R)`` → ®6* ``+-`` → ±7* ``...`` → …8* ``?....`` → ?..9* ``!....`` → !..10* ``????????`` → ???11* ``!!!!!`` → !!!12* ``,,,`` → ,13* ``--`` → &ndash14* ``---`` → &mdash15"""16 17from __future__ import annotations18 19import logging20import re21 22from ..token import Token23from .state_core import StateCore24 25LOGGER = logging.getLogger(__name__)26 27# TODO:28# - fractionals 1/2, 1/4, 3/4 -> ½, ¼, ¾29# - multiplication 2 x 4 -> 2 × 430 31RARE_RE = re.compile(r"\+-|\.\.|\?\?\?\?|!!!!|,,|--")32 33# Workaround for phantomjs - need regex without /g flag,34# or root check will fail every second time35# SCOPED_ABBR_TEST_RE = r"\((c|tm|r)\)"36 37SCOPED_ABBR_RE = re.compile(r"\((c|tm|r)\)", flags=re.IGNORECASE)38 39PLUS_MINUS_RE = re.compile(r"\+-")40 41ELLIPSIS_RE = re.compile(r"\.{2,}")42 43ELLIPSIS_QUESTION_EXCLAMATION_RE = re.compile(r"([?!])…")44 45QUESTION_EXCLAMATION_RE = re.compile(r"([?!]){4,}")46 47COMMA_RE = re.compile(r",{2,}")48 49EM_DASH_RE = re.compile(r"(^|[^-])---(?=[^-]|$)", flags=re.MULTILINE)50 51EN_DASH_RE = re.compile(r"(^|\s)--(?=\s|$)", flags=re.MULTILINE)52 53EN_DASH_INDENT_RE = re.compile(r"(^|[^-\s])--(?=[^-\s]|$)", flags=re.MULTILINE)54 55 56SCOPED_ABBR = {"c": "©", "r": "®", "tm": "™"}57 58 59def replaceFn(match: re.Match[str]) -> str:60    return SCOPED_ABBR[match.group(1).lower()]61 62 63def replace_scoped(inlineTokens: list[Token]) -> None:64    inside_autolink = 065 66    for token in inlineTokens:67        if token.type == "text" and not inside_autolink:68            token.content = SCOPED_ABBR_RE.sub(replaceFn, token.content)69 70        if token.type == "link_open" and token.info == "auto":71            inside_autolink -= 172 73        if token.type == "link_close" and token.info == "auto":74            inside_autolink += 175 76 77def replace_rare(inlineTokens: list[Token]) -> None:78    inside_autolink = 079 80    for token in inlineTokens:81        if (82            token.type == "text"83            and (not inside_autolink)84            and RARE_RE.search(token.content)85        ):86            # +- -> ±87            token.content = PLUS_MINUS_RE.sub("±", token.content)88 89            # .., ..., ....... -> …90            token.content = ELLIPSIS_RE.sub("…", token.content)91 92            # but ?..... & !..... -> ?.. & !..93            token.content = ELLIPSIS_QUESTION_EXCLAMATION_RE.sub("\\1..", token.content)94            token.content = QUESTION_EXCLAMATION_RE.sub("\\1\\1\\1", token.content)95 96            # ,,  ,,,  ,,,, -> ,97            token.content = COMMA_RE.sub(",", token.content)98 99            # em-dash100            token.content = EM_DASH_RE.sub("\\1\u2014", token.content)101 102            # en-dash103            token.content = EN_DASH_RE.sub("\\1\u2013", token.content)104            token.content = EN_DASH_INDENT_RE.sub("\\1\u2013", token.content)105 106        if token.type == "link_open" and token.info == "auto":107            inside_autolink -= 1108 109        if token.type == "link_close" and token.info == "auto":110            inside_autolink += 1111 112 113def replace(state: StateCore) -> None:114    if not state.md.options.typographer:115        return116 117    for token in state.tokens:118        if token.type != "inline":119            continue120        if token.children is None:121            continue122 123        if SCOPED_ABBR_RE.search(token.content):124            replace_scoped(token.children)125 126        if RARE_RE.search(token.content):127            replace_rare(token.children)128 
codekingpro/portable-devtools · Team Ai