diff options
Diffstat (limited to 'venv/lib/python3.11/site-packages/markdown_it')
134 files changed, 0 insertions, 6976 deletions
| diff --git a/venv/lib/python3.11/site-packages/markdown_it/__init__.py b/venv/lib/python3.11/site-packages/markdown_it/__init__.py deleted file mode 100644 index 6606868..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -"""A Python port of Markdown-It""" -__all__ = ("MarkdownIt",) -__version__ = "3.0.0" - -from .main import MarkdownIt diff --git a/venv/lib/python3.11/site-packages/markdown_it/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/__pycache__/__init__.cpython-311.pycBinary files differ deleted file mode 100644 index 2ac62da..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/__pycache__/__init__.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/__pycache__/_compat.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/__pycache__/_compat.cpython-311.pycBinary files differ deleted file mode 100644 index 92744db..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/__pycache__/_compat.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/__pycache__/_punycode.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/__pycache__/_punycode.cpython-311.pycBinary files differ deleted file mode 100644 index 97e1c83..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/__pycache__/_punycode.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/__pycache__/main.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/__pycache__/main.cpython-311.pycBinary files differ deleted file mode 100644 index 017e18d..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/__pycache__/main.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/__pycache__/parser_block.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/__pycache__/parser_block.cpython-311.pycBinary files differ deleted file mode 100644 index eff7abc..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/__pycache__/parser_block.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/__pycache__/parser_core.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/__pycache__/parser_core.cpython-311.pycBinary files differ deleted file mode 100644 index 2d778ca..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/__pycache__/parser_core.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/__pycache__/parser_inline.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/__pycache__/parser_inline.cpython-311.pycBinary files differ deleted file mode 100644 index 881d979..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/__pycache__/parser_inline.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/__pycache__/renderer.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/__pycache__/renderer.cpython-311.pycBinary files differ deleted file mode 100644 index 2d67586..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/__pycache__/renderer.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/__pycache__/ruler.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/__pycache__/ruler.cpython-311.pycBinary files differ deleted file mode 100644 index 4dd122d..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/__pycache__/ruler.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/__pycache__/token.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/__pycache__/token.cpython-311.pycBinary files differ deleted file mode 100644 index a0b3423..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/__pycache__/token.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/__pycache__/tree.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/__pycache__/tree.cpython-311.pycBinary files differ deleted file mode 100644 index cbea0ea..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/__pycache__/tree.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/__pycache__/utils.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/__pycache__/utils.cpython-311.pycBinary files differ deleted file mode 100644 index 0de143a..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/__pycache__/utils.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/_compat.py b/venv/lib/python3.11/site-packages/markdown_it/_compat.py deleted file mode 100644 index 974d431..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/_compat.py +++ /dev/null @@ -1,11 +0,0 @@ -from __future__ import annotations - -from collections.abc import Mapping -import sys -from typing import Any - -DATACLASS_KWARGS: Mapping[str, Any] -if sys.version_info >= (3, 10): -    DATACLASS_KWARGS = {"slots": True} -else: -    DATACLASS_KWARGS = {} diff --git a/venv/lib/python3.11/site-packages/markdown_it/_punycode.py b/venv/lib/python3.11/site-packages/markdown_it/_punycode.py deleted file mode 100644 index f9baad2..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/_punycode.py +++ /dev/null @@ -1,67 +0,0 @@ -# Copyright 2014 Mathias Bynens <https://mathiasbynens.be/> -# Copyright 2021 Taneli Hukkinen -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -import codecs -import re -from typing import Callable - -REGEX_SEPARATORS = re.compile(r"[\x2E\u3002\uFF0E\uFF61]") -REGEX_NON_ASCII = re.compile(r"[^\0-\x7E]") - - -def encode(uni: str) -> str: -    return codecs.encode(uni, encoding="punycode").decode() - - -def decode(ascii: str) -> str: -    return codecs.decode(ascii, encoding="punycode")  # type: ignore - - -def map_domain(string: str, fn: Callable[[str], str]) -> str: -    parts = string.split("@") -    result = "" -    if len(parts) > 1: -        # In email addresses, only the domain name should be punycoded. Leave -        # the local part (i.e. everything up to `@`) intact. -        result = parts[0] + "@" -        string = parts[1] -    labels = REGEX_SEPARATORS.split(string) -    encoded = ".".join(fn(label) for label in labels) -    return result + encoded - - -def to_unicode(obj: str) -> str: -    def mapping(obj: str) -> str: -        if obj.startswith("xn--"): -            return decode(obj[4:].lower()) -        return obj - -    return map_domain(obj, mapping) - - -def to_ascii(obj: str) -> str: -    def mapping(obj: str) -> str: -        if REGEX_NON_ASCII.search(obj): -            return "xn--" + encode(obj) -        return obj - -    return map_domain(obj, mapping) diff --git a/venv/lib/python3.11/site-packages/markdown_it/cli/__init__.py b/venv/lib/python3.11/site-packages/markdown_it/cli/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/cli/__init__.py +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/cli/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/cli/__pycache__/__init__.cpython-311.pycBinary files differ deleted file mode 100644 index b6581dd..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/cli/__pycache__/__init__.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/cli/__pycache__/parse.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/cli/__pycache__/parse.cpython-311.pycBinary files differ deleted file mode 100644 index 1f4bebc..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/cli/__pycache__/parse.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/cli/parse.py b/venv/lib/python3.11/site-packages/markdown_it/cli/parse.py deleted file mode 100644 index 890d5de..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/cli/parse.py +++ /dev/null @@ -1,109 +0,0 @@ -#!/usr/bin/env python -""" -CLI interface to markdown-it-py - -Parse one or more markdown files, convert each to HTML, and print to stdout. -""" -from __future__ import annotations - -import argparse -from collections.abc import Iterable, Sequence -import sys - -from markdown_it import __version__ -from markdown_it.main import MarkdownIt - -version_str = "markdown-it-py [version {}]".format(__version__) - - -def main(args: Sequence[str] | None = None) -> int: -    namespace = parse_args(args) -    if namespace.filenames: -        convert(namespace.filenames) -    else: -        interactive() -    return 0 - - -def convert(filenames: Iterable[str]) -> None: -    for filename in filenames: -        convert_file(filename) - - -def convert_file(filename: str) -> None: -    """ -    Parse a Markdown file and dump the output to stdout. -    """ -    try: -        with open(filename, "r", encoding="utf8", errors="ignore") as fin: -            rendered = MarkdownIt().render(fin.read()) -            print(rendered, end="") -    except OSError: -        sys.stderr.write(f'Cannot open file "{filename}".\n') -        sys.exit(1) - - -def interactive() -> None: -    """ -    Parse user input, dump to stdout, rinse and repeat. -    Python REPL style. -    """ -    print_heading() -    contents = [] -    more = False -    while True: -        try: -            prompt, more = ("... ", True) if more else (">>> ", True) -            contents.append(input(prompt) + "\n") -        except EOFError: -            print("\n" + MarkdownIt().render("\n".join(contents)), end="") -            more = False -            contents = [] -        except KeyboardInterrupt: -            print("\nExiting.") -            break - - -def parse_args(args: Sequence[str] | None) -> argparse.Namespace: -    """Parse input CLI arguments.""" -    parser = argparse.ArgumentParser( -        description="Parse one or more markdown files, " -        "convert each to HTML, and print to stdout", -        # NOTE: Remember to update README.md w/ the output of `markdown-it -h` -        epilog=( -            f""" -Interactive: - -  $ markdown-it -  markdown-it-py [version {__version__}] (interactive) -  Type Ctrl-D to complete input, or Ctrl-C to exit. -  >>> # Example -  ... > markdown *input* -  ... -  <h1>Example</h1> -  <blockquote> -  <p>markdown <em>input</em></p> -  </blockquote> - -Batch: - -  $ markdown-it README.md README.footer.md > index.html -""" -        ), -        formatter_class=argparse.RawDescriptionHelpFormatter, -    ) -    parser.add_argument("-v", "--version", action="version", version=version_str) -    parser.add_argument( -        "filenames", nargs="*", help="specify an optional list of files to convert" -    ) -    return parser.parse_args(args) - - -def print_heading() -> None: -    print("{} (interactive)".format(version_str)) -    print("Type Ctrl-D to complete input, or Ctrl-C to exit.") - - -if __name__ == "__main__": -    exit_code = main(sys.argv[1:]) -    sys.exit(exit_code) diff --git a/venv/lib/python3.11/site-packages/markdown_it/common/__init__.py b/venv/lib/python3.11/site-packages/markdown_it/common/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/common/__init__.py +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/common/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/common/__pycache__/__init__.cpython-311.pycBinary files differ deleted file mode 100644 index eefb1d9..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/common/__pycache__/__init__.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/common/__pycache__/entities.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/common/__pycache__/entities.cpython-311.pycBinary files differ deleted file mode 100644 index 0f727f7..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/common/__pycache__/entities.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/common/__pycache__/html_blocks.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/common/__pycache__/html_blocks.cpython-311.pycBinary files differ deleted file mode 100644 index a59fe25..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/common/__pycache__/html_blocks.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/common/__pycache__/html_re.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/common/__pycache__/html_re.cpython-311.pycBinary files differ deleted file mode 100644 index a71e80d..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/common/__pycache__/html_re.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/common/__pycache__/normalize_url.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/common/__pycache__/normalize_url.cpython-311.pycBinary files differ deleted file mode 100644 index d084e07..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/common/__pycache__/normalize_url.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/common/__pycache__/utils.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/common/__pycache__/utils.cpython-311.pycBinary files differ deleted file mode 100644 index 24e8539..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/common/__pycache__/utils.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/common/entities.py b/venv/lib/python3.11/site-packages/markdown_it/common/entities.py deleted file mode 100644 index 6bb2d34..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/common/entities.py +++ /dev/null @@ -1,4 +0,0 @@ -"""HTML5 entities map: { name -> characters }.""" -import html.entities - -entities = {name.rstrip(";"): chars for name, chars in html.entities.html5.items()} diff --git a/venv/lib/python3.11/site-packages/markdown_it/common/html_blocks.py b/venv/lib/python3.11/site-packages/markdown_it/common/html_blocks.py deleted file mode 100644 index 8b199af..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/common/html_blocks.py +++ /dev/null @@ -1,68 +0,0 @@ -"""List of valid html blocks names, according to commonmark spec -http://jgm.github.io/CommonMark/spec.html#html-blocks -""" - -block_names = [ -    "address", -    "article", -    "aside", -    "base", -    "basefont", -    "blockquote", -    "body", -    "caption", -    "center", -    "col", -    "colgroup", -    "dd", -    "details", -    "dialog", -    "dir", -    "div", -    "dl", -    "dt", -    "fieldset", -    "figcaption", -    "figure", -    "footer", -    "form", -    "frame", -    "frameset", -    "h1", -    "h2", -    "h3", -    "h4", -    "h5", -    "h6", -    "head", -    "header", -    "hr", -    "html", -    "iframe", -    "legend", -    "li", -    "link", -    "main", -    "menu", -    "menuitem", -    "nav", -    "noframes", -    "ol", -    "optgroup", -    "option", -    "p", -    "param", -    "section", -    "source", -    "summary", -    "table", -    "tbody", -    "td", -    "tfoot", -    "th", -    "thead", -    "title", -    "tr", -    "track", -    "ul", -] diff --git a/venv/lib/python3.11/site-packages/markdown_it/common/html_re.py b/venv/lib/python3.11/site-packages/markdown_it/common/html_re.py deleted file mode 100644 index f0c336d..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/common/html_re.py +++ /dev/null @@ -1,40 +0,0 @@ -"""Regexps to match html elements -""" - -import re - -attr_name = "[a-zA-Z_:][a-zA-Z0-9:._-]*" - -unquoted = "[^\"'=<>`\\x00-\\x20]+" -single_quoted = "'[^']*'" -double_quoted = '"[^"]*"' - -attr_value = "(?:" + unquoted + "|" + single_quoted + "|" + double_quoted + ")" - -attribute = "(?:\\s+" + attr_name + "(?:\\s*=\\s*" + attr_value + ")?)" - -open_tag = "<[A-Za-z][A-Za-z0-9\\-]*" + attribute + "*\\s*\\/?>" - -close_tag = "<\\/[A-Za-z][A-Za-z0-9\\-]*\\s*>" -comment = "<!---->|<!--(?:-?[^>-])(?:-?[^-])*-->" -processing = "<[?][\\s\\S]*?[?]>" -declaration = "<![A-Z]+\\s+[^>]*>" -cdata = "<!\\[CDATA\\[[\\s\\S]*?\\]\\]>" - -HTML_TAG_RE = re.compile( -    "^(?:" -    + open_tag -    + "|" -    + close_tag -    + "|" -    + comment -    + "|" -    + processing -    + "|" -    + declaration -    + "|" -    + cdata -    + ")" -) -HTML_OPEN_CLOSE_TAG_STR = "^(?:" + open_tag + "|" + close_tag + ")" -HTML_OPEN_CLOSE_TAG_RE = re.compile(HTML_OPEN_CLOSE_TAG_STR) diff --git a/venv/lib/python3.11/site-packages/markdown_it/common/normalize_url.py b/venv/lib/python3.11/site-packages/markdown_it/common/normalize_url.py deleted file mode 100644 index 92720b3..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/common/normalize_url.py +++ /dev/null @@ -1,81 +0,0 @@ -from __future__ import annotations - -from collections.abc import Callable -from contextlib import suppress -import re -from urllib.parse import quote, unquote, urlparse, urlunparse  # noqa: F401 - -import mdurl - -from .. import _punycode - -RECODE_HOSTNAME_FOR = ("http:", "https:", "mailto:") - - -def normalizeLink(url: str) -> str: -    """Normalize destination URLs in links - -    :: - -        [label]:   destination   'title' -                ^^^^^^^^^^^ -    """ -    parsed = mdurl.parse(url, slashes_denote_host=True) - -    # Encode hostnames in urls like: -    # `http://host/`, `https://host/`, `mailto:user@host`, `//host/` -    # -    # We don't encode unknown schemas, because it's likely that we encode -    # something we shouldn't (e.g. `skype:name` treated as `skype:host`) -    # -    if parsed.hostname and ( -        not parsed.protocol or parsed.protocol in RECODE_HOSTNAME_FOR -    ): -        with suppress(Exception): -            parsed = parsed._replace(hostname=_punycode.to_ascii(parsed.hostname)) - -    return mdurl.encode(mdurl.format(parsed)) - - -def normalizeLinkText(url: str) -> str: -    """Normalize autolink content - -    :: - -        <destination> -         ~~~~~~~~~~~ -    """ -    parsed = mdurl.parse(url, slashes_denote_host=True) - -    # Encode hostnames in urls like: -    # `http://host/`, `https://host/`, `mailto:user@host`, `//host/` -    # -    # We don't encode unknown schemas, because it's likely that we encode -    # something we shouldn't (e.g. `skype:name` treated as `skype:host`) -    # -    if parsed.hostname and ( -        not parsed.protocol or parsed.protocol in RECODE_HOSTNAME_FOR -    ): -        with suppress(Exception): -            parsed = parsed._replace(hostname=_punycode.to_unicode(parsed.hostname)) - -    # add '%' to exclude list because of https://github.com/markdown-it/markdown-it/issues/720 -    return mdurl.decode(mdurl.format(parsed), mdurl.DECODE_DEFAULT_CHARS + "%") - - -BAD_PROTO_RE = re.compile(r"^(vbscript|javascript|file|data):") -GOOD_DATA_RE = re.compile(r"^data:image\/(gif|png|jpeg|webp);") - - -def validateLink(url: str, validator: Callable[[str], bool] | None = None) -> bool: -    """Validate URL link is allowed in output. - -    This validator can prohibit more than really needed to prevent XSS. -    It's a tradeoff to keep code simple and to be secure by default. - -    Note: url should be normalized at this point, and existing entities decoded. -    """ -    if validator is not None: -        return validator(url) -    url = url.strip().lower() -    return bool(GOOD_DATA_RE.search(url)) if BAD_PROTO_RE.search(url) else True diff --git a/venv/lib/python3.11/site-packages/markdown_it/common/utils.py b/venv/lib/python3.11/site-packages/markdown_it/common/utils.py deleted file mode 100644 index 0d11e3e..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/common/utils.py +++ /dev/null @@ -1,318 +0,0 @@ -"""Utilities for parsing source text -""" -from __future__ import annotations - -import re -from typing import Match, TypeVar - -from .entities import entities - - -def charCodeAt(src: str, pos: int) -> int | None: -    """ -    Returns the Unicode value of the character at the specified location. - -    @param - index The zero-based index of the desired character. -    If there is no character at the specified index, NaN is returned. - -    This was added for compatibility with python -    """ -    try: -        return ord(src[pos]) -    except IndexError: -        return None - - -def charStrAt(src: str, pos: int) -> str | None: -    """ -    Returns the Unicode value of the character at the specified location. - -    @param - index The zero-based index of the desired character. -    If there is no character at the specified index, NaN is returned. - -    This was added for compatibility with python -    """ -    try: -        return src[pos] -    except IndexError: -        return None - - -_ItemTV = TypeVar("_ItemTV") - - -def arrayReplaceAt( -    src: list[_ItemTV], pos: int, newElements: list[_ItemTV] -) -> list[_ItemTV]: -    """ -    Remove element from array and put another array at those position. -    Useful for some operations with tokens -    """ -    return src[:pos] + newElements + src[pos + 1 :] - - -def isValidEntityCode(c: int) -> bool: -    # broken sequence -    if c >= 0xD800 and c <= 0xDFFF: -        return False -    # never used -    if c >= 0xFDD0 and c <= 0xFDEF: -        return False -    if ((c & 0xFFFF) == 0xFFFF) or ((c & 0xFFFF) == 0xFFFE): -        return False -    # control codes -    if c >= 0x00 and c <= 0x08: -        return False -    if c == 0x0B: -        return False -    if c >= 0x0E and c <= 0x1F: -        return False -    if c >= 0x7F and c <= 0x9F: -        return False -    # out of range -    if c > 0x10FFFF: -        return False -    return True - - -def fromCodePoint(c: int) -> str: -    """Convert ordinal to unicode. - -    Note, in the original Javascript two string characters were required, -    for codepoints larger than `0xFFFF`. -    But Python 3 can represent any unicode codepoint in one character. -    """ -    return chr(c) - - -# UNESCAPE_MD_RE = re.compile(r'\\([!"#$%&\'()*+,\-.\/:;<=>?@[\\\]^_`{|}~])') -# ENTITY_RE_g       = re.compile(r'&([a-z#][a-z0-9]{1,31})', re.IGNORECASE) -UNESCAPE_ALL_RE = re.compile( -    r'\\([!"#$%&\'()*+,\-.\/:;<=>?@[\\\]^_`{|}~])' + "|" + r"&([a-z#][a-z0-9]{1,31});", -    re.IGNORECASE, -) -DIGITAL_ENTITY_BASE10_RE = re.compile(r"#([0-9]{1,8})") -DIGITAL_ENTITY_BASE16_RE = re.compile(r"#x([a-f0-9]{1,8})", re.IGNORECASE) - - -def replaceEntityPattern(match: str, name: str) -> str: -    """Convert HTML entity patterns, -    see https://spec.commonmark.org/0.30/#entity-references -    """ -    if name in entities: -        return entities[name] - -    code: None | int = None -    if pat := DIGITAL_ENTITY_BASE10_RE.fullmatch(name): -        code = int(pat.group(1), 10) -    elif pat := DIGITAL_ENTITY_BASE16_RE.fullmatch(name): -        code = int(pat.group(1), 16) - -    if code is not None and isValidEntityCode(code): -        return fromCodePoint(code) - -    return match - - -def unescapeAll(string: str) -> str: -    def replacer_func(match: Match[str]) -> str: -        escaped = match.group(1) -        if escaped: -            return escaped -        entity = match.group(2) -        return replaceEntityPattern(match.group(), entity) - -    if "\\" not in string and "&" not in string: -        return string -    return UNESCAPE_ALL_RE.sub(replacer_func, string) - - -ESCAPABLE = r"""\\!"#$%&'()*+,./:;<=>?@\[\]^`{}|_~-""" -ESCAPE_CHAR = re.compile(r"\\([" + ESCAPABLE + r"])") - - -def stripEscape(string: str) -> str: -    """Strip escape \\ characters""" -    return ESCAPE_CHAR.sub(r"\1", string) - - -def escapeHtml(raw: str) -> str: -    """Replace special characters "&", "<", ">" and '"' to HTML-safe sequences.""" -    # like html.escape, but without escaping single quotes -    raw = raw.replace("&", "&")  # Must be done first! -    raw = raw.replace("<", "<") -    raw = raw.replace(">", ">") -    raw = raw.replace('"', """) -    return raw - - -# ////////////////////////////////////////////////////////////////////////////// - -REGEXP_ESCAPE_RE = re.compile(r"[.?*+^$[\]\\(){}|-]") - - -def escapeRE(string: str) -> str: -    string = REGEXP_ESCAPE_RE.sub("\\$&", string) -    return string - - -# ////////////////////////////////////////////////////////////////////////////// - - -def isSpace(code: int | None) -> bool: -    """Check if character code is a whitespace.""" -    return code in (0x09, 0x20) - - -def isStrSpace(ch: str | None) -> bool: -    """Check if character is a whitespace.""" -    return ch in ("\t", " ") - - -MD_WHITESPACE = { -    0x09,  # \t -    0x0A,  # \n -    0x0B,  # \v -    0x0C,  # \f -    0x0D,  # \r -    0x20,  # space -    0xA0, -    0x1680, -    0x202F, -    0x205F, -    0x3000, -} - - -def isWhiteSpace(code: int) -> bool: -    r"""Zs (unicode class) || [\t\f\v\r\n]""" -    if code >= 0x2000 and code <= 0x200A: -        return True -    return code in MD_WHITESPACE - - -# ////////////////////////////////////////////////////////////////////////////// - -UNICODE_PUNCT_RE = re.compile( -    r"[!-#%-\*,-\/:;\?@\[-\]_\{\}\xA1\xA7\xAB\xB6\xB7\xBB\xBF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061E\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u09FD\u0A76\u0AF0\u0C84\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166D\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E4E\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]|\uD800[\uDD00-\uDD02\uDF9F\uDFD0]|\uD801\uDD6F|\uD802[\uDC57\uDD1F\uDD3F\uDE50-\uDE58\uDE7F\uDEF0-\uDEF6\uDF39-\uDF3F\uDF99-\uDF9C]|\uD803[\uDF55-\uDF59]|\uD804[\uDC47-\uDC4D\uDCBB\uDCBC\uDCBE-\uDCC1\uDD40-\uDD43\uDD74\uDD75\uDDC5-\uDDC8\uDDCD\uDDDB\uDDDD-\uDDDF\uDE38-\uDE3D\uDEA9]|\uD805[\uDC4B-\uDC4F\uDC5B\uDC5D\uDCC6\uDDC1-\uDDD7\uDE41-\uDE43\uDE60-\uDE6C\uDF3C-\uDF3E]|\uD806[\uDC3B\uDE3F-\uDE46\uDE9A-\uDE9C\uDE9E-\uDEA2]|\uD807[\uDC41-\uDC45\uDC70\uDC71\uDEF7\uDEF8]|\uD809[\uDC70-\uDC74]|\uD81A[\uDE6E\uDE6F\uDEF5\uDF37-\uDF3B\uDF44]|\uD81B[\uDE97-\uDE9A]|\uD82F\uDC9F|\uD836[\uDE87-\uDE8B]|\uD83A[\uDD5E\uDD5F]"  # noqa: E501 -) - - -# Currently without astral characters support. -def isPunctChar(ch: str) -> bool: -    """Check if character is a punctuation character.""" -    return UNICODE_PUNCT_RE.search(ch) is not None - - -MD_ASCII_PUNCT = { -    0x21,  # /* ! */ -    0x22,  # /* " */ -    0x23,  # /* # */ -    0x24,  # /* $ */ -    0x25,  # /* % */ -    0x26,  # /* & */ -    0x27,  # /* ' */ -    0x28,  # /* ( */ -    0x29,  # /* ) */ -    0x2A,  # /* * */ -    0x2B,  # /* + */ -    0x2C,  # /* , */ -    0x2D,  # /* - */ -    0x2E,  # /* . */ -    0x2F,  # /* / */ -    0x3A,  # /* : */ -    0x3B,  # /* ; */ -    0x3C,  # /* < */ -    0x3D,  # /* = */ -    0x3E,  # /* > */ -    0x3F,  # /* ? */ -    0x40,  # /* @ */ -    0x5B,  # /* [ */ -    0x5C,  # /* \ */ -    0x5D,  # /* ] */ -    0x5E,  # /* ^ */ -    0x5F,  # /* _ */ -    0x60,  # /* ` */ -    0x7B,  # /* { */ -    0x7C,  # /* | */ -    0x7D,  # /* } */ -    0x7E,  # /* ~ */ -} - - -def isMdAsciiPunct(ch: int) -> bool: -    """Markdown ASCII punctuation characters. - -    :: - -        !, ", #, $, %, &, ', (, ), *, +, ,, -, ., /, :, ;, <, =, >, ?, @, [, \\, ], ^, _, `, {, |, }, or ~ - -    See http://spec.commonmark.org/0.15/#ascii-punctuation-character - -    Don't confuse with unicode punctuation !!! It lacks some chars in ascii range. - -    """  # noqa: E501 -    return ch in MD_ASCII_PUNCT - - -def normalizeReference(string: str) -> str: -    """Helper to unify [reference labels].""" -    # Trim and collapse whitespace -    # -    string = re.sub(r"\s+", " ", string.strip()) - -    # In node v10 'ẞ'.toLowerCase() === 'Ṿ', which is presumed to be a bug -    # fixed in v12 (couldn't find any details). -    # -    # So treat this one as a special case -    # (remove this when node v10 is no longer supported). -    # -    # if ('ẞ'.toLowerCase() === 'Ṿ') { -    #   str = str.replace(/ẞ/g, 'ß') -    # } - -    # .toLowerCase().toUpperCase() should get rid of all differences -    # between letter variants. -    # -    # Simple .toLowerCase() doesn't normalize 125 code points correctly, -    # and .toUpperCase doesn't normalize 6 of them (list of exceptions: -    # İ, ϴ, ẞ, Ω, K, Å - those are already uppercased, but have differently -    # uppercased versions). -    # -    # Here's an example showing how it happens. Lets take greek letter omega: -    # uppercase U+0398 (Θ), U+03f4 (ϴ) and lowercase U+03b8 (θ), U+03d1 (ϑ) -    # -    # Unicode entries: -    # 0398;GREEK CAPITAL LETTER THETA;Lu;0;L;;;;;N;;;;03B8 -    # 03B8;GREEK SMALL LETTER THETA;Ll;0;L;;;;;N;;;0398;;0398 -    # 03D1;GREEK THETA SYMBOL;Ll;0;L;<compat> 03B8;;;;N;GREEK SMALL LETTER SCRIPT THETA;;0398;;0398 -    # 03F4;GREEK CAPITAL THETA SYMBOL;Lu;0;L;<compat> 0398;;;;N;;;;03B8 -    # -    # Case-insensitive comparison should treat all of them as equivalent. -    # -    # But .toLowerCase() doesn't change ϑ (it's already lowercase), -    # and .toUpperCase() doesn't change ϴ (already uppercase). -    # -    # Applying first lower then upper case normalizes any character: -    # '\u0398\u03f4\u03b8\u03d1'.toLowerCase().toUpperCase() === '\u0398\u0398\u0398\u0398' -    # -    # Note: this is equivalent to unicode case folding; unicode normalization -    # is a different step that is not required here. -    # -    # Final result should be uppercased, because it's later stored in an object -    # (this avoid a conflict with Object.prototype members, -    # most notably, `__proto__`) -    # -    return string.lower().upper() - - -LINK_OPEN_RE = re.compile(r"^<a[>\s]", flags=re.IGNORECASE) -LINK_CLOSE_RE = re.compile(r"^</a\s*>", flags=re.IGNORECASE) - - -def isLinkOpen(string: str) -> bool: -    return bool(LINK_OPEN_RE.search(string)) - - -def isLinkClose(string: str) -> bool: -    return bool(LINK_CLOSE_RE.search(string)) diff --git a/venv/lib/python3.11/site-packages/markdown_it/helpers/__init__.py b/venv/lib/python3.11/site-packages/markdown_it/helpers/__init__.py deleted file mode 100644 index 3dbbdd1..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/helpers/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -"""Functions for parsing Links -""" -__all__ = ("parseLinkLabel", "parseLinkDestination", "parseLinkTitle") -from .parse_link_destination import parseLinkDestination -from .parse_link_label import parseLinkLabel -from .parse_link_title import parseLinkTitle diff --git a/venv/lib/python3.11/site-packages/markdown_it/helpers/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/helpers/__pycache__/__init__.cpython-311.pycBinary files differ deleted file mode 100644 index f1d7692..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/helpers/__pycache__/__init__.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/helpers/__pycache__/parse_link_destination.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/helpers/__pycache__/parse_link_destination.cpython-311.pycBinary files differ deleted file mode 100644 index 3885f6b..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/helpers/__pycache__/parse_link_destination.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/helpers/__pycache__/parse_link_label.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/helpers/__pycache__/parse_link_label.cpython-311.pycBinary files differ deleted file mode 100644 index 29b8d7e..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/helpers/__pycache__/parse_link_label.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/helpers/__pycache__/parse_link_title.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/helpers/__pycache__/parse_link_title.cpython-311.pycBinary files differ deleted file mode 100644 index fa29677..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/helpers/__pycache__/parse_link_title.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/helpers/parse_link_destination.py b/venv/lib/python3.11/site-packages/markdown_it/helpers/parse_link_destination.py deleted file mode 100644 index f42b224..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/helpers/parse_link_destination.py +++ /dev/null @@ -1,86 +0,0 @@ -""" -Parse link destination -""" - -from ..common.utils import charCodeAt, unescapeAll - - -class _Result: -    __slots__ = ("ok", "pos", "lines", "str") - -    def __init__(self) -> None: -        self.ok = False -        self.pos = 0 -        self.lines = 0 -        self.str = "" - - -def parseLinkDestination(string: str, pos: int, maximum: int) -> _Result: -    lines = 0 -    start = pos -    result = _Result() - -    if charCodeAt(string, pos) == 0x3C:  # /* < */ -        pos += 1 -        while pos < maximum: -            code = charCodeAt(string, pos) -            if code == 0x0A:  # /* \n */) -                return result -            if code == 0x3C:  # / * < * / -                return result -            if code == 0x3E:  # /* > */) { -                result.pos = pos + 1 -                result.str = unescapeAll(string[start + 1 : pos]) -                result.ok = True -                return result - -            if code == 0x5C and pos + 1 < maximum:  # \ -                pos += 2 -                continue - -            pos += 1 - -        # no closing '>' -        return result - -    # this should be ... } else { ... branch - -    level = 0 -    while pos < maximum: -        code = charCodeAt(string, pos) - -        if code is None or code == 0x20: -            break - -        # ascii control characters -        if code < 0x20 or code == 0x7F: -            break - -        if code == 0x5C and pos + 1 < maximum: -            if charCodeAt(string, pos + 1) == 0x20: -                break -            pos += 2 -            continue - -        if code == 0x28:  # /* ( */) -            level += 1 -            if level > 32: -                return result - -        if code == 0x29:  # /* ) */) -            if level == 0: -                break -            level -= 1 - -        pos += 1 - -    if start == pos: -        return result -    if level != 0: -        return result - -    result.str = unescapeAll(string[start:pos]) -    result.lines = lines -    result.pos = pos -    result.ok = True -    return result diff --git a/venv/lib/python3.11/site-packages/markdown_it/helpers/parse_link_label.py b/venv/lib/python3.11/site-packages/markdown_it/helpers/parse_link_label.py deleted file mode 100644 index 01c653c..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/helpers/parse_link_label.py +++ /dev/null @@ -1,43 +0,0 @@ -""" -Parse link label - -this function assumes that first character ("[") already matches -returns the end of the label - -""" -from markdown_it.rules_inline import StateInline - - -def parseLinkLabel(state: StateInline, start: int, disableNested: bool = False) -> int: -    labelEnd = -1 -    oldPos = state.pos -    found = False - -    state.pos = start + 1 -    level = 1 - -    while state.pos < state.posMax: -        marker = state.src[state.pos] -        if marker == "]": -            level -= 1 -            if level == 0: -                found = True -                break - -        prevPos = state.pos -        state.md.inline.skipToken(state) -        if marker == "[": -            if prevPos == state.pos - 1: -                # increase level if we find text `[`, -                # which is not a part of any token -                level += 1 -            elif disableNested: -                state.pos = oldPos -                return -1 -    if found: -        labelEnd = state.pos - -    # restore old state -    state.pos = oldPos - -    return labelEnd diff --git a/venv/lib/python3.11/site-packages/markdown_it/helpers/parse_link_title.py b/venv/lib/python3.11/site-packages/markdown_it/helpers/parse_link_title.py deleted file mode 100644 index 8f58933..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/helpers/parse_link_title.py +++ /dev/null @@ -1,60 +0,0 @@ -"""Parse link title -""" -from ..common.utils import charCodeAt, unescapeAll - - -class _Result: -    __slots__ = ("ok", "pos", "lines", "str") - -    def __init__(self) -> None: -        self.ok = False -        self.pos = 0 -        self.lines = 0 -        self.str = "" - -    def __str__(self) -> str: -        return self.str - - -def parseLinkTitle(string: str, pos: int, maximum: int) -> _Result: -    lines = 0 -    start = pos -    result = _Result() - -    if pos >= maximum: -        return result - -    marker = charCodeAt(string, pos) - -    # /* " */  /* ' */  /* ( */ -    if marker != 0x22 and marker != 0x27 and marker != 0x28: -        return result - -    pos += 1 - -    # if opening marker is "(", switch it to closing marker ")" -    if marker == 0x28: -        marker = 0x29 - -    while pos < maximum: -        code = charCodeAt(string, pos) -        if code == marker: -            title = string[start + 1 : pos] -            title = unescapeAll(title) -            result.pos = pos + 1 -            result.lines = lines -            result.str = title -            result.ok = True -            return result -        elif code == 0x28 and marker == 0x29:  # /* ( */  /* ) */ -            return result -        elif code == 0x0A: -            lines += 1 -        elif code == 0x5C and pos + 1 < maximum:  # /* \ */ -            pos += 1 -            if charCodeAt(string, pos) == 0x0A: -                lines += 1 - -        pos += 1 - -    return result diff --git a/venv/lib/python3.11/site-packages/markdown_it/main.py b/venv/lib/python3.11/site-packages/markdown_it/main.py deleted file mode 100644 index bb294a9..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/main.py +++ /dev/null @@ -1,355 +0,0 @@ -from __future__ import annotations - -from collections.abc import Callable, Generator, Iterable, Mapping, MutableMapping -from contextlib import contextmanager -from typing import Any, Literal, overload - -from . import helpers, presets -from .common import normalize_url, utils -from .parser_block import ParserBlock -from .parser_core import ParserCore -from .parser_inline import ParserInline -from .renderer import RendererHTML, RendererProtocol -from .rules_core.state_core import StateCore -from .token import Token -from .utils import EnvType, OptionsDict, OptionsType, PresetType - -try: -    import linkify_it -except ModuleNotFoundError: -    linkify_it = None - - -_PRESETS: dict[str, PresetType] = { -    "default": presets.default.make(), -    "js-default": presets.js_default.make(), -    "zero": presets.zero.make(), -    "commonmark": presets.commonmark.make(), -    "gfm-like": presets.gfm_like.make(), -} - - -class MarkdownIt: -    def __init__( -        self, -        config: str | PresetType = "commonmark", -        options_update: Mapping[str, Any] | None = None, -        *, -        renderer_cls: Callable[[MarkdownIt], RendererProtocol] = RendererHTML, -    ): -        """Main parser class - -        :param config: name of configuration to load or a pre-defined dictionary -        :param options_update: dictionary that will be merged into ``config["options"]`` -        :param renderer_cls: the class to load as the renderer: -            ``self.renderer = renderer_cls(self) -        """ -        # add modules -        self.utils = utils -        self.helpers = helpers - -        # initialise classes -        self.inline = ParserInline() -        self.block = ParserBlock() -        self.core = ParserCore() -        self.renderer = renderer_cls(self) -        self.linkify = linkify_it.LinkifyIt() if linkify_it else None - -        # set the configuration -        if options_update and not isinstance(options_update, Mapping): -            # catch signature change where renderer_cls was not used as a key-word -            raise TypeError( -                f"options_update should be a mapping: {options_update}" -                "\n(Perhaps you intended this to be the renderer_cls?)" -            ) -        self.configure(config, options_update=options_update) - -    def __repr__(self) -> str: -        return f"{self.__class__.__module__}.{self.__class__.__name__}()" - -    @overload -    def __getitem__(self, name: Literal["inline"]) -> ParserInline: -        ... - -    @overload -    def __getitem__(self, name: Literal["block"]) -> ParserBlock: -        ... - -    @overload -    def __getitem__(self, name: Literal["core"]) -> ParserCore: -        ... - -    @overload -    def __getitem__(self, name: Literal["renderer"]) -> RendererProtocol: -        ... - -    @overload -    def __getitem__(self, name: str) -> Any: -        ... - -    def __getitem__(self, name: str) -> Any: -        return { -            "inline": self.inline, -            "block": self.block, -            "core": self.core, -            "renderer": self.renderer, -        }[name] - -    def set(self, options: OptionsType) -> None: -        """Set parser options (in the same format as in constructor). -        Probably, you will never need it, but you can change options after constructor call. - -        __Note:__ To achieve the best possible performance, don't modify a -        `markdown-it` instance options on the fly. If you need multiple configurations -        it's best to create multiple instances and initialize each with separate config. -        """ -        self.options = OptionsDict(options) - -    def configure( -        self, presets: str | PresetType, options_update: Mapping[str, Any] | None = None -    ) -> MarkdownIt: -        """Batch load of all options and component settings. -        This is an internal method, and you probably will not need it. -        But if you will - see available presets and data structure -        [here](https://github.com/markdown-it/markdown-it/tree/master/lib/presets) - -        We strongly recommend to use presets instead of direct config loads. -        That will give better compatibility with next versions. -        """ -        if isinstance(presets, str): -            if presets not in _PRESETS: -                raise KeyError(f"Wrong `markdown-it` preset '{presets}', check name") -            config = _PRESETS[presets] -        else: -            config = presets - -        if not config: -            raise ValueError("Wrong `markdown-it` config, can't be empty") - -        options = config.get("options", {}) or {} -        if options_update: -            options = {**options, **options_update}  # type: ignore - -        self.set(options)  # type: ignore - -        if "components" in config: -            for name, component in config["components"].items(): -                rules = component.get("rules", None) -                if rules: -                    self[name].ruler.enableOnly(rules) -                rules2 = component.get("rules2", None) -                if rules2: -                    self[name].ruler2.enableOnly(rules2) - -        return self - -    def get_all_rules(self) -> dict[str, list[str]]: -        """Return the names of all active rules.""" -        rules = { -            chain: self[chain].ruler.get_all_rules() -            for chain in ["core", "block", "inline"] -        } -        rules["inline2"] = self.inline.ruler2.get_all_rules() -        return rules - -    def get_active_rules(self) -> dict[str, list[str]]: -        """Return the names of all active rules.""" -        rules = { -            chain: self[chain].ruler.get_active_rules() -            for chain in ["core", "block", "inline"] -        } -        rules["inline2"] = self.inline.ruler2.get_active_rules() -        return rules - -    def enable( -        self, names: str | Iterable[str], ignoreInvalid: bool = False -    ) -> MarkdownIt: -        """Enable list or rules. (chainable) - -        :param names: rule name or list of rule names to enable. -        :param ignoreInvalid: set `true` to ignore errors when rule not found. - -        It will automatically find appropriate components, -        containing rules with given names. If rule not found, and `ignoreInvalid` -        not set - throws exception. - -        Example:: - -            md = MarkdownIt().enable(['sub', 'sup']).disable('smartquotes') - -        """ -        result = [] - -        if isinstance(names, str): -            names = [names] - -        for chain in ["core", "block", "inline"]: -            result.extend(self[chain].ruler.enable(names, True)) -        result.extend(self.inline.ruler2.enable(names, True)) - -        missed = [name for name in names if name not in result] -        if missed and not ignoreInvalid: -            raise ValueError(f"MarkdownIt. Failed to enable unknown rule(s): {missed}") - -        return self - -    def disable( -        self, names: str | Iterable[str], ignoreInvalid: bool = False -    ) -> MarkdownIt: -        """The same as [[MarkdownIt.enable]], but turn specified rules off. (chainable) - -        :param names: rule name or list of rule names to disable. -        :param ignoreInvalid: set `true` to ignore errors when rule not found. - -        """ -        result = [] - -        if isinstance(names, str): -            names = [names] - -        for chain in ["core", "block", "inline"]: -            result.extend(self[chain].ruler.disable(names, True)) -        result.extend(self.inline.ruler2.disable(names, True)) - -        missed = [name for name in names if name not in result] -        if missed and not ignoreInvalid: -            raise ValueError(f"MarkdownIt. Failed to disable unknown rule(s): {missed}") -        return self - -    @contextmanager -    def reset_rules(self) -> Generator[None, None, None]: -        """A context manager, that will reset the current enabled rules on exit.""" -        chain_rules = self.get_active_rules() -        yield -        for chain, rules in chain_rules.items(): -            if chain != "inline2": -                self[chain].ruler.enableOnly(rules) -        self.inline.ruler2.enableOnly(chain_rules["inline2"]) - -    def add_render_rule( -        self, name: str, function: Callable[..., Any], fmt: str = "html" -    ) -> None: -        """Add a rule for rendering a particular Token type. - -        Only applied when ``renderer.__output__ == fmt`` -        """ -        if self.renderer.__output__ == fmt: -            self.renderer.rules[name] = function.__get__(self.renderer)  # type: ignore - -    def use( -        self, plugin: Callable[..., None], *params: Any, **options: Any -    ) -> MarkdownIt: -        """Load specified plugin with given params into current parser instance. (chainable) - -        It's just a sugar to call `plugin(md, params)` with curring. - -        Example:: - -            def func(tokens, idx): -                tokens[idx].content = tokens[idx].content.replace('foo', 'bar') -            md = MarkdownIt().use(plugin, 'foo_replace', 'text', func) - -        """ -        plugin(self, *params, **options) -        return self - -    def parse(self, src: str, env: EnvType | None = None) -> list[Token]: -        """Parse the source string to a token stream - -        :param src: source string -        :param env: environment sandbox - -        Parse input string and return list of block tokens (special token type -        "inline" will contain list of inline tokens). - -        `env` is used to pass data between "distributed" rules and return additional -        metadata like reference info, needed for the renderer. It also can be used to -        inject data in specific cases. Usually, you will be ok to pass `{}`, -        and then pass updated object to renderer. -        """ -        env = {} if env is None else env -        if not isinstance(env, MutableMapping): -            raise TypeError(f"Input data should be a MutableMapping, not {type(env)}") -        if not isinstance(src, str): -            raise TypeError(f"Input data should be a string, not {type(src)}") -        state = StateCore(src, self, env) -        self.core.process(state) -        return state.tokens - -    def render(self, src: str, env: EnvType | None = None) -> Any: -        """Render markdown string into html. It does all magic for you :). - -        :param src: source string -        :param env: environment sandbox -        :returns: The output of the loaded renderer - -        `env` can be used to inject additional metadata (`{}` by default). -        But you will not need it with high probability. See also comment -        in [[MarkdownIt.parse]]. -        """ -        env = {} if env is None else env -        return self.renderer.render(self.parse(src, env), self.options, env) - -    def parseInline(self, src: str, env: EnvType | None = None) -> list[Token]: -        """The same as [[MarkdownIt.parse]] but skip all block rules. - -        :param src: source string -        :param env: environment sandbox - -        It returns the -        block tokens list with the single `inline` element, containing parsed inline -        tokens in `children` property. Also updates `env` object. -        """ -        env = {} if env is None else env -        if not isinstance(env, MutableMapping): -            raise TypeError(f"Input data should be an MutableMapping, not {type(env)}") -        if not isinstance(src, str): -            raise TypeError(f"Input data should be a string, not {type(src)}") -        state = StateCore(src, self, env) -        state.inlineMode = True -        self.core.process(state) -        return state.tokens - -    def renderInline(self, src: str, env: EnvType | None = None) -> Any: -        """Similar to [[MarkdownIt.render]] but for single paragraph content. - -        :param src: source string -        :param env: environment sandbox - -        Similar to [[MarkdownIt.render]] but for single paragraph content. Result -        will NOT be wrapped into `<p>` tags. -        """ -        env = {} if env is None else env -        return self.renderer.render(self.parseInline(src, env), self.options, env) - -    # link methods - -    def validateLink(self, url: str) -> bool: -        """Validate if the URL link is allowed in output. - -        This validator can prohibit more than really needed to prevent XSS. -        It's a tradeoff to keep code simple and to be secure by default. - -        Note: the url should be normalized at this point, and existing entities decoded. -        """ -        return normalize_url.validateLink(url) - -    def normalizeLink(self, url: str) -> str: -        """Normalize destination URLs in links - -        :: - -            [label]:   destination   'title' -                    ^^^^^^^^^^^ -        """ -        return normalize_url.normalizeLink(url) - -    def normalizeLinkText(self, link: str) -> str: -        """Normalize autolink content - -        :: - -            <destination> -            ~~~~~~~~~~~ -        """ -        return normalize_url.normalizeLinkText(link) diff --git a/venv/lib/python3.11/site-packages/markdown_it/parser_block.py b/venv/lib/python3.11/site-packages/markdown_it/parser_block.py deleted file mode 100644 index 72360f9..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/parser_block.py +++ /dev/null @@ -1,111 +0,0 @@ -"""Block-level tokenizer.""" -from __future__ import annotations - -import logging -from typing import TYPE_CHECKING, Callable - -from . import rules_block -from .ruler import Ruler -from .rules_block.state_block import StateBlock -from .token import Token -from .utils import EnvType - -if TYPE_CHECKING: -    from markdown_it import MarkdownIt - -LOGGER = logging.getLogger(__name__) - - -RuleFuncBlockType = Callable[[StateBlock, int, int, bool], bool] -"""(state: StateBlock, startLine: int, endLine: int, silent: bool) -> matched: bool) - -`silent` disables token generation, useful for lookahead. -""" - -_rules: list[tuple[str, RuleFuncBlockType, list[str]]] = [ -    # First 2 params - rule name & source. Secondary array - list of rules, -    # which can be terminated by this one. -    ("table", rules_block.table, ["paragraph", "reference"]), -    ("code", rules_block.code, []), -    ("fence", rules_block.fence, ["paragraph", "reference", "blockquote", "list"]), -    ( -        "blockquote", -        rules_block.blockquote, -        ["paragraph", "reference", "blockquote", "list"], -    ), -    ("hr", rules_block.hr, ["paragraph", "reference", "blockquote", "list"]), -    ("list", rules_block.list_block, ["paragraph", "reference", "blockquote"]), -    ("reference", rules_block.reference, []), -    ("html_block", rules_block.html_block, ["paragraph", "reference", "blockquote"]), -    ("heading", rules_block.heading, ["paragraph", "reference", "blockquote"]), -    ("lheading", rules_block.lheading, []), -    ("paragraph", rules_block.paragraph, []), -] - - -class ParserBlock: -    """ -    ParserBlock#ruler -> Ruler - -    [[Ruler]] instance. Keep configuration of block rules. -    """ - -    def __init__(self) -> None: -        self.ruler = Ruler[RuleFuncBlockType]() -        for name, rule, alt in _rules: -            self.ruler.push(name, rule, {"alt": alt}) - -    def tokenize(self, state: StateBlock, startLine: int, endLine: int) -> None: -        """Generate tokens for input range.""" -        rules = self.ruler.getRules("") -        line = startLine -        maxNesting = state.md.options.maxNesting -        hasEmptyLines = False - -        while line < endLine: -            state.line = line = state.skipEmptyLines(line) -            if line >= endLine: -                break -            if state.sCount[line] < state.blkIndent: -                # Termination condition for nested calls. -                # Nested calls currently used for blockquotes & lists -                break -            if state.level >= maxNesting: -                # If nesting level exceeded - skip tail to the end. -                # That's not ordinary situation and we should not care about content. -                state.line = endLine -                break - -            # Try all possible rules. -            # On success, rule should: -            # - update `state.line` -            # - update `state.tokens` -            # - return True -            for rule in rules: -                if rule(state, line, endLine, False): -                    break - -            # set state.tight if we had an empty line before current tag -            # i.e. latest empty line should not count -            state.tight = not hasEmptyLines - -            line = state.line - -            # paragraph might "eat" one newline after it in nested lists -            if (line - 1) < endLine and state.isEmpty(line - 1): -                hasEmptyLines = True - -            if line < endLine and state.isEmpty(line): -                hasEmptyLines = True -                line += 1 -                state.line = line - -    def parse( -        self, src: str, md: MarkdownIt, env: EnvType, outTokens: list[Token] -    ) -> list[Token] | None: -        """Process input string and push block tokens into `outTokens`.""" -        if not src: -            return None -        state = StateBlock(src, md, env, outTokens) -        self.tokenize(state, state.line, state.lineMax) -        return state.tokens diff --git a/venv/lib/python3.11/site-packages/markdown_it/parser_core.py b/venv/lib/python3.11/site-packages/markdown_it/parser_core.py deleted file mode 100644 index ca5ab25..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/parser_core.py +++ /dev/null @@ -1,45 +0,0 @@ -""" - * class Core - * - * Top-level rules executor. Glues block/inline parsers and does intermediate - * transformations. -""" -from __future__ import annotations - -from typing import Callable - -from .ruler import Ruler -from .rules_core import ( -    block, -    inline, -    linkify, -    normalize, -    replace, -    smartquotes, -    text_join, -) -from .rules_core.state_core import StateCore - -RuleFuncCoreType = Callable[[StateCore], None] - -_rules: list[tuple[str, RuleFuncCoreType]] = [ -    ("normalize", normalize), -    ("block", block), -    ("inline", inline), -    ("linkify", linkify), -    ("replacements", replace), -    ("smartquotes", smartquotes), -    ("text_join", text_join), -] - - -class ParserCore: -    def __init__(self) -> None: -        self.ruler = Ruler[RuleFuncCoreType]() -        for name, rule in _rules: -            self.ruler.push(name, rule) - -    def process(self, state: StateCore) -> None: -        """Executes core chain rules.""" -        for rule in self.ruler.getRules(""): -            rule(state) diff --git a/venv/lib/python3.11/site-packages/markdown_it/parser_inline.py b/venv/lib/python3.11/site-packages/markdown_it/parser_inline.py deleted file mode 100644 index 0026c38..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/parser_inline.py +++ /dev/null @@ -1,147 +0,0 @@ -"""Tokenizes paragraph content. -""" -from __future__ import annotations - -from typing import TYPE_CHECKING, Callable - -from . import rules_inline -from .ruler import Ruler -from .rules_inline.state_inline import StateInline -from .token import Token -from .utils import EnvType - -if TYPE_CHECKING: -    from markdown_it import MarkdownIt - - -# Parser rules -RuleFuncInlineType = Callable[[StateInline, bool], bool] -"""(state: StateInline, silent: bool) -> matched: bool) - -`silent` disables token generation, useful for lookahead. -""" -_rules: list[tuple[str, RuleFuncInlineType]] = [ -    ("text", rules_inline.text), -    ("linkify", rules_inline.linkify), -    ("newline", rules_inline.newline), -    ("escape", rules_inline.escape), -    ("backticks", rules_inline.backtick), -    ("strikethrough", rules_inline.strikethrough.tokenize), -    ("emphasis", rules_inline.emphasis.tokenize), -    ("link", rules_inline.link), -    ("image", rules_inline.image), -    ("autolink", rules_inline.autolink), -    ("html_inline", rules_inline.html_inline), -    ("entity", rules_inline.entity), -] - -# Note `rule2` ruleset was created specifically for emphasis/strikethrough -# post-processing and may be changed in the future. -# -# Don't use this for anything except pairs (plugins working with `balance_pairs`). -# -RuleFuncInline2Type = Callable[[StateInline], None] -_rules2: list[tuple[str, RuleFuncInline2Type]] = [ -    ("balance_pairs", rules_inline.link_pairs), -    ("strikethrough", rules_inline.strikethrough.postProcess), -    ("emphasis", rules_inline.emphasis.postProcess), -    # rules for pairs separate '**' into its own text tokens, which may be left unused, -    # rule below merges unused segments back with the rest of the text -    ("fragments_join", rules_inline.fragments_join), -] - - -class ParserInline: -    def __init__(self) -> None: -        self.ruler = Ruler[RuleFuncInlineType]() -        for name, rule in _rules: -            self.ruler.push(name, rule) -        # Second ruler used for post-processing (e.g. in emphasis-like rules) -        self.ruler2 = Ruler[RuleFuncInline2Type]() -        for name, rule2 in _rules2: -            self.ruler2.push(name, rule2) - -    def skipToken(self, state: StateInline) -> None: -        """Skip single token by running all rules in validation mode; -        returns `True` if any rule reported success -        """ -        ok = False -        pos = state.pos -        rules = self.ruler.getRules("") -        maxNesting = state.md.options["maxNesting"] -        cache = state.cache - -        if pos in cache: -            state.pos = cache[pos] -            return - -        if state.level < maxNesting: -            for rule in rules: -                #  Increment state.level and decrement it later to limit recursion. -                # It's harmless to do here, because no tokens are created. -                # But ideally, we'd need a separate private state variable for this purpose. -                state.level += 1 -                ok = rule(state, True) -                state.level -= 1 -                if ok: -                    break -        else: -            # Too much nesting, just skip until the end of the paragraph. -            # -            # NOTE: this will cause links to behave incorrectly in the following case, -            #       when an amount of `[` is exactly equal to `maxNesting + 1`: -            # -            #       [[[[[[[[[[[[[[[[[[[[[foo]() -            # -            # TODO: remove this workaround when CM standard will allow nested links -            #       (we can replace it by preventing links from being parsed in -            #       validation mode) -            # -            state.pos = state.posMax - -        if not ok: -            state.pos += 1 -        cache[pos] = state.pos - -    def tokenize(self, state: StateInline) -> None: -        """Generate tokens for input range.""" -        ok = False -        rules = self.ruler.getRules("") -        end = state.posMax -        maxNesting = state.md.options["maxNesting"] - -        while state.pos < end: -            # Try all possible rules. -            # On success, rule should: -            # -            # - update `state.pos` -            # - update `state.tokens` -            # - return true - -            if state.level < maxNesting: -                for rule in rules: -                    ok = rule(state, False) -                    if ok: -                        break - -            if ok: -                if state.pos >= end: -                    break -                continue - -            state.pending += state.src[state.pos] -            state.pos += 1 - -        if state.pending: -            state.pushPending() - -    def parse( -        self, src: str, md: MarkdownIt, env: EnvType, tokens: list[Token] -    ) -> list[Token]: -        """Process input string and push inline tokens into `tokens`""" -        state = StateInline(src, md, env, tokens) -        self.tokenize(state) -        rules2 = self.ruler2.getRules("") -        for rule in rules2: -            rule(state) -        return state.tokens diff --git a/venv/lib/python3.11/site-packages/markdown_it/port.yaml b/venv/lib/python3.11/site-packages/markdown_it/port.yaml deleted file mode 100644 index 3e289e9..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/port.yaml +++ /dev/null @@ -1,48 +0,0 @@ -- package: markdown-it/markdown-it -  version: 13.0.1 -  commit: e843acc9edad115cbf8cf85e676443f01658be08 -  date: May 3, 2022 -  notes: -    - Rename variables that use python built-in names, e.g. -      - `max` -> `maximum` -      - `len` -> `length` -      - `str` -> `string` -    - | -      Convert JS `for` loops to `while` loops -      this is generally the main difference between the codes, -      because in python you can't do e.g. `for {i=1;i<x;i++} {}` -    - | -      `env` is a common Python dictionary, and so does not have attribute access to keys, -      as with JavaScript dictionaries. -      `options` have attribute access only to core markdownit configuration options -    - | -      `Token.attrs` is a dictionary, instead of a list of lists. -      Upstream the list format is only used to guarantee order: https://github.com/markdown-it/markdown-it/issues/142, -      but in Python 3.7+ order of dictionaries is guaranteed. -      One should anyhow use the `attrGet`, `attrSet`, `attrPush` and `attrJoin` methods -      to manipulate `Token.attrs`, which have an identical signature to those upstream. -    - Use python version of `charCodeAt` -    - | -      Use `str` units instead of `int`s to represent Unicode codepoints. -      This provides a significant performance boost -    - | -      In markdown_it/rules_block/reference.py, -      record line range in state.env["references"] and add state.env["duplicate_refs"] -      This is to allow renderers to report on issues regarding references -    - | -      The `MarkdownIt.__init__` signature is slightly different for updating options, -      since you must always specify the config first, e.g. -      use `MarkdownIt("commonmark", {"html": False})` instead of `MarkdownIt({"html": False})` -    - The default configuration preset for `MarkdownIt` is "commonmark" not "default" -    - Allow custom renderer to be passed to `MarkdownIt` -    - | -      change render method signatures -      `func(tokens, idx, options, env, slf)` to -      `func(self, tokens, idx, options, env)` -    - | -      Extensions add render methods by format -      `MarkdownIt.add_render_rule(name, function, fmt="html")`, -      rather than `MarkdownIt.renderer.rules[name] = function` -      and renderers should declare a class property `__output__ = "html"`. -      This allows for extensibility to more than just HTML renderers -    - inline tokens in tables are assigned a map (this is helpful for propagation to children) diff --git a/venv/lib/python3.11/site-packages/markdown_it/presets/__init__.py b/venv/lib/python3.11/site-packages/markdown_it/presets/__init__.py deleted file mode 100644 index 1e6796a..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/presets/__init__.py +++ /dev/null @@ -1,28 +0,0 @@ -__all__ = ("commonmark", "default", "zero", "js_default", "gfm_like") - -from . import commonmark, default, zero -from ..utils import PresetType - -js_default = default - - -class gfm_like:  # noqa: N801 -    """GitHub Flavoured Markdown (GFM) like. - -    This adds the linkify, table and strikethrough components to CommmonMark. - -    Note, it lacks task-list items and raw HTML filtering, -    to meet the the full GFM specification -    (see https://github.github.com/gfm/#autolinks-extension-). -    """ - -    @staticmethod -    def make() -> PresetType: -        config = commonmark.make() -        config["components"]["core"]["rules"].append("linkify") -        config["components"]["block"]["rules"].append("table") -        config["components"]["inline"]["rules"].extend(["strikethrough", "linkify"]) -        config["components"]["inline"]["rules2"].append("strikethrough") -        config["options"]["linkify"] = True -        config["options"]["html"] = True -        return config diff --git a/venv/lib/python3.11/site-packages/markdown_it/presets/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/presets/__pycache__/__init__.cpython-311.pycBinary files differ deleted file mode 100644 index 8e831e4..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/presets/__pycache__/__init__.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/presets/__pycache__/commonmark.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/presets/__pycache__/commonmark.cpython-311.pycBinary files differ deleted file mode 100644 index 75b1981..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/presets/__pycache__/commonmark.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/presets/__pycache__/default.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/presets/__pycache__/default.cpython-311.pycBinary files differ deleted file mode 100644 index 64f5427..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/presets/__pycache__/default.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/presets/__pycache__/zero.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/presets/__pycache__/zero.cpython-311.pycBinary files differ deleted file mode 100644 index d1607f5..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/presets/__pycache__/zero.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/presets/commonmark.py b/venv/lib/python3.11/site-packages/markdown_it/presets/commonmark.py deleted file mode 100644 index 3990d43..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/presets/commonmark.py +++ /dev/null @@ -1,74 +0,0 @@ -"""Commonmark default options. - -This differs to presets.default, -primarily in that it allows HTML and does not enable components: - -- block: table -- inline: strikethrough -""" -from ..utils import PresetType - - -def make() -> PresetType: -    return { -        "options": { -            "maxNesting": 20,  # Internal protection, recursion limit -            "html": True,  # Enable HTML tags in source, -            # this is just a shorthand for .enable(["html_inline", "html_block"]) -            # used by the linkify rule: -            "linkify": False,  # autoconvert URL-like texts to links -            # used by the replacements and smartquotes rules -            # Enable some language-neutral replacements + quotes beautification -            "typographer": False, -            # used by the smartquotes rule: -            # Double + single quotes replacement pairs, when typographer enabled, -            # and smartquotes on. Could be either a String or an Array. -            # -            # For example, you can use '«»„“' for Russian, '„“‚‘' for German, -            # and ['«\xA0', '\xA0»', '‹\xA0', '\xA0›'] for French (including nbsp). -            "quotes": "\u201c\u201d\u2018\u2019",  # /* “”‘’ */ -            # Renderer specific; these options are used directly in the HTML renderer -            "xhtmlOut": True,  # Use '/' to close single tags (<br />) -            "breaks": False,  # Convert '\n' in paragraphs into <br> -            "langPrefix": "language-",  # CSS language prefix for fenced blocks -            # Highlighter function. Should return escaped HTML, -            # or '' if the source string is not changed and should be escaped externally. -            # If result starts with <pre... internal wrapper is skipped. -            # -            # function (/*str, lang, attrs*/) { return ''; } -            # -            "highlight": None, -        }, -        "components": { -            "core": {"rules": ["normalize", "block", "inline", "text_join"]}, -            "block": { -                "rules": [ -                    "blockquote", -                    "code", -                    "fence", -                    "heading", -                    "hr", -                    "html_block", -                    "lheading", -                    "list", -                    "reference", -                    "paragraph", -                ] -            }, -            "inline": { -                "rules": [ -                    "autolink", -                    "backticks", -                    "emphasis", -                    "entity", -                    "escape", -                    "html_inline", -                    "image", -                    "link", -                    "newline", -                    "text", -                ], -                "rules2": ["balance_pairs", "emphasis", "fragments_join"], -            }, -        }, -    } diff --git a/venv/lib/python3.11/site-packages/markdown_it/presets/default.py b/venv/lib/python3.11/site-packages/markdown_it/presets/default.py deleted file mode 100644 index c9ab902..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/presets/default.py +++ /dev/null @@ -1,35 +0,0 @@ -"""markdown-it default options.""" -from ..utils import PresetType - - -def make() -> PresetType: -    return { -        "options": { -            "maxNesting": 100,  # Internal protection, recursion limit -            "html": False,  # Enable HTML tags in source -            # this is just a shorthand for .disable(["html_inline", "html_block"]) -            # used by the linkify rule: -            "linkify": False,  # autoconvert URL-like texts to links -            # used by the replacements and smartquotes rules: -            # Enable some language-neutral replacements + quotes beautification -            "typographer": False, -            # used by the smartquotes rule: -            # Double + single quotes replacement pairs, when typographer enabled, -            # and smartquotes on. Could be either a String or an Array. -            # For example, you can use '«»„“' for Russian, '„“‚‘' for German, -            # and ['«\xA0', '\xA0»', '‹\xA0', '\xA0›'] for French (including nbsp). -            "quotes": "\u201c\u201d\u2018\u2019",  # /* “”‘’ */ -            # Renderer specific; these options are used directly in the HTML renderer -            "xhtmlOut": False,  # Use '/' to close single tags (<br />) -            "breaks": False,  # Convert '\n' in paragraphs into <br> -            "langPrefix": "language-",  # CSS language prefix for fenced blocks -            # Highlighter function. Should return escaped HTML, -            # or '' if the source string is not changed and should be escaped externally. -            # If result starts with <pre... internal wrapper is skipped. -            # -            # function (/*str, lang, attrs*/) { return ''; } -            # -            "highlight": None, -        }, -        "components": {"core": {}, "block": {}, "inline": {}}, -    } diff --git a/venv/lib/python3.11/site-packages/markdown_it/presets/zero.py b/venv/lib/python3.11/site-packages/markdown_it/presets/zero.py deleted file mode 100644 index 2f69a58..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/presets/zero.py +++ /dev/null @@ -1,43 +0,0 @@ -""" -"Zero" preset, with nothing enabled. Useful for manual configuring of simple -modes. For example, to parse bold/italic only. -""" -from ..utils import PresetType - - -def make() -> PresetType: -    return { -        "options": { -            "maxNesting": 20,  # Internal protection, recursion limit -            "html": False,  # Enable HTML tags in source -            # this is just a shorthand for .disable(["html_inline", "html_block"]) -            # used by the linkify rule: -            "linkify": False,  # autoconvert URL-like texts to links -            # used by the replacements and smartquotes rules: -            # Enable some language-neutral replacements + quotes beautification -            "typographer": False, -            # used by the smartquotes rule: -            # Double + single quotes replacement pairs, when typographer enabled, -            # and smartquotes on. Could be either a String or an Array. -            # For example, you can use '«»„“' for Russian, '„“‚‘' for German, -            # and ['«\xA0', '\xA0»', '‹\xA0', '\xA0›'] for French (including nbsp). -            "quotes": "\u201c\u201d\u2018\u2019",  # /* “”‘’ */ -            # Renderer specific; these options are used directly in the HTML renderer -            "xhtmlOut": False,  # Use '/' to close single tags (<br />) -            "breaks": False,  # Convert '\n' in paragraphs into <br> -            "langPrefix": "language-",  # CSS language prefix for fenced blocks -            # Highlighter function. Should return escaped HTML, -            # or '' if the source string is not changed and should be escaped externally. -            # If result starts with <pre... internal wrapper is skipped. -            # function (/*str, lang, attrs*/) { return ''; } -            "highlight": None, -        }, -        "components": { -            "core": {"rules": ["normalize", "block", "inline", "text_join"]}, -            "block": {"rules": ["paragraph"]}, -            "inline": { -                "rules": ["text"], -                "rules2": ["balance_pairs", "fragments_join"], -            }, -        }, -    } diff --git a/venv/lib/python3.11/site-packages/markdown_it/py.typed b/venv/lib/python3.11/site-packages/markdown_it/py.typed deleted file mode 100644 index 7632ecf..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/py.typed +++ /dev/null @@ -1 +0,0 @@ -# Marker file for PEP 561 diff --git a/venv/lib/python3.11/site-packages/markdown_it/renderer.py b/venv/lib/python3.11/site-packages/markdown_it/renderer.py deleted file mode 100644 index 7fee9ff..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/renderer.py +++ /dev/null @@ -1,336 +0,0 @@ -""" -class Renderer - -Generates HTML from parsed token stream. Each instance has independent -copy of rules. Those can be rewritten with ease. Also, you can add new -rules if you create plugin and adds new token types. -""" -from __future__ import annotations - -from collections.abc import Sequence -import inspect -from typing import Any, ClassVar, Protocol - -from .common.utils import escapeHtml, unescapeAll -from .token import Token -from .utils import EnvType, OptionsDict - - -class RendererProtocol(Protocol): -    __output__: ClassVar[str] - -    def render( -        self, tokens: Sequence[Token], options: OptionsDict, env: EnvType -    ) -> Any: -        ... - - -class RendererHTML(RendererProtocol): -    """Contains render rules for tokens. Can be updated and extended. - -    Example: - -    Each rule is called as independent static function with fixed signature: - -    :: - -        class Renderer: -            def token_type_name(self, tokens, idx, options, env) { -                # ... -                return renderedHTML - -    :: - -        class CustomRenderer(RendererHTML): -            def strong_open(self, tokens, idx, options, env): -                return '<b>' -            def strong_close(self, tokens, idx, options, env): -                return '</b>' - -        md = MarkdownIt(renderer_cls=CustomRenderer) - -        result = md.render(...) - -    See https://github.com/markdown-it/markdown-it/blob/master/lib/renderer.js -    for more details and examples. -    """ - -    __output__ = "html" - -    def __init__(self, parser: Any = None): -        self.rules = { -            k: v -            for k, v in inspect.getmembers(self, predicate=inspect.ismethod) -            if not (k.startswith("render") or k.startswith("_")) -        } - -    def render( -        self, tokens: Sequence[Token], options: OptionsDict, env: EnvType -    ) -> str: -        """Takes token stream and generates HTML. - -        :param tokens: list on block tokens to render -        :param options: params of parser instance -        :param env: additional data from parsed input - -        """ -        result = "" - -        for i, token in enumerate(tokens): -            if token.type == "inline": -                if token.children: -                    result += self.renderInline(token.children, options, env) -            elif token.type in self.rules: -                result += self.rules[token.type](tokens, i, options, env) -            else: -                result += self.renderToken(tokens, i, options, env) - -        return result - -    def renderInline( -        self, tokens: Sequence[Token], options: OptionsDict, env: EnvType -    ) -> str: -        """The same as ``render``, but for single token of `inline` type. - -        :param tokens: list on block tokens to render -        :param options: params of parser instance -        :param env: additional data from parsed input (references, for example) -        """ -        result = "" - -        for i, token in enumerate(tokens): -            if token.type in self.rules: -                result += self.rules[token.type](tokens, i, options, env) -            else: -                result += self.renderToken(tokens, i, options, env) - -        return result - -    def renderToken( -        self, -        tokens: Sequence[Token], -        idx: int, -        options: OptionsDict, -        env: EnvType, -    ) -> str: -        """Default token renderer. - -        Can be overridden by custom function - -        :param idx: token index to render -        :param options: params of parser instance -        """ -        result = "" -        needLf = False -        token = tokens[idx] - -        # Tight list paragraphs -        if token.hidden: -            return "" - -        # Insert a newline between hidden paragraph and subsequent opening -        # block-level tag. -        # -        # For example, here we should insert a newline before blockquote: -        #  - a -        #    > -        # -        if token.block and token.nesting != -1 and idx and tokens[idx - 1].hidden: -            result += "\n" - -        # Add token name, e.g. `<img` -        result += ("</" if token.nesting == -1 else "<") + token.tag - -        # Encode attributes, e.g. `<img src="foo"` -        result += self.renderAttrs(token) - -        # Add a slash for self-closing tags, e.g. `<img src="foo" /` -        if token.nesting == 0 and options["xhtmlOut"]: -            result += " /" - -        # Check if we need to add a newline after this tag -        if token.block: -            needLf = True - -            if token.nesting == 1 and (idx + 1 < len(tokens)): -                nextToken = tokens[idx + 1] - -                if nextToken.type == "inline" or nextToken.hidden:  # noqa: SIM114 -                    # Block-level tag containing an inline tag. -                    # -                    needLf = False - -                elif nextToken.nesting == -1 and nextToken.tag == token.tag: -                    # Opening tag + closing tag of the same type. E.g. `<li></li>`. -                    # -                    needLf = False - -        result += ">\n" if needLf else ">" - -        return result - -    @staticmethod -    def renderAttrs(token: Token) -> str: -        """Render token attributes to string.""" -        result = "" - -        for key, value in token.attrItems(): -            result += " " + escapeHtml(key) + '="' + escapeHtml(str(value)) + '"' - -        return result - -    def renderInlineAsText( -        self, -        tokens: Sequence[Token] | None, -        options: OptionsDict, -        env: EnvType, -    ) -> str: -        """Special kludge for image `alt` attributes to conform CommonMark spec. - -        Don't try to use it! Spec requires to show `alt` content with stripped markup, -        instead of simple escaping. - -        :param tokens: list on block tokens to render -        :param options: params of parser instance -        :param env: additional data from parsed input -        """ -        result = "" - -        for token in tokens or []: -            if token.type == "text": -                result += token.content -            elif token.type == "image": -                if token.children: -                    result += self.renderInlineAsText(token.children, options, env) -            elif token.type == "softbreak": -                result += "\n" - -        return result - -    ################################################### - -    def code_inline( -        self, tokens: Sequence[Token], idx: int, options: OptionsDict, env: EnvType -    ) -> str: -        token = tokens[idx] -        return ( -            "<code" -            + self.renderAttrs(token) -            + ">" -            + escapeHtml(tokens[idx].content) -            + "</code>" -        ) - -    def code_block( -        self, -        tokens: Sequence[Token], -        idx: int, -        options: OptionsDict, -        env: EnvType, -    ) -> str: -        token = tokens[idx] - -        return ( -            "<pre" -            + self.renderAttrs(token) -            + "><code>" -            + escapeHtml(tokens[idx].content) -            + "</code></pre>\n" -        ) - -    def fence( -        self, -        tokens: Sequence[Token], -        idx: int, -        options: OptionsDict, -        env: EnvType, -    ) -> str: -        token = tokens[idx] -        info = unescapeAll(token.info).strip() if token.info else "" -        langName = "" -        langAttrs = "" - -        if info: -            arr = info.split(maxsplit=1) -            langName = arr[0] -            if len(arr) == 2: -                langAttrs = arr[1] - -        if options.highlight: -            highlighted = options.highlight( -                token.content, langName, langAttrs -            ) or escapeHtml(token.content) -        else: -            highlighted = escapeHtml(token.content) - -        if highlighted.startswith("<pre"): -            return highlighted + "\n" - -        # If language exists, inject class gently, without modifying original token. -        # May be, one day we will add .deepClone() for token and simplify this part, but -        # now we prefer to keep things local. -        if info: -            # Fake token just to render attributes -            tmpToken = Token(type="", tag="", nesting=0, attrs=token.attrs.copy()) -            tmpToken.attrJoin("class", options.langPrefix + langName) - -            return ( -                "<pre><code" -                + self.renderAttrs(tmpToken) -                + ">" -                + highlighted -                + "</code></pre>\n" -            ) - -        return ( -            "<pre><code" -            + self.renderAttrs(token) -            + ">" -            + highlighted -            + "</code></pre>\n" -        ) - -    def image( -        self, -        tokens: Sequence[Token], -        idx: int, -        options: OptionsDict, -        env: EnvType, -    ) -> str: -        token = tokens[idx] - -        # "alt" attr MUST be set, even if empty. Because it's mandatory and -        # should be placed on proper position for tests. -        if token.children: -            token.attrSet("alt", self.renderInlineAsText(token.children, options, env)) -        else: -            token.attrSet("alt", "") - -        return self.renderToken(tokens, idx, options, env) - -    def hardbreak( -        self, tokens: Sequence[Token], idx: int, options: OptionsDict, env: EnvType -    ) -> str: -        return "<br />\n" if options.xhtmlOut else "<br>\n" - -    def softbreak( -        self, tokens: Sequence[Token], idx: int, options: OptionsDict, env: EnvType -    ) -> str: -        return ( -            ("<br />\n" if options.xhtmlOut else "<br>\n") if options.breaks else "\n" -        ) - -    def text( -        self, tokens: Sequence[Token], idx: int, options: OptionsDict, env: EnvType -    ) -> str: -        return escapeHtml(tokens[idx].content) - -    def html_block( -        self, tokens: Sequence[Token], idx: int, options: OptionsDict, env: EnvType -    ) -> str: -        return tokens[idx].content - -    def html_inline( -        self, tokens: Sequence[Token], idx: int, options: OptionsDict, env: EnvType -    ) -> str: -        return tokens[idx].content diff --git a/venv/lib/python3.11/site-packages/markdown_it/ruler.py b/venv/lib/python3.11/site-packages/markdown_it/ruler.py deleted file mode 100644 index bd8baba..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/ruler.py +++ /dev/null @@ -1,276 +0,0 @@ -""" -class Ruler - -Helper class, used by [[MarkdownIt#core]], [[MarkdownIt#block]] and -[[MarkdownIt#inline]] to manage sequences of functions (rules): - -- keep rules in defined order -- assign the name to each rule -- enable/disable rules -- add/replace rules -- allow assign rules to additional named chains (in the same) -- caching lists of active rules - -You will not need use this class directly until write plugins. For simple -rules control use [[MarkdownIt.disable]], [[MarkdownIt.enable]] and -[[MarkdownIt.use]]. -""" -from __future__ import annotations - -from collections.abc import Iterable -from dataclasses import dataclass, field -from typing import TYPE_CHECKING, Generic, TypedDict, TypeVar -import warnings - -from markdown_it._compat import DATACLASS_KWARGS - -from .utils import EnvType - -if TYPE_CHECKING: -    from markdown_it import MarkdownIt - - -class StateBase: -    def __init__(self, src: str, md: MarkdownIt, env: EnvType): -        self.src = src -        self.env = env -        self.md = md - -    @property -    def src(self) -> str: -        return self._src - -    @src.setter -    def src(self, value: str) -> None: -        self._src = value -        self._srcCharCode: tuple[int, ...] | None = None - -    @property -    def srcCharCode(self) -> tuple[int, ...]: -        warnings.warn( -            "StateBase.srcCharCode is deprecated. Use StateBase.src instead.", -            DeprecationWarning, -            stacklevel=2, -        ) -        if self._srcCharCode is None: -            self._srcCharCode = tuple(ord(c) for c in self._src) -        return self._srcCharCode - - -class RuleOptionsType(TypedDict, total=False): -    alt: list[str] - - -RuleFuncTv = TypeVar("RuleFuncTv") -"""A rule function, whose signature is dependent on the state type.""" - - -@dataclass(**DATACLASS_KWARGS) -class Rule(Generic[RuleFuncTv]): -    name: str -    enabled: bool -    fn: RuleFuncTv = field(repr=False) -    alt: list[str] - - -class Ruler(Generic[RuleFuncTv]): -    def __init__(self) -> None: -        # List of added rules. -        self.__rules__: list[Rule[RuleFuncTv]] = [] -        # Cached rule chains. -        # First level - chain name, '' for default. -        # Second level - diginal anchor for fast filtering by charcodes. -        self.__cache__: dict[str, list[RuleFuncTv]] | None = None - -    def __find__(self, name: str) -> int: -        """Find rule index by name""" -        for i, rule in enumerate(self.__rules__): -            if rule.name == name: -                return i -        return -1 - -    def __compile__(self) -> None: -        """Build rules lookup cache""" -        chains = {""} -        # collect unique names -        for rule in self.__rules__: -            if not rule.enabled: -                continue -            for name in rule.alt: -                chains.add(name) -        self.__cache__ = {} -        for chain in chains: -            self.__cache__[chain] = [] -            for rule in self.__rules__: -                if not rule.enabled: -                    continue -                if chain and (chain not in rule.alt): -                    continue -                self.__cache__[chain].append(rule.fn) - -    def at( -        self, ruleName: str, fn: RuleFuncTv, options: RuleOptionsType | None = None -    ) -> None: -        """Replace rule by name with new function & options. - -        :param ruleName: rule name to replace. -        :param fn: new rule function. -        :param options: new rule options (not mandatory). -        :raises: KeyError if name not found -        """ -        index = self.__find__(ruleName) -        options = options or {} -        if index == -1: -            raise KeyError(f"Parser rule not found: {ruleName}") -        self.__rules__[index].fn = fn -        self.__rules__[index].alt = options.get("alt", []) -        self.__cache__ = None - -    def before( -        self, -        beforeName: str, -        ruleName: str, -        fn: RuleFuncTv, -        options: RuleOptionsType | None = None, -    ) -> None: -        """Add new rule to chain before one with given name. - -        :param beforeName: new rule will be added before this one. -        :param ruleName: new rule will be added before this one. -        :param fn: new rule function. -        :param options: new rule options (not mandatory). -        :raises: KeyError if name not found -        """ -        index = self.__find__(beforeName) -        options = options or {} -        if index == -1: -            raise KeyError(f"Parser rule not found: {beforeName}") -        self.__rules__.insert( -            index, Rule[RuleFuncTv](ruleName, True, fn, options.get("alt", [])) -        ) -        self.__cache__ = None - -    def after( -        self, -        afterName: str, -        ruleName: str, -        fn: RuleFuncTv, -        options: RuleOptionsType | None = None, -    ) -> None: -        """Add new rule to chain after one with given name. - -        :param afterName: new rule will be added after this one. -        :param ruleName: new rule will be added after this one. -        :param fn: new rule function. -        :param options: new rule options (not mandatory). -        :raises: KeyError if name not found -        """ -        index = self.__find__(afterName) -        options = options or {} -        if index == -1: -            raise KeyError(f"Parser rule not found: {afterName}") -        self.__rules__.insert( -            index + 1, Rule[RuleFuncTv](ruleName, True, fn, options.get("alt", [])) -        ) -        self.__cache__ = None - -    def push( -        self, ruleName: str, fn: RuleFuncTv, options: RuleOptionsType | None = None -    ) -> None: -        """Push new rule to the end of chain. - -        :param ruleName: new rule will be added to the end of chain. -        :param fn: new rule function. -        :param options: new rule options (not mandatory). - -        """ -        self.__rules__.append( -            Rule[RuleFuncTv](ruleName, True, fn, (options or {}).get("alt", [])) -        ) -        self.__cache__ = None - -    def enable( -        self, names: str | Iterable[str], ignoreInvalid: bool = False -    ) -> list[str]: -        """Enable rules with given names. - -        :param names: name or list of rule names to enable. -        :param ignoreInvalid: ignore errors when rule not found -        :raises: KeyError if name not found and not ignoreInvalid -        :return: list of found rule names -        """ -        if isinstance(names, str): -            names = [names] -        result: list[str] = [] -        for name in names: -            idx = self.__find__(name) -            if (idx < 0) and ignoreInvalid: -                continue -            if (idx < 0) and not ignoreInvalid: -                raise KeyError(f"Rules manager: invalid rule name {name}") -            self.__rules__[idx].enabled = True -            result.append(name) -        self.__cache__ = None -        return result - -    def enableOnly( -        self, names: str | Iterable[str], ignoreInvalid: bool = False -    ) -> list[str]: -        """Enable rules with given names, and disable everything else. - -        :param names: name or list of rule names to enable. -        :param ignoreInvalid: ignore errors when rule not found -        :raises: KeyError if name not found and not ignoreInvalid -        :return: list of found rule names -        """ -        if isinstance(names, str): -            names = [names] -        for rule in self.__rules__: -            rule.enabled = False -        return self.enable(names, ignoreInvalid) - -    def disable( -        self, names: str | Iterable[str], ignoreInvalid: bool = False -    ) -> list[str]: -        """Disable rules with given names. - -        :param names: name or list of rule names to enable. -        :param ignoreInvalid: ignore errors when rule not found -        :raises: KeyError if name not found and not ignoreInvalid -        :return: list of found rule names -        """ -        if isinstance(names, str): -            names = [names] -        result = [] -        for name in names: -            idx = self.__find__(name) -            if (idx < 0) and ignoreInvalid: -                continue -            if (idx < 0) and not ignoreInvalid: -                raise KeyError(f"Rules manager: invalid rule name {name}") -            self.__rules__[idx].enabled = False -            result.append(name) -        self.__cache__ = None -        return result - -    def getRules(self, chainName: str = "") -> list[RuleFuncTv]: -        """Return array of active functions (rules) for given chain name. -        It analyzes rules configuration, compiles caches if not exists and returns result. - -        Default chain name is `''` (empty string). It can't be skipped. -        That's done intentionally, to keep signature monomorphic for high speed. - -        """ -        if self.__cache__ is None: -            self.__compile__() -            assert self.__cache__ is not None -        # Chain can be empty, if rules disabled. But we still have to return Array. -        return self.__cache__.get(chainName, []) or [] - -    def get_all_rules(self) -> list[str]: -        """Return all available rule names.""" -        return [r.name for r in self.__rules__] - -    def get_active_rules(self) -> list[str]: -        """Return the active rule names.""" -        return [r.name for r in self.__rules__ if r.enabled] diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_block/__init__.py b/venv/lib/python3.11/site-packages/markdown_it/rules_block/__init__.py deleted file mode 100644 index bcf138d..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_block/__init__.py +++ /dev/null @@ -1,27 +0,0 @@ -__all__ = ( -    "StateBlock", -    "paragraph", -    "heading", -    "lheading", -    "code", -    "fence", -    "hr", -    "list_block", -    "reference", -    "blockquote", -    "html_block", -    "table", -) - -from .blockquote import blockquote -from .code import code -from .fence import fence -from .heading import heading -from .hr import hr -from .html_block import html_block -from .lheading import lheading -from .list import list_block -from .paragraph import paragraph -from .reference import reference -from .state_block import StateBlock -from .table import table diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/__init__.cpython-311.pycBinary files differ deleted file mode 100644 index bec9bf5..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/__init__.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/blockquote.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/blockquote.cpython-311.pycBinary files differ deleted file mode 100644 index 1760cd6..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/blockquote.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/code.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/code.cpython-311.pycBinary files differ deleted file mode 100644 index 55bb402..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/code.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/fence.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/fence.cpython-311.pycBinary files differ deleted file mode 100644 index c2a3bd7..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/fence.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/heading.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/heading.cpython-311.pycBinary files differ deleted file mode 100644 index f136f53..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/heading.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/hr.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/hr.cpython-311.pycBinary files differ deleted file mode 100644 index 728038d..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/hr.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/html_block.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/html_block.cpython-311.pycBinary files differ deleted file mode 100644 index 5380c0a..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/html_block.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/lheading.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/lheading.cpython-311.pycBinary files differ deleted file mode 100644 index f7c061d..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/lheading.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/list.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/list.cpython-311.pycBinary files differ deleted file mode 100644 index 96b4b51..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/list.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/paragraph.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/paragraph.cpython-311.pycBinary files differ deleted file mode 100644 index 70deb5f..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/paragraph.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/reference.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/reference.cpython-311.pycBinary files differ deleted file mode 100644 index a776c36..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/reference.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/state_block.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/state_block.cpython-311.pycBinary files differ deleted file mode 100644 index 2f99a61..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/state_block.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/table.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/table.cpython-311.pycBinary files differ deleted file mode 100644 index 95ee334..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_block/__pycache__/table.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_block/blockquote.py b/venv/lib/python3.11/site-packages/markdown_it/rules_block/blockquote.py deleted file mode 100644 index 0c9081b..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_block/blockquote.py +++ /dev/null @@ -1,299 +0,0 @@ -# Block quotes -from __future__ import annotations - -import logging - -from ..common.utils import isStrSpace -from .state_block import StateBlock - -LOGGER = logging.getLogger(__name__) - - -def blockquote(state: StateBlock, startLine: int, endLine: int, silent: bool) -> bool: -    LOGGER.debug( -        "entering blockquote: %s, %s, %s, %s", state, startLine, endLine, silent -    ) - -    oldLineMax = state.lineMax -    pos = state.bMarks[startLine] + state.tShift[startLine] -    max = state.eMarks[startLine] - -    if state.is_code_block(startLine): -        return False - -    # check the block quote marker -    try: -        if state.src[pos] != ">": -            return False -    except IndexError: -        return False -    pos += 1 - -    # we know that it's going to be a valid blockquote, -    # so no point trying to find the end of it in silent mode -    if silent: -        return True - -    # set offset past spaces and ">" -    initial = offset = state.sCount[startLine] + 1 - -    try: -        second_char: str | None = state.src[pos] -    except IndexError: -        second_char = None - -    # skip one optional space after '>' -    if second_char == " ": -        # ' >   test ' -        #     ^ -- position start of line here: -        pos += 1 -        initial += 1 -        offset += 1 -        adjustTab = False -        spaceAfterMarker = True -    elif second_char == "\t": -        spaceAfterMarker = True - -        if (state.bsCount[startLine] + offset) % 4 == 3: -            # '  >\t  test ' -            #       ^ -- position start of line here (tab has width==1) -            pos += 1 -            initial += 1 -            offset += 1 -            adjustTab = False -        else: -            # ' >\t  test ' -            #    ^ -- position start of line here + shift bsCount slightly -            #         to make extra space appear -            adjustTab = True - -    else: -        spaceAfterMarker = False - -    oldBMarks = [state.bMarks[startLine]] -    state.bMarks[startLine] = pos - -    while pos < max: -        ch = state.src[pos] - -        if isStrSpace(ch): -            if ch == "\t": -                offset += ( -                    4 -                    - (offset + state.bsCount[startLine] + (1 if adjustTab else 0)) % 4 -                ) -            else: -                offset += 1 - -        else: -            break - -        pos += 1 - -    oldBSCount = [state.bsCount[startLine]] -    state.bsCount[startLine] = ( -        state.sCount[startLine] + 1 + (1 if spaceAfterMarker else 0) -    ) - -    lastLineEmpty = pos >= max - -    oldSCount = [state.sCount[startLine]] -    state.sCount[startLine] = offset - initial - -    oldTShift = [state.tShift[startLine]] -    state.tShift[startLine] = pos - state.bMarks[startLine] - -    terminatorRules = state.md.block.ruler.getRules("blockquote") - -    oldParentType = state.parentType -    state.parentType = "blockquote" - -    # Search the end of the block -    # -    # Block ends with either: -    #  1. an empty line outside: -    #     ``` -    #     > test -    # -    #     ``` -    #  2. an empty line inside: -    #     ``` -    #     > -    #     test -    #     ``` -    #  3. another tag: -    #     ``` -    #     > test -    #      - - - -    #     ``` - -    # for (nextLine = startLine + 1; nextLine < endLine; nextLine++) { -    nextLine = startLine + 1 -    while nextLine < endLine: -        # check if it's outdented, i.e. it's inside list item and indented -        # less than said list item: -        # -        # ``` -        # 1. anything -        #    > current blockquote -        # 2. checking this line -        # ``` -        isOutdented = state.sCount[nextLine] < state.blkIndent - -        pos = state.bMarks[nextLine] + state.tShift[nextLine] -        max = state.eMarks[nextLine] - -        if pos >= max: -            # Case 1: line is not inside the blockquote, and this line is empty. -            break - -        evaluatesTrue = state.src[pos] == ">" and not isOutdented -        pos += 1 -        if evaluatesTrue: -            # This line is inside the blockquote. - -            # set offset past spaces and ">" -            initial = offset = state.sCount[nextLine] + 1 - -            try: -                next_char: str | None = state.src[pos] -            except IndexError: -                next_char = None - -            # skip one optional space after '>' -            if next_char == " ": -                # ' >   test ' -                #     ^ -- position start of line here: -                pos += 1 -                initial += 1 -                offset += 1 -                adjustTab = False -                spaceAfterMarker = True -            elif next_char == "\t": -                spaceAfterMarker = True - -                if (state.bsCount[nextLine] + offset) % 4 == 3: -                    # '  >\t  test ' -                    #       ^ -- position start of line here (tab has width==1) -                    pos += 1 -                    initial += 1 -                    offset += 1 -                    adjustTab = False -                else: -                    # ' >\t  test ' -                    #    ^ -- position start of line here + shift bsCount slightly -                    #         to make extra space appear -                    adjustTab = True - -            else: -                spaceAfterMarker = False - -            oldBMarks.append(state.bMarks[nextLine]) -            state.bMarks[nextLine] = pos - -            while pos < max: -                ch = state.src[pos] - -                if isStrSpace(ch): -                    if ch == "\t": -                        offset += ( -                            4 -                            - ( -                                offset -                                + state.bsCount[nextLine] -                                + (1 if adjustTab else 0) -                            ) -                            % 4 -                        ) -                    else: -                        offset += 1 -                else: -                    break - -                pos += 1 - -            lastLineEmpty = pos >= max - -            oldBSCount.append(state.bsCount[nextLine]) -            state.bsCount[nextLine] = ( -                state.sCount[nextLine] + 1 + (1 if spaceAfterMarker else 0) -            ) - -            oldSCount.append(state.sCount[nextLine]) -            state.sCount[nextLine] = offset - initial - -            oldTShift.append(state.tShift[nextLine]) -            state.tShift[nextLine] = pos - state.bMarks[nextLine] - -            nextLine += 1 -            continue - -        # Case 2: line is not inside the blockquote, and the last line was empty. -        if lastLineEmpty: -            break - -        # Case 3: another tag found. -        terminate = False - -        for terminatorRule in terminatorRules: -            if terminatorRule(state, nextLine, endLine, True): -                terminate = True -                break - -        if terminate: -            # Quirk to enforce "hard termination mode" for paragraphs; -            # normally if you call `tokenize(state, startLine, nextLine)`, -            # paragraphs will look below nextLine for paragraph continuation, -            # but if blockquote is terminated by another tag, they shouldn't -            state.lineMax = nextLine - -            if state.blkIndent != 0: -                # state.blkIndent was non-zero, we now set it to zero, -                # so we need to re-calculate all offsets to appear as -                # if indent wasn't changed -                oldBMarks.append(state.bMarks[nextLine]) -                oldBSCount.append(state.bsCount[nextLine]) -                oldTShift.append(state.tShift[nextLine]) -                oldSCount.append(state.sCount[nextLine]) -                state.sCount[nextLine] -= state.blkIndent - -            break - -        oldBMarks.append(state.bMarks[nextLine]) -        oldBSCount.append(state.bsCount[nextLine]) -        oldTShift.append(state.tShift[nextLine]) -        oldSCount.append(state.sCount[nextLine]) - -        # A negative indentation means that this is a paragraph continuation -        # -        state.sCount[nextLine] = -1 - -        nextLine += 1 - -    oldIndent = state.blkIndent -    state.blkIndent = 0 - -    token = state.push("blockquote_open", "blockquote", 1) -    token.markup = ">" -    token.map = lines = [startLine, 0] - -    state.md.block.tokenize(state, startLine, nextLine) - -    token = state.push("blockquote_close", "blockquote", -1) -    token.markup = ">" - -    state.lineMax = oldLineMax -    state.parentType = oldParentType -    lines[1] = state.line - -    # Restore original tShift; this might not be necessary since the parser -    # has already been here, but just to make sure we can do that. -    for i, item in enumerate(oldTShift): -        state.bMarks[i + startLine] = oldBMarks[i] -        state.tShift[i + startLine] = item -        state.sCount[i + startLine] = oldSCount[i] -        state.bsCount[i + startLine] = oldBSCount[i] - -    state.blkIndent = oldIndent - -    return True diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_block/code.py b/venv/lib/python3.11/site-packages/markdown_it/rules_block/code.py deleted file mode 100644 index 89db9ce..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_block/code.py +++ /dev/null @@ -1,35 +0,0 @@ -"""Code block (4 spaces padded).""" -import logging - -from .state_block import StateBlock - -LOGGER = logging.getLogger(__name__) - - -def code(state: StateBlock, startLine: int, endLine: int, silent: bool) -> bool: -    LOGGER.debug("entering code: %s, %s, %s, %s", state, startLine, endLine, silent) - -    if not state.is_code_block(startLine): -        return False - -    last = nextLine = startLine + 1 - -    while nextLine < endLine: -        if state.isEmpty(nextLine): -            nextLine += 1 -            continue - -        if state.is_code_block(nextLine): -            nextLine += 1 -            last = nextLine -            continue - -        break - -    state.line = last - -    token = state.push("code_block", "code", 0) -    token.content = state.getLines(startLine, last, 4 + state.blkIndent, False) + "\n" -    token.map = [startLine, state.line] - -    return True diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_block/fence.py b/venv/lib/python3.11/site-packages/markdown_it/rules_block/fence.py deleted file mode 100644 index 263f1b8..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_block/fence.py +++ /dev/null @@ -1,101 +0,0 @@ -# fences (``` lang, ~~~ lang) -import logging - -from .state_block import StateBlock - -LOGGER = logging.getLogger(__name__) - - -def fence(state: StateBlock, startLine: int, endLine: int, silent: bool) -> bool: -    LOGGER.debug("entering fence: %s, %s, %s, %s", state, startLine, endLine, silent) - -    haveEndMarker = False -    pos = state.bMarks[startLine] + state.tShift[startLine] -    maximum = state.eMarks[startLine] - -    if state.is_code_block(startLine): -        return False - -    if pos + 3 > maximum: -        return False - -    marker = state.src[pos] - -    if marker not in ("~", "`"): -        return False - -    # scan marker length -    mem = pos -    pos = state.skipCharsStr(pos, marker) - -    length = pos - mem - -    if length < 3: -        return False - -    markup = state.src[mem:pos] -    params = state.src[pos:maximum] - -    if marker == "`" and marker in params: -        return False - -    # Since start is found, we can report success here in validation mode -    if silent: -        return True - -    # search end of block -    nextLine = startLine - -    while True: -        nextLine += 1 -        if nextLine >= endLine: -            # unclosed block should be autoclosed by end of document. -            # also block seems to be autoclosed by end of parent -            break - -        pos = mem = state.bMarks[nextLine] + state.tShift[nextLine] -        maximum = state.eMarks[nextLine] - -        if pos < maximum and state.sCount[nextLine] < state.blkIndent: -            # non-empty line with negative indent should stop the list: -            # - ``` -            #  test -            break - -        try: -            if state.src[pos] != marker: -                continue -        except IndexError: -            break - -        if state.is_code_block(nextLine): -            continue - -        pos = state.skipCharsStr(pos, marker) - -        # closing code fence must be at least as long as the opening one -        if pos - mem < length: -            continue - -        # make sure tail has spaces only -        pos = state.skipSpaces(pos) - -        if pos < maximum: -            continue - -        haveEndMarker = True -        # found! -        break - -    # If a fence has heading spaces, they should be removed from its inner block -    length = state.sCount[startLine] - -    state.line = nextLine + (1 if haveEndMarker else 0) - -    token = state.push("fence", "code", 0) -    token.info = params -    token.content = state.getLines(startLine + 1, nextLine, length, True) -    token.markup = markup -    token.map = [startLine, state.line] - -    return True diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_block/heading.py b/venv/lib/python3.11/site-packages/markdown_it/rules_block/heading.py deleted file mode 100644 index 850ffb5..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_block/heading.py +++ /dev/null @@ -1,68 +0,0 @@ -""" Atex heading (#, ##, ...) """ -from __future__ import annotations - -import logging - -from ..common.utils import isStrSpace -from .state_block import StateBlock - -LOGGER = logging.getLogger(__name__) - - -def heading(state: StateBlock, startLine: int, endLine: int, silent: bool) -> bool: -    LOGGER.debug("entering heading: %s, %s, %s, %s", state, startLine, endLine, silent) - -    pos = state.bMarks[startLine] + state.tShift[startLine] -    maximum = state.eMarks[startLine] - -    if state.is_code_block(startLine): -        return False - -    ch: str | None = state.src[pos] - -    if ch != "#" or pos >= maximum: -        return False - -    # count heading level -    level = 1 -    pos += 1 -    try: -        ch = state.src[pos] -    except IndexError: -        ch = None -    while ch == "#" and pos < maximum and level <= 6: -        level += 1 -        pos += 1 -        try: -            ch = state.src[pos] -        except IndexError: -            ch = None - -    if level > 6 or (pos < maximum and not isStrSpace(ch)): -        return False - -    if silent: -        return True - -    # Let's cut tails like '    ###  ' from the end of string - -    maximum = state.skipSpacesBack(maximum, pos) -    tmp = state.skipCharsStrBack(maximum, "#", pos) -    if tmp > pos and isStrSpace(state.src[tmp - 1]): -        maximum = tmp - -    state.line = startLine + 1 - -    token = state.push("heading_open", "h" + str(level), 1) -    token.markup = "########"[:level] -    token.map = [startLine, state.line] - -    token = state.push("inline", "", 0) -    token.content = state.src[pos:maximum].strip() -    token.map = [startLine, state.line] -    token.children = [] - -    token = state.push("heading_close", "h" + str(level), -1) -    token.markup = "########"[:level] - -    return True diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_block/hr.py b/venv/lib/python3.11/site-packages/markdown_it/rules_block/hr.py deleted file mode 100644 index 16df05f..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_block/hr.py +++ /dev/null @@ -1,55 +0,0 @@ -"""Horizontal rule - -At least 3 of these characters on a line * - _ -""" -import logging - -from ..common.utils import isStrSpace -from .state_block import StateBlock - -LOGGER = logging.getLogger(__name__) - - -def hr(state: StateBlock, startLine: int, endLine: int, silent: bool) -> bool: -    LOGGER.debug("entering hr: %s, %s, %s, %s", state, startLine, endLine, silent) - -    pos = state.bMarks[startLine] + state.tShift[startLine] -    maximum = state.eMarks[startLine] - -    if state.is_code_block(startLine): -        return False - -    try: -        marker = state.src[pos] -    except IndexError: -        return False -    pos += 1 - -    # Check hr marker -    if marker not in ("*", "-", "_"): -        return False - -    # markers can be mixed with spaces, but there should be at least 3 of them - -    cnt = 1 -    while pos < maximum: -        ch = state.src[pos] -        pos += 1 -        if ch != marker and not isStrSpace(ch): -            return False -        if ch == marker: -            cnt += 1 - -    if cnt < 3: -        return False - -    if silent: -        return True - -    state.line = startLine + 1 - -    token = state.push("hr", "hr", 0) -    token.map = [startLine, state.line] -    token.markup = marker * (cnt + 1) - -    return True diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_block/html_block.py b/venv/lib/python3.11/site-packages/markdown_it/rules_block/html_block.py deleted file mode 100644 index 3d43f6e..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_block/html_block.py +++ /dev/null @@ -1,90 +0,0 @@ -# HTML block -from __future__ import annotations - -import logging -import re - -from ..common.html_blocks import block_names -from ..common.html_re import HTML_OPEN_CLOSE_TAG_STR -from .state_block import StateBlock - -LOGGER = logging.getLogger(__name__) - -# An array of opening and corresponding closing sequences for html tags, -# last argument defines whether it can terminate a paragraph or not -HTML_SEQUENCES: list[tuple[re.Pattern[str], re.Pattern[str], bool]] = [ -    ( -        re.compile(r"^<(script|pre|style|textarea)(?=(\s|>|$))", re.IGNORECASE), -        re.compile(r"<\/(script|pre|style|textarea)>", re.IGNORECASE), -        True, -    ), -    (re.compile(r"^<!--"), re.compile(r"-->"), True), -    (re.compile(r"^<\?"), re.compile(r"\?>"), True), -    (re.compile(r"^<![A-Z]"), re.compile(r">"), True), -    (re.compile(r"^<!\[CDATA\["), re.compile(r"\]\]>"), True), -    ( -        re.compile("^</?(" + "|".join(block_names) + ")(?=(\\s|/?>|$))", re.IGNORECASE), -        re.compile(r"^$"), -        True, -    ), -    (re.compile(HTML_OPEN_CLOSE_TAG_STR + "\\s*$"), re.compile(r"^$"), False), -] - - -def html_block(state: StateBlock, startLine: int, endLine: int, silent: bool) -> bool: -    LOGGER.debug( -        "entering html_block: %s, %s, %s, %s", state, startLine, endLine, silent -    ) -    pos = state.bMarks[startLine] + state.tShift[startLine] -    maximum = state.eMarks[startLine] - -    if state.is_code_block(startLine): -        return False - -    if not state.md.options.get("html", None): -        return False - -    if state.src[pos] != "<": -        return False - -    lineText = state.src[pos:maximum] - -    html_seq = None -    for HTML_SEQUENCE in HTML_SEQUENCES: -        if HTML_SEQUENCE[0].search(lineText): -            html_seq = HTML_SEQUENCE -            break - -    if not html_seq: -        return False - -    if silent: -        # true if this sequence can be a terminator, false otherwise -        return html_seq[2] - -    nextLine = startLine + 1 - -    # If we are here - we detected HTML block. -    # Let's roll down till block end. -    if not html_seq[1].search(lineText): -        while nextLine < endLine: -            if state.sCount[nextLine] < state.blkIndent: -                break - -            pos = state.bMarks[nextLine] + state.tShift[nextLine] -            maximum = state.eMarks[nextLine] -            lineText = state.src[pos:maximum] - -            if html_seq[1].search(lineText): -                if len(lineText) != 0: -                    nextLine += 1 -                break -            nextLine += 1 - -    state.line = nextLine - -    token = state.push("html_block", "", 0) -    token.map = [startLine, nextLine] -    token.content = state.getLines(startLine, nextLine, state.blkIndent, True) - -    return True diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_block/lheading.py b/venv/lib/python3.11/site-packages/markdown_it/rules_block/lheading.py deleted file mode 100644 index 3522207..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_block/lheading.py +++ /dev/null @@ -1,86 +0,0 @@ -# lheading (---, ==) -import logging - -from .state_block import StateBlock - -LOGGER = logging.getLogger(__name__) - - -def lheading(state: StateBlock, startLine: int, endLine: int, silent: bool) -> bool: -    LOGGER.debug("entering lheading: %s, %s, %s, %s", state, startLine, endLine, silent) - -    level = None -    nextLine = startLine + 1 -    ruler = state.md.block.ruler -    terminatorRules = ruler.getRules("paragraph") - -    if state.is_code_block(startLine): -        return False - -    oldParentType = state.parentType -    state.parentType = "paragraph"  # use paragraph to match terminatorRules - -    # jump line-by-line until empty one or EOF -    while nextLine < endLine and not state.isEmpty(nextLine): -        # this would be a code block normally, but after paragraph -        # it's considered a lazy continuation regardless of what's there -        if state.sCount[nextLine] - state.blkIndent > 3: -            nextLine += 1 -            continue - -        # Check for underline in setext header -        if state.sCount[nextLine] >= state.blkIndent: -            pos = state.bMarks[nextLine] + state.tShift[nextLine] -            maximum = state.eMarks[nextLine] - -            if pos < maximum: -                marker = state.src[pos] - -                if marker in ("-", "="): -                    pos = state.skipCharsStr(pos, marker) -                    pos = state.skipSpaces(pos) - -                    # /* = */ -                    if pos >= maximum: -                        level = 1 if marker == "=" else 2 -                        break - -        # quirk for blockquotes, this line should already be checked by that rule -        if state.sCount[nextLine] < 0: -            nextLine += 1 -            continue - -        # Some tags can terminate paragraph without empty line. -        terminate = False -        for terminatorRule in terminatorRules: -            if terminatorRule(state, nextLine, endLine, True): -                terminate = True -                break -        if terminate: -            break - -        nextLine += 1 - -    if not level: -        # Didn't find valid underline -        return False - -    content = state.getLines(startLine, nextLine, state.blkIndent, False).strip() - -    state.line = nextLine + 1 - -    token = state.push("heading_open", "h" + str(level), 1) -    token.markup = marker -    token.map = [startLine, state.line] - -    token = state.push("inline", "", 0) -    token.content = content -    token.map = [startLine, state.line - 1] -    token.children = [] - -    token = state.push("heading_close", "h" + str(level), -1) -    token.markup = marker - -    state.parentType = oldParentType - -    return True diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_block/list.py b/venv/lib/python3.11/site-packages/markdown_it/rules_block/list.py deleted file mode 100644 index d8070d7..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_block/list.py +++ /dev/null @@ -1,345 +0,0 @@ -# Lists -import logging - -from ..common.utils import isStrSpace -from .state_block import StateBlock - -LOGGER = logging.getLogger(__name__) - - -# Search `[-+*][\n ]`, returns next pos after marker on success -# or -1 on fail. -def skipBulletListMarker(state: StateBlock, startLine: int) -> int: -    pos = state.bMarks[startLine] + state.tShift[startLine] -    maximum = state.eMarks[startLine] - -    try: -        marker = state.src[pos] -    except IndexError: -        return -1 -    pos += 1 - -    if marker not in ("*", "-", "+"): -        return -1 - -    if pos < maximum: -        ch = state.src[pos] - -        if not isStrSpace(ch): -            # " -test " - is not a list item -            return -1 - -    return pos - - -# Search `\d+[.)][\n ]`, returns next pos after marker on success -# or -1 on fail. -def skipOrderedListMarker(state: StateBlock, startLine: int) -> int: -    start = state.bMarks[startLine] + state.tShift[startLine] -    pos = start -    maximum = state.eMarks[startLine] - -    # List marker should have at least 2 chars (digit + dot) -    if pos + 1 >= maximum: -        return -1 - -    ch = state.src[pos] -    pos += 1 - -    ch_ord = ord(ch) -    # /* 0 */  /* 9 */ -    if ch_ord < 0x30 or ch_ord > 0x39: -        return -1 - -    while True: -        # EOL -> fail -        if pos >= maximum: -            return -1 - -        ch = state.src[pos] -        pos += 1 - -        # /* 0 */  /* 9 */ -        ch_ord = ord(ch) -        if ch_ord >= 0x30 and ch_ord <= 0x39: -            # List marker should have no more than 9 digits -            # (prevents integer overflow in browsers) -            if pos - start >= 10: -                return -1 - -            continue - -        # found valid marker -        if ch in (")", "."): -            break - -        return -1 - -    if pos < maximum: -        ch = state.src[pos] - -        if not isStrSpace(ch): -            # " 1.test " - is not a list item -            return -1 - -    return pos - - -def markTightParagraphs(state: StateBlock, idx: int) -> None: -    level = state.level + 2 - -    i = idx + 2 -    length = len(state.tokens) - 2 -    while i < length: -        if state.tokens[i].level == level and state.tokens[i].type == "paragraph_open": -            state.tokens[i + 2].hidden = True -            state.tokens[i].hidden = True -            i += 2 -        i += 1 - - -def list_block(state: StateBlock, startLine: int, endLine: int, silent: bool) -> bool: -    LOGGER.debug("entering list: %s, %s, %s, %s", state, startLine, endLine, silent) - -    isTerminatingParagraph = False -    tight = True - -    if state.is_code_block(startLine): -        return False - -    # Special case: -    #  - item 1 -    #   - item 2 -    #    - item 3 -    #     - item 4 -    #      - this one is a paragraph continuation -    if ( -        state.listIndent >= 0 -        and state.sCount[startLine] - state.listIndent >= 4 -        and state.sCount[startLine] < state.blkIndent -    ): -        return False - -    # limit conditions when list can interrupt -    # a paragraph (validation mode only) -    # Next list item should still terminate previous list item -    # -    # This code can fail if plugins use blkIndent as well as lists, -    # but I hope the spec gets fixed long before that happens. -    # -    if ( -        silent -        and state.parentType == "paragraph" -        and state.sCount[startLine] >= state.blkIndent -    ): -        isTerminatingParagraph = True - -    # Detect list type and position after marker -    posAfterMarker = skipOrderedListMarker(state, startLine) -    if posAfterMarker >= 0: -        isOrdered = True -        start = state.bMarks[startLine] + state.tShift[startLine] -        markerValue = int(state.src[start : posAfterMarker - 1]) - -        # If we're starting a new ordered list right after -        # a paragraph, it should start with 1. -        if isTerminatingParagraph and markerValue != 1: -            return False -    else: -        posAfterMarker = skipBulletListMarker(state, startLine) -        if posAfterMarker >= 0: -            isOrdered = False -        else: -            return False - -    # If we're starting a new unordered list right after -    # a paragraph, first line should not be empty. -    if ( -        isTerminatingParagraph -        and state.skipSpaces(posAfterMarker) >= state.eMarks[startLine] -    ): -        return False - -    # We should terminate list on style change. Remember first one to compare. -    markerChar = state.src[posAfterMarker - 1] - -    # For validation mode we can terminate immediately -    if silent: -        return True - -    # Start list -    listTokIdx = len(state.tokens) - -    if isOrdered: -        token = state.push("ordered_list_open", "ol", 1) -        if markerValue != 1: -            token.attrs = {"start": markerValue} - -    else: -        token = state.push("bullet_list_open", "ul", 1) - -    token.map = listLines = [startLine, 0] -    token.markup = markerChar - -    # -    # Iterate list items -    # - -    nextLine = startLine -    prevEmptyEnd = False -    terminatorRules = state.md.block.ruler.getRules("list") - -    oldParentType = state.parentType -    state.parentType = "list" - -    while nextLine < endLine: -        pos = posAfterMarker -        maximum = state.eMarks[nextLine] - -        initial = offset = ( -            state.sCount[nextLine] -            + posAfterMarker -            - (state.bMarks[startLine] + state.tShift[startLine]) -        ) - -        while pos < maximum: -            ch = state.src[pos] - -            if ch == "\t": -                offset += 4 - (offset + state.bsCount[nextLine]) % 4 -            elif ch == " ": -                offset += 1 -            else: -                break - -            pos += 1 - -        contentStart = pos - -        # trimming space in "-    \n  3" case, indent is 1 here -        indentAfterMarker = 1 if contentStart >= maximum else offset - initial - -        # If we have more than 4 spaces, the indent is 1 -        # (the rest is just indented code block) -        if indentAfterMarker > 4: -            indentAfterMarker = 1 - -        # "  -  test" -        #  ^^^^^ - calculating total length of this thing -        indent = initial + indentAfterMarker - -        # Run subparser & write tokens -        token = state.push("list_item_open", "li", 1) -        token.markup = markerChar -        token.map = itemLines = [startLine, 0] -        if isOrdered: -            token.info = state.src[start : posAfterMarker - 1] - -        # change current state, then restore it after parser subcall -        oldTight = state.tight -        oldTShift = state.tShift[startLine] -        oldSCount = state.sCount[startLine] - -        #  - example list -        # ^ listIndent position will be here -        #   ^ blkIndent position will be here -        # -        oldListIndent = state.listIndent -        state.listIndent = state.blkIndent -        state.blkIndent = indent - -        state.tight = True -        state.tShift[startLine] = contentStart - state.bMarks[startLine] -        state.sCount[startLine] = offset - -        if contentStart >= maximum and state.isEmpty(startLine + 1): -            # workaround for this case -            # (list item is empty, list terminates before "foo"): -            # ~~~~~~~~ -            #   - -            # -            #     foo -            # ~~~~~~~~ -            state.line = min(state.line + 2, endLine) -        else: -            # NOTE in list.js this was: -            # state.md.block.tokenize(state, startLine, endLine, True) -            # but  tokeniz does not take the final parameter -            state.md.block.tokenize(state, startLine, endLine) - -        # If any of list item is tight, mark list as tight -        if (not state.tight) or prevEmptyEnd: -            tight = False - -        # Item become loose if finish with empty line, -        # but we should filter last element, because it means list finish -        prevEmptyEnd = (state.line - startLine) > 1 and state.isEmpty(state.line - 1) - -        state.blkIndent = state.listIndent -        state.listIndent = oldListIndent -        state.tShift[startLine] = oldTShift -        state.sCount[startLine] = oldSCount -        state.tight = oldTight - -        token = state.push("list_item_close", "li", -1) -        token.markup = markerChar - -        nextLine = startLine = state.line -        itemLines[1] = nextLine - -        if nextLine >= endLine: -            break - -        contentStart = state.bMarks[startLine] - -        # -        # Try to check if list is terminated or continued. -        # -        if state.sCount[nextLine] < state.blkIndent: -            break - -        if state.is_code_block(startLine): -            break - -        # fail if terminating block found -        terminate = False -        for terminatorRule in terminatorRules: -            if terminatorRule(state, nextLine, endLine, True): -                terminate = True -                break - -        if terminate: -            break - -        # fail if list has another type -        if isOrdered: -            posAfterMarker = skipOrderedListMarker(state, nextLine) -            if posAfterMarker < 0: -                break -            start = state.bMarks[nextLine] + state.tShift[nextLine] -        else: -            posAfterMarker = skipBulletListMarker(state, nextLine) -            if posAfterMarker < 0: -                break - -        if markerChar != state.src[posAfterMarker - 1]: -            break - -    # Finalize list -    if isOrdered: -        token = state.push("ordered_list_close", "ol", -1) -    else: -        token = state.push("bullet_list_close", "ul", -1) - -    token.markup = markerChar - -    listLines[1] = nextLine -    state.line = nextLine - -    state.parentType = oldParentType - -    # mark paragraphs tight if needed -    if tight: -        markTightParagraphs(state, listTokIdx) - -    return True diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_block/paragraph.py b/venv/lib/python3.11/site-packages/markdown_it/rules_block/paragraph.py deleted file mode 100644 index 5388a4b..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_block/paragraph.py +++ /dev/null @@ -1,65 +0,0 @@ -"""Paragraph.""" -import logging - -from .state_block import StateBlock - -LOGGER = logging.getLogger(__name__) - - -def paragraph(state: StateBlock, startLine: int, endLine: int, silent: bool) -> bool: -    LOGGER.debug( -        "entering paragraph: %s, %s, %s, %s", state, startLine, endLine, silent -    ) - -    nextLine = startLine + 1 -    ruler = state.md.block.ruler -    terminatorRules = ruler.getRules("paragraph") -    endLine = state.lineMax - -    oldParentType = state.parentType -    state.parentType = "paragraph" - -    # jump line-by-line until empty one or EOF -    while nextLine < endLine: -        if state.isEmpty(nextLine): -            break -        # this would be a code block normally, but after paragraph -        # it's considered a lazy continuation regardless of what's there -        if state.sCount[nextLine] - state.blkIndent > 3: -            nextLine += 1 -            continue - -        # quirk for blockquotes, this line should already be checked by that rule -        if state.sCount[nextLine] < 0: -            nextLine += 1 -            continue - -        # Some tags can terminate paragraph without empty line. -        terminate = False -        for terminatorRule in terminatorRules: -            if terminatorRule(state, nextLine, endLine, True): -                terminate = True -                break - -        if terminate: -            break - -        nextLine += 1 - -    content = state.getLines(startLine, nextLine, state.blkIndent, False).strip() - -    state.line = nextLine - -    token = state.push("paragraph_open", "p", 1) -    token.map = [startLine, state.line] - -    token = state.push("inline", "", 0) -    token.content = content -    token.map = [startLine, state.line] -    token.children = [] - -    token = state.push("paragraph_close", "p", -1) - -    state.parentType = oldParentType - -    return True diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_block/reference.py b/venv/lib/python3.11/site-packages/markdown_it/rules_block/reference.py deleted file mode 100644 index b77944b..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_block/reference.py +++ /dev/null @@ -1,215 +0,0 @@ -import logging - -from ..common.utils import charCodeAt, isSpace, normalizeReference -from .state_block import StateBlock - -LOGGER = logging.getLogger(__name__) - - -def reference(state: StateBlock, startLine: int, _endLine: int, silent: bool) -> bool: -    LOGGER.debug( -        "entering reference: %s, %s, %s, %s", state, startLine, _endLine, silent -    ) - -    lines = 0 -    pos = state.bMarks[startLine] + state.tShift[startLine] -    maximum = state.eMarks[startLine] -    nextLine = startLine + 1 - -    if state.is_code_block(startLine): -        return False - -    if state.src[pos] != "[": -        return False - -    # Simple check to quickly interrupt scan on [link](url) at the start of line. -    # Can be useful on practice: https:#github.com/markdown-it/markdown-it/issues/54 -    while pos < maximum: -        # /* ] */  /* \ */  /* : */ -        if state.src[pos] == "]" and state.src[pos - 1] != "\\": -            if pos + 1 == maximum: -                return False -            if state.src[pos + 1] != ":": -                return False -            break -        pos += 1 - -    endLine = state.lineMax - -    # jump line-by-line until empty one or EOF -    terminatorRules = state.md.block.ruler.getRules("reference") - -    oldParentType = state.parentType -    state.parentType = "reference" - -    while nextLine < endLine and not state.isEmpty(nextLine): -        # this would be a code block normally, but after paragraph -        # it's considered a lazy continuation regardless of what's there -        if state.sCount[nextLine] - state.blkIndent > 3: -            nextLine += 1 -            continue - -        # quirk for blockquotes, this line should already be checked by that rule -        if state.sCount[nextLine] < 0: -            nextLine += 1 -            continue - -        # Some tags can terminate paragraph without empty line. -        terminate = False -        for terminatorRule in terminatorRules: -            if terminatorRule(state, nextLine, endLine, True): -                terminate = True -                break - -        if terminate: -            break - -        nextLine += 1 - -    string = state.getLines(startLine, nextLine, state.blkIndent, False).strip() -    maximum = len(string) - -    labelEnd = None -    pos = 1 -    while pos < maximum: -        ch = charCodeAt(string, pos) -        if ch == 0x5B:  # /* [ */ -            return False -        elif ch == 0x5D:  # /* ] */ -            labelEnd = pos -            break -        elif ch == 0x0A:  # /* \n */ -            lines += 1 -        elif ch == 0x5C:  # /* \ */ -            pos += 1 -            if pos < maximum and charCodeAt(string, pos) == 0x0A: -                lines += 1 -        pos += 1 - -    if ( -        labelEnd is None or labelEnd < 0 or charCodeAt(string, labelEnd + 1) != 0x3A -    ):  # /* : */ -        return False - -    # [label]:   destination   'title' -    #         ^^^ skip optional whitespace here -    pos = labelEnd + 2 -    while pos < maximum: -        ch = charCodeAt(string, pos) -        if ch == 0x0A: -            lines += 1 -        elif isSpace(ch): -            pass -        else: -            break -        pos += 1 - -    # [label]:   destination   'title' -    #            ^^^^^^^^^^^ parse this -    res = state.md.helpers.parseLinkDestination(string, pos, maximum) -    if not res.ok: -        return False - -    href = state.md.normalizeLink(res.str) -    if not state.md.validateLink(href): -        return False - -    pos = res.pos -    lines += res.lines - -    # save cursor state, we could require to rollback later -    destEndPos = pos -    destEndLineNo = lines - -    # [label]:   destination   'title' -    #                       ^^^ skipping those spaces -    start = pos -    while pos < maximum: -        ch = charCodeAt(string, pos) -        if ch == 0x0A: -            lines += 1 -        elif isSpace(ch): -            pass -        else: -            break -        pos += 1 - -    # [label]:   destination   'title' -    #                          ^^^^^^^ parse this -    res = state.md.helpers.parseLinkTitle(string, pos, maximum) -    if pos < maximum and start != pos and res.ok: -        title = res.str -        pos = res.pos -        lines += res.lines -    else: -        title = "" -        pos = destEndPos -        lines = destEndLineNo - -    # skip trailing spaces until the rest of the line -    while pos < maximum: -        ch = charCodeAt(string, pos) -        if not isSpace(ch): -            break -        pos += 1 - -    if pos < maximum and charCodeAt(string, pos) != 0x0A and title: -        # garbage at the end of the line after title, -        # but it could still be a valid reference if we roll back -        title = "" -        pos = destEndPos -        lines = destEndLineNo -        while pos < maximum: -            ch = charCodeAt(string, pos) -            if not isSpace(ch): -                break -            pos += 1 - -    if pos < maximum and charCodeAt(string, pos) != 0x0A: -        # garbage at the end of the line -        return False - -    label = normalizeReference(string[1:labelEnd]) -    if not label: -        # CommonMark 0.20 disallows empty labels -        return False - -    # Reference can not terminate anything. This check is for safety only. -    if silent: -        return True - -    if "references" not in state.env: -        state.env["references"] = {} - -    state.line = startLine + lines + 1 - -    # note, this is not part of markdown-it JS, but is useful for renderers -    if state.md.options.get("inline_definitions", False): -        token = state.push("definition", "", 0) -        token.meta = { -            "id": label, -            "title": title, -            "url": href, -            "label": string[1:labelEnd], -        } -        token.map = [startLine, state.line] - -    if label not in state.env["references"]: -        state.env["references"][label] = { -            "title": title, -            "href": href, -            "map": [startLine, state.line], -        } -    else: -        state.env.setdefault("duplicate_refs", []).append( -            { -                "title": title, -                "href": href, -                "label": label, -                "map": [startLine, state.line], -            } -        ) - -    state.parentType = oldParentType - -    return True diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_block/state_block.py b/venv/lib/python3.11/site-packages/markdown_it/rules_block/state_block.py deleted file mode 100644 index 445ad26..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_block/state_block.py +++ /dev/null @@ -1,261 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING, Literal - -from ..common.utils import isStrSpace -from ..ruler import StateBase -from ..token import Token -from ..utils import EnvType - -if TYPE_CHECKING: -    from markdown_it.main import MarkdownIt - - -class StateBlock(StateBase): -    def __init__( -        self, src: str, md: MarkdownIt, env: EnvType, tokens: list[Token] -    ) -> None: -        self.src = src - -        # link to parser instance -        self.md = md - -        self.env = env - -        # -        # Internal state variables -        # - -        self.tokens = tokens - -        self.bMarks: list[int] = []  # line begin offsets for fast jumps -        self.eMarks: list[int] = []  # line end offsets for fast jumps -        # offsets of the first non-space characters (tabs not expanded) -        self.tShift: list[int] = [] -        self.sCount: list[int] = []  # indents for each line (tabs expanded) - -        # An amount of virtual spaces (tabs expanded) between beginning -        # of each line (bMarks) and real beginning of that line. -        # -        # It exists only as a hack because blockquotes override bMarks -        # losing information in the process. -        # -        # It's used only when expanding tabs, you can think about it as -        # an initial tab length, e.g. bsCount=21 applied to string `\t123` -        # means first tab should be expanded to 4-21%4 === 3 spaces. -        # -        self.bsCount: list[int] = [] - -        # block parser variables -        self.blkIndent = 0  # required block content indent (for example, if we are -        # inside a list, it would be positioned after list marker) -        self.line = 0  # line index in src -        self.lineMax = 0  # lines count -        self.tight = False  # loose/tight mode for lists -        self.ddIndent = -1  # indent of the current dd block (-1 if there isn't any) -        self.listIndent = -1  # indent of the current list block (-1 if there isn't any) - -        # can be 'blockquote', 'list', 'root', 'paragraph' or 'reference' -        # used in lists to determine if they interrupt a paragraph -        self.parentType = "root" - -        self.level = 0 - -        # renderer -        self.result = "" - -        # Create caches -        # Generate markers. -        indent_found = False - -        start = pos = indent = offset = 0 -        length = len(self.src) - -        for pos, character in enumerate(self.src): -            if not indent_found: -                if isStrSpace(character): -                    indent += 1 - -                    if character == "\t": -                        offset += 4 - offset % 4 -                    else: -                        offset += 1 -                    continue -                else: -                    indent_found = True - -            if character == "\n" or pos == length - 1: -                if character != "\n": -                    pos += 1 -                self.bMarks.append(start) -                self.eMarks.append(pos) -                self.tShift.append(indent) -                self.sCount.append(offset) -                self.bsCount.append(0) - -                indent_found = False -                indent = 0 -                offset = 0 -                start = pos + 1 - -        # Push fake entry to simplify cache bounds checks -        self.bMarks.append(length) -        self.eMarks.append(length) -        self.tShift.append(0) -        self.sCount.append(0) -        self.bsCount.append(0) - -        self.lineMax = len(self.bMarks) - 1  # don't count last fake line - -        # pre-check if code blocks are enabled, to speed up is_code_block method -        self._code_enabled = "code" in self.md["block"].ruler.get_active_rules() - -    def __repr__(self) -> str: -        return ( -            f"{self.__class__.__name__}" -            f"(line={self.line},level={self.level},tokens={len(self.tokens)})" -        ) - -    def push(self, ttype: str, tag: str, nesting: Literal[-1, 0, 1]) -> Token: -        """Push new token to "stream".""" -        token = Token(ttype, tag, nesting) -        token.block = True -        if nesting < 0: -            self.level -= 1  # closing tag -        token.level = self.level -        if nesting > 0: -            self.level += 1  # opening tag -        self.tokens.append(token) -        return token - -    def isEmpty(self, line: int) -> bool: -        """.""" -        return (self.bMarks[line] + self.tShift[line]) >= self.eMarks[line] - -    def skipEmptyLines(self, from_pos: int) -> int: -        """.""" -        while from_pos < self.lineMax: -            try: -                if (self.bMarks[from_pos] + self.tShift[from_pos]) < self.eMarks[ -                    from_pos -                ]: -                    break -            except IndexError: -                pass -            from_pos += 1 -        return from_pos - -    def skipSpaces(self, pos: int) -> int: -        """Skip spaces from given position.""" -        while True: -            try: -                current = self.src[pos] -            except IndexError: -                break -            if not isStrSpace(current): -                break -            pos += 1 -        return pos - -    def skipSpacesBack(self, pos: int, minimum: int) -> int: -        """Skip spaces from given position in reverse.""" -        if pos <= minimum: -            return pos -        while pos > minimum: -            pos -= 1 -            if not isStrSpace(self.src[pos]): -                return pos + 1 -        return pos - -    def skipChars(self, pos: int, code: int) -> int: -        """Skip character code from given position.""" -        while True: -            try: -                current = self.srcCharCode[pos] -            except IndexError: -                break -            if current != code: -                break -            pos += 1 -        return pos - -    def skipCharsStr(self, pos: int, ch: str) -> int: -        """Skip character string from given position.""" -        while True: -            try: -                current = self.src[pos] -            except IndexError: -                break -            if current != ch: -                break -            pos += 1 -        return pos - -    def skipCharsBack(self, pos: int, code: int, minimum: int) -> int: -        """Skip character code reverse from given position - 1.""" -        if pos <= minimum: -            return pos -        while pos > minimum: -            pos -= 1 -            if code != self.srcCharCode[pos]: -                return pos + 1 -        return pos - -    def skipCharsStrBack(self, pos: int, ch: str, minimum: int) -> int: -        """Skip character string reverse from given position - 1.""" -        if pos <= minimum: -            return pos -        while pos > minimum: -            pos -= 1 -            if ch != self.src[pos]: -                return pos + 1 -        return pos - -    def getLines(self, begin: int, end: int, indent: int, keepLastLF: bool) -> str: -        """Cut lines range from source.""" -        line = begin -        if begin >= end: -            return "" - -        queue = [""] * (end - begin) - -        i = 1 -        while line < end: -            lineIndent = 0 -            lineStart = first = self.bMarks[line] -            last = ( -                self.eMarks[line] + 1 -                if line + 1 < end or keepLastLF -                else self.eMarks[line] -            ) - -            while (first < last) and (lineIndent < indent): -                ch = self.src[first] -                if isStrSpace(ch): -                    if ch == "\t": -                        lineIndent += 4 - (lineIndent + self.bsCount[line]) % 4 -                    else: -                        lineIndent += 1 -                elif first - lineStart < self.tShift[line]: -                    lineIndent += 1 -                else: -                    break -                first += 1 - -            if lineIndent > indent: -                # partially expanding tabs in code blocks, e.g '\t\tfoobar' -                # with indent=2 becomes '  \tfoobar' -                queue[i - 1] = (" " * (lineIndent - indent)) + self.src[first:last] -            else: -                queue[i - 1] = self.src[first:last] - -            line += 1 -            i += 1 - -        return "".join(queue) - -    def is_code_block(self, line: int) -> bool: -        """Check if line is a code block, -        i.e. the code block rule is enabled and text is indented by more than 3 spaces. -        """ -        return self._code_enabled and (self.sCount[line] - self.blkIndent) >= 4 diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_block/table.py b/venv/lib/python3.11/site-packages/markdown_it/rules_block/table.py deleted file mode 100644 index 4b666c1..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_block/table.py +++ /dev/null @@ -1,236 +0,0 @@ -# GFM table, https://github.github.com/gfm/#tables-extension- -from __future__ import annotations - -import re - -from ..common.utils import charStrAt, isStrSpace -from .state_block import StateBlock - -headerLineRe = re.compile(r"^:?-+:?$") -enclosingPipesRe = re.compile(r"^\||\|$") - - -def getLine(state: StateBlock, line: int) -> str: -    pos = state.bMarks[line] + state.tShift[line] -    maximum = state.eMarks[line] - -    # return state.src.substr(pos, max - pos) -    return state.src[pos:maximum] - - -def escapedSplit(string: str) -> list[str]: -    result: list[str] = [] -    pos = 0 -    max = len(string) -    isEscaped = False -    lastPos = 0 -    current = "" -    ch = charStrAt(string, pos) - -    while pos < max: -        if ch == "|": -            if not isEscaped: -                # pipe separating cells, '|' -                result.append(current + string[lastPos:pos]) -                current = "" -                lastPos = pos + 1 -            else: -                # escaped pipe, '\|' -                current += string[lastPos : pos - 1] -                lastPos = pos - -        isEscaped = ch == "\\" -        pos += 1 - -        ch = charStrAt(string, pos) - -    result.append(current + string[lastPos:]) - -    return result - - -def table(state: StateBlock, startLine: int, endLine: int, silent: bool) -> bool: -    tbodyLines = None - -    # should have at least two lines -    if startLine + 2 > endLine: -        return False - -    nextLine = startLine + 1 - -    if state.sCount[nextLine] < state.blkIndent: -        return False - -    if state.is_code_block(nextLine): -        return False - -    # first character of the second line should be '|', '-', ':', -    # and no other characters are allowed but spaces; -    # basically, this is the equivalent of /^[-:|][-:|\s]*$/ regexp - -    pos = state.bMarks[nextLine] + state.tShift[nextLine] -    if pos >= state.eMarks[nextLine]: -        return False -    first_ch = state.src[pos] -    pos += 1 -    if first_ch not in ("|", "-", ":"): -        return False - -    if pos >= state.eMarks[nextLine]: -        return False -    second_ch = state.src[pos] -    pos += 1 -    if second_ch not in ("|", "-", ":") and not isStrSpace(second_ch): -        return False - -    # if first character is '-', then second character must not be a space -    # (due to parsing ambiguity with list) -    if first_ch == "-" and isStrSpace(second_ch): -        return False - -    while pos < state.eMarks[nextLine]: -        ch = state.src[pos] - -        if ch not in ("|", "-", ":") and not isStrSpace(ch): -            return False - -        pos += 1 - -    lineText = getLine(state, startLine + 1) - -    columns = lineText.split("|") -    aligns = [] -    for i in range(len(columns)): -        t = columns[i].strip() -        if not t: -            # allow empty columns before and after table, but not in between columns; -            # e.g. allow ` |---| `, disallow ` ---||--- ` -            if i == 0 or i == len(columns) - 1: -                continue -            else: -                return False - -        if not headerLineRe.search(t): -            return False -        if charStrAt(t, len(t) - 1) == ":": -            aligns.append("center" if charStrAt(t, 0) == ":" else "right") -        elif charStrAt(t, 0) == ":": -            aligns.append("left") -        else: -            aligns.append("") - -    lineText = getLine(state, startLine).strip() -    if "|" not in lineText: -        return False -    if state.is_code_block(startLine): -        return False -    columns = escapedSplit(lineText) -    if columns and columns[0] == "": -        columns.pop(0) -    if columns and columns[-1] == "": -        columns.pop() - -    # header row will define an amount of columns in the entire table, -    # and align row should be exactly the same (the rest of the rows can differ) -    columnCount = len(columns) -    if columnCount == 0 or columnCount != len(aligns): -        return False - -    if silent: -        return True - -    oldParentType = state.parentType -    state.parentType = "table" - -    # use 'blockquote' lists for termination because it's -    # the most similar to tables -    terminatorRules = state.md.block.ruler.getRules("blockquote") - -    token = state.push("table_open", "table", 1) -    token.map = tableLines = [startLine, 0] - -    token = state.push("thead_open", "thead", 1) -    token.map = [startLine, startLine + 1] - -    token = state.push("tr_open", "tr", 1) -    token.map = [startLine, startLine + 1] - -    for i in range(len(columns)): -        token = state.push("th_open", "th", 1) -        if aligns[i]: -            token.attrs = {"style": "text-align:" + aligns[i]} - -        token = state.push("inline", "", 0) -        # note in markdown-it this map was removed in v12.0.0 however, we keep it, -        # since it is helpful to propagate to children tokens -        token.map = [startLine, startLine + 1] -        token.content = columns[i].strip() -        token.children = [] - -        token = state.push("th_close", "th", -1) - -    token = state.push("tr_close", "tr", -1) -    token = state.push("thead_close", "thead", -1) - -    nextLine = startLine + 2 -    while nextLine < endLine: -        if state.sCount[nextLine] < state.blkIndent: -            break - -        terminate = False -        for i in range(len(terminatorRules)): -            if terminatorRules[i](state, nextLine, endLine, True): -                terminate = True -                break - -        if terminate: -            break -        lineText = getLine(state, nextLine).strip() -        if not lineText: -            break -        if state.is_code_block(nextLine): -            break -        columns = escapedSplit(lineText) -        if columns and columns[0] == "": -            columns.pop(0) -        if columns and columns[-1] == "": -            columns.pop() - -        if nextLine == startLine + 2: -            token = state.push("tbody_open", "tbody", 1) -            token.map = tbodyLines = [startLine + 2, 0] - -        token = state.push("tr_open", "tr", 1) -        token.map = [nextLine, nextLine + 1] - -        for i in range(columnCount): -            token = state.push("td_open", "td", 1) -            if aligns[i]: -                token.attrs = {"style": "text-align:" + aligns[i]} - -            token = state.push("inline", "", 0) -            # note in markdown-it this map was removed in v12.0.0 however, we keep it, -            # since it is helpful to propagate to children tokens -            token.map = [nextLine, nextLine + 1] -            try: -                token.content = columns[i].strip() if columns[i] else "" -            except IndexError: -                token.content = "" -            token.children = [] - -            token = state.push("td_close", "td", -1) - -        token = state.push("tr_close", "tr", -1) - -        nextLine += 1 - -    if tbodyLines: -        token = state.push("tbody_close", "tbody", -1) -        tbodyLines[1] = nextLine - -    token = state.push("table_close", "table", -1) - -    tableLines[1] = nextLine -    state.parentType = oldParentType -    state.line = nextLine -    return True diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_core/__init__.py b/venv/lib/python3.11/site-packages/markdown_it/rules_core/__init__.py deleted file mode 100644 index c9c5368..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_core/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -__all__ = ( -    "StateCore", -    "normalize", -    "block", -    "inline", -    "replace", -    "smartquotes", -    "linkify", -    "text_join", -) - -from .block import block -from .inline import inline -from .linkify import linkify -from .normalize import normalize -from .replacements import replace -from .smartquotes import smartquotes -from .state_core import StateCore -from .text_join import text_join diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_core/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_core/__pycache__/__init__.cpython-311.pycBinary files differ deleted file mode 100644 index 95b3b14..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_core/__pycache__/__init__.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_core/__pycache__/block.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_core/__pycache__/block.cpython-311.pycBinary files differ deleted file mode 100644 index 2703987..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_core/__pycache__/block.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_core/__pycache__/inline.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_core/__pycache__/inline.cpython-311.pycBinary files differ deleted file mode 100644 index 2a5fa58..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_core/__pycache__/inline.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_core/__pycache__/linkify.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_core/__pycache__/linkify.cpython-311.pycBinary files differ deleted file mode 100644 index e414e36..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_core/__pycache__/linkify.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_core/__pycache__/normalize.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_core/__pycache__/normalize.cpython-311.pycBinary files differ deleted file mode 100644 index 32b20aa..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_core/__pycache__/normalize.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_core/__pycache__/replacements.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_core/__pycache__/replacements.cpython-311.pycBinary files differ deleted file mode 100644 index 6d38796..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_core/__pycache__/replacements.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_core/__pycache__/smartquotes.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_core/__pycache__/smartquotes.cpython-311.pycBinary files differ deleted file mode 100644 index d0ff760..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_core/__pycache__/smartquotes.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_core/__pycache__/state_core.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_core/__pycache__/state_core.cpython-311.pycBinary files differ deleted file mode 100644 index 30863c1..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_core/__pycache__/state_core.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_core/__pycache__/text_join.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_core/__pycache__/text_join.cpython-311.pycBinary files differ deleted file mode 100644 index 28deb1b..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_core/__pycache__/text_join.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_core/block.py b/venv/lib/python3.11/site-packages/markdown_it/rules_core/block.py deleted file mode 100644 index a6c3bb8..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_core/block.py +++ /dev/null @@ -1,13 +0,0 @@ -from ..token import Token -from .state_core import StateCore - - -def block(state: StateCore) -> None: -    if state.inlineMode: -        token = Token("inline", "", 0) -        token.content = state.src -        token.map = [0, 1] -        token.children = [] -        state.tokens.append(token) -    else: -        state.md.block.parse(state.src, state.md, state.env, state.tokens) diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_core/inline.py b/venv/lib/python3.11/site-packages/markdown_it/rules_core/inline.py deleted file mode 100644 index c3fd0b5..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_core/inline.py +++ /dev/null @@ -1,10 +0,0 @@ -from .state_core import StateCore - - -def inline(state: StateCore) -> None: -    """Parse inlines""" -    for token in state.tokens: -        if token.type == "inline": -            if token.children is None: -                token.children = [] -            state.md.inline.parse(token.content, state.md, state.env, token.children) diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_core/linkify.py b/venv/lib/python3.11/site-packages/markdown_it/rules_core/linkify.py deleted file mode 100644 index efbc9d4..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_core/linkify.py +++ /dev/null @@ -1,149 +0,0 @@ -from __future__ import annotations - -import re -from typing import Protocol - -from ..common.utils import arrayReplaceAt, isLinkClose, isLinkOpen -from ..token import Token -from .state_core import StateCore - -HTTP_RE = re.compile(r"^http://") -MAILTO_RE = re.compile(r"^mailto:") -TEST_MAILTO_RE = re.compile(r"^mailto:", flags=re.IGNORECASE) - - -def linkify(state: StateCore) -> None: -    """Rule for identifying plain-text links.""" -    if not state.md.options.linkify: -        return - -    if not state.md.linkify: -        raise ModuleNotFoundError("Linkify enabled but not installed.") - -    for inline_token in state.tokens: -        if inline_token.type != "inline" or not state.md.linkify.pretest( -            inline_token.content -        ): -            continue - -        tokens = inline_token.children - -        htmlLinkLevel = 0 - -        # We scan from the end, to keep position when new tags added. -        # Use reversed logic in links start/end match -        assert tokens is not None -        i = len(tokens) -        while i >= 1: -            i -= 1 -            assert isinstance(tokens, list) -            currentToken = tokens[i] - -            # Skip content of markdown links -            if currentToken.type == "link_close": -                i -= 1 -                while ( -                    tokens[i].level != currentToken.level -                    and tokens[i].type != "link_open" -                ): -                    i -= 1 -                continue - -            # Skip content of html tag links -            if currentToken.type == "html_inline": -                if isLinkOpen(currentToken.content) and htmlLinkLevel > 0: -                    htmlLinkLevel -= 1 -                if isLinkClose(currentToken.content): -                    htmlLinkLevel += 1 -            if htmlLinkLevel > 0: -                continue - -            if currentToken.type == "text" and state.md.linkify.test( -                currentToken.content -            ): -                text = currentToken.content -                links: list[_LinkType] = state.md.linkify.match(text) or [] - -                # Now split string to nodes -                nodes = [] -                level = currentToken.level -                lastPos = 0 - -                # forbid escape sequence at the start of the string, -                # this avoids http\://example.com/ from being linkified as -                # http:<a href="//example.com/">//example.com/</a> -                if ( -                    links -                    and links[0].index == 0 -                    and i > 0 -                    and tokens[i - 1].type == "text_special" -                ): -                    links = links[1:] - -                for link in links: -                    url = link.url -                    fullUrl = state.md.normalizeLink(url) -                    if not state.md.validateLink(fullUrl): -                        continue - -                    urlText = link.text - -                    # Linkifier might send raw hostnames like "example.com", where url -                    # starts with domain name. So we prepend http:// in those cases, -                    # and remove it afterwards. -                    if not link.schema: -                        urlText = HTTP_RE.sub( -                            "", state.md.normalizeLinkText("http://" + urlText) -                        ) -                    elif link.schema == "mailto:" and TEST_MAILTO_RE.search(urlText): -                        urlText = MAILTO_RE.sub( -                            "", state.md.normalizeLinkText("mailto:" + urlText) -                        ) -                    else: -                        urlText = state.md.normalizeLinkText(urlText) - -                    pos = link.index - -                    if pos > lastPos: -                        token = Token("text", "", 0) -                        token.content = text[lastPos:pos] -                        token.level = level -                        nodes.append(token) - -                    token = Token("link_open", "a", 1) -                    token.attrs = {"href": fullUrl} -                    token.level = level -                    level += 1 -                    token.markup = "linkify" -                    token.info = "auto" -                    nodes.append(token) - -                    token = Token("text", "", 0) -                    token.content = urlText -                    token.level = level -                    nodes.append(token) - -                    token = Token("link_close", "a", -1) -                    level -= 1 -                    token.level = level -                    token.markup = "linkify" -                    token.info = "auto" -                    nodes.append(token) - -                    lastPos = link.last_index - -                if lastPos < len(text): -                    token = Token("text", "", 0) -                    token.content = text[lastPos:] -                    token.level = level -                    nodes.append(token) - -                inline_token.children = tokens = arrayReplaceAt(tokens, i, nodes) - - -class _LinkType(Protocol): -    url: str -    text: str -    index: int -    last_index: int -    schema: str | None diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_core/normalize.py b/venv/lib/python3.11/site-packages/markdown_it/rules_core/normalize.py deleted file mode 100644 index c9f8d0d..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_core/normalize.py +++ /dev/null @@ -1,18 +0,0 @@ -"""Normalize input string.""" -import re - -from .state_core import StateCore - -# https://spec.commonmark.org/0.29/#line-ending -NEWLINES_RE = re.compile(r"\r\n?|\n") -NULL_RE = re.compile(r"\0") - - -def normalize(state: StateCore) -> None: -    # Normalize newlines -    string = NEWLINES_RE.sub("\n", state.src) - -    # Replace NULL characters -    string = NULL_RE.sub("\uFFFD", string) - -    state.src = string diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_core/replacements.py b/venv/lib/python3.11/site-packages/markdown_it/rules_core/replacements.py deleted file mode 100644 index 14912e1..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_core/replacements.py +++ /dev/null @@ -1,126 +0,0 @@ -"""Simple typographic replacements - -* ``(c)``, ``(C)`` → © -* ``(tm)``, ``(TM)`` → ™ -* ``(r)``, ``(R)`` → ® -* ``+-`` → ± -* ``...`` → … -* ``?....`` → ?.. -* ``!....`` → !.. -* ``????????`` → ??? -* ``!!!!!`` → !!! -* ``,,,`` → , -* ``--`` → &ndash -* ``---`` → &mdash -""" -from __future__ import annotations - -import logging -import re - -from ..token import Token -from .state_core import StateCore - -LOGGER = logging.getLogger(__name__) - -# TODO: -# - fractionals 1/2, 1/4, 3/4 -> ½, ¼, ¾ -# - multiplication 2 x 4 -> 2 × 4 - -RARE_RE = re.compile(r"\+-|\.\.|\?\?\?\?|!!!!|,,|--") - -# Workaround for phantomjs - need regex without /g flag, -# or root check will fail every second time -# SCOPED_ABBR_TEST_RE = r"\((c|tm|r)\)" - -SCOPED_ABBR_RE = re.compile(r"\((c|tm|r)\)", flags=re.IGNORECASE) - -PLUS_MINUS_RE = re.compile(r"\+-") - -ELLIPSIS_RE = re.compile(r"\.{2,}") - -ELLIPSIS_QUESTION_EXCLAMATION_RE = re.compile(r"([?!])…") - -QUESTION_EXCLAMATION_RE = re.compile(r"([?!]){4,}") - -COMMA_RE = re.compile(r",{2,}") - -EM_DASH_RE = re.compile(r"(^|[^-])---(?=[^-]|$)", flags=re.MULTILINE) - -EN_DASH_RE = re.compile(r"(^|\s)--(?=\s|$)", flags=re.MULTILINE) - -EN_DASH_INDENT_RE = re.compile(r"(^|[^-\s])--(?=[^-\s]|$)", flags=re.MULTILINE) - - -SCOPED_ABBR = {"c": "©", "r": "®", "tm": "™"} - - -def replaceFn(match: re.Match[str]) -> str: -    return SCOPED_ABBR[match.group(1).lower()] - - -def replace_scoped(inlineTokens: list[Token]) -> None: -    inside_autolink = 0 - -    for token in inlineTokens: -        if token.type == "text" and not inside_autolink: -            token.content = SCOPED_ABBR_RE.sub(replaceFn, token.content) - -        if token.type == "link_open" and token.info == "auto": -            inside_autolink -= 1 - -        if token.type == "link_close" and token.info == "auto": -            inside_autolink += 1 - - -def replace_rare(inlineTokens: list[Token]) -> None: -    inside_autolink = 0 - -    for token in inlineTokens: -        if ( -            token.type == "text" -            and (not inside_autolink) -            and RARE_RE.search(token.content) -        ): -            # +- -> ± -            token.content = PLUS_MINUS_RE.sub("±", token.content) - -            # .., ..., ....... -> … -            token.content = ELLIPSIS_RE.sub("…", token.content) - -            # but ?..... & !..... -> ?.. & !.. -            token.content = ELLIPSIS_QUESTION_EXCLAMATION_RE.sub("\\1..", token.content) -            token.content = QUESTION_EXCLAMATION_RE.sub("\\1\\1\\1", token.content) - -            # ,,  ,,,  ,,,, -> , -            token.content = COMMA_RE.sub(",", token.content) - -            # em-dash -            token.content = EM_DASH_RE.sub("\\1\u2014", token.content) - -            # en-dash -            token.content = EN_DASH_RE.sub("\\1\u2013", token.content) -            token.content = EN_DASH_INDENT_RE.sub("\\1\u2013", token.content) - -        if token.type == "link_open" and token.info == "auto": -            inside_autolink -= 1 - -        if token.type == "link_close" and token.info == "auto": -            inside_autolink += 1 - - -def replace(state: StateCore) -> None: -    if not state.md.options.typographer: -        return - -    for token in state.tokens: -        if token.type != "inline": -            continue -        if token.children is None: -            continue - -        if SCOPED_ABBR_RE.search(token.content): -            replace_scoped(token.children) - -        if RARE_RE.search(token.content): -            replace_rare(token.children) diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_core/smartquotes.py b/venv/lib/python3.11/site-packages/markdown_it/rules_core/smartquotes.py deleted file mode 100644 index c98fbd7..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_core/smartquotes.py +++ /dev/null @@ -1,202 +0,0 @@ -"""Convert straight quotation marks to typographic ones -""" -from __future__ import annotations - -import re -from typing import Any - -from ..common.utils import charCodeAt, isMdAsciiPunct, isPunctChar, isWhiteSpace -from ..token import Token -from .state_core import StateCore - -QUOTE_TEST_RE = re.compile(r"['\"]") -QUOTE_RE = re.compile(r"['\"]") -APOSTROPHE = "\u2019"  # ’ - - -def replaceAt(string: str, index: int, ch: str) -> str: -    # When the index is negative, the behavior is different from the js version. -    # But basically, the index will not be negative. -    assert index >= 0 -    return string[:index] + ch + string[index + 1 :] - - -def process_inlines(tokens: list[Token], state: StateCore) -> None: -    stack: list[dict[str, Any]] = [] - -    for i, token in enumerate(tokens): -        thisLevel = token.level - -        j = 0 -        for j in range(len(stack))[::-1]: -            if stack[j]["level"] <= thisLevel: -                break -        else: -            # When the loop is terminated without a "break". -            # Subtract 1 to get the same index as the js version. -            j -= 1 - -        stack = stack[: j + 1] - -        if token.type != "text": -            continue - -        text = token.content -        pos = 0 -        maximum = len(text) - -        while pos < maximum: -            goto_outer = False -            lastIndex = pos -            t = QUOTE_RE.search(text[lastIndex:]) -            if not t: -                break - -            canOpen = canClose = True -            pos = t.start(0) + lastIndex + 1 -            isSingle = t.group(0) == "'" - -            # Find previous character, -            # default to space if it's the beginning of the line -            lastChar: None | int = 0x20 - -            if t.start(0) + lastIndex - 1 >= 0: -                lastChar = charCodeAt(text, t.start(0) + lastIndex - 1) -            else: -                for j in range(i)[::-1]: -                    if tokens[j].type == "softbreak" or tokens[j].type == "hardbreak": -                        break -                    # should skip all tokens except 'text', 'html_inline' or 'code_inline' -                    if not tokens[j].content: -                        continue - -                    lastChar = charCodeAt(tokens[j].content, len(tokens[j].content) - 1) -                    break - -            # Find next character, -            # default to space if it's the end of the line -            nextChar: None | int = 0x20 - -            if pos < maximum: -                nextChar = charCodeAt(text, pos) -            else: -                for j in range(i + 1, len(tokens)): -                    # nextChar defaults to 0x20 -                    if tokens[j].type == "softbreak" or tokens[j].type == "hardbreak": -                        break -                    # should skip all tokens except 'text', 'html_inline' or 'code_inline' -                    if not tokens[j].content: -                        continue - -                    nextChar = charCodeAt(tokens[j].content, 0) -                    break - -            isLastPunctChar = lastChar is not None and ( -                isMdAsciiPunct(lastChar) or isPunctChar(chr(lastChar)) -            ) -            isNextPunctChar = nextChar is not None and ( -                isMdAsciiPunct(nextChar) or isPunctChar(chr(nextChar)) -            ) - -            isLastWhiteSpace = lastChar is not None and isWhiteSpace(lastChar) -            isNextWhiteSpace = nextChar is not None and isWhiteSpace(nextChar) - -            if isNextWhiteSpace:  # noqa: SIM114 -                canOpen = False -            elif isNextPunctChar and not (isLastWhiteSpace or isLastPunctChar): -                canOpen = False - -            if isLastWhiteSpace:  # noqa: SIM114 -                canClose = False -            elif isLastPunctChar and not (isNextWhiteSpace or isNextPunctChar): -                canClose = False - -            if nextChar == 0x22 and t.group(0) == '"':  # 0x22: "  # noqa: SIM102 -                if ( -                    lastChar is not None and lastChar >= 0x30 and lastChar <= 0x39 -                ):  # 0x30: 0, 0x39: 9 -                    # special case: 1"" - count first quote as an inch -                    canClose = canOpen = False - -            if canOpen and canClose: -                # Replace quotes in the middle of punctuation sequence, but not -                # in the middle of the words, i.e.: -                # -                # 1. foo " bar " baz - not replaced -                # 2. foo-"-bar-"-baz - replaced -                # 3. foo"bar"baz     - not replaced -                canOpen = isLastPunctChar -                canClose = isNextPunctChar - -            if not canOpen and not canClose: -                # middle of word -                if isSingle: -                    token.content = replaceAt( -                        token.content, t.start(0) + lastIndex, APOSTROPHE -                    ) -                continue - -            if canClose: -                # this could be a closing quote, rewind the stack to get a match -                for j in range(len(stack))[::-1]: -                    item = stack[j] -                    if stack[j]["level"] < thisLevel: -                        break -                    if item["single"] == isSingle and stack[j]["level"] == thisLevel: -                        item = stack[j] - -                        if isSingle: -                            openQuote = state.md.options.quotes[2] -                            closeQuote = state.md.options.quotes[3] -                        else: -                            openQuote = state.md.options.quotes[0] -                            closeQuote = state.md.options.quotes[1] - -                        # replace token.content *before* tokens[item.token].content, -                        # because, if they are pointing at the same token, replaceAt -                        # could mess up indices when quote length != 1 -                        token.content = replaceAt( -                            token.content, t.start(0) + lastIndex, closeQuote -                        ) -                        tokens[item["token"]].content = replaceAt( -                            tokens[item["token"]].content, item["pos"], openQuote -                        ) - -                        pos += len(closeQuote) - 1 -                        if item["token"] == i: -                            pos += len(openQuote) - 1 - -                        text = token.content -                        maximum = len(text) - -                        stack = stack[:j] -                        goto_outer = True -                        break -                if goto_outer: -                    goto_outer = False -                    continue - -            if canOpen: -                stack.append( -                    { -                        "token": i, -                        "pos": t.start(0) + lastIndex, -                        "single": isSingle, -                        "level": thisLevel, -                    } -                ) -            elif canClose and isSingle: -                token.content = replaceAt( -                    token.content, t.start(0) + lastIndex, APOSTROPHE -                ) - - -def smartquotes(state: StateCore) -> None: -    if not state.md.options.typographer: -        return - -    for token in state.tokens: -        if token.type != "inline" or not QUOTE_RE.search(token.content): -            continue -        if token.children is not None: -            process_inlines(token.children, state) diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_core/state_core.py b/venv/lib/python3.11/site-packages/markdown_it/rules_core/state_core.py deleted file mode 100644 index a938041..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_core/state_core.py +++ /dev/null @@ -1,25 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING - -from ..ruler import StateBase -from ..token import Token -from ..utils import EnvType - -if TYPE_CHECKING: -    from markdown_it import MarkdownIt - - -class StateCore(StateBase): -    def __init__( -        self, -        src: str, -        md: MarkdownIt, -        env: EnvType, -        tokens: list[Token] | None = None, -    ) -> None: -        self.src = src -        self.md = md  # link to parser instance -        self.env = env -        self.tokens: list[Token] = tokens or [] -        self.inlineMode = False diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_core/text_join.py b/venv/lib/python3.11/site-packages/markdown_it/rules_core/text_join.py deleted file mode 100644 index d54ccbb..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_core/text_join.py +++ /dev/null @@ -1,34 +0,0 @@ -"""Join raw text tokens with the rest of the text - -This is set as a separate rule to provide an opportunity for plugins -to run text replacements after text join, but before escape join. - -For example, `\\:)` shouldn't be replaced with an emoji. -""" -from __future__ import annotations - -from ..token import Token -from .state_core import StateCore - - -def text_join(state: StateCore) -> None: -    """Join raw text for escape sequences (`text_special`) tokens with the rest of the text""" - -    for inline_token in state.tokens[:]: -        if inline_token.type != "inline": -            continue - -        # convert text_special to text and join all adjacent text nodes -        new_tokens: list[Token] = [] -        for child_token in inline_token.children or []: -            if child_token.type == "text_special": -                child_token.type = "text" -            if ( -                child_token.type == "text" -                and new_tokens -                and new_tokens[-1].type == "text" -            ): -                new_tokens[-1].content += child_token.content -            else: -                new_tokens.append(child_token) -        inline_token.children = new_tokens diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__init__.py b/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__init__.py deleted file mode 100644 index 3a8026e..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__init__.py +++ /dev/null @@ -1,31 +0,0 @@ -__all__ = ( -    "StateInline", -    "text", -    "fragments_join", -    "link_pairs", -    "linkify", -    "escape", -    "newline", -    "backtick", -    "emphasis", -    "image", -    "link", -    "autolink", -    "entity", -    "html_inline", -    "strikethrough", -) -from . import emphasis, strikethrough -from .autolink import autolink -from .backticks import backtick -from .balance_pairs import link_pairs -from .entity import entity -from .escape import escape -from .fragments_join import fragments_join -from .html_inline import html_inline -from .image import image -from .link import link -from .linkify import linkify -from .newline import newline -from .state_inline import StateInline -from .text import text diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/__init__.cpython-311.pycBinary files differ deleted file mode 100644 index ac048d7..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/__init__.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/autolink.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/autolink.cpython-311.pycBinary files differ deleted file mode 100644 index 15c5b40..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/autolink.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/backticks.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/backticks.cpython-311.pycBinary files differ deleted file mode 100644 index 6d0114b..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/backticks.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/balance_pairs.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/balance_pairs.cpython-311.pycBinary files differ deleted file mode 100644 index 9297508..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/balance_pairs.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/emphasis.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/emphasis.cpython-311.pycBinary files differ deleted file mode 100644 index d1923ec..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/emphasis.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/entity.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/entity.cpython-311.pycBinary files differ deleted file mode 100644 index c302f88..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/entity.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/escape.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/escape.cpython-311.pycBinary files differ deleted file mode 100644 index 7389e27..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/escape.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/fragments_join.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/fragments_join.cpython-311.pycBinary files differ deleted file mode 100644 index 1c1e20d..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/fragments_join.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/html_inline.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/html_inline.cpython-311.pycBinary files differ deleted file mode 100644 index a77d98a..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/html_inline.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/image.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/image.cpython-311.pycBinary files differ deleted file mode 100644 index 485976b..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/image.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/link.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/link.cpython-311.pycBinary files differ deleted file mode 100644 index ba75953..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/link.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/linkify.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/linkify.cpython-311.pycBinary files differ deleted file mode 100644 index 7cb2ef9..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/linkify.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/newline.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/newline.cpython-311.pycBinary files differ deleted file mode 100644 index 2134530..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/newline.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/state_inline.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/state_inline.cpython-311.pycBinary files differ deleted file mode 100644 index 9095837..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/state_inline.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/strikethrough.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/strikethrough.cpython-311.pycBinary files differ deleted file mode 100644 index 006536a..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/strikethrough.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/text.cpython-311.pyc b/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/text.cpython-311.pycBinary files differ deleted file mode 100644 index 4f56489..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/__pycache__/text.cpython-311.pyc +++ /dev/null diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/autolink.py b/venv/lib/python3.11/site-packages/markdown_it/rules_inline/autolink.py deleted file mode 100644 index 295d963..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/autolink.py +++ /dev/null @@ -1,77 +0,0 @@ -# Process autolinks '<protocol:...>' -import re - -from .state_inline import StateInline - -EMAIL_RE = re.compile( -    r"^([a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)$"  # noqa: E501 -) -AUTOLINK_RE = re.compile(r"^([a-zA-Z][a-zA-Z0-9+.\-]{1,31}):([^<>\x00-\x20]*)$") - - -def autolink(state: StateInline, silent: bool) -> bool: -    pos = state.pos - -    if state.src[pos] != "<": -        return False - -    start = state.pos -    maximum = state.posMax - -    while True: -        pos += 1 -        if pos >= maximum: -            return False - -        ch = state.src[pos] - -        if ch == "<": -            return False -        if ch == ">": -            break - -    url = state.src[start + 1 : pos] - -    if AUTOLINK_RE.search(url) is not None: -        fullUrl = state.md.normalizeLink(url) -        if not state.md.validateLink(fullUrl): -            return False - -        if not silent: -            token = state.push("link_open", "a", 1) -            token.attrs = {"href": fullUrl} -            token.markup = "autolink" -            token.info = "auto" - -            token = state.push("text", "", 0) -            token.content = state.md.normalizeLinkText(url) - -            token = state.push("link_close", "a", -1) -            token.markup = "autolink" -            token.info = "auto" - -        state.pos += len(url) + 2 -        return True - -    if EMAIL_RE.search(url) is not None: -        fullUrl = state.md.normalizeLink("mailto:" + url) -        if not state.md.validateLink(fullUrl): -            return False - -        if not silent: -            token = state.push("link_open", "a", 1) -            token.attrs = {"href": fullUrl} -            token.markup = "autolink" -            token.info = "auto" - -            token = state.push("text", "", 0) -            token.content = state.md.normalizeLinkText(url) - -            token = state.push("link_close", "a", -1) -            token.markup = "autolink" -            token.info = "auto" - -        state.pos += len(url) + 2 -        return True - -    return False diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/backticks.py b/venv/lib/python3.11/site-packages/markdown_it/rules_inline/backticks.py deleted file mode 100644 index fc60d6b..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/backticks.py +++ /dev/null @@ -1,72 +0,0 @@ -# Parse backticks -import re - -from .state_inline import StateInline - -regex = re.compile("^ (.+) $") - - -def backtick(state: StateInline, silent: bool) -> bool: -    pos = state.pos - -    if state.src[pos] != "`": -        return False - -    start = pos -    pos += 1 -    maximum = state.posMax - -    # scan marker length -    while pos < maximum and (state.src[pos] == "`"): -        pos += 1 - -    marker = state.src[start:pos] -    openerLength = len(marker) - -    if state.backticksScanned and state.backticks.get(openerLength, 0) <= start: -        if not silent: -            state.pending += marker -        state.pos += openerLength -        return True - -    matchStart = matchEnd = pos - -    # Nothing found in the cache, scan until the end of the line (or until marker is found) -    while True: -        try: -            matchStart = state.src.index("`", matchEnd) -        except ValueError: -            break -        matchEnd = matchStart + 1 - -        # scan marker length -        while matchEnd < maximum and (state.src[matchEnd] == "`"): -            matchEnd += 1 - -        closerLength = matchEnd - matchStart - -        if closerLength == openerLength: -            # Found matching closer length. -            if not silent: -                token = state.push("code_inline", "code", 0) -                token.markup = marker -                token.content = state.src[pos:matchStart].replace("\n", " ") -                if ( -                    token.content.startswith(" ") -                    and token.content.endswith(" ") -                    and len(token.content.strip()) > 0 -                ): -                    token.content = token.content[1:-1] -            state.pos = matchEnd -            return True - -        # Some different length found, put it in cache as upper limit of where closer can be found -        state.backticks[closerLength] = matchStart - -    # Scanned through the end, didn't find anything -    state.backticksScanned = True - -    if not silent: -        state.pending += marker -    state.pos += openerLength -    return True diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/balance_pairs.py b/venv/lib/python3.11/site-packages/markdown_it/rules_inline/balance_pairs.py deleted file mode 100644 index bbb2101..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/balance_pairs.py +++ /dev/null @@ -1,137 +0,0 @@ -"""Balance paired characters (*, _, etc) in inline tokens.""" -from __future__ import annotations - -from .state_inline import Delimiter, StateInline - - -def processDelimiters(state: StateInline, delimiters: list[Delimiter]) -> None: -    """For each opening emphasis-like marker find a matching closing one.""" -    if not delimiters: -        return - -    openersBottom = {} -    maximum = len(delimiters) - -    # headerIdx is the first delimiter of the current (where closer is) delimiter run -    headerIdx = 0 -    lastTokenIdx = -2  # needs any value lower than -1 -    jumps: list[int] = [] -    closerIdx = 0 -    while closerIdx < maximum: -        closer = delimiters[closerIdx] - -        jumps.append(0) - -        # markers belong to same delimiter run if: -        #  - they have adjacent tokens -        #  - AND markers are the same -        # -        if ( -            delimiters[headerIdx].marker != closer.marker -            or lastTokenIdx != closer.token - 1 -        ): -            headerIdx = closerIdx -        lastTokenIdx = closer.token - -        # Length is only used for emphasis-specific "rule of 3", -        # if it's not defined (in strikethrough or 3rd party plugins), -        # we can default it to 0 to disable those checks. -        # -        closer.length = closer.length or 0 - -        if not closer.close: -            closerIdx += 1 -            continue - -        # Previously calculated lower bounds (previous fails) -        # for each marker, each delimiter length modulo 3, -        # and for whether this closer can be an opener; -        # https://github.com/commonmark/cmark/commit/34250e12ccebdc6372b8b49c44fab57c72443460 -        if closer.marker not in openersBottom: -            openersBottom[closer.marker] = [-1, -1, -1, -1, -1, -1] - -        minOpenerIdx = openersBottom[closer.marker][ -            (3 if closer.open else 0) + (closer.length % 3) -        ] - -        openerIdx = headerIdx - jumps[headerIdx] - 1 - -        newMinOpenerIdx = openerIdx - -        while openerIdx > minOpenerIdx: -            opener = delimiters[openerIdx] - -            if opener.marker != closer.marker: -                openerIdx -= jumps[openerIdx] + 1 -                continue - -            if opener.open and opener.end < 0: -                isOddMatch = False - -                # from spec: -                # -                # If one of the delimiters can both open and close emphasis, then the -                # sum of the lengths of the delimiter runs containing the opening and -                # closing delimiters must not be a multiple of 3 unless both lengths -                # are multiples of 3. -                # -                if ( -                    (opener.close or closer.open) -                    and ((opener.length + closer.length) % 3 == 0) -                    and (opener.length % 3 != 0 or closer.length % 3 != 0) -                ): -                    isOddMatch = True - -                if not isOddMatch: -                    # If previous delimiter cannot be an opener, we can safely skip -                    # the entire sequence in future checks. This is required to make -                    # sure algorithm has linear complexity (see *_*_*_*_*_... case). -                    # -                    if openerIdx > 0 and not delimiters[openerIdx - 1].open: -                        lastJump = jumps[openerIdx - 1] + 1 -                    else: -                        lastJump = 0 - -                    jumps[closerIdx] = closerIdx - openerIdx + lastJump -                    jumps[openerIdx] = lastJump - -                    closer.open = False -                    opener.end = closerIdx -                    opener.close = False -                    newMinOpenerIdx = -1 - -                    # treat next token as start of run, -                    # it optimizes skips in **<...>**a**<...>** pathological case -                    lastTokenIdx = -2 - -                    break - -            openerIdx -= jumps[openerIdx] + 1 - -        if newMinOpenerIdx != -1: -            # If match for this delimiter run failed, we want to set lower bound for -            # future lookups. This is required to make sure algorithm has linear -            # complexity. -            # -            # See details here: -            # https:#github.com/commonmark/cmark/issues/178#issuecomment-270417442 -            # -            openersBottom[closer.marker][ -                (3 if closer.open else 0) + ((closer.length or 0) % 3) -            ] = newMinOpenerIdx - -        closerIdx += 1 - - -def link_pairs(state: StateInline) -> None: -    tokens_meta = state.tokens_meta -    maximum = len(state.tokens_meta) - -    processDelimiters(state, state.delimiters) - -    curr = 0 -    while curr < maximum: -        curr_meta = tokens_meta[curr] -        if curr_meta and "delimiters" in curr_meta: -            processDelimiters(state, curr_meta["delimiters"]) -        curr += 1 diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/emphasis.py b/venv/lib/python3.11/site-packages/markdown_it/rules_inline/emphasis.py deleted file mode 100644 index 9a98f9e..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/emphasis.py +++ /dev/null @@ -1,102 +0,0 @@ -# Process *this* and _that_ -# -from __future__ import annotations - -from .state_inline import Delimiter, StateInline - - -def tokenize(state: StateInline, silent: bool) -> bool: -    """Insert each marker as a separate text token, and add it to delimiter list""" -    start = state.pos -    marker = state.src[start] - -    if silent: -        return False - -    if marker not in ("_", "*"): -        return False - -    scanned = state.scanDelims(state.pos, marker == "*") - -    for _ in range(scanned.length): -        token = state.push("text", "", 0) -        token.content = marker -        state.delimiters.append( -            Delimiter( -                marker=ord(marker), -                length=scanned.length, -                token=len(state.tokens) - 1, -                end=-1, -                open=scanned.can_open, -                close=scanned.can_close, -            ) -        ) - -    state.pos += scanned.length - -    return True - - -def _postProcess(state: StateInline, delimiters: list[Delimiter]) -> None: -    i = len(delimiters) - 1 -    while i >= 0: -        startDelim = delimiters[i] - -        # /* _ */  /* * */ -        if startDelim.marker != 0x5F and startDelim.marker != 0x2A: -            i -= 1 -            continue - -        # Process only opening markers -        if startDelim.end == -1: -            i -= 1 -            continue - -        endDelim = delimiters[startDelim.end] - -        # If the previous delimiter has the same marker and is adjacent to this one, -        # merge those into one strong delimiter. -        # -        # `<em><em>whatever</em></em>` -> `<strong>whatever</strong>` -        # -        isStrong = ( -            i > 0 -            and delimiters[i - 1].end == startDelim.end + 1 -            # check that first two markers match and adjacent -            and delimiters[i - 1].marker == startDelim.marker -            and delimiters[i - 1].token == startDelim.token - 1 -            # check that last two markers are adjacent (we can safely assume they match) -            and delimiters[startDelim.end + 1].token == endDelim.token + 1 -        ) - -        ch = chr(startDelim.marker) - -        token = state.tokens[startDelim.token] -        token.type = "strong_open" if isStrong else "em_open" -        token.tag = "strong" if isStrong else "em" -        token.nesting = 1 -        token.markup = ch + ch if isStrong else ch -        token.content = "" - -        token = state.tokens[endDelim.token] -        token.type = "strong_close" if isStrong else "em_close" -        token.tag = "strong" if isStrong else "em" -        token.nesting = -1 -        token.markup = ch + ch if isStrong else ch -        token.content = "" - -        if isStrong: -            state.tokens[delimiters[i - 1].token].content = "" -            state.tokens[delimiters[startDelim.end + 1].token].content = "" -            i -= 1 - -        i -= 1 - - -def postProcess(state: StateInline) -> None: -    """Walk through delimiter list and replace text tokens with tags.""" -    _postProcess(state, state.delimiters) - -    for token in state.tokens_meta: -        if token and "delimiters" in token: -            _postProcess(state, token["delimiters"]) diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/entity.py b/venv/lib/python3.11/site-packages/markdown_it/rules_inline/entity.py deleted file mode 100644 index ec9d396..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/entity.py +++ /dev/null @@ -1,53 +0,0 @@ -# Process html entity - {, ¯, ", ... -import re - -from ..common.entities import entities -from ..common.utils import fromCodePoint, isValidEntityCode -from .state_inline import StateInline - -DIGITAL_RE = re.compile(r"^&#((?:x[a-f0-9]{1,6}|[0-9]{1,7}));", re.IGNORECASE) -NAMED_RE = re.compile(r"^&([a-z][a-z0-9]{1,31});", re.IGNORECASE) - - -def entity(state: StateInline, silent: bool) -> bool: -    pos = state.pos -    maximum = state.posMax - -    if state.src[pos] != "&": -        return False - -    if pos + 1 >= maximum: -        return False - -    if state.src[pos + 1] == "#": -        if match := DIGITAL_RE.search(state.src[pos:]): -            if not silent: -                match1 = match.group(1) -                code = ( -                    int(match1[1:], 16) if match1[0].lower() == "x" else int(match1, 10) -                ) - -                token = state.push("text_special", "", 0) -                token.content = ( -                    fromCodePoint(code) -                    if isValidEntityCode(code) -                    else fromCodePoint(0xFFFD) -                ) -                token.markup = match.group(0) -                token.info = "entity" - -            state.pos += len(match.group(0)) -            return True - -    else: -        if (match := NAMED_RE.search(state.src[pos:])) and match.group(1) in entities: -            if not silent: -                token = state.push("text_special", "", 0) -                token.content = entities[match.group(1)] -                token.markup = match.group(0) -                token.info = "entity" - -            state.pos += len(match.group(0)) -            return True - -    return False diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/escape.py b/venv/lib/python3.11/site-packages/markdown_it/rules_inline/escape.py deleted file mode 100644 index 9f68b5d..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/escape.py +++ /dev/null @@ -1,92 +0,0 @@ -""" -Process escaped chars and hardbreaks -""" -from ..common.utils import isStrSpace -from .state_inline import StateInline - - -def escape(state: StateInline, silent: bool) -> bool: -    """Process escaped chars and hardbreaks.""" -    pos = state.pos -    maximum = state.posMax - -    if state.src[pos] != "\\": -        return False - -    pos += 1 - -    # '\' at the end of the inline block -    if pos >= maximum: -        return False - -    ch1 = state.src[pos] -    ch1_ord = ord(ch1) -    if ch1 == "\n": -        if not silent: -            state.push("hardbreak", "br", 0) -        pos += 1 -        # skip leading whitespaces from next line -        while pos < maximum: -            ch = state.src[pos] -            if not isStrSpace(ch): -                break -            pos += 1 - -        state.pos = pos -        return True - -    escapedStr = state.src[pos] - -    if ch1_ord >= 0xD800 and ch1_ord <= 0xDBFF and pos + 1 < maximum: -        ch2 = state.src[pos + 1] -        ch2_ord = ord(ch2) -        if ch2_ord >= 0xDC00 and ch2_ord <= 0xDFFF: -            escapedStr += ch2 -            pos += 1 - -    origStr = "\\" + escapedStr - -    if not silent: -        token = state.push("text_special", "", 0) -        token.content = escapedStr if ch1 in _ESCAPED else origStr -        token.markup = origStr -        token.info = "escape" - -    state.pos = pos + 1 -    return True - - -_ESCAPED = { -    "!", -    '"', -    "#", -    "$", -    "%", -    "&", -    "'", -    "(", -    ")", -    "*", -    "+", -    ",", -    "-", -    ".", -    "/", -    ":", -    ";", -    "<", -    "=", -    ">", -    "?", -    "@", -    "[", -    "\\", -    "]", -    "^", -    "_", -    "`", -    "{", -    "|", -    "}", -    "~", -} diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/fragments_join.py b/venv/lib/python3.11/site-packages/markdown_it/rules_inline/fragments_join.py deleted file mode 100644 index f795c13..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/fragments_join.py +++ /dev/null @@ -1,43 +0,0 @@ -from .state_inline import StateInline - - -def fragments_join(state: StateInline) -> None: -    """ -    Clean up tokens after emphasis and strikethrough postprocessing: -    merge adjacent text nodes into one and re-calculate all token levels - -    This is necessary because initially emphasis delimiter markers (``*, _, ~``) -    are treated as their own separate text tokens. Then emphasis rule either -    leaves them as text (needed to merge with adjacent text) or turns them -    into opening/closing tags (which messes up levels inside). -    """ -    level = 0 -    maximum = len(state.tokens) - -    curr = last = 0 -    while curr < maximum: -        # re-calculate levels after emphasis/strikethrough turns some text nodes -        # into opening/closing tags -        if state.tokens[curr].nesting < 0: -            level -= 1  # closing tag -        state.tokens[curr].level = level -        if state.tokens[curr].nesting > 0: -            level += 1  # opening tag - -        if ( -            state.tokens[curr].type == "text" -            and curr + 1 < maximum -            and state.tokens[curr + 1].type == "text" -        ): -            # collapse two adjacent text nodes -            state.tokens[curr + 1].content = ( -                state.tokens[curr].content + state.tokens[curr + 1].content -            ) -        else: -            if curr != last: -                state.tokens[last] = state.tokens[curr] -            last += 1 -        curr += 1 - -    if curr != last: -        del state.tokens[last:] diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/html_inline.py b/venv/lib/python3.11/site-packages/markdown_it/rules_inline/html_inline.py deleted file mode 100644 index 9065e1d..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/html_inline.py +++ /dev/null @@ -1,43 +0,0 @@ -# Process html tags -from ..common.html_re import HTML_TAG_RE -from ..common.utils import isLinkClose, isLinkOpen -from .state_inline import StateInline - - -def isLetter(ch: int) -> bool: -    lc = ch | 0x20  # to lower case -    # /* a */ and /* z */ -    return (lc >= 0x61) and (lc <= 0x7A) - - -def html_inline(state: StateInline, silent: bool) -> bool: -    pos = state.pos - -    if not state.md.options.get("html", None): -        return False - -    # Check start -    maximum = state.posMax -    if state.src[pos] != "<" or pos + 2 >= maximum: -        return False - -    # Quick fail on second char -    ch = state.src[pos + 1] -    if ch not in ("!", "?", "/") and not isLetter(ord(ch)):  # /* / */ -        return False - -    match = HTML_TAG_RE.search(state.src[pos:]) -    if not match: -        return False - -    if not silent: -        token = state.push("html_inline", "", 0) -        token.content = state.src[pos : pos + len(match.group(0))] - -        if isLinkOpen(token.content): -            state.linkLevel += 1 -        if isLinkClose(token.content): -            state.linkLevel -= 1 - -    state.pos += len(match.group(0)) -    return True diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/image.py b/venv/lib/python3.11/site-packages/markdown_it/rules_inline/image.py deleted file mode 100644 index b4a32a9..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/image.py +++ /dev/null @@ -1,148 +0,0 @@ -# Process  -from __future__ import annotations - -from ..common.utils import isStrSpace, normalizeReference -from ..token import Token -from .state_inline import StateInline - - -def image(state: StateInline, silent: bool) -> bool: -    label = None -    href = "" -    oldPos = state.pos -    max = state.posMax - -    if state.src[state.pos] != "!": -        return False - -    if state.pos + 1 < state.posMax and state.src[state.pos + 1] != "[": -        return False - -    labelStart = state.pos + 2 -    labelEnd = state.md.helpers.parseLinkLabel(state, state.pos + 1, False) - -    # parser failed to find ']', so it's not a valid link -    if labelEnd < 0: -        return False - -    pos = labelEnd + 1 - -    if pos < max and state.src[pos] == "(": -        # -        # Inline link -        # - -        # [link](  <href>  "title"  ) -        #        ^^ skipping these spaces -        pos += 1 -        while pos < max: -            ch = state.src[pos] -            if not isStrSpace(ch) and ch != "\n": -                break -            pos += 1 - -        if pos >= max: -            return False - -        # [link](  <href>  "title"  ) -        #          ^^^^^^ parsing link destination -        start = pos -        res = state.md.helpers.parseLinkDestination(state.src, pos, state.posMax) -        if res.ok: -            href = state.md.normalizeLink(res.str) -            if state.md.validateLink(href): -                pos = res.pos -            else: -                href = "" - -        # [link](  <href>  "title"  ) -        #                ^^ skipping these spaces -        start = pos -        while pos < max: -            ch = state.src[pos] -            if not isStrSpace(ch) and ch != "\n": -                break -            pos += 1 - -        # [link](  <href>  "title"  ) -        #                  ^^^^^^^ parsing link title -        res = state.md.helpers.parseLinkTitle(state.src, pos, state.posMax) -        if pos < max and start != pos and res.ok: -            title = res.str -            pos = res.pos - -            # [link](  <href>  "title"  ) -            #                         ^^ skipping these spaces -            while pos < max: -                ch = state.src[pos] -                if not isStrSpace(ch) and ch != "\n": -                    break -                pos += 1 -        else: -            title = "" - -        if pos >= max or state.src[pos] != ")": -            state.pos = oldPos -            return False - -        pos += 1 - -    else: -        # -        # Link reference -        # -        if "references" not in state.env: -            return False - -        # /* [ */ -        if pos < max and state.src[pos] == "[": -            start = pos + 1 -            pos = state.md.helpers.parseLinkLabel(state, pos) -            if pos >= 0: -                label = state.src[start:pos] -                pos += 1 -            else: -                pos = labelEnd + 1 -        else: -            pos = labelEnd + 1 - -        # covers label == '' and label == undefined -        # (collapsed reference link and shortcut reference link respectively) -        if not label: -            label = state.src[labelStart:labelEnd] - -        label = normalizeReference(label) - -        ref = state.env["references"].get(label, None) -        if not ref: -            state.pos = oldPos -            return False - -        href = ref["href"] -        title = ref["title"] - -    # -    # We found the end of the link, and know for a fact it's a valid link -    # so all that's left to do is to call tokenizer. -    # -    if not silent: -        content = state.src[labelStart:labelEnd] - -        tokens: list[Token] = [] -        state.md.inline.parse(content, state.md, state.env, tokens) - -        token = state.push("image", "img", 0) -        token.attrs = {"src": href, "alt": ""} -        token.children = tokens or None -        token.content = content - -        if title: -            token.attrSet("title", title) - -        # note, this is not part of markdown-it JS, but is useful for renderers -        if label and state.md.options.get("store_labels", False): -            token.meta["label"] = label - -    state.pos = pos -    state.posMax = max -    return True diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/link.py b/venv/lib/python3.11/site-packages/markdown_it/rules_inline/link.py deleted file mode 100644 index 78cf912..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/link.py +++ /dev/null @@ -1,151 +0,0 @@ -# Process [link](<to> "stuff") - -from ..common.utils import isStrSpace, normalizeReference -from .state_inline import StateInline - - -def link(state: StateInline, silent: bool) -> bool: -    href = "" -    title = "" -    label = None -    oldPos = state.pos -    maximum = state.posMax -    start = state.pos -    parseReference = True - -    if state.src[state.pos] != "[": -        return False - -    labelStart = state.pos + 1 -    labelEnd = state.md.helpers.parseLinkLabel(state, state.pos, True) - -    # parser failed to find ']', so it's not a valid link -    if labelEnd < 0: -        return False - -    pos = labelEnd + 1 - -    if pos < maximum and state.src[pos] == "(": -        # -        # Inline link -        # - -        # might have found a valid shortcut link, disable reference parsing -        parseReference = False - -        # [link](  <href>  "title"  ) -        #        ^^ skipping these spaces -        pos += 1 -        while pos < maximum: -            ch = state.src[pos] -            if not isStrSpace(ch) and ch != "\n": -                break -            pos += 1 - -        if pos >= maximum: -            return False - -        # [link](  <href>  "title"  ) -        #          ^^^^^^ parsing link destination -        start = pos -        res = state.md.helpers.parseLinkDestination(state.src, pos, state.posMax) -        if res.ok: -            href = state.md.normalizeLink(res.str) -            if state.md.validateLink(href): -                pos = res.pos -            else: -                href = "" - -            # [link](  <href>  "title"  ) -            #                ^^ skipping these spaces -            start = pos -            while pos < maximum: -                ch = state.src[pos] -                if not isStrSpace(ch) and ch != "\n": -                    break -                pos += 1 - -            # [link](  <href>  "title"  ) -            #                  ^^^^^^^ parsing link title -            res = state.md.helpers.parseLinkTitle(state.src, pos, state.posMax) -            if pos < maximum and start != pos and res.ok: -                title = res.str -                pos = res.pos - -                # [link](  <href>  "title"  ) -                #                         ^^ skipping these spaces -                while pos < maximum: -                    ch = state.src[pos] -                    if not isStrSpace(ch) and ch != "\n": -                        break -                    pos += 1 - -        if pos >= maximum or state.src[pos] != ")": -            # parsing a valid shortcut link failed, fallback to reference -            parseReference = True - -        pos += 1 - -    if parseReference: -        # -        # Link reference -        # -        if "references" not in state.env: -            return False - -        if pos < maximum and state.src[pos] == "[": -            start = pos + 1 -            pos = state.md.helpers.parseLinkLabel(state, pos) -            if pos >= 0: -                label = state.src[start:pos] -                pos += 1 -            else: -                pos = labelEnd + 1 - -        else: -            pos = labelEnd + 1 - -        # covers label == '' and label == undefined -        # (collapsed reference link and shortcut reference link respectively) -        if not label: -            label = state.src[labelStart:labelEnd] - -        label = normalizeReference(label) - -        ref = ( -            state.env["references"][label] if label in state.env["references"] else None -        ) -        if not ref: -            state.pos = oldPos -            return False - -        href = ref["href"] -        title = ref["title"] - -    # -    # We found the end of the link, and know for a fact it's a valid link -    # so all that's left to do is to call tokenizer. -    # -    if not silent: -        state.pos = labelStart -        state.posMax = labelEnd - -        token = state.push("link_open", "a", 1) -        token.attrs = {"href": href} - -        if title: -            token.attrSet("title", title) - -        # note, this is not part of markdown-it JS, but is useful for renderers -        if label and state.md.options.get("store_labels", False): -            token.meta["label"] = label - -        state.linkLevel += 1 -        state.md.inline.tokenize(state) -        state.linkLevel -= 1 - -        token = state.push("link_close", "a", -1) - -    state.pos = pos -    state.posMax = maximum -    return True diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/linkify.py b/venv/lib/python3.11/site-packages/markdown_it/rules_inline/linkify.py deleted file mode 100644 index a8a1815..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/linkify.py +++ /dev/null @@ -1,61 +0,0 @@ -"""Process links like https://example.org/""" -import re - -from .state_inline import StateInline - -# RFC3986: scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) -SCHEME_RE = re.compile(r"(?:^|[^a-z0-9.+-])([a-z][a-z0-9.+-]*)$", re.IGNORECASE) - - -def linkify(state: StateInline, silent: bool) -> bool: -    """Rule for identifying plain-text links.""" -    if not state.md.options.linkify: -        return False -    if state.linkLevel > 0: -        return False -    if not state.md.linkify: -        raise ModuleNotFoundError("Linkify enabled but not installed.") - -    pos = state.pos -    maximum = state.posMax - -    if ( -        (pos + 3) > maximum -        or state.src[pos] != ":" -        or state.src[pos + 1] != "/" -        or state.src[pos + 2] != "/" -    ): -        return False - -    if not (match := SCHEME_RE.match(state.pending)): -        return False - -    proto = match.group(1) -    if not (link := state.md.linkify.match_at_start(state.src[pos - len(proto) :])): -        return False -    url: str = link.url - -    # disallow '*' at the end of the link (conflicts with emphasis) -    url = url.rstrip("*") - -    full_url = state.md.normalizeLink(url) -    if not state.md.validateLink(full_url): -        return False - -    if not silent: -        state.pending = state.pending[: -len(proto)] - -        token = state.push("link_open", "a", 1) -        token.attrs = {"href": full_url} -        token.markup = "linkify" -        token.info = "auto" - -        token = state.push("text", "", 0) -        token.content = state.md.normalizeLinkText(url) - -        token = state.push("link_close", "a", -1) -        token.markup = "linkify" -        token.info = "auto" - -    state.pos += len(url) - len(proto) -    return True diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/newline.py b/venv/lib/python3.11/site-packages/markdown_it/rules_inline/newline.py deleted file mode 100644 index ca8f1db..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/newline.py +++ /dev/null @@ -1,43 +0,0 @@ -"""Proceess '\n'.""" -from ..common.utils import charStrAt, isStrSpace -from .state_inline import StateInline - - -def newline(state: StateInline, silent: bool) -> bool: -    pos = state.pos - -    if state.src[pos] != "\n": -        return False - -    pmax = len(state.pending) - 1 -    maximum = state.posMax - -    # '  \n' -> hardbreak -    # Lookup in pending chars is bad practice! Don't copy to other rules! -    # Pending string is stored in concat mode, indexed lookups will cause -    # conversion to flat mode. -    if not silent: -        if pmax >= 0 and charStrAt(state.pending, pmax) == " ": -            if pmax >= 1 and charStrAt(state.pending, pmax - 1) == " ": -                # Find whitespaces tail of pending chars. -                ws = pmax - 1 -                while ws >= 1 and charStrAt(state.pending, ws - 1) == " ": -                    ws -= 1 -                state.pending = state.pending[:ws] - -                state.push("hardbreak", "br", 0) -            else: -                state.pending = state.pending[:-1] -                state.push("softbreak", "br", 0) - -        else: -            state.push("softbreak", "br", 0) - -    pos += 1 - -    # skip heading spaces for next line -    while pos < maximum and isStrSpace(state.src[pos]): -        pos += 1 - -    state.pos = pos -    return True diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/state_inline.py b/venv/lib/python3.11/site-packages/markdown_it/rules_inline/state_inline.py deleted file mode 100644 index c0c491c..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/state_inline.py +++ /dev/null @@ -1,166 +0,0 @@ -from __future__ import annotations - -from collections import namedtuple -from dataclasses import dataclass -from typing import TYPE_CHECKING, Any, Literal - -from .._compat import DATACLASS_KWARGS -from ..common.utils import isMdAsciiPunct, isPunctChar, isWhiteSpace -from ..ruler import StateBase -from ..token import Token -from ..utils import EnvType - -if TYPE_CHECKING: -    from markdown_it import MarkdownIt - - -@dataclass(**DATACLASS_KWARGS) -class Delimiter: -    # Char code of the starting marker (number). -    marker: int - -    # Total length of these series of delimiters. -    length: int - -    # A position of the token this delimiter corresponds to. -    token: int - -    # If this delimiter is matched as a valid opener, `end` will be -    # equal to its position, otherwise it's `-1`. -    end: int - -    # Boolean flags that determine if this delimiter could open or close -    # an emphasis. -    open: bool -    close: bool - -    level: bool | None = None - - -Scanned = namedtuple("Scanned", ["can_open", "can_close", "length"]) - - -class StateInline(StateBase): -    def __init__( -        self, src: str, md: MarkdownIt, env: EnvType, outTokens: list[Token] -    ) -> None: -        self.src = src -        self.env = env -        self.md = md -        self.tokens = outTokens -        self.tokens_meta: list[dict[str, Any] | None] = [None] * len(outTokens) - -        self.pos = 0 -        self.posMax = len(self.src) -        self.level = 0 -        self.pending = "" -        self.pendingLevel = 0 - -        # Stores { start: end } pairs. Useful for backtrack -        # optimization of pairs parse (emphasis, strikes). -        self.cache: dict[int, int] = {} - -        # List of emphasis-like delimiters for current tag -        self.delimiters: list[Delimiter] = [] - -        # Stack of delimiter lists for upper level tags -        self._prev_delimiters: list[list[Delimiter]] = [] - -        # backticklength => last seen position -        self.backticks: dict[int, int] = {} -        self.backticksScanned = False - -        # Counter used to disable inline linkify-it execution -        # inside <a> and markdown links -        self.linkLevel = 0 - -    def __repr__(self) -> str: -        return ( -            f"{self.__class__.__name__}" -            f"(pos=[{self.pos} of {self.posMax}], token={len(self.tokens)})" -        ) - -    def pushPending(self) -> Token: -        token = Token("text", "", 0) -        token.content = self.pending -        token.level = self.pendingLevel -        self.tokens.append(token) -        self.pending = "" -        return token - -    def push(self, ttype: str, tag: str, nesting: Literal[-1, 0, 1]) -> Token: -        """Push new token to "stream". -        If pending text exists - flush it as text token -        """ -        if self.pending: -            self.pushPending() - -        token = Token(ttype, tag, nesting) -        token_meta = None - -        if nesting < 0: -            # closing tag -            self.level -= 1 -            self.delimiters = self._prev_delimiters.pop() - -        token.level = self.level - -        if nesting > 0: -            # opening tag -            self.level += 1 -            self._prev_delimiters.append(self.delimiters) -            self.delimiters = [] -            token_meta = {"delimiters": self.delimiters} - -        self.pendingLevel = self.level -        self.tokens.append(token) -        self.tokens_meta.append(token_meta) -        return token - -    def scanDelims(self, start: int, canSplitWord: bool) -> Scanned: -        """ -        Scan a sequence of emphasis-like markers, and determine whether -        it can start an emphasis sequence or end an emphasis sequence. - -         - start - position to scan from (it should point at a valid marker); -         - canSplitWord - determine if these markers can be found inside a word - -        """ -        pos = start -        maximum = self.posMax -        marker = self.src[start] - -        # treat beginning of the line as a whitespace -        lastChar = self.src[start - 1] if start > 0 else " " - -        while pos < maximum and self.src[pos] == marker: -            pos += 1 - -        count = pos - start - -        # treat end of the line as a whitespace -        nextChar = self.src[pos] if pos < maximum else " " - -        isLastPunctChar = isMdAsciiPunct(ord(lastChar)) or isPunctChar(lastChar) -        isNextPunctChar = isMdAsciiPunct(ord(nextChar)) or isPunctChar(nextChar) - -        isLastWhiteSpace = isWhiteSpace(ord(lastChar)) -        isNextWhiteSpace = isWhiteSpace(ord(nextChar)) - -        left_flanking = not ( -            isNextWhiteSpace -            or (isNextPunctChar and not (isLastWhiteSpace or isLastPunctChar)) -        ) -        right_flanking = not ( -            isLastWhiteSpace -            or (isLastPunctChar and not (isNextWhiteSpace or isNextPunctChar)) -        ) - -        if not canSplitWord: -            can_open = left_flanking and ((not right_flanking) or isLastPunctChar) -            can_close = right_flanking and ((not left_flanking) or isNextPunctChar) -        else: -            can_open = left_flanking -            can_close = right_flanking - -        return Scanned(can_open, can_close, count) diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/strikethrough.py b/venv/lib/python3.11/site-packages/markdown_it/rules_inline/strikethrough.py deleted file mode 100644 index ec81628..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/strikethrough.py +++ /dev/null @@ -1,127 +0,0 @@ -# ~~strike through~~ -from __future__ import annotations - -from .state_inline import Delimiter, StateInline - - -def tokenize(state: StateInline, silent: bool) -> bool: -    """Insert each marker as a separate text token, and add it to delimiter list""" -    start = state.pos -    ch = state.src[start] - -    if silent: -        return False - -    if ch != "~": -        return False - -    scanned = state.scanDelims(state.pos, True) -    length = scanned.length - -    if length < 2: -        return False - -    if length % 2: -        token = state.push("text", "", 0) -        token.content = ch -        length -= 1 - -    i = 0 -    while i < length: -        token = state.push("text", "", 0) -        token.content = ch + ch -        state.delimiters.append( -            Delimiter( -                marker=ord(ch), -                length=0,  # disable "rule of 3" length checks meant for emphasis -                token=len(state.tokens) - 1, -                end=-1, -                open=scanned.can_open, -                close=scanned.can_close, -            ) -        ) - -        i += 2 - -    state.pos += scanned.length - -    return True - - -def _postProcess(state: StateInline, delimiters: list[Delimiter]) -> None: -    loneMarkers = [] -    maximum = len(delimiters) - -    i = 0 -    while i < maximum: -        startDelim = delimiters[i] - -        if startDelim.marker != 0x7E:  # /* ~ */ -            i += 1 -            continue - -        if startDelim.end == -1: -            i += 1 -            continue - -        endDelim = delimiters[startDelim.end] - -        token = state.tokens[startDelim.token] -        token.type = "s_open" -        token.tag = "s" -        token.nesting = 1 -        token.markup = "~~" -        token.content = "" - -        token = state.tokens[endDelim.token] -        token.type = "s_close" -        token.tag = "s" -        token.nesting = -1 -        token.markup = "~~" -        token.content = "" - -        if ( -            state.tokens[endDelim.token - 1].type == "text" -            and state.tokens[endDelim.token - 1].content == "~" -        ): -            loneMarkers.append(endDelim.token - 1) - -        i += 1 - -    # If a marker sequence has an odd number of characters, it's split -    # like this: `~~~~~` -> `~` + `~~` + `~~`, leaving one marker at the -    # start of the sequence. -    # -    # So, we have to move all those markers after subsequent s_close tags. -    # -    while loneMarkers: -        i = loneMarkers.pop() -        j = i + 1 - -        while (j < len(state.tokens)) and (state.tokens[j].type == "s_close"): -            j += 1 - -        j -= 1 - -        if i != j: -            token = state.tokens[j] -            state.tokens[j] = state.tokens[i] -            state.tokens[i] = token - - -def postProcess(state: StateInline) -> None: -    """Walk through delimiter list and replace text tokens with tags.""" -    tokens_meta = state.tokens_meta -    maximum = len(state.tokens_meta) -    _postProcess(state, state.delimiters) - -    curr = 0 -    while curr < maximum: -        try: -            curr_meta = tokens_meta[curr] -        except IndexError: -            pass -        else: -            if curr_meta and "delimiters" in curr_meta: -                _postProcess(state, curr_meta["delimiters"]) -        curr += 1 diff --git a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/text.py b/venv/lib/python3.11/site-packages/markdown_it/rules_inline/text.py deleted file mode 100644 index f306b2e..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/rules_inline/text.py +++ /dev/null @@ -1,53 +0,0 @@ -# Skip text characters for text token, place those to pending buffer -# and increment current pos -from .state_inline import StateInline - -# Rule to skip pure text -# '{}$%@~+=:' reserved for extensions - -# !!!! Don't confuse with "Markdown ASCII Punctuation" chars -# http://spec.commonmark.org/0.15/#ascii-punctuation-character - - -_TerminatorChars = { -    "\n", -    "!", -    "#", -    "$", -    "%", -    "&", -    "*", -    "+", -    "-", -    ":", -    "<", -    "=", -    ">", -    "@", -    "[", -    "\\", -    "]", -    "^", -    "_", -    "`", -    "{", -    "}", -    "~", -} - - -def text(state: StateInline, silent: bool) -> bool: -    pos = state.pos -    posMax = state.posMax -    while (pos < posMax) and state.src[pos] not in _TerminatorChars: -        pos += 1 - -    if pos == state.pos: -        return False - -    if not silent: -        state.pending += state.src[state.pos : pos] - -    state.pos = pos - -    return True diff --git a/venv/lib/python3.11/site-packages/markdown_it/token.py b/venv/lib/python3.11/site-packages/markdown_it/token.py deleted file mode 100644 index 90008b7..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/token.py +++ /dev/null @@ -1,180 +0,0 @@ -from __future__ import annotations - -from collections.abc import Callable, MutableMapping -import dataclasses as dc -from typing import Any, Literal -import warnings - -from markdown_it._compat import DATACLASS_KWARGS - - -def convert_attrs(value: Any) -> Any: -    """Convert Token.attrs set as ``None`` or ``[[key, value], ...]`` to a dict. - -    This improves compatibility with upstream markdown-it. -    """ -    if not value: -        return {} -    if isinstance(value, list): -        return dict(value) -    return value - - -@dc.dataclass(**DATACLASS_KWARGS) -class Token: -    type: str -    """Type of the token (string, e.g. "paragraph_open")""" - -    tag: str -    """HTML tag name, e.g. 'p'""" - -    nesting: Literal[-1, 0, 1] -    """Level change (number in {-1, 0, 1} set), where: -    -  `1` means the tag is opening -    -  `0` means the tag is self-closing -    - `-1` means the tag is closing -    """ - -    attrs: dict[str, str | int | float] = dc.field(default_factory=dict) -    """HTML attributes. -    Note this differs from the upstream "list of lists" format, -    although than an instance can still be initialised with this format. -    """ - -    map: list[int] | None = None -    """Source map info. Format: `[ line_begin, line_end ]`""" - -    level: int = 0 -    """Nesting level, the same as `state.level`""" - -    children: list[Token] | None = None -    """Array of child nodes (inline and img tokens).""" - -    content: str = "" -    """Inner content, in the case of a self-closing tag (code, html, fence, etc.),""" - -    markup: str = "" -    """'*' or '_' for emphasis, fence string for fence, etc.""" - -    info: str = "" -    """Additional information: -    - Info string for "fence" tokens -    - The value "auto" for autolink "link_open" and "link_close" tokens -    - The string value of the item marker for ordered-list "list_item_open" tokens -    """ - -    meta: dict[Any, Any] = dc.field(default_factory=dict) -    """A place for plugins to store any arbitrary data""" - -    block: bool = False -    """True for block-level tokens, false for inline tokens. -    Used in renderer to calculate line breaks -    """ - -    hidden: bool = False -    """If true, ignore this element when rendering. -    Used for tight lists to hide paragraphs. -    """ - -    def __post_init__(self) -> None: -        self.attrs = convert_attrs(self.attrs) - -    def attrIndex(self, name: str) -> int: -        warnings.warn(  # noqa: B028 -            "Token.attrIndex should not be used, since Token.attrs is a dictionary", -            UserWarning, -        ) -        if name not in self.attrs: -            return -1 -        return list(self.attrs.keys()).index(name) - -    def attrItems(self) -> list[tuple[str, str | int | float]]: -        """Get (key, value) list of attrs.""" -        return list(self.attrs.items()) - -    def attrPush(self, attrData: tuple[str, str | int | float]) -> None: -        """Add `[ name, value ]` attribute to list. Init attrs if necessary.""" -        name, value = attrData -        self.attrSet(name, value) - -    def attrSet(self, name: str, value: str | int | float) -> None: -        """Set `name` attribute to `value`. Override old value if exists.""" -        self.attrs[name] = value - -    def attrGet(self, name: str) -> None | str | int | float: -        """Get the value of attribute `name`, or null if it does not exist.""" -        return self.attrs.get(name, None) - -    def attrJoin(self, name: str, value: str) -> None: -        """Join value to existing attribute via space. -        Or create new attribute if not exists. -        Useful to operate with token classes. -        """ -        if name in self.attrs: -            current = self.attrs[name] -            if not isinstance(current, str): -                raise TypeError( -                    f"existing attr 'name' is not a str: {self.attrs[name]}" -                ) -            self.attrs[name] = f"{current} {value}" -        else: -            self.attrs[name] = value - -    def copy(self, **changes: Any) -> Token: -        """Return a shallow copy of the instance.""" -        return dc.replace(self, **changes) - -    def as_dict( -        self, -        *, -        children: bool = True, -        as_upstream: bool = True, -        meta_serializer: Callable[[dict[Any, Any]], Any] | None = None, -        filter: Callable[[str, Any], bool] | None = None, -        dict_factory: Callable[..., MutableMapping[str, Any]] = dict, -    ) -> MutableMapping[str, Any]: -        """Return the token as a dictionary. - -        :param children: Also convert children to dicts -        :param as_upstream: Ensure the output dictionary is equal to that created by markdown-it -            For example, attrs are converted to null or lists -        :param meta_serializer: hook for serializing ``Token.meta`` -        :param filter: A callable whose return code determines whether an -            attribute or element is included (``True``) or dropped (``False``). -            Is called with the (key, value) pair. -        :param dict_factory: A callable to produce dictionaries from. -            For example, to produce ordered dictionaries instead of normal Python -            dictionaries, pass in ``collections.OrderedDict``. - -        """ -        mapping = dict_factory((f.name, getattr(self, f.name)) for f in dc.fields(self)) -        if filter: -            mapping = dict_factory((k, v) for k, v in mapping.items() if filter(k, v)) -        if as_upstream and "attrs" in mapping: -            mapping["attrs"] = ( -                None -                if not mapping["attrs"] -                else [[k, v] for k, v in mapping["attrs"].items()] -            ) -        if meta_serializer and "meta" in mapping: -            mapping["meta"] = meta_serializer(mapping["meta"]) -        if children and mapping.get("children", None): -            mapping["children"] = [ -                child.as_dict( -                    children=children, -                    filter=filter, -                    dict_factory=dict_factory, -                    as_upstream=as_upstream, -                    meta_serializer=meta_serializer, -                ) -                for child in mapping["children"] -            ] -        return mapping - -    @classmethod -    def from_dict(cls, dct: MutableMapping[str, Any]) -> Token: -        """Convert a dict to a Token.""" -        token = cls(**dct) -        if token.children: -            token.children = [cls.from_dict(c) for c in token.children]  # type: ignore[arg-type] -        return token diff --git a/venv/lib/python3.11/site-packages/markdown_it/tree.py b/venv/lib/python3.11/site-packages/markdown_it/tree.py deleted file mode 100644 index 6641e5a..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/tree.py +++ /dev/null @@ -1,345 +0,0 @@ -"""A tree representation of a linear markdown-it token stream. - -This module is not part of upstream JavaScript markdown-it. -""" -from __future__ import annotations - -from collections.abc import Generator, Sequence -import textwrap -from typing import Any, NamedTuple, TypeVar, overload - -from .token import Token - - -class _NesterTokens(NamedTuple): -    opening: Token -    closing: Token - - -_NodeType = TypeVar("_NodeType", bound="SyntaxTreeNode") - - -class SyntaxTreeNode: -    """A Markdown syntax tree node. - -    A class that can be used to construct a tree representation of a linear -    `markdown-it-py` token stream. - -    Each node in the tree represents either: -      - root of the Markdown document -      - a single unnested `Token` -      - a `Token` "_open" and "_close" token pair, and the tokens nested in -          between -    """ - -    def __init__( -        self, tokens: Sequence[Token] = (), *, create_root: bool = True -    ) -> None: -        """Initialize a `SyntaxTreeNode` from a token stream. - -        If `create_root` is True, create a root node for the document. -        """ -        # Only nodes representing an unnested token have self.token -        self.token: Token | None = None - -        # Only containers have nester tokens -        self.nester_tokens: _NesterTokens | None = None - -        # Root node does not have self.parent -        self._parent: Any = None - -        # Empty list unless a non-empty container, or unnested token that has -        # children (i.e. inline or img) -        self._children: list[Any] = [] - -        if create_root: -            self._set_children_from_tokens(tokens) -            return - -        if not tokens: -            raise ValueError( -                "Can only create root from empty token sequence." -                " Set `create_root=True`." -            ) -        elif len(tokens) == 1: -            inline_token = tokens[0] -            if inline_token.nesting: -                raise ValueError( -                    "Unequal nesting level at the start and end of token stream." -                ) -            self.token = inline_token -            if inline_token.children: -                self._set_children_from_tokens(inline_token.children) -        else: -            self.nester_tokens = _NesterTokens(tokens[0], tokens[-1]) -            self._set_children_from_tokens(tokens[1:-1]) - -    def __repr__(self) -> str: -        return f"{type(self).__name__}({self.type})" - -    @overload -    def __getitem__(self: _NodeType, item: int) -> _NodeType: -        ... - -    @overload -    def __getitem__(self: _NodeType, item: slice) -> list[_NodeType]: -        ... - -    def __getitem__(self: _NodeType, item: int | slice) -> _NodeType | list[_NodeType]: -        return self.children[item] - -    def to_tokens(self: _NodeType) -> list[Token]: -        """Recover the linear token stream.""" - -        def recursive_collect_tokens(node: _NodeType, token_list: list[Token]) -> None: -            if node.type == "root": -                for child in node.children: -                    recursive_collect_tokens(child, token_list) -            elif node.token: -                token_list.append(node.token) -            else: -                assert node.nester_tokens -                token_list.append(node.nester_tokens.opening) -                for child in node.children: -                    recursive_collect_tokens(child, token_list) -                token_list.append(node.nester_tokens.closing) - -        tokens: list[Token] = [] -        recursive_collect_tokens(self, tokens) -        return tokens - -    @property -    def children(self: _NodeType) -> list[_NodeType]: -        return self._children - -    @children.setter -    def children(self: _NodeType, value: list[_NodeType]) -> None: -        self._children = value - -    @property -    def parent(self: _NodeType) -> _NodeType | None: -        return self._parent  # type: ignore - -    @parent.setter -    def parent(self: _NodeType, value: _NodeType | None) -> None: -        self._parent = value - -    @property -    def is_root(self) -> bool: -        """Is the node a special root node?""" -        return not (self.token or self.nester_tokens) - -    @property -    def is_nested(self) -> bool: -        """Is this node nested?. - -        Returns `True` if the node represents a `Token` pair and tokens in the -        sequence between them, where `Token.nesting` of the first `Token` in -        the pair is 1 and nesting of the other `Token` is -1. -        """ -        return bool(self.nester_tokens) - -    @property -    def siblings(self: _NodeType) -> Sequence[_NodeType]: -        """Get siblings of the node. - -        Gets the whole group of siblings, including self. -        """ -        if not self.parent: -            return [self] -        return self.parent.children - -    @property -    def type(self) -> str: -        """Get a string type of the represented syntax. - -        - "root" for root nodes -        - `Token.type` if the node represents an unnested token -        - `Token.type` of the opening token, with "_open" suffix stripped, if -            the node represents a nester token pair -        """ -        if self.is_root: -            return "root" -        if self.token: -            return self.token.type -        assert self.nester_tokens -        return _removesuffix(self.nester_tokens.opening.type, "_open") - -    @property -    def next_sibling(self: _NodeType) -> _NodeType | None: -        """Get the next node in the sequence of siblings. - -        Returns `None` if this is the last sibling. -        """ -        self_index = self.siblings.index(self) -        if self_index + 1 < len(self.siblings): -            return self.siblings[self_index + 1] -        return None - -    @property -    def previous_sibling(self: _NodeType) -> _NodeType | None: -        """Get the previous node in the sequence of siblings. - -        Returns `None` if this is the first sibling. -        """ -        self_index = self.siblings.index(self) -        if self_index - 1 >= 0: -            return self.siblings[self_index - 1] -        return None - -    def _add_child( -        self, -        tokens: Sequence[Token], -    ) -> None: -        """Make a child node for `self`.""" -        child = type(self)(tokens, create_root=False) -        child.parent = self -        self.children.append(child) - -    def _set_children_from_tokens(self, tokens: Sequence[Token]) -> None: -        """Convert the token stream to a tree structure and set the resulting -        nodes as children of `self`.""" -        reversed_tokens = list(reversed(tokens)) -        while reversed_tokens: -            token = reversed_tokens.pop() - -            if not token.nesting: -                self._add_child([token]) -                continue -            if token.nesting != 1: -                raise ValueError("Invalid token nesting") - -            nested_tokens = [token] -            nesting = 1 -            while reversed_tokens and nesting: -                token = reversed_tokens.pop() -                nested_tokens.append(token) -                nesting += token.nesting -            if nesting: -                raise ValueError(f"unclosed tokens starting {nested_tokens[0]}") - -            self._add_child(nested_tokens) - -    def pretty( -        self, *, indent: int = 2, show_text: bool = False, _current: int = 0 -    ) -> str: -        """Create an XML style string of the tree.""" -        prefix = " " * _current -        text = prefix + f"<{self.type}" -        if not self.is_root and self.attrs: -            text += " " + " ".join(f"{k}={v!r}" for k, v in self.attrs.items()) -        text += ">" -        if ( -            show_text -            and not self.is_root -            and self.type in ("text", "text_special") -            and self.content -        ): -            text += "\n" + textwrap.indent(self.content, prefix + " " * indent) -        for child in self.children: -            text += "\n" + child.pretty( -                indent=indent, show_text=show_text, _current=_current + indent -            ) -        return text - -    def walk( -        self: _NodeType, *, include_self: bool = True -    ) -> Generator[_NodeType, None, None]: -        """Recursively yield all descendant nodes in the tree starting at self. - -        The order mimics the order of the underlying linear token -        stream (i.e. depth first). -        """ -        if include_self: -            yield self -        for child in self.children: -            yield from child.walk(include_self=True) - -    # NOTE: -    # The values of the properties defined below directly map to properties -    # of the underlying `Token`s. A root node does not translate to a `Token` -    # object, so calling these property getters on a root node will raise an -    # `AttributeError`. -    # -    # There is no mapping for `Token.nesting` because the `is_nested` property -    # provides that data, and can be called on any node type, including root. - -    def _attribute_token(self) -> Token: -        """Return the `Token` that is used as the data source for the -        properties defined below.""" -        if self.token: -            return self.token -        if self.nester_tokens: -            return self.nester_tokens.opening -        raise AttributeError("Root node does not have the accessed attribute") - -    @property -    def tag(self) -> str: -        """html tag name, e.g. \"p\" """ -        return self._attribute_token().tag - -    @property -    def attrs(self) -> dict[str, str | int | float]: -        """Html attributes.""" -        return self._attribute_token().attrs - -    def attrGet(self, name: str) -> None | str | int | float: -        """Get the value of attribute `name`, or null if it does not exist.""" -        return self._attribute_token().attrGet(name) - -    @property -    def map(self) -> tuple[int, int] | None: -        """Source map info. Format: `tuple[ line_begin, line_end ]`""" -        map_ = self._attribute_token().map -        if map_: -            # Type ignore because `Token`s attribute types are not perfect -            return tuple(map_)  # type: ignore -        return None - -    @property -    def level(self) -> int: -        """nesting level, the same as `state.level`""" -        return self._attribute_token().level - -    @property -    def content(self) -> str: -        """In a case of self-closing tag (code, html, fence, etc.), it -        has contents of this tag.""" -        return self._attribute_token().content - -    @property -    def markup(self) -> str: -        """'*' or '_' for emphasis, fence string for fence, etc.""" -        return self._attribute_token().markup - -    @property -    def info(self) -> str: -        """fence infostring""" -        return self._attribute_token().info - -    @property -    def meta(self) -> dict[Any, Any]: -        """A place for plugins to store an arbitrary data.""" -        return self._attribute_token().meta - -    @property -    def block(self) -> bool: -        """True for block-level tokens, false for inline tokens.""" -        return self._attribute_token().block - -    @property -    def hidden(self) -> bool: -        """If it's true, ignore this element when rendering. -        Used for tight lists to hide paragraphs.""" -        return self._attribute_token().hidden - - -def _removesuffix(string: str, suffix: str) -> str: -    """Remove a suffix from a string. - -    Replace this with str.removesuffix() from stdlib when minimum Python -    version is 3.9. -    """ -    if suffix and string.endswith(suffix): -        return string[: -len(suffix)] -    return string diff --git a/venv/lib/python3.11/site-packages/markdown_it/utils.py b/venv/lib/python3.11/site-packages/markdown_it/utils.py deleted file mode 100644 index a979372..0000000 --- a/venv/lib/python3.11/site-packages/markdown_it/utils.py +++ /dev/null @@ -1,176 +0,0 @@ -from __future__ import annotations - -from collections.abc import MutableMapping as MutableMappingABC -from pathlib import Path -from typing import Any, Callable, Iterable, MutableMapping, TypedDict, cast - -EnvType = MutableMapping[str, Any]  # note: could use TypeAlias in python 3.10 -"""Type for the environment sandbox used in parsing and rendering, -which stores mutable variables for use by plugins and rules. -""" - - -class OptionsType(TypedDict): -    """Options for parsing.""" - -    maxNesting: int -    """Internal protection, recursion limit.""" -    html: bool -    """Enable HTML tags in source.""" -    linkify: bool -    """Enable autoconversion of URL-like texts to links.""" -    typographer: bool -    """Enable smartquotes and replacements.""" -    quotes: str -    """Quote characters.""" -    xhtmlOut: bool -    """Use '/' to close single tags (<br />).""" -    breaks: bool -    """Convert newlines in paragraphs into <br>.""" -    langPrefix: str -    """CSS language prefix for fenced blocks.""" -    highlight: Callable[[str, str, str], str] | None -    """Highlighter function: (content, lang, attrs) -> str.""" - - -class PresetType(TypedDict): -    """Preset configuration for markdown-it.""" - -    options: OptionsType -    """Options for parsing.""" -    components: MutableMapping[str, MutableMapping[str, list[str]]] -    """Components for parsing and rendering.""" - - -class OptionsDict(MutableMappingABC):  # type: ignore -    """A dictionary, with attribute access to core markdownit configuration options.""" - -    # Note: ideally we would probably just remove attribute access entirely, -    # but we keep it for backwards compatibility. - -    def __init__(self, options: OptionsType) -> None: -        self._options = cast(OptionsType, dict(options)) - -    def __getitem__(self, key: str) -> Any: -        return self._options[key]  # type: ignore[literal-required] - -    def __setitem__(self, key: str, value: Any) -> None: -        self._options[key] = value  # type: ignore[literal-required] - -    def __delitem__(self, key: str) -> None: -        del self._options[key]  # type: ignore - -    def __iter__(self) -> Iterable[str]:  # type: ignore -        return iter(self._options) - -    def __len__(self) -> int: -        return len(self._options) - -    def __repr__(self) -> str: -        return repr(self._options) - -    def __str__(self) -> str: -        return str(self._options) - -    @property -    def maxNesting(self) -> int: -        """Internal protection, recursion limit.""" -        return self._options["maxNesting"] - -    @maxNesting.setter -    def maxNesting(self, value: int) -> None: -        self._options["maxNesting"] = value - -    @property -    def html(self) -> bool: -        """Enable HTML tags in source.""" -        return self._options["html"] - -    @html.setter -    def html(self, value: bool) -> None: -        self._options["html"] = value - -    @property -    def linkify(self) -> bool: -        """Enable autoconversion of URL-like texts to links.""" -        return self._options["linkify"] - -    @linkify.setter -    def linkify(self, value: bool) -> None: -        self._options["linkify"] = value - -    @property -    def typographer(self) -> bool: -        """Enable smartquotes and replacements.""" -        return self._options["typographer"] - -    @typographer.setter -    def typographer(self, value: bool) -> None: -        self._options["typographer"] = value - -    @property -    def quotes(self) -> str: -        """Quote characters.""" -        return self._options["quotes"] - -    @quotes.setter -    def quotes(self, value: str) -> None: -        self._options["quotes"] = value - -    @property -    def xhtmlOut(self) -> bool: -        """Use '/' to close single tags (<br />).""" -        return self._options["xhtmlOut"] - -    @xhtmlOut.setter -    def xhtmlOut(self, value: bool) -> None: -        self._options["xhtmlOut"] = value - -    @property -    def breaks(self) -> bool: -        """Convert newlines in paragraphs into <br>.""" -        return self._options["breaks"] - -    @breaks.setter -    def breaks(self, value: bool) -> None: -        self._options["breaks"] = value - -    @property -    def langPrefix(self) -> str: -        """CSS language prefix for fenced blocks.""" -        return self._options["langPrefix"] - -    @langPrefix.setter -    def langPrefix(self, value: str) -> None: -        self._options["langPrefix"] = value - -    @property -    def highlight(self) -> Callable[[str, str, str], str] | None: -        """Highlighter function: (content, langName, langAttrs) -> escaped HTML.""" -        return self._options["highlight"] - -    @highlight.setter -    def highlight(self, value: Callable[[str, str, str], str] | None) -> None: -        self._options["highlight"] = value - - -def read_fixture_file(path: str | Path) -> list[list[Any]]: -    text = Path(path).read_text(encoding="utf-8") -    tests = [] -    section = 0 -    last_pos = 0 -    lines = text.splitlines(keepends=True) -    for i in range(len(lines)): -        if lines[i].rstrip() == ".": -            if section == 0: -                tests.append([i, lines[i - 1].strip()]) -                section = 1 -            elif section == 1: -                tests[-1].append("".join(lines[last_pos + 1 : i])) -                section = 2 -            elif section == 2: -                tests[-1].append("".join(lines[last_pos + 1 : i])) -                section = 0 - -            last_pos = i -    return tests | 
