pax_global_header00006660000000000000000000000064152653716750014533gustar00rootroot0000000000000052 comment=f19057fdf339affb61ca63c7fe28df7a951ec588 lepture-mistune-f19057f/000077500000000000000000000000001526537167500152405ustar00rootroot00000000000000lepture-mistune-f19057f/.editorconfig000066400000000000000000000002311526537167500177110ustar00rootroot00000000000000root=true [*] insert_final_newline = true end_of_line = lf indent_style = space indent_size = 2 [*.py] indent_size = 4 trim_trailing_whitespace = true lepture-mistune-f19057f/.github/000077500000000000000000000000001526537167500166005ustar00rootroot00000000000000lepture-mistune-f19057f/.github/FUNDING.yml000066400000000000000000000003741526537167500204210ustar00rootroot00000000000000# These are supported funding model platforms github: [lepture] patreon: lepture open_collective: # Replace with a single Open Collective username ko_fi: # Replace with a single Ko-fi username tidelift: pypi/mistune custom: https://lepture.com/donate lepture-mistune-f19057f/.github/SECURITY.md000066400000000000000000000002521526537167500203700ustar00rootroot00000000000000# Security If you discover a security vulnerability, **do not submit a public issue or patch**. Instead, please report it privately through the **GitHub Security** tab. lepture-mistune-f19057f/.github/workflows/000077500000000000000000000000001526537167500206355ustar00rootroot00000000000000lepture-mistune-f19057f/.github/workflows/pypi.yml000066400000000000000000000022561526537167500223460ustar00rootroot00000000000000name: Release to PyPI on: push: tags: - "v*" jobs: build: name: build dist files runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 - uses: astral-sh/setup-uv@v10.3.0 with: python-version: "3.10" - name: build dist run: uv build - uses: actions/upload-artifact@v6 with: name: artifacts path: dist/* if-no-files-found: error publish: permissions: id-token: write environment: name: pypi-release name: release to pypi needs: build runs-on: ubuntu-latest steps: - uses: actions/download-artifact@v7 with: name: artifacts path: dist - name: Push build artifacts to PyPI uses: pypa/gh-action-pypi-publish@release/v1 release: permissions: contents: write name: write release note runs-on: ubuntu-latest needs: publish steps: - uses: actions/checkout@v7 with: fetch-depth: 0 - uses: actions/setup-node@v6 with: node-version: 24 - run: npx changelogithub --no-group continue-on-error: true env: GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} lepture-mistune-f19057f/.github/workflows/tests.yml000066400000000000000000000045621526537167500225310ustar00rootroot00000000000000name: Run tests on: push: branches-ignore: - 'wip-*' pull_request: branches-ignore: - 'wip-*' workflow_dispatch: jobs: lint: runs-on: ubuntu-latest permissions: contents: read steps: - uses: actions/checkout@v7 - uses: astral-sh/setup-uv@v10.3.0 with: python-version: "3.13" - name: ruff lint run: uv run --locked --group lint ruff check . - name: mypy lint run: uv run --locked --group lint mypy docs: needs: lint runs-on: ubuntu-latest permissions: contents: read steps: - uses: actions/checkout@v7 - uses: astral-sh/setup-uv@v10.3.0 with: python-version: "3.13" - name: Build documentation without remote inventories env: MISTUNE_DOCS_OFFLINE: "1" run: uv run --locked --group docs sphinx-build -W -b dummy docs /tmp/mistune-docs test: needs: lint runs-on: ubuntu-latest permissions: contents: read pull-requests: read strategy: fail-fast: false max-parallel: 3 matrix: python-version: - "3.10" - "3.11" - "3.12" - "3.13" - "3.14" - "3.15" - "pypy3.11" steps: - uses: actions/checkout@v7 - name: Set up uv and Python ${{ matrix.python-version }} uses: astral-sh/setup-uv@v10.3.0 with: python-version: ${{ matrix.python-version }} - name: Report coverage run: uv run --locked --group test pytest --cov=mistune --cov-branch --cov-report=xml - name: Upload coverage reports to Codecov uses: codecov/codecov-action@v7 with: token: ${{ secrets.CODECOV_TOKEN }} sonar: needs: test runs-on: ubuntu-latest permissions: contents: read pull-requests: read steps: - uses: actions/checkout@v7 with: ref: ${{ github.event.pull_request.head.sha || github.sha }} - uses: astral-sh/setup-uv@v10.3.0 with: python-version: "3.13" - name: Generate coverage run: uv run --locked --group test pytest --cov=mistune --cov-branch --cov-report=xml - name: SonarCloud Scan uses: SonarSource/sonarqube-scan-action@v8 continue-on-error: true env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} lepture-mistune-f19057f/.gitignore000066400000000000000000000003331526537167500172270ustar00rootroot00000000000000*.pyc *.pyo *.egg-info .idea __pycache__ bin build develop-eggs dist eggs parts .DS_Store .installed.cfg docs/_build cover/ .tox *.bak *.c *.so .venv/ plans/ .python-version .coverage htmlcov .eggs coverage.xml demo.py lepture-mistune-f19057f/.readthedocs.yaml000066400000000000000000000003061526537167500204660ustar00rootroot00000000000000version: 2 build: os: "ubuntu-lts-latest" tools: python: "3.13" sphinx: configuration: docs/conf.py python: install: - method: uv command: sync groups: - docs lepture-mistune-f19057f/LICENSE000066400000000000000000000027031526537167500162470ustar00rootroot00000000000000Copyright (c) 2014, Hsiaoming Yang All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the creator nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. lepture-mistune-f19057f/MANIFEST.in000066400000000000000000000003371526537167500170010ustar00rootroot00000000000000# include all test files but avoid including .pyc recursive-include benchmark *.py *.txt recursive-include tests *.json *.html *.md *.py *.txt # include documentation sources but not built docs graft docs prune docs/_build lepture-mistune-f19057f/Makefile000066400000000000000000000005751526537167500167070ustar00rootroot00000000000000.PHONY: clean-pyc clean-build build-docs clean: clean-build clean-pyc clean-build: @rm -fr build/ @rm -fr dist/ @rm -fr *.egg-info @rm -fr .coverage clean-pyc: @find . -name '*.pyc' -exec rm -f {} + @find . -name '*.pyo' -exec rm -f {} + @find . -name '*~' -exec rm -f {} + @find . -name '__pycache__' -exec rm -fr {} + build-docs: @sphinx-build docs build/_html -a lepture-mistune-f19057f/README.md000066400000000000000000000276711526537167500165340ustar00rootroot00000000000000
Mistune v3 A fast yet powerful Python Markdown parser with renderers and plugins. [![Build Status](https://github.com/lepture/mistune/actions/workflows/tests.yml/badge.svg)](https://github.com/lepture/mistune/actions) [![PyPI version](https://img.shields.io/pypi/v/mistune.svg)](https://pypi.org/project/mistune) [![conda-forge version](https://img.shields.io/conda/v/conda-forge/mistune.svg?label=conda-forge&colorB=0090ff)](https://anaconda.org/conda-forge/mistune) [![PyPI Downloads](https://static.pepy.tech/badge/mistune/month)](https://pepy.tech/projects/mistune) [![Code Coverage](https://codecov.io/gh/lepture/mistune/branch/main/graph/badge.svg?token=mcpitD54Tx)](https://codecov.io/gh/lepture/mistune) [![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=lepture_mistune&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=lepture_mistune) [![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=lepture_mistune&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=lepture_mistune)
> [!NOTE] > > I’ve released [Wenmode](https://github.com/lepture/wenmode), a new Markdown parser inspired by the lessons learned from Mistune. > > Wenmode focuses on fast CommonMark-style parsing, explicit rule composition, mdast-compatible AST output, safe HTML defaults, streaming output, and pluggable renderers. > > In the current benchmark suite, Wenmode’s core Markdown-to-HTML path is about 1.5-1.8x as fast as Mistune across the tested documentation corpora. See the [benchmark results](https://wenmode.lepture.com/benchmarks/) for the exact setup and numbers. Check [benchmark results for Wenmode](https://github.com/lepture/wenmode#benchmark). ## Sponsors
Convert Word, Excel, and text-based PDF files to Markdown—or turn Markdown into Word, Excel, and PDF—with Spire.Office for Python. Automate document conversion directly in Python, without requiring Microsoft Office.
## Install To install mistune: ``` $ pip install mistune ``` ## Overview Convert Markdown to HTML with ease: ```python import mistune markdown = mistune.create_markdown() markdown(your_markdown_text) ``` `create_markdown()` escapes raw HTML by default. For compatibility, `mistune.html(trusted_markdown_text)` enables raw HTML and several plugins; use that legacy helper only for trusted input or sanitize its output externally. ## Security Reporting If you find a security bug, please do not send a public issue or patch. Follow the repository's [security policy](.github/SECURITY.md) to report it privately. ## Benchmarks
Here is the benchmark score on my computer. Check the `benchmark/bench.py` script. ``` mistune (3.0.0) - atx: 13.901472091674805ms mistune (slow) - atx: 13.122797012329102ms mistune (fast) - atx: 13.248443603515625ms mistune (full) - atx: 15.445232391357422ms markdown (3.3.7) - atx: 48.41303825378418ms markdown2 (2.4.3) - atx: 379.30870056152344ms mistletoe (0.8.2) - atx: 25.46215057373047ms markdown_it (2.1.0) - atx: 42.37723350524902ms mistune (3.0.0) - setext: 8.43048095703125ms mistune (slow) - setext: 8.97979736328125ms mistune (fast) - setext: 8.122920989990234ms mistune (full) - setext: 9.525299072265625ms markdown (3.3.7) - setext: 30.74812889099121ms markdown2 (2.4.3) - setext: 218.90878677368164ms mistletoe (0.8.2) - setext: 20.46680450439453ms markdown_it (2.1.0) - setext: 27.010202407836914ms mistune (3.0.0) - normal_ul: 60.910940170288086ms mistune (slow) - normal_ul: 59.69667434692383ms mistune (fast) - normal_ul: 60.41216850280762ms mistune (full) - normal_ul: 62.89219856262207ms markdown (3.3.7) - normal_ul: 83.7857723236084ms markdown2 (2.4.3) - normal_ul: 175.36139488220215ms mistletoe (0.8.2) - normal_ul: 74.82385635375977ms markdown_it (2.1.0) - normal_ul: 103.0113697052002ms mistune (3.0.0) - insane_ul: 104.1865348815918ms mistune (slow) - insane_ul: 105.83090782165527ms mistune (fast) - insane_ul: 103.03664207458496ms mistune (full) - insane_ul: 105.80086708068848ms markdown (3.3.7) - insane_ul: 133.82673263549805ms markdown2 (2.4.3) - insane_ul: 337.23902702331543ms mistletoe (0.8.2) - insane_ul: 122.10249900817871ms markdown_it (2.1.0) - insane_ul: 85.92629432678223ms mistune (3.0.0) - normal_ol: 25.092601776123047ms mistune (slow) - normal_ol: 25.321483612060547ms mistune (fast) - normal_ol: 25.11453628540039ms mistune (full) - normal_ol: 25.945663452148438ms markdown (3.3.7) - normal_ol: 43.30158233642578ms markdown2 (2.4.3) - normal_ol: 75.87885856628418ms mistletoe (0.8.2) - normal_ol: 33.63537788391113ms markdown_it (2.1.0) - normal_ol: 40.307044982910156ms mistune (3.0.0) - insane_ol: 46.201229095458984ms mistune (slow) - insane_ol: 49.14569854736328ms mistune (fast) - insane_ol: 45.96853256225586ms mistune (full) - insane_ol: 47.544002532958984ms markdown (3.3.7) - insane_ol: 50.154924392700195ms markdown2 (2.4.3) - insane_ol: 210.48712730407715ms mistletoe (0.8.2) - insane_ol: 84.07974243164062ms markdown_it (2.1.0) - insane_ol: 83.61554145812988ms mistune (3.0.0) - blockquote: 15.484809875488281ms mistune (slow) - blockquote: 16.12544059753418ms mistune (fast) - blockquote: 15.350818634033203ms mistune (full) - blockquote: 16.104936599731445ms markdown (3.3.7) - blockquote: 63.04144859313965ms markdown2 (2.4.3) - blockquote: 702.4445533752441ms mistletoe (0.8.2) - blockquote: 28.56159210205078ms markdown_it (2.1.0) - blockquote: 37.35041618347168ms mistune (3.0.0) - blockhtml: 7.898569107055664ms mistune (slow) - blockhtml: 7.080316543579102ms mistune (fast) - blockhtml: 7.414340972900391ms mistune (full) - blockhtml: 8.559703826904297ms markdown (3.3.7) - blockhtml: 46.65660858154297ms markdown2 (2.4.3) - blockhtml: 122.09773063659668ms mistletoe (0.8.2) - blockhtml: 12.23611831665039ms markdown_it (2.1.0) - blockhtml: 26.836156845092773ms mistune (3.0.0) - fenced: 4.281282424926758ms mistune (slow) - fenced: 4.092931747436523ms mistune (fast) - fenced: 4.024267196655273ms mistune (full) - fenced: 4.453897476196289ms markdown (3.3.7) - fenced: 33.83779525756836ms markdown2 (2.4.3) - fenced: 92.49091148376465ms mistletoe (0.8.2) - fenced: 9.19342041015625ms markdown_it (2.1.0) - fenced: 12.503623962402344ms mistune (3.0.0) - paragraph: 95.94106674194336ms mistune (slow) - paragraph: 561.2788200378418ms mistune (fast) - paragraph: 93.597412109375ms mistune (full) - paragraph: 110.09836196899414ms markdown (3.3.7) - paragraph: 304.1346073150635ms markdown2 (2.4.3) - paragraph: 267.84825325012207ms mistletoe (0.8.2) - paragraph: 779.3235778808594ms markdown_it (2.1.0) - paragraph: 825.5178928375244ms mistune (3.0.0) - emphasis: 23.591041564941406ms mistune (slow) - emphasis: 16.934871673583984ms mistune (fast) - emphasis: 23.232460021972656ms mistune (full) - emphasis: 25.2840518951416ms markdown (3.3.7) - emphasis: 76.50399208068848ms markdown2 (2.4.3) - emphasis: 9.393930435180664ms mistletoe (0.8.2) - emphasis: 33.68663787841797ms markdown_it (2.1.0) - emphasis: 60.90521812438965ms mistune (3.0.0) - auto_links: 3.7980079650878906ms mistune (slow) - auto_links: 3.3910274505615234ms mistune (fast) - auto_links: 3.6630630493164062ms mistune (full) - auto_links: 3.9186477661132812ms markdown (3.3.7) - auto_links: 23.04673194885254ms markdown2 (2.4.3) - auto_links: 6.537914276123047ms mistletoe (0.8.2) - auto_links: 8.360624313354492ms markdown_it (2.1.0) - auto_links: 19.732236862182617ms mistune (3.0.0) - std_links: 21.920442581176758ms mistune (slow) - std_links: 17.487764358520508ms mistune (fast) - std_links: 19.87743377685547ms mistune (full) - std_links: 24.514198303222656ms markdown (3.3.7) - std_links: 39.1237735748291ms markdown2 (2.4.3) - std_links: 14.519691467285156ms mistletoe (0.8.2) - std_links: 22.84979820251465ms markdown_it (2.1.0) - std_links: 32.60660171508789ms mistune (3.0.0) - ref_links: 47.673940658569336ms mistune (slow) - ref_links: 39.449214935302734ms mistune (fast) - ref_links: 44.81911659240723ms mistune (full) - ref_links: 52.37579345703125ms markdown (3.3.7) - ref_links: 87.65625953674316ms markdown2 (2.4.3) - ref_links: 23.118972778320312ms mistletoe (0.8.2) - ref_links: 59.136390686035156ms markdown_it (2.1.0) - ref_links: 80.44648170471191ms mistune (3.0.0) - readme: 56.607723236083984ms mistune (slow) - readme: 68.8173770904541ms mistune (fast) - readme: 53.86018753051758ms mistune (full) - readme: 61.25998497009277ms markdown (3.3.7) - readme: 211.02523803710938ms markdown2 (2.4.3) - readme: 533.4112644195557ms mistletoe (0.8.2) - readme: 110.12959480285645ms markdown_it (2.1.0) - readme: 247.9879856109619ms ```
All results are in milliseconds (ms). | / Parser ➡ Case ⬇ | mistune (3.0.0) | mistune (slow) | mistune (fast) | mistune (full) | markdown (3.3.7) | markdown2 (2.4.3) | mistletoe (0.8.2) | markdown_it (2.1.0) | | -------------- | --------------: | -------------: | -------------: | -------------: | ---------------: | ----------------: | ----------------: | ------------------: | | **atx** | 13.90 | 13.12 | 13.25 | 15.45 | 48.41 | 379.31 | 25.46 | 42.38 | | **setext** | 8.43 | 8.98 | 8.12 | 9.53 | 30.75 | 218.91 | 20.47 | 27.01 | | **normal_ul** | 60.91 | 59.70 | 60.41 | 62.89 | 83.79 | 175.36 | 74.82 | 103.01 | | **insane_ul** | 104.19 | 105.83 | 103.04 | 105.80 | 133.83 | 337.24 | 122.10 | 85.93 | | **normal_ol** | 25.10 | 25.32 | 25.11 | 25.95 | 43.30 | 75.88 | 33.64 | 40.31 | | **insane_ol** | 46.20 | 49.15 | 45.97 | 47.54 | 50.15 | 210.49 | 84.08 | 83.62 | | **blockquote** | 15.48 | 16.13 | 15.35 | 16.10 | 63.04 | 702.44 | 28.56 | 37.35 | | **blockhtml** | 7.90 | 7.08 | 7.41 | 8.56 | 46.66 | 122.10 | 12.24 | 26.84 | | **fenced** | 4.28 | 4.09 | 4.02 | 4.45 | 33.84 | 92.49 | 9.19 | 12.50 | | **paragraph** | 95.94 | 561.28 | 93.60 | 110.10 | 304.13 | 267.85 | 779.32 | 825.52 | | **emphasis** | 23.59 | 16.93 | 23.23 | 25.28 | 76.50 | 9.39 | 33.69 | 60.91 | | **auto_links** | 3.80 | 3.39 | 3.66 | 3.92 | 23.05 | 6.54 | 8.36 | 19.73 | | **std_links** | 21.92 | 17.49 | 19.88 | 24.51 | 39.12 | 14.52 | 22.85 | 32.61 | | **ref_links** | 47.67 | 39.45 | 44.82 | 52.38 | 87.66 | 23.12 | 59.14 | 80.45 | | **readme** | 56.61 | 68.82 | 53.86 | 61.26 | 211.03 | 533.41 | 110.13 | 247.99 | ## License Mistune is licensed under BSD. Please see LICENSE for licensing details. lepture-mistune-f19057f/README.rst000066400000000000000000000012551526537167500167320ustar00rootroot00000000000000Mistune v3 ========== A fast yet powerful Python Markdown parser with renderers and plugins. Overview -------- Convert Markdown to HTML with ease: .. code-block:: python import mistune markdown = mistune.create_markdown() markdown(your_markdown_text) ``create_markdown()`` escapes raw HTML by default. The legacy ``mistune.html(trusted_markdown_text)`` helper enables raw HTML and several plugins; use it only for trusted input or sanitize its output externally. Useful Links ------------ 1. GitHub: https://github.com/lepture/mistune 2. Docs: https://mistune.lepture.com/ License ------- Mistune is licensed under BSD. Please see LICENSE for licensing details. lepture-mistune-f19057f/benchmark/000077500000000000000000000000001526537167500171725ustar00rootroot00000000000000lepture-mistune-f19057f/benchmark/bench.py000066400000000000000000000063511526537167500206300ustar00rootroot00000000000000import os import sys import time ROOT_DIR = os.path.dirname(__file__) sys.path.insert(0, os.path.join(ROOT_DIR, "..")) CASES = {} def load_case(filename): if filename == "readme.txt": filepath = os.path.join(ROOT_DIR, "../README.md") else: filepath = os.path.join(ROOT_DIR, "cases", filename) with open(filepath, "r") as f: content = f.read() name = filename.replace(".txt", "") CASES[name] = content return content def run_case(method, content, count=100): # ignore first trigger method(content) start = time.time() while count > 0: method(content) count -= 1 duration = time.time() - start return duration * 1000 def get_markdown_parsers(): parsers = {} import mistune from mistune.directives import Admonition, Include, RSTDirective, TableOfContents parsers[f"mistune ({mistune.__version__})"] = mistune.html parsers["mistune (core)"] = mistune.create_markdown(escape=False) parsers["mistune (full)"] = mistune.create_markdown( escape=False, plugins=[ "url", "abbr", "ruby", "strikethrough", "mark", "insert", "subscript", "superscript", "footnotes", "def_list", "math", "table", "task_lists", RSTDirective( [ Admonition(), TableOfContents(), Include(), ] ), ], ) try: import mistune_v1 parsers[f"mistune ({mistune_v1.__version__})"] = mistune_v1.markdown except ImportError: pass try: import markdown parsers[f"markdown ({markdown.__version__})"] = markdown.markdown except ImportError: pass try: from markdown2 import Markdown from markdown2 import __version__ as m2v markdowner = Markdown() parsers[f"markdown2 ({m2v})"] = markdowner.convert except ImportError: pass try: import mistletoe parsers[f"mistletoe ({mistletoe.__version__})"] = mistletoe.markdown except ImportError: pass try: from markdown_it import MarkdownIt from markdown_it import __version__ as mitv md = MarkdownIt() parsers[f"markdown_it ({mitv})"] = md.render except ImportError: pass return parsers def benchmarks(cases, count=100): methods = get_markdown_parsers() for name in cases: content = load_case(name + ".txt") for md_name in methods: func = methods[md_name] duration = run_case(func, content, count) print(f"{md_name} - {name}: {duration}ms") if __name__ == "__main__": cases = [ # block "atx", "setext", "normal_ul", "insane_ul", "normal_ol", "insane_ol", "blockquote", "blockhtml", "fenced", "paragraph", # inline "emphasis", "auto_links", "std_links", "ref_links", "readme", ] if len(sys.argv) > 1: benchmarks(sys.argv[1:]) else: benchmarks(cases) lepture-mistune-f19057f/benchmark/bench_edges.py000066400000000000000000000301551526537167500217760ustar00rootroot00000000000000"""Benchmark adversarial Markdown inputs. Run one case with: python benchmark/bench_edges.py --case blank-list-continuations The ``normalized`` column is the time growth divided by the input-size growth. Values near 1 indicate linear scaling; values near 2 indicate that doubling the input takes roughly four times as long. """ from __future__ import annotations import argparse import math import statistics import time from collections.abc import Callable from dataclasses import dataclass from typing import Optional @dataclass(frozen=True) class EdgeCase: name: str category: str generate: Callable[[int], str] make_markdown: Callable[[str], object] sizes: tuple[int, ...] @dataclass(frozen=True) class Result: case: str renderer: str size: int bytes: int best: float mean: float growth: Optional[float] normalized_growth: Optional[float] def markdown_factory(renderer: str = "html", plugins: Optional[list[str]] = None) -> Callable[[str], object]: def make_markdown(_renderer: str = renderer, _plugins: Optional[list[str]] = plugins): import mistune return mistune.create_markdown(renderer=_renderer, escape=False, plugins=_plugins) return make_markdown CORE = markdown_factory() SPOILER = markdown_factory(plugins=["spoiler"]) MATH = markdown_factory(plugins=["math"]) FOOTNOTES = markdown_factory(plugins=["footnotes"]) GITHUB = markdown_factory(plugins=["table", "task_lists"]) STRIKETHROUGH = markdown_factory(plugins=["strikethrough"]) MARK = markdown_factory(plugins=["mark"]) INSERT = markdown_factory(plugins=["insert"]) EDGE_CASES = { "deep-blockquote": EdgeCase("deep-blockquote", "containers", lambda n: "> " * n + "text\n", CORE, (100, 1000, 10000)), "deep-list": EdgeCase("deep-list", "containers", lambda n: "- " * n + "text\n", CORE, (100, 1000, 10000)), "blockquote-depth-boundary": EdgeCase( "blockquote-depth-boundary", "containers", lambda n: "> " * n + "text\n", CORE, (99, 100, 101, 1000) ), "alternating-containers": EdgeCase( "alternating-containers", "containers", lambda n: "> - " * n + "text\n", CORE, (64, 128, 256) ), "deep-block-spoiler": EdgeCase( "deep-block-spoiler", "containers", lambda n: ">! " * n + "text\n", SPOILER, (100, 1000, 10000) ), "unmatched-links": EdgeCase("unmatched-links", "inline", lambda n: "[" * n + "\n", CORE, (1000, 10000, 100000)), "nested-link-labels": EdgeCase( "nested-link-labels", "inline", lambda n: "[" * n + "text" + "]" * n + "(/url)\n", CORE, (200, 1000, 5000) ), "nested-image-labels": EdgeCase( "nested-image-labels", "inline", lambda n: "![" * n + "text" + "](/url)" * n + "\n", CORE, (200, 1000, 5000) ), "repeated-link-suffixes": EdgeCase( "repeated-link-suffixes", "inline", lambda n: "[" * n + "a" + "](/u)" * n + "\n", CORE, (200, 1000, 5000) ), "unclosed-inline-title": EdgeCase( "unclosed-inline-title", "inline", lambda n: '[x](y "' + "\\!" * n + ")", CORE, (1000, 5000, 10000) ), "dense-emphasis": EdgeCase("dense-emphasis", "inline", lambda n: "*a" * n + "\n", CORE, (1000, 10000, 100000)), "long-code-span-runs": EdgeCase( "long-code-span-runs", "inline", lambda n: "`" * n + "text" + "`" * (n - 1) + "\n", CORE, (1000, 10000, 100000) ), "successful-long-code-span": EdgeCase( "successful-long-code-span", "inline", lambda n: "`" * n + "text" + "`" * n + "\n", CORE, (1000, 10000, 100000) ), "many-wrong-code-runs": EdgeCase( "many-wrong-code-runs", "inline", lambda n: "``start " + "`x" * n + " ``\n", CORE, (1000, 10000, 100000) ), "link-label-long-code-runs": EdgeCase( "link-label-long-code-runs", "inline", lambda n: "[" + "`" * n + "text" + "`" * (n - 1) + "](/url)\n", CORE, (1000, 10000, 100000), ), "unclosed-link-destinations": EdgeCase( "unclosed-link-destinations", "inline", lambda n: "[](" * n + " [ok](/ok)\n", CORE, (1000, 5000, 10000) ), "unclosed-inline-comments": EdgeCase( "unclosed-inline-comments", "inline", lambda n: "text " + " lepture-mistune-f19057f/benchmark/cases/blockquote.txt000066400000000000000000000002231526537167500231760ustar00rootroot00000000000000> Block quote content > > Block quote paragraph > Second block quote > > Nested block quote > > > > > > > > > > > > > > > > > > > > > Block quote lepture-mistune-f19057f/benchmark/cases/emphasis.txt000066400000000000000000000002761526537167500226470ustar00rootroot00000000000000case for emphasis: **bold** __bold__ *italic* _italic_, **bold and *italic***, **bold *italic* and __bold__**. ______________foo______________ and *********bar********* **__**__bold__**__** lepture-mistune-f19057f/benchmark/cases/fenced.txt000066400000000000000000000003631526537167500222570ustar00rootroot00000000000000``` function foo() { return 'foo' } ``` ```js function foo() { return 'foo' } ``` ~~~python def foo(): return 'foo' ~~~ ~~~python filename=foo.py def foo(): return 'foo' ~~~ ```` ``` function foo() { return 'foo' } ``` ```` lepture-mistune-f19057f/benchmark/cases/insane_ol.txt000066400000000000000000000007621526537167500230050ustar00rootroot000000000000001. List Item 2. List Item 3) List Item 3. List Item 5) List Item - List Item List Item 2. List Item 3. List Item 4. List Item 5. List Item 6. List Item 7. List Item 8. List Item 9. List Item 10. List Item 11. List Item 6) List Item 1. New list 2. Loose item 10) List Item List Item List Item List Item lepture-mistune-f19057f/benchmark/cases/insane_ul.txt000066400000000000000000000012401526537167500230030ustar00rootroot00000000000000- List Item - List Item - List Item - List Item - List Item - List Item - List Item - List Item - List Item - List Item - List Item - List Item - List Item - List Item - List Item - List Item - List Item - List Item - List Item - List Item - List Item - List Item - Loose List Item Loose paragraph - List Item - List Item - List Item + List Item - List Item - List Item - List Item * List Item List Item List Item List Item lepture-mistune-f19057f/benchmark/cases/normal_ol.txt000066400000000000000000000002171526537167500230130ustar00rootroot000000000000001. List Item 2. List Item 3) List Item 3. List Item 1) New list 2) Loose item 10. List Item List Item List Item List Item lepture-mistune-f19057f/benchmark/cases/normal_ul.txt000066400000000000000000000004711526537167500230230ustar00rootroot00000000000000- List Item - List Item - List Item - List Item - List Item - List Item - List Item - List Item + List Item - List Item - List Item - List Item * List Item List Item List Item List Item * List Item List Item List Item List Item * List Item List Item List Item List Item lepture-mistune-f19057f/benchmark/cases/paragraph.txt000066400000000000000000000356571526537167500230160ustar00rootroot00000000000000Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam eget quam egestas, gravida quam sed, faucibus turpis. Curabitur commodo sit amet arcu vitae hendrerit. Curabitur posuere quis nisi a lobortis. Maecenas consectetur neque ut sem pulvinar tincidunt. Etiam mattis ligula at quam varius, vel laoreet diam interdum. Proin vel tempus arcu, venenatis facilisis diam. Praesent justo sapien, mattis in tempus et, luctus fermentum mi. Proin mattis felis eget augue mollis aliquet. Donec bibendum sem orci, a maximus nisi molestie in. Vestibulum et varius nisl, a sodales ligula. Curabitur gravida massa vel enim facilisis, id dapibus mauris tincidunt. Morbi pretium velit velit, vel accumsan lacus malesuada et. Vivamus massa elit, feugiat at aliquet ac, eleifend eget dui. Donec hendrerit metus elementum augue gravida posuere. Quisque convallis egestas augue. Fusce vel pulvinar dui. Sed tincidunt felis nec placerat feugiat. Fusce laoreet ligula a ipsum suscipit, id vehicula tortor scelerisque. Sed placerat est massa, sit amet egestas magna interdum in. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Ut eget pretium felis. Fusce rhoncus fringilla ipsum, sed varius ante placerat nec. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Proin a maximus massa. Vestibulum placerat urna quis venenatis ullamcorper. Morbi finibus imperdiet ligula ac feugiat. Fusce consectetur gravida leo id efficitur. Suspendisse potenti. Vivamus pellentesque turpis a erat sodales venenatis vel quis justo. Ut vitae viverra dui. Quisque non sagittis lectus. Nunc libero nisi, fermentum vitae imperdiet vel, pulvinar ut augue. Maecenas at magna vel dolor tempor luctus. Etiam consectetur est eu tortor luctus tristique. Aliquam rhoncus enim non felis feugiat gravida. Suspendisse eget lorem hendrerit, pellentesque dolor et, scelerisque nisl. Donec sit amet lacus a tellus mattis pretium. Sed urna lectus, gravida sed est vel, molestie luctus neque. Phasellus finibus tempor odio. Nunc ullamcorper dui at nunc sodales sagittis. In mattis dolor vitae sem efficitur, vel auctor ipsum suscipit. Mauris nec orci non justo facilisis posuere. Sed id tortor vel est elementum pellentesque non luctus lectus. Proin at quam non turpis dapibus dapibus ac nec felis. Phasellus sapien nisi, pulvinar sit amet aliquam ac, imperdiet vel leo. Nunc a nisi massa. Aenean ultricies sed dui id dapibus. Sed sit amet risus et nisl mattis consequat. Praesent semper orci eget sem imperdiet cursus. Donec fringilla convallis turpis, in sodales metus elementum dignissim. Nunc eu cursus elit. Sed malesuada, velit hendrerit volutpat varius, leo metus tristique quam, a imperdiet nunc urna a purus. Donec id tristique quam, dictum egestas ligula. Morbi varius suscipit bibendum. Etiam id diam tempor magna finibus viverra. Duis auctor interdum lorem, eget porttitor turpis. Pellentesque at malesuada eros. Vestibulum efficitur eget neque sit amet posuere. Ut est leo, ullamcorper efficitur lobortis sit amet, facilisis ut purus. Cras hendrerit eu erat vitae dignissim. Aenean et pharetra lectus. Etiam sed elementum lectus, ut interdum ligula. Nunc egestas nulla posuere, feugiat leo non, condimentum eros. Fusce scelerisque turpis lacus, a dapibus diam mattis ut. Quisque vestibulum laoreet libero, in lobortis felis ultrices id. Vivamus id tellus efficitur, porta purus at, consequat magna. Donec dapibus justo dolor. Aliquam erat volutpat. Aenean at tortor libero. Suspendisse pharetra mi urna, a accumsan mi placerat et. Proin accumsan, nunc id tristique auctor, magna leo rhoncus nisl, at commodo sem lorem et lectus. Integer massa dolor, fringilla at enim et, blandit imperdiet purus. Phasellus sit amet leo at dolor ornare ultricies. Etiam a convallis velit. Proin auctor, sem non lacinia luctus, purus metus luctus ipsum, aliquet placerat arcu felis a erat. Cras et consequat leo, sagittis ultrices sem. Nullam egestas ipsum eget porttitor tempus. Ut laoreet non lectus quis imperdiet. Duis tempus in magna eget ornare. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Curabitur a sagittis justo, et suscipit nibh. Proin sed lorem lacinia, efficitur quam sed, imperdiet felis. Morbi in condimentum arcu. Sed sodales vehicula nunc, vitae mollis ipsum faucibus ut. Suspendisse ornare efficitur turpis, non placerat nisl aliquet et. Aliquam aliquam, justo eu tincidunt ornare, nisi elit tempor velit, placerat pulvinar erat tortor vehicula erat. Nam euismod turpis eu congue pulvinar. Pellentesque fringilla sapien ac mauris efficitur viverra. Suspendisse hendrerit leo et erat condimentum sagittis. Ut lacinia mattis pharetra. Ut semper lacinia tristique. Nullam fermentum nunc in erat interdum interdum. Pellentesque fringilla, purus nec commodo elementum, nulla arcu elementum diam, vel aliquam est ante in dolor. Integer vel elit posuere, commodo felis non, aliquet diam. Duis cursus enim at metus sodales ultricies. Mauris ultricies id elit eget elementum. Aenean elementum nisi quis vehicula placerat. Morbi lobortis, neque quis lobortis vehicula, arcu nisi blandit elit, eget rhoncus orci mauris a massa. Donec a purus bibendum, vulputate tortor id, bibendum metus. Donec eget sagittis sem. Maecenas metus ex, cursus a mollis a, imperdiet sed felis. Integer gravida, lacus eget posuere laoreet, velit dui tincidunt turpis, vel hendrerit sem massa iaculis odio. Proin a metus fringilla, ullamcorper nisl nec, imperdiet massa. Maecenas sollicitudin egestas varius. Nulla dictum, nunc ut venenatis ornare, mi nibh viverra leo, a aliquam tellus velit ac erat. Nulla eget faucibus urna. Phasellus sit amet neque quis est finibus elementum. In hac habitasse platea dictumst. Quisque ultricies, orci vel bibendum venenatis, nibh nisl iaculis ipsum, sit amet interdum tortor neque non urna. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque convallis in nibh sit amet pulvinar. Vivamus sed orci magna. Quisque fermentum leo nunc, sit amet fringilla lacus ultrices consectetur. Nulla ullamcorper interdum aliquam. Nunc sagittis lectus eget mauris molestie consectetur. Vivamus et imperdiet tortor. Fusce faucibus velit quis rutrum tincidunt. Quisque consectetur blandit massa a facilisis. Phasellus faucibus dui eu pretium laoreet. Nullam scelerisque pulvinar ante quis elementum. Curabitur placerat sem eu neque fringilla interdum. Aliquam metus purus, vulputate ut augue vel, aliquam interdum risus. Cras a lacus et nulla feugiat vestibulum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus sagittis dui enim, et dictum erat ornare in. Donec fringilla placerat ipsum, et viverra metus tincidunt et. Duis vestibulum elit pharetra mauris mattis tempor. Maecenas a finibus tortor. Nullam sed massa ac velit lacinia rutrum quis non purus. Vestibulum neque odio, accumsan vitae posuere a, tempus sit amet est. Phasellus justo dui, rhoncus non orci convallis, pulvinar consectetur ante. Suspendisse pellentesque enim magna, non accumsan tortor egestas sit amet. Proin et placerat urna, in pretium metus. Sed nulla enim, lacinia vitae nisl id, rhoncus aliquam dui. Aliquam tincidunt diam arcu, eget facilisis tellus commodo quis. Morbi luctus bibendum viverra. Donec eget elementum ex. Integer posuere turpis ac neque elementum volutpat. Nulla lacinia sem vitae nisi mattis, at iaculis tellus congue. Donec sed luctus magna. Sed sit amet gravida metus. Ut non dolor hendrerit, ultricies odio eget, pretium tortor. Suspendisse potenti. In maximus ornare felis, at rutrum enim viverra quis. Curabitur at diam ultricies, pretium lacus sed, sollicitudin dolor. Vestibulum consectetur nunc a ipsum rhoncus dapibus. In eget augue non leo blandit consectetur. Nullam ut ullamcorper nulla. Sed vulputate justo et leo scelerisque sollicitudin. Ut tincidunt volutpat placerat. Curabitur ultrices dolor eu quam venenatis, a scelerisque mi commodo. Phasellus vel venenatis ante. Integer vulputate, mi eu lacinia fermentum, sapien purus sodales massa, at malesuada urna lorem laoreet ligula. Fusce sit amet faucibus purus, id facilisis turpis. Cras sit amet vestibulum elit, ac facilisis sem. Proin eleifend semper enim non fringilla. Donec vitae justo sed sapien gravida porta sit amet in velit. Nullam a diam quis orci auctor sagittis vitae ac libero. Cras porta, nunc et auctor lobortis, ligula elit lacinia nisi, quis ultrices elit mi ac lorem. Morbi eu ligula eget turpis rhoncus aliquet et at nunc. Vivamus fermentum vitae metus vel suscipit. Donec ante metus, auctor et sapien ac, tempor eleifend sapien. Nunc viverra augue sit amet felis egestas, id pellentesque libero vulputate. Cras faucibus, risus ac suscipit semper, ipsum ante porta diam, eleifend luctus ante lectus ac ligula. Curabitur in magna ac nisl fermentum volutpat sit amet at nunc. Curabitur condimentum tempor risus in maximus. Integer ut congue nunc, eu lobortis metus. Nam vulputate nisl ut ligula blandit ornare. Suspendisse blandit pulvinar urna ac pulvinar. Maecenas rutrum pretium turpis sit amet faucibus. Fusce commodo tempor nunc, quis tincidunt felis. Pellentesque eu fermentum libero, at rutrum lacus. Quisque volutpat dui ante, sed ullamcorper odio vestibulum ut. Donec nec est tempus, bibendum est ac, placerat orci. Praesent ligula orci, commodo id iaculis vel, tristique id neque. Donec sed rhoncus arcu, vel pharetra enim. Cras convallis eu tortor sit amet venenatis. Duis posuere scelerisque justo sed posuere. Suspendisse facilisis, metus vel pharetra rutrum, augue enim gravida arcu, non fringilla sem tellus vel tortor. Cras vitae purus et erat lobortis auctor. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Praesent magna tellus, semper vitae mauris vulputate, finibus porta sem. Mauris et ipsum accumsan, dapibus dui ut, hendrerit magna. Nam malesuada odio non orci tempor, ut gravida velit faucibus. Vestibulum molestie eu nunc at tempus. Maecenas lacinia consequat lorem non dapibus. In at ultricies nisl. Fusce pretium ac nisi non euismod. Nunc ut metus turpis. Donec efficitur tincidunt mattis. Sed lacus lorem, bibendum non magna at, iaculis viverra est. Proin sed interdum ligula. Maecenas gravida finibus augue, a laoreet nisl. Fusce quis tempus sapien. Pellentesque vitae nulla risus. Fusce nec arcu ipsum. Pellentesque dapibus congue arcu ac ornare. Donec sagittis enim id dui hendrerit molestie eu pellentesque est. Donec et dui lacus. Mauris vulputate dui a turpis malesuada lacinia. Nullam non dolor pellentesque, ultrices justo id, blandit enim. Vestibulum dapibus vestibulum quam, vel lobortis sapien eleifend vitae. Sed volutpat libero sed odio vehicula ullamcorper in non nunc. Nullam placerat diam sed ex interdum, ut egestas nibh posuere. Pellentesque ac ante mauris. Etiam turpis nulla, aliquam ut nibh a, lacinia tincidunt augue. Cras ultricies nibh turpis, in consequat quam pulvinar non. Aenean vel nunc quam. Sed pulvinar mauris nec metus pulvinar vulputate. Praesent vitae varius quam, consequat sagittis sapien. In vitae tristique lacus. Aenean egestas, elit at semper porta, enim nisi eleifend lorem, at consequat sapien est suscipit velit. Duis a odio risus. In in dolor condimentum, fringilla arcu egestas, sollicitudin dui. Pellentesque laoreet lacinia dignissim. Praesent ac consectetur magna. Aliquam rutrum augue et tellus tristique consectetur. Integer sollicitudin sollicitudin imperdiet. Duis in felis fringilla, dictum risus quis, egestas odio. Nulla eu aliquet sem, sed sollicitudin felis. Nullam mauris odio, fermentum at vulputate eu, tincidunt a orci. Ut vehicula bibendum metus sed efficitur. Suspendisse dui risus, accumsan in consectetur id, dignissim a dolor. Quisque vel volutpat libero, non hendrerit lorem. Sed purus sem, accumsan id eros sed, dapibus porta est. Cras ac consequat lectus. Nam bibendum malesuada metus, id varius lorem scelerisque a. In volutpat sapien eget varius lacinia. Fusce lobortis interdum dolor, non cursus lectus. Ut blandit arcu sed dui pulvinar, ornare mattis urna porta. Nunc nibh diam, posuere vitae eleifend aliquet, egestas a magna. Morbi in orci libero. Integer tincidunt nunc rhoncus blandit gravida. Nullam cursus consequat ante vel sodales. Quisque viverra turpis vel ultrices mattis. Cras efficitur ipsum leo, sed elementum massa lacinia eget. Etiam ac massa lorem. Vivamus vitae eros ipsum. Maecenas facilisis, purus in laoreet maximus, ipsum libero luctus sem, ullamcorper dignissim erat lorem at justo. Mauris laoreet, arcu at ultricies posuere, mauris libero lacinia nibh, non faucibus velit mauris at purus. Vivamus mollis hendrerit neque vitae suscipit. Pellentesque ultricies porttitor ex id euismod. Praesent fermentum facilisis enim et aliquam. Nulla feugiat lacinia purus, vel egestas elit maximus vel. Vestibulum nunc libero, ultricies sed orci in, placerat varius eros. Cras id nibh sed erat tincidunt scelerisque vel in ante. Nulla facilisi. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Cras iaculis convallis nisl, eu ultrices odio efficitur in. Donec eleifend nulla nec justo commodo, ac consectetur quam consequat. Vivamus mattis condimentum massa, in accumsan purus ornare ut. Nulla ac auctor arcu, nec tincidunt nibh. Maecenas vitae nulla vel risus pretium faucibus. Morbi vel facilisis massa. Etiam tempus ornare turpis, a finibus ex aliquam eu. Praesent aliquam libero non accumsan sollicitudin. Proin imperdiet libero diam, vel malesuada leo maximus a. Ut vestibulum tortor et faucibus pellentesque. Curabitur sed malesuada augue. Ut eu dignissim eros. Integer pharetra efficitur est ut semper. Sed at lacinia justo, ut imperdiet nulla. Phasellus bibendum libero sit amet tellus imperdiet, eu consequat lorem tincidunt. Cras porttitor semper sem nec commodo. Maecenas eget nisi id velit posuere iaculis. Nulla ut scelerisque dui. Quisque sollicitudin luctus lacus, id condimentum lectus vestibulum at. Quisque euismod ex dui, at ullamcorper quam interdum egestas. Vestibulum dapibus efficitur tellus sed efficitur. Cras in felis ac lacus laoreet rutrum. Praesent eget nunc placerat, feugiat sem eu, elementum eros. Mauris vitae porta lorem, a viverra magna. Aliquam quam diam, bibendum eu ante a, iaculis tincidunt tellus. Interdum et malesuada fames ac ante ipsum primis in faucibus. Integer mattis molestie libero a fermentum. Integer pharetra, leo ut placerat tempor, nisi velit laoreet purus, vel lobortis libero leo quis tortor. Nunc viverra erat vel enim tempor, nec egestas ligula laoreet. Nam finibus, orci vitae euismod dapibus, felis erat pretium lorem, sed laoreet purus erat ut ligula. Curabitur eu rutrum purus. Nunc non efficitur ex. Vivamus non pretium erat, eget viverra diam. Donec ac orci ac mi lacinia posuere. Integer venenatis est hendrerit velit pretium rutrum. Donec vehicula mattis mi vitae vehicula. Donec eget tortor efficitur nulla semper sollicitudin. Aliquam nisl nisi, consectetur id leo quis, imperdiet fringilla diam. Nulla ultricies ipsum sapien, a posuere eros porttitor nec. Nam pretium auctor nunc at auctor. Quisque mattis velit nec tortor aliquet porttitor. Proin nulla ligula, hendrerit in fermentum sed, imperdiet ac ligula. lepture-mistune-f19057f/benchmark/cases/ref_links.txt000066400000000000000000000004011526537167500230000ustar00rootroot00000000000000[f1]: /bar [f2]: /bar "baz" [f3]: [f4]: "baz" [foo][f1] [foo][f2] [foo][f3] [foo][f4] [f1][] [f2][] [f3][] [f4][] [f1] [f2] [f3] [f4] ![foo][f1] ![foo][f2] ![foo][f3] ![foo][f4] ![f1][] ![f2][] ![f3][] ![f4][] ![f1] ![f2] ![f3] ![f4] lepture-mistune-f19057f/benchmark/cases/setext.txt000066400000000000000000000001141526537167500223410ustar00rootroot00000000000000h1 == h2 -- ---- heading ------- h1 == h1 == h1 == h1 h1 h1 h1 h1 h1 == lepture-mistune-f19057f/benchmark/cases/std_links.txt000066400000000000000000000002041526537167500230170ustar00rootroot00000000000000[foo](/bar) [foo](/bar "baz") [foo]() [foo]( "baz") ![foo](/bar) ![foo](/bar "baz") ![foo]() ![foo]( "baz") lepture-mistune-f19057f/docs/000077500000000000000000000000001526537167500161705ustar00rootroot00000000000000lepture-mistune-f19057f/docs/Makefile000066400000000000000000000011721526537167500176310ustar00rootroot00000000000000# Minimal makefile for Sphinx documentation # # You can set these variables from the command line, and also # from the environment for the first two. SPHINXOPTS ?= SPHINXBUILD ?= sphinx-build SOURCEDIR = . BUILDDIR = _build # Put it first so that "make" without argument is like "make help". help: @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) .PHONY: help Makefile # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) lepture-mistune-f19057f/docs/_static/000077500000000000000000000000001526537167500176165ustar00rootroot00000000000000lepture-mistune-f19057f/docs/_static/dark-icon.svg000066400000000000000000000047401526537167500222130ustar00rootroot00000000000000lepture-mistune-f19057f/docs/_static/light-icon.svg000066400000000000000000000047401526537167500224010ustar00rootroot00000000000000lepture-mistune-f19057f/docs/_static/logo-black.svg000066400000000000000000000233301526537167500223520ustar00rootroot00000000000000lepture-mistune-f19057f/docs/_static/logo-white.svg000066400000000000000000000233321526537167500224200ustar00rootroot00000000000000lepture-mistune-f19057f/docs/_templates/000077500000000000000000000000001526537167500203255ustar00rootroot00000000000000lepture-mistune-f19057f/docs/_templates/partials/000077500000000000000000000000001526537167500221445ustar00rootroot00000000000000lepture-mistune-f19057f/docs/_templates/partials/extra-foot.html000066400000000000000000000002211526537167500251150ustar00rootroot00000000000000 lepture-mistune-f19057f/docs/_templates/partials/globaltoc-above.html000066400000000000000000000012251526537167500260720ustar00rootroot00000000000000 lepture-mistune-f19057f/docs/advanced.rst000066400000000000000000000302661526537167500204760ustar00rootroot00000000000000Advanced Guide ============== Create plugins -------------- Mistune has many built-in plugins. To learn how to write a plugin, read the source code in ``mistune/plugins``. This section uses the math plugin as an example. The plugin is in ``mistune/plugins/math.py``: .. code-block:: python def math(md): md.block.register('block_math', BLOCK_MATH_PATTERN, parse_block_math, before='list') md.inline.register('inline_math', INLINE_MATH_PATTERN, parse_inline_math, before='link') if md.renderer and md.renderer.NAME == 'html': md.renderer.register('block_math', render_block_math) md.renderer.register('inline_math', render_inline_math) The ``md`` parameter is a :class:`Markdown` instance. This example registers one block-level math rule and one inline-level math rule. Block-Level Plugin ~~~~~~~~~~~~~~~~~~ The ``md.block.register`` function registers a block-level plugin. In the math example: .. code-block:: text $$ \operatorname{ker} f=\{g\in G:f(g)=e_{H}\}{\mbox{.}} $$ This is block-level math syntax. The ``BLOCK_MATH_PATTERN`` value is: .. code-block:: python # a block-level pattern must start with ^ BLOCK_MATH_PATTERN = r'^ {0,3}\$\$[ \t]*\n(?P.+?)\n\$\$[ \t]*$' # regex represents: BLOCK_MATH_PATTERN = ( r'^ {0,3}' # the line can start with 0 to 3 spaces, like other CommonMark block elements r'\$\$' # followed by $$ r'[ \t]*\n' # this line can contain spaces and tabs r'(?P.+?)' # math content; use a named group r'\n\$\$[ \t]*$' # end with $$, spaces, and tabs ) # to make the math pattern stricter, use: BLOCK_MATH_PATTERN = r'^\$\$\n(?P.+?)\n\$\$$' Then the block parsing function: .. code-block:: python def parse_block_math(block, m, state): text = m.group('math_text') # use ``state.append_token`` to save the parsed block math token state.append_token({'type': 'block_math', 'raw': text}) # return the end position of the parsed text # Python does not count ``$``, so add 1 # if the pattern does not end with ``$``, do not add 1 return m.end() + 1 The ``token`` must contain ``type``. Other keys are optional. Examples: .. code-block:: python {'type': 'thematic_break'} #
{'type': 'paragraph', 'text': text} {'type': 'block_code', 'raw': code} {'type': 'heading', 'text': text, 'attrs': {'level': level}} - **text**: the inline parser parses this text - **raw**: the inline parser does not parse this content - **attrs**: the renderer uses this extra information Inline-Level Plugin ~~~~~~~~~~~~~~~~~~~ The ``md.inline.register`` function registers an inline-level plugin. In the math example: .. code-block:: text function $f$ This is inline-level math syntax. The ``INLINE_MATH_PATTERN`` value is: .. code-block:: python INLINE_MATH_PATTERN = r'\$(?!\s)(?P.+?)(?!\s)\$' # regex represents: INLINE_MATH_PATTERN = ( r'\$' # start with $ r'(?!\s)' # not whitespace r'(?P.+?)' # content between `$`; use a named group r'(?!\s)' # not whitespace r'\$' # end with $ ) Then the inline parsing function: .. code-block:: python def parse_inline_math(inline, m, state): text = m.group('math_text') # use ``state.append_token`` to save the parsed inline math token state.append_token({'type': 'inline_math', 'raw': text}) # return the end position of the parsed text return m.end() The inline token value has the same form as the block token. Available keys: ``type``, ``raw``, ``text``, ``attrs``. Plugin renderers ~~~~~~~~~~~~~~~~ Add default HTML renderers for your plugin. A renderer function has this form: .. code-block:: python def render_hr(renderer): # token with only type, like: # {'type': 'hr'} return '
' def render_math(renderer, text): # token with type and (text or raw), e.g.: # {'type': 'block_math', 'raw': 'a^b'} return '
$$' + text + '$$
' def render_link(renderer, text, **attrs): # token with type, text or raw, and attrs href = renderer.safe_url(attrs['url']) return f'{text}' If the current Markdown instance uses an HTML renderer, register the plugin renderer to convert Markdown to HTML. Write directives ---------------- Mistune has built-in directives. For details, see :ref:`directives`. The built-in directives are in ``mistune/directives``. Read that source code to learn how to write a new directive. .. _parsing-ast-tokens: Parsing AST tokens ------------------ Mistune provides direct access to AST tokens. Create a Markdown object with ``mistune.create_markdown(renderer='ast')`` (see :ref:`abstract-syntax-tree`). Then traverse the returned AST to integrate Mistune's parser into other systems. .. code-block:: python import mistune markdown = mistune.create_markdown(renderer='ast') tokens = markdown( '''# Title Subtitle -------- Hello World!''' ) stk = list(reversed(tokens)) while stk: token = stk.pop() print({k:v for k, v in token.items() if k != 'children'}) if 'children' in token: for child in reversed(token['children']): stk.append(child) The following sections describe tokens that can occur in ``renderer='ast'`` mode. Token structure ~~~~~~~~~~~~~~~ An AST token is a ``dict``. It must contain the ``'type'`` key. The value is the token type, such as ``'text'``, ``'emphasis'``, or ``'strong'``. If the token has child tokens, they are in a ``list`` under the ``'children'`` key. Inline elements ~~~~~~~~~~~~~~~ .. code-block:: python { 'type': 'linebreak' } { 'type': 'softbreak' } { 'type': 'text', 'raw': str } { 'type': 'emphasis', 'children': list[dict] } { 'type': 'strong', 'children': list[dict] } { 'type': 'codespan', 'raw': str } { 'type': 'inline_html', 'raw': str } # links and images # # 'children' contains elements in the link text section. If you # write something like [**text**](url), **text** goes to 'children'. # This behavior is identical for both images and links, but the HTML # renderer extracts only the text part of children when actually # putting it into 'alt' attribute (e.g., ![**text**](url) returns # text, not **text**) # # for reference links and images (like [text][label], [label], etc.), # 'ref' and 'label' are also given. Both contain the same content, # but 'ref' is an uppercase version, while 'label' is case-sensitive. # { 'type': 'image', 'children': list[dict], # link text 'attrs': { 'url': str, 'title': str | None # is None if not given }, 'ref': str, # omitted if not reference links and images 'label': str # omitted if not reference links and images } { 'type': 'link', 'children': list[dict], # link text 'attrs': { 'url': str, 'title': str | None # is None if not given }, 'ref': str, # omitted if not reference links and images 'label': str # omitted if not reference links and images } Block elements ~~~~~~~~~~~~~~ .. code-block:: python { 'type': 'blank_line' } { 'type': 'thematic_break' } { 'type': 'paragraph', 'children': list[dict] } # 'block_text' is a special text block that occurs in 'tight' lists. # # when a list is tight (i.e., there is no blank line between any list # items or their children), and if a leaf list item contains only a # paragraph, that paragraph's 'type' is changed to 'block_text' # ('children' remains the same). # # block_texts are immediately put between
  • ...
  • , where paragraphs # (occurring in 'loose' lists) are rendered like
  • ...

  • . # { 'type': 'block_text', 'children': list[dict] } # 'style' can be 'atx' or 'setext' { 'type': 'heading', 'children': list[dict], 'attrs': {'level': int}, 'style': str } { 'type': 'block_quote', 'children': list[dict] } { 'type': 'block_html', 'raw': str } { 'type': 'block_code', 'raw': str, 'style': 'indent' } # fenced block code { 'type': 'block_code', 'raw': str, 'style': 'fenced', 'marker': str, 'attrs': {'info': str} # appears if info string is given } List elements ~~~~~~~~~~~~~ .. code-block:: python { 'type': 'list', 'children': [{'type': 'list_item', 'children': list[dict]}, ...], 'tight': bool, # whether the list is 'tight' or 'loose' 'bullet': str, # list marker character 'attrs': { 'depth': int, 'ordered': bool, # whether the list is ordered or unordered 'start': int # appears if the list is ordered and start != 1 } } Plugin elements ~~~~~~~~~~~~~~~ .. code-block:: python # strikethrough, mark, insert, superscript, and subscript plugin { 'type': 'strikethrough', 'children': list[dict] } { 'type': 'mark', 'children': list[dict] } { 'type': 'insert', 'children': list[dict] } { 'type': 'superscript', 'children': list[dict] } { 'type': 'subscript', 'children': list[dict] } # footnotes plugin { 'type': 'footnote_ref', 'raw': str, 'attrs': {'index': int} } { 'type': 'footnotes', 'children': [ { 'type': 'footnote_item', 'children': [{'type': 'paragraph', 'children': list[dict]}], 'attrs': {'key': str, 'index': int} }, ... ] } # table plugin { 'type': 'table', 'children': [ { 'type': 'table_head', 'children': [ { 'type': 'table_cell', 'children': list[dict], 'attrs': { # 'align' is 'center', 'left', 'right', or None 'align': str | None, 'head': True } }, ... ] }, { 'type': 'table_body', 'children': [ { 'type': 'table_row', 'children': [ { 'type': 'table_cell', 'children': list[dict], 'attrs': { # 'align' is 'center', 'left', 'right', or None 'align': str | None, 'head': False } }, ... ] }, ... ] } ] } # url plugin does not add new elements # (it uses 'link' element just like normal links) # task_lists plugin # # task_list_item appears in the same contexts as list_item. # { 'type': 'task_list_item', 'children': list[dict], 'attrs': {'checked': bool} } # def_list plugin # # similar to regular lists, sole paragraphs in def_list_items are # converted to 'block_texts' if the definition list is tight. # { 'type': 'def_list', 'children': [ { 'type': 'def_list_head', 'children': list[dict] }, { 'type': 'def_list_item', 'children': list[dict] }, ... ] } # abbr plugin { 'type': 'abbr', 'children': [{'type': 'text', 'raw': str}], 'attrs': {'title': str} } # math plugin { 'type': 'block_math', 'raw': str } { 'type': 'inline_math', 'raw': str } # ruby plugin { 'type': 'ruby', 'raw': str, 'attrs': {'rt': str} } # spoiler plugin { 'type': 'block_spoiler', 'children': list[dict] } { 'type': 'inline_spoiler', 'children': list[dict] } lepture-mistune-f19057f/docs/api.rst000066400000000000000000000041061526537167500174740ustar00rootroot00000000000000API Reference ============= This page lists the public API for developers. .. module:: mistune Basic ----- .. function:: html(text: str) :param text: Markdown-formatted text Convert Markdown text to HTML without escaping. For example:: text = '**hello** world' mistune.html(text) # => '

    hello world

    ' .. autofunction:: create_markdown Utilities --------- .. autofunction:: escape .. autofunction:: escape_url .. autofunction:: safe_entity .. autofunction:: unikey Advanced -------- .. autoclass:: Markdown .. autoclass:: BlockState :inherited-members: .. autoclass:: InlineState :inherited-members: .. autoclass:: BlockParser :inherited-members: register .. autoclass:: InlineParser :inherited-members: register Plugins ------- .. module:: mistune.plugins.footnotes .. autofunction:: footnotes .. module:: mistune.plugins.task_lists .. autofunction:: task_lists .. module:: mistune.plugins.abbr .. autofunction:: abbr .. module:: mistune.plugins.def_list .. autofunction:: def_list .. module:: mistune.plugins.table .. autofunction:: table .. autofunction:: table_in_quote .. autofunction:: table_in_list .. module:: mistune.plugins.math .. autofunction:: math .. autofunction:: math_in_quote .. autofunction:: math_in_list .. module:: mistune.plugins.ruby .. autofunction:: ruby .. module:: mistune.plugins.formatting .. autofunction:: strikethrough .. autofunction:: mark .. autofunction:: insert .. autofunction:: superscript .. autofunction:: subscript .. module:: mistune.plugins.spoiler .. autofunction:: spoiler Renderers --------- .. module:: mistune.renderers.html .. autoclass:: HTMLRenderer .. module:: mistune.renderers.markdown .. autoclass:: MarkdownRenderer .. module:: mistune.renderers.rst .. autoclass:: RSTRenderer TOC hook -------- .. module:: mistune.toc .. autofunction:: add_toc_hook .. autofunction:: render_toc_ul Directives ---------- .. module:: mistune.directives .. autoclass:: RSTDirective .. autoclass:: FencedDirective lepture-mistune-f19057f/docs/changes.rst000066400000000000000000000170031526537167500203330ustar00rootroot00000000000000Changelog ========= Here is the full history of mistune v3. Version 3.4.0 ------------- **Released on Oct 19, 2026** * Add Python 3.15 support and include it in the CI test matrix. * Require Python 3.10 or later. * Parse inline links with an opening-bracket stack and replace per-syntax failure caches with source-local delimiter scanning. * Share one inline nesting budget across images, links, emphasis, and plugins. Expose ``InlineParser.max_nested_level``; the older ``max_emphasis_depth`` and ``max_image_depth`` settings configure the same limit. * Preserve later valid syntax when a candidate fails or reaches a nesting limit, rather than treating the remaining input as unparsed text. * Enforce CommonMark's 999-character reference label limit, balanced and bounded destination parentheses, and link title constraints. * Improve performance for unclosed inline HTML, unmatched code delimiters, deeply nested images, and repeated text fragments. * Recognize inline HTML comments permitted by CommonMark 0.31.2. * Parse links containing full reference images without treating the image's reference label as a nested link. * Preserve reference definitions parsed inside multi-paragraph footnotes. * Accept definition-list markers indented by up to three spaces. * Prefer longer registered abbreviation matches over shorter prefixes. * Require at least one digit in ordered list continuation markers. * Add Markdown rendering for strikethrough, mark, and insert plugins. * Preserve escaped pipes in table code spans, literal trailing heading hashes, meaningful code span edge spaces, and leading blank lines in Markdown output. * Keep images whose alt text matches their URL from becoming autolinks. * Preserve non-line-break separator characters in rendered lists and hard line breaks in tight ReST list items. * Document per-document renderer context and correct the custom Markdown renderer example. * Preserve literal backslashes, image introducers, HTML delimiters and entity prefixes when rendering Markdown for a round trip. * Only recognize task list markers in a list item's leading paragraph, preserving literal markers in headings. * Bound the global convenience-parser cache and avoid retaining caller-owned renderers and plugin objects. * Add public HTML output helpers for raw HTML, attributes, and URL policy. * Share collision-safe default heading IDs between both TOC APIs. * Add explicit start-character hints for custom inline rules; unhinted custom rules now use the correctness-first regular-expression scanner. * Consolidate adversarial parser growth tests and document the security model. Version 3.3.4 ------------- **Released on Jul 22, 2026** * Harden inline parsing against deeply nested and adversarial link, image, emphasis, formatting, math, and reference inputs. * Improve performance for repeated link suffixes, dense emphasis, unclosed formatting markers, inline spoilers, and adjacent ruby tokens. * Refactor the inline parser into dedicated emphasis and link modules. * Escape literal ``*``/``_`` emphasis markers in the Markdown renderer so round-tripping escaped text does not re-introduce emphasis. Version 3.3.3 ------------- **Released on Jul 9, 2026** * Limit deeply nested emphasis and image parsing to avoid ``RecursionError``. * Fix repeated link suffix and unclosed formatting marker performance issues. * Fix unclosed inline spoiler performance issues. * Avoid recursive parsing for adjacent ruby tokens. * Speed up footnote reference indexing. Version 3.3.2 ------------- **Released on Jun 23, 2026** * Fix Python 3.8 import compatibility in the inline parser. * Fix mypy compatibility for list parsing on Python 3.8 and 3.9+. Version 3.3.1 ------------- **Released on Jun 22, 2026** * Fix ``abbr`` plugin compatibility with escaped inline text. * Normalize included Markdown line endings before parsing directives. Version 3.3.0 ------------- **Released on Jun 21, 2026** * Improve CommonMark compatibility and parser performance. * Add command line entrypoint with UTF-8 output. * Support display and backtick math. * Render plugin list and table nodes in Markdown renderer. * Escape leading block markers in Markdown renderer. * Fix RST renderer for block quotes nested in lists. * Avoid generated heading ID collisions in TOC. * Harden URL, image, figure, and include directive handling. * Fix quadratic scans in inline links, reference links, and formatting markers. * Fix math escaping, currency pattern matching, and cross-line matching. Version 3.2.1 ------------- **Released on May 3, 2026** * Escape link in ``render_toc_ul``. * Escape text in math plugin. * Fix regex for math plugin. * Escape heading's ID attribute. * Fix ``LINK_TITLE_RE`` to prevent DoS. * Escape class attribute for admonition directive. * Remove double-encoding of image alt text. * Escape class attribute for image directive. * Fix width/height attribute for image directive. Version 3.2.0 ------------- **Released on Dec 23, 2025** * Announce supports for python 3.14 * Fix footnotes plugins for code blocks, ref links, blockquote and etc. * Fix ref links in TOC. Version 3.1.4 ------------- **Released on Aug 29, 2025** * Add fenced directive break rule in list parser. * Prevent removing unicode whitespace when parsing atx heading. Version 3.1.3 ------------- **Released on Mar 19, 2025** * Announce supports for python 3.12 and 3.13 Version 3.1.2 ------------- **Released on Feb 19, 2025** * Fix ``footnotes`` plugin for AST renderer Version 3.1.1 ------------- **Released on Jan 28, 2025** * Fix ``render_toc_ul`` method for empty iterable * Fix ruby plugin's regex pattern and HTML rendering Version 3.1.0 ------------- **Released on Dec 30, 2024** * Fix only HTML-escape URLs when rendering to HTML * Add block_quote prefix on empty lines too Version 3.0.2 ------------- **Released on Sep 30, 2023** * Fix list parser to avoid RecursionError Version 3.0.1 ------------- **Released on Jun 10, 2023** * Add ``py.typed`` for mypy * Add ``tests``, ``docs`` for sdist * Support ``renderer="ast"`` for rendering AST Version 3.0.0 ------------- **Released on Jun 08, 2023** * Do not strip leading unicode spaces like emsp * Ensure new line at end of the text Version 3.0.0rc5 ---------------- **Released on Mar 22, 2023** * Fix fenced directives * Fix inline link parser * Fix block math plugin for multiple lines * Fix empty list item for markdown renderer Version 3.0.0rc4 ---------------- **Released on Nov 30, 2022** * Fix plugin footnotes when there is no newline at the end * Move safe HTML entities to HTMLRenderer * Redesign directives parsing * Add Image and Figure directive Version 3.0.0rc3 ---------------- **Released on Nov 25, 2022** * Render inline math with ``\(`` and ``\)`` * Added ``RSTRenderer``, and ``MarkdownRenderer`` * Fix ``toc_hook`` method * **Breaking change**, rename ``RstDirective`` to ``RSTDirective`` Version 3.0.0rc2 ---------------- **Released on Nov 6, 2022** * Add **spoiler** plugin * Add ``collapse`` option for ``TableOfContents`` directive * **Breaking change** on directive design, added fenced directive Version 3.0.0rc1 ---------------- **Released on Sep 26, 2022** * Add **superscript** plugin Version 3.0.0a3 --------------- **Released on Jul 14, 2022** * Fix ruby plugin * Change toc parameter ``depth`` to ``level`` Version 3.0.0a2 --------------- **Released on Jul 13, 2022** * Escape block code in HTMLRenderer * Fix parsing links Version 3.0.0a1 --------------- **Released on Jul 12, 2022** This is the first release of v3. Features included: * redesigned mistune * plugins * directives lepture-mistune-f19057f/docs/cli.rst000066400000000000000000000035301526537167500174720ustar00rootroot00000000000000Command line tools ================== .. meta:: :description: How to use the command line tools of Mistune to convert Markdown to HTML, Markdown, and reStructuredText. Mistune includes a command line tool. Use ``-h`` to show its options:: $ python -m mistune -h Mistune, a sane and fast Python Markdown parser. Examples: $ python -m mistune -m "Hi **Markdown**"

    Hi Markdown

    $ python -m mistune -f README.md

    ... $ cat README.md | python -m mistune

    ... options: -h, --help show this help message and exit -m, --message MESSAGE the Markdown message to convert -f, --file FILE the Markdown file to convert -p, --plugin NAME [NAME ...] specify a plugin to use --escape enable the escape option --hardwrap enable the hardwrap option -o, --output OUTPUT write the rendered result into file -r, --renderer RENDERER specify the output renderer --version show program's version number and exit Convert Markdown to HTML ------------------------ By default, the command line tool converts Markdown text to HTML:: $ python -m mistune -f README.md Convert Markdown to reStructuredText ------------------------------------ Mistune includes a reStructuredText renderer. Specify it with ``-r rst``:: $ python -m mistune -f README.md -r rst Reformat Markdown ----------------- Use the Markdown renderer to reformat a Markdown file:: $ python -m mistune -f README.md -r markdown -o README.md This command reformats the text in ``README.md``. UNIX Pipes ---------- The command line tool supports UNIX pipes. For example:: $ echo "foo **bar**" | python -m mistune lepture-mistune-f19057f/docs/community.rst000066400000000000000000000005051526537167500207460ustar00rootroot00000000000000Community Extensions ==================== This page lists plugins and directives from the community. * `mistune-telegram `_ - Converts Markdown to Telegram format. * `mistune-json `_ - Converts Markdown to HTML-based JSON objects. lepture-mistune-f19057f/docs/conf.py000066400000000000000000000067271526537167500175030ustar00rootroot00000000000000import os import mistune project = "Mistune" copyright = "2019, Hsiaoming Yang" author = "Hsiaoming Yang" master_doc = "index" # The full version, including alpha/beta/rc tags version = mistune.__version__ release = version # -- General configuration --------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ "sphinx.ext.autodoc", "sphinx.ext.intersphinx", "shibuya.sponsors", ] sponsors_json_url = "https://cdn.jsdelivr.net/gh/lepture/lepture/sponsors.json" if os.environ.get("MISTUNE_DOCS_OFFLINE") == "1": intersphinx_mapping = {} else: intersphinx_mapping = { "python": ("https://docs.python.org/3", None), } # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # html_theme = "shibuya" html_context = { "source_type": "github", "source_user": "lepture", "source_repo": "mistune", } html_theme_options = { "accent_color": "indigo", "light_logo": "_static/logo-black.svg", "dark_logo": "_static/logo-white.svg", "twitter_site": "lepture", "twitter_creator": "lepture", "twitter_url": "https://twitter.com/lepture", "github_url": "https://github.com/lepture/mistune", "nav_links": [ { "title": "Projects", "children": [ { "title": "Shibuya", "url": "https://shibuya.lepture.com/", "summary": "A responsive, good looking with modern design documentation theme for Sphinx.", }, { "title": "Pygments Styles", "url": "https://pygments-styles.org/", "summary": "A curated collection of Pygments styles based on VS Code themes.", }, { "title": "Sphinx Iconify", "url": "https://sphinx-iconify.lepture.com/", "summary": "A sphinx extension to use <iconify-icon> web component.", }, { "title": "Mistune", "url": "http://mistune.lepture.com/", "summary": "A fast yet powerful Python Markdown parser with renderers and plugins.", }, { "title": "Wenmode", "url": "http://wenmode.lepture.com/", "summary": "A fast, composable Markdown parser and renderer toolkit.", }, ], }, {"title": "Sponsors", "url": "/sponsors"}, ], } # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ["_static"] html_copy_source = False html_show_sourcelink = False html_favicon = "_static/light-icon.svg" lepture-mistune-f19057f/docs/directives.rst000066400000000000000000000072731526537167500210740ustar00rootroot00000000000000.. _directives: Directives ========== A directive is an explicit markup block. It is extensible. Mistune v3 supports two directive styles: 1. reStructuredText style 2. fenced style .. versionchanged:: 3.0 Fenced-style directives were added in 3.0. Mistune v3 supports multiple directive styles. Thus, do not add each directive directly to the ``plugins`` parameter of ``mistune.create_markdown``. Wrap each directive in a directive style object instead:: import mistune from mistune.directives import FencedDirective, RSTDirective from mistune.directives import Admonition, TableOfContents markdown = mistune.create_markdown(plugins=[ 'math', 'footnotes', # ... FencedDirective([ Admonition(), TableOfContents(), ]), ]) markdown = mistune.create_markdown(plugins=[ 'math', 'footnotes', # ... RSTDirective([ Admonition(), TableOfContents(), ]), ]) A **reStructuredText** directive uses syntax from reStructuredText_: .. code-block:: text .. directive-type:: title :option-key: option value :option-key: option value content text here A **fenced** directive looks like a fenced code block. It uses syntax from `markdown-it-docutils`_: .. code-block:: text ```{directive-type} title :option-key: option value :option-key: option value content text here ``` .. _reStructuredText: https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#directives .. _`markdown-it-docutils`: https://executablebooks.github.io/markdown-it-docutils/ Choose the directive style that is best for your project. Admonitions ----------- The reStructuredText style syntax: .. code-block:: text .. warning:: You are looking at the **dev** documentation. Check out our [stable](/stable/) documentation instead. The fenced style syntax: .. code-block:: text ```{warning} You are looking at the **dev** documentation. Check out our [stable](/stable/) documentation instead. ``` Admonitions support these ``directive-name`` values: .. code-block:: text attention caution danger error hint important note tip warning To enable admonitions:: import mistune from mistune.directives import Admonition markdown = mistune.create_markdown( plugins=[ ... RSTDirective([Admonition()]), # FencedDirective([Admonition()]), ] ) Table of Contents ----------------- .. code-block:: text .. toc:: Table of Contents :max-level: 3 The TOC plugin is a directive. It adds a table of contents to the document. This example puts the TOC before the headings: .. code-block:: text Here is the first paragraph, and we put TOC below. .. toc:: # H1 title ## H2 title # H1 title The rendered HTML contains the TOC at the ``.. toc::`` position. To enable the TOC plugin:: import mistune from mistune.directives import RSTDirective, TableOfContents markdown = mistune.create_markdown( plugins=[ # ... RSTDirective([TableOfContents()]), ] ) Include ------- .. code-block:: text .. include:: hello.md The ``include`` plugin embeds content from other files. Use it for documentation generators. Image ----- .. code-block:: text ```{image} https://domain/path.png :alt: alt text :width: 800 :height: 500 ``` Figure ------ .. code-block:: text ```{figure} https://domain/path.png :alt: alt text :width: 800 :height: 500 ``` lepture-mistune-f19057f/docs/guide.rst000066400000000000000000000105671526537167500200300ustar00rootroot00000000000000How to Use Mistune ================== Create a reusable parser to convert untrusted Markdown text to HTML safely:: import mistune markdown = mistune.create_markdown() markdown(YOUR_MARKDOWN_TEXT) ``create_markdown()`` escapes raw HTML and rejects unsafe URL schemes by default. See :doc:`security` for the complete trust model. Legacy convenience parser ------------------------- The ``mistune.html()`` compatibility helper enables these features by default: * It does not escape HTML tags. * It uses the **strikethrough** plugin. * It uses the **table** plugin. * It uses the **footnote** plugin. Use it only for trusted Markdown or when an external HTML sanitizer processes the result:: mistune.html(TRUSTED_MARKDOWN_TEXT) Customize Mistune ----------------- Use ``create_markdown()`` to create a Markdown instance:: import mistune markdown = mistune.create_markdown() This function creates an escaped Markdown instance with no plugins:: markdown('

    hello
    ') # ==> '

    <div>hello</div>

    ' Create a non-escaped instance:: markdown = mistune.create_markdown(escape=False) markdown('
    hello
    ') # ==> '
    hello
    ' Add plugins:: markdown = mistune.create_markdown() markdown('~~s~~') # ==> '

    ~~s~~

    ' markdown = mistune.create_markdown(plugins=['strikethrough']) markdown('~~s~~') # ==> '

    s

    ' For the list of built-in plugins, see :ref:`plugins`. Customize Renderer ------------------ Mistune lets you customize output with renderers. For example, this renderer adds syntax highlighting to fenced code blocks:: import mistune from pygments import highlight from pygments.lexers import get_lexer_by_name from pygments.formatters import html class HighlightRenderer(mistune.HTMLRenderer): def block_code(self, code, info=None): if info: lexer = get_lexer_by_name(info, stripall=True) formatter = html.HtmlFormatter() return highlight(code, lexer, formatter) return '
    ' + mistune.escape(code) + '
    ' markdown = mistune.create_markdown(renderer=HighlightRenderer()) print(markdown('```python\nassert 1 == 1\n```')) This renderer uses Pygments to highlight fenced code blocks. For more renderer details, see :ref:`renderers`. Per-document renderer context ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Use ``state.env`` to pass context for one document. The HTML rendering methods receive text and token attributes, rather than the state itself. Override ``render_token`` to read the context before delegating to the HTML renderer. For example, this renderer prefixes image URLs for each document:: class ImagePrefixRenderer(mistune.HTMLRenderer): def render_token(self, token, state): if token['type'] == 'image': attrs = dict(token['attrs']) attrs['url'] = state.env.get('image_prefix', '') + attrs['url'] token = dict(token, attrs=attrs) return super().render_token(token, state) markdown = mistune.create_markdown(renderer=ImagePrefixRenderer()) state = markdown.block.state_cls() state.env['image_prefix'] = '/assets/' html, state = markdown.parse('![Logo](logo.png)', state=state) print(html.strip()) #

    Logo

    Create a fresh state for each document. This keeps the context out of mutable renderer attributes. Copying the image token and its attributes also leaves the original parsed URL intact. Delegating to ``HTMLRenderer`` retains its normal escaping and URL-scheme checks. .. _abstract-syntax-tree: Abstract syntax tree -------------------- Mistune can produce AST tokens without a renderer:: markdown = mistune.create_markdown(renderer=None) This ``markdown`` function returns a list of tokens instead of HTML:: text = 'hello **world**' markdown(text) # ==> [ { 'type': 'paragraph', 'children': [ {'type': 'text', 'raw': 'hello '}, {'type': 'strong', 'children': [{'type': 'text', 'raw': 'world'}]} ] } ] You can also pass ``renderer='ast'`` when you create the Markdown instance:: markdown = mistune.create_markdown(renderer='ast') For details on how to parse these tokens, see :ref:`parsing-ast-tokens`. lepture-mistune-f19057f/docs/index.rst000066400000000000000000000016401526537167500200320ustar00rootroot00000000000000.. mistune documentation master file, created by sphinx-quickstart on Wed Sep 18 13:29:37 2019. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. Mistune: Python Markdown Parser =============================== Release v\ |version|. Mistune is a fast Python Markdown parser. It includes renderers and plugins, and it is compatible with CommonMark 0.31.2. Do you use an old Mistune release? See these documents: - https://mistune.lepture.com/en/v0.8.4/ - https://mistune.lepture.com/en/v2/ Installation ------------ Install Mistune with `pip `_. .. parsed-literal:: $ pip install mistune==\ |version| Mistune has no external dependencies. User Guide ---------- .. toctree:: :maxdepth: 2 guide security cli renderers plugins directives advanced api upgrade community changes lepture-mistune-f19057f/docs/plugins.rst000066400000000000000000000260221526537167500204050ustar00rootroot00000000000000.. _plugins: Built-in Plugins ================ .. meta:: :description: List of Mistune built-in plugins, their syntax and how to enable them. Mistune includes many built-in plugins, including common markup extensions. .. note:: Mistune keeps the historical ``speedup`` plugin only for compatibility. The core parsers now include its paragraph and inline text fast paths. Thus, Mistune accepts ``plugins=['speedup']`` but ignores it. .. _strikethrough: strikethrough ------------- .. code-block:: text ~~here is the content~~ ``mistune.html()`` enables the strikethrough plugin by default. To create a Markdown instance with this plugin:: markdown = mistune.create_markdown(plugins=['strikethrough']) You can also pass the plugin function directly:: from mistune.plugins.formatting import strikethrough renderer = mistune.HTMLRenderer() markdown = mistune.Markdown(renderer, plugins=[strikethrough]) footnotes --------- .. code-block:: text content in paragraph with footnote[^1] markup. [^1]: footnote explain ``mistune.html()`` enables the footnotes plugin by default. To create a Markdown instance with this plugin:: markdown = mistune.create_markdown(plugins=['footnotes']) You can also pass the plugin function directly:: from mistune.plugins.footnotes import footnotes renderer = mistune.HTMLRenderer() markdown = mistune.Markdown(renderer, plugins=[footnotes]) table ----- Simple formatted table: .. code-block:: text First Header | Second Header ------------- | ------------- Content Cell | Content Cell Content Cell | Content Cell Complex formatted table: .. code-block:: text | First Header | Second Header | | ------------- | ------------- | | Content Cell | Content Cell | | Content Cell | Content Cell | Align formatted table: .. code-block:: text Left Header | Center Header | Right Header :----------- | :-------------: | ------------: Content Cell | Content Cell | Content Cell | Left Header | Center Header | Right Header | | :---------- | :-------------: | ------------: | | Content Cell | Content Cell | Content Cell | ``mistune.html()`` enables the table plugin by default. To create a Markdown instance with this plugin:: markdown = mistune.create_markdown(plugins=['table']) You can also pass the plugin function directly:: from mistune.plugins.table import table renderer = mistune.HTMLRenderer() markdown = mistune.Markdown(renderer, plugins=[table]) url --- The URL plugin creates links from raw URLs: .. code-block:: text For instance, https://typlog.com/ This input produces: .. code-block:: html

    For instance, https://typlog.com/

    ``mistune.html()`` does not enable this plugin by default. Mistune keeps raw URLs explicit. We suggest that writers use this link syntax: .. code-block:: text To enable the **url** plugin with your Markdown instance:: markdown = mistune.create_markdown(plugins=['url']) You can also pass the plugin function directly:: from mistune.plugins.url import url renderer = mistune.HTMLRenderer() markdown = mistune.Markdown(renderer, plugins=[url]) task_lists ---------- The task lists plugin creates GitHub-style task list items: .. code-block:: text - [x] item 1 - [ ] item 2 This input produces: .. code-block:: html
    • item 1
    • item 2
    ``mistune.html()`` does not enable this plugin by default. To enable the **task_lists** plugin with your Markdown instance:: markdown = mistune.create_markdown(plugins=['task_lists']) You can also pass the plugin function directly:: from mistune.plugins.task_lists import task_lists renderer = mistune.HTMLRenderer() markdown = mistune.Markdown(renderer, plugins=[task_lists]) def_list -------- The def_list plugin creates HTML definition lists: .. code-block:: text First term : First definition : Second definition Second term : Third definition This input produces: .. code-block:: html
    First term
    First definition
    Second definition
    Second term
    Third definition
    ``mistune.html()`` does not enable this plugin by default. To enable the **def_list** plugin with your Markdown instance:: markdown = mistune.create_markdown(plugins=['def_list']) You can also pass the plugin function directly:: from mistune.plugins.def_list import def_list renderer = mistune.HTMLRenderer() markdown = mistune.Markdown(renderer, plugins=[def_list]) abbr ---- The abbr plugin creates abbreviations: .. code-block:: text The HTML specification is maintained by the W3C. *[HTML]: Hyper Text Markup Language *[W3C]: World Wide Web Consortium This input produces: .. code-block:: html The HTML specification is maintained by the W3C. ``mistune.html()`` does not enable this plugin by default. To enable the **abbr** plugin with your Markdown instance:: markdown = mistune.create_markdown(plugins=['abbr']) You can also pass the plugin function directly:: from mistune.plugins.abbr import abbr renderer = mistune.HTMLRenderer() markdown = mistune.Markdown(renderer, plugins=[abbr]) mark ---- The mark plugin adds ```` tags. To mark text, surround it with ``==``: .. code-block:: text ==mark me== ==mark with\=\=equal== This input produces: .. code-block:: html mark me mark with==equal ``mistune.html()`` does not enable this plugin by default. To enable the **mark** plugin with your Markdown instance:: markdown = mistune.create_markdown(plugins=['mark']) You can also pass the plugin function directly:: from mistune.plugins.formatting import mark renderer = mistune.HTMLRenderer() markdown = mistune.Markdown(renderer, plugins=[mark]) insert ------ The insert plugin adds ```` tags. To insert text, surround it with ``^^``: .. code-block:: text ^^insert me^^ ^^insert\^\^me^^ This input produces: .. code-block:: html insert me insert^^me ``mistune.html()`` does not enable this plugin by default. To enable the **insert** plugin with your Markdown instance:: markdown = mistune.create_markdown(plugins=['insert']) You can also pass the plugin function directly:: from mistune.plugins.formatting import insert renderer = mistune.HTMLRenderer() markdown = mistune.Markdown(renderer, plugins=[insert]) superscript ----------- The superscript plugin adds ```` tags. The syntax is: .. code-block:: text Hello^superscript^ This input produces: .. code-block:: html

    Hellosuperscript

    ``mistune.html()`` does not enable this plugin by default. To enable the **superscript** plugin with your Markdown instance:: markdown = mistune.create_markdown(plugins=['superscript']) You can also pass the plugin function directly:: from mistune.plugins.formatting import superscript renderer = mistune.HTMLRenderer() markdown = mistune.Markdown(renderer, plugins=[superscript]) subscript --------- The subscript plugin adds ```` tags. The syntax is: .. code-block:: text Hello~subscript~ CH~3~CH~2~OH This input produces: .. code-block:: html

    Hellosubscript

    CH3CH2OH

    ``mistune.html()`` does not enable this plugin by default. To enable the **subscript** plugin with your Markdown instance:: markdown = mistune.create_markdown(plugins=['subscript']) You can also pass the plugin function directly:: from mistune.plugins.formatting import subscript renderer = mistune.HTMLRenderer() markdown = mistune.Markdown(renderer, plugins=[subscript]) math ---- The math plugin wraps block-level math syntax in ``
    ``. It wraps inline-level math syntax in ````. Block math uses ``$$`` markers: .. code-block:: text $$ \operatorname{ker} f=\{g\in G:f(g)=e_{H}\}{\mbox{.}} $$ This input produces: .. code-block:: html
    $$ \operatorname{ker} f=\{g\in G:f(g)=e_{H}\}{\mbox{.}} $$
    Inline math uses ``$`` markers: .. code-block:: text function $f$ This input produces: .. code-block:: html

    function $f$

    ``mistune.html()`` does not enable this plugin by default. To enable the **math** plugin with your Markdown instance:: markdown = mistune.create_markdown(plugins=['math']) You can also pass the plugin function directly:: from mistune.plugins.math import math renderer = mistune.HTMLRenderer() markdown = mistune.Markdown(renderer, plugins=[math]) ruby ---- The ruby plugin adds ```` tags. These examples show ruby syntax: .. code-block:: text [漢字(ㄏㄢˋㄗˋ)] [link]: /url [漢字(ㄏㄢˋㄗˋ)][link] [漢字(ㄏㄢˋㄗˋ)](/url) [漢(ㄏㄢˋ)字(ㄗˋ)] This input produces: .. code-block:: html

    漢字ㄏㄢˋㄗˋ

    漢字ㄏㄢˋㄗˋ

    漢字ㄏㄢˋㄗˋ

    漢ㄏㄢˋ字ㄗˋ

    ``mistune.html()`` does not enable this plugin by default. To enable the **ruby** plugin with your Markdown instance:: markdown = mistune.create_markdown(plugins=['ruby']) You can also pass the plugin function directly:: from mistune.plugins.ruby import ruby renderer = mistune.HTMLRenderer() markdown = mistune.Markdown(renderer, plugins=[ruby]) Blog post: https://lepture.com/en/2022/markdown-ruby-markup spoiler ------- The spoiler plugin wraps block-level syntax in ``
    ``. It wraps inline-level syntax in ````. A block-level spoiler is like a block quote, but it uses the ``>!`` marker: .. code-block:: text >! here is the spoiler content >! >! it will be hidden This input produces: .. code-block:: html

    here is the spoiler content

    it will be hidden

    An inline spoiler is surrounded with ``>!`` and ``!<``: .. code-block:: text this is the >! hidden text !< This input produces: .. code-block:: html

    this is the hidden text

    ``mistune.html()`` does not enable this plugin by default. To enable the **spoiler** plugin with your Markdown instance:: markdown = mistune.create_markdown(plugins=['spoiler']) You can also pass the plugin function directly:: from mistune.plugins.spoiler import spoiler renderer = mistune.HTMLRenderer() markdown = mistune.Markdown(renderer, plugins=[spoiler]) lepture-mistune-f19057f/docs/renderers.rst000066400000000000000000000155161526537167500207230ustar00rootroot00000000000000.. _renderers: Renderers ========= Mistune has several built-in renderers, including: - :class:`mistune.renderers.html.HTMLRenderer` - :class:`mistune.renderers.markdown.MarkdownRenderer` - :class:`mistune.renderers.rst.RSTRenderer` You can add more renderers. Customize HTMLRenderer ---------------------- Create a renderer subclass to customize HTML output. This example adds inline math syntax: .. code:: `$a^2=4$` To render this syntax, create a subclass of ``mistune.HTMLRenderer``: .. code-block:: python import mistune from mistune import HTMLRenderer, escape class MyRenderer(HTMLRenderer): def codespan(self, text): if text.startswith('$') and text.endswith('$'): return '' + escape(text) + '' return '' + escape(text) + '' # use the custom renderer markdown = mistune.create_markdown(renderer=MyRenderer()) print(markdown('hi `$a^2=4$`')) Customize plugin output ~~~~~~~~~~~~~~~~~~~~~~~ You can also override methods supplied by plugins. Enable the plugin to parse its syntax, then define the matching method on your ``HTMLRenderer`` subclass. For example, add a CSS class to tables: .. code-block:: python import mistune class TableRenderer(mistune.HTMLRenderer): def table(self, text): return '\n' + text + '
    \n' markdown = mistune.create_markdown( renderer=TableRenderer(), plugins=['table'], ) print(markdown('| Name | Count |\n| --- | ---: |\n| Apples | 3 |')) The subclass method takes precedence over the plugin's registered renderer. The other table methods keep their default behavior, including header cells and column alignment. ``text`` already contains the rendered child HTML; do not escape it again. Plugin methods are registered on the renderer instance, not defined on ``HTMLRenderer`` itself, so ``super().table(text)`` is not available. To reuse the default table output inside an override, import ``render_table`` from ``mistune.plugins.table`` and call ``render_table(self, text)``. HTML safety methods ~~~~~~~~~~~~~~~~~~~ ``HTMLRenderer`` exposes output-context helpers for custom renderers and plugins: * ``escape_enabled`` reports and controls whether raw HTML tokens are escaped. * ``escape_raw(value)`` conditionally escapes a raw HTML token. * ``escape_attribute(value)`` always escapes an HTML attribute value. * ``render_attrs(attrs)`` renders fixed attribute names, omits ``None`` and ``False`` values, and escapes every non-boolean value. Invalid attribute names raise ``ValueError``. * ``sanitize_url(url)`` applies the renderer's URL protocol policy and returns either the original URL or ``#harmful-link``. Keep URL filtering separate from attribute escaping. For example:: class LinkRenderer(HTMLRenderer): def link(self, text, url, title=None): attrs = {'href': self.sanitize_url(url), 'title': title} return '' + text + '' ``safe_url(url)`` remains available for compatibility and returns an attribute-escaped result. Available methods ~~~~~~~~~~~~~~~~~ This list shows the renderer methods for ``HTMLRenderer``. It also includes methods from plugins: .. code-block:: # inline level text(self, text) link(self, text, url, title=None) image(self, alt, url, title=None) emphasis(self, text) strong(self, text) codespan(self, text) linebreak(self) softbreak(self) inline_html(self, html) # block level paragraph(self, text) heading(self, text, level, **attrs) blank_line(self) thematic_break(self) block_text(self, text) block_code(self, code, info=None) block_quote(self, text) block_html(self, html) block_error(self, html) list(self, text, ordered, **attrs) list_item(self, text, **attrs) # provided by strikethrough plugin strikethrough(self, text) # provided by mark plugin mark(self, text) # provided by insert plugin insert(self, text) # provided by subscript plugin subscript(self, text) # provided by abbr plugin abbr(self, text, title) # provided by ruby plugin ruby(self, text, rt) # provided by task_lists plugin task_list_item(self, text, checked=False, **attrs) # provided by table plugin table(self, text) table_head(self, text) table_body(self, text) table_row(self, text) table_cell(self, text, align=None, head=False) # provided by footnotes plugin footnote_ref(self, key, index) footnotes(self, text) footnote_item(self, text, key, index) # provided by def_list plugin def_list(self, text) def_list_head(self, text) def_list_item(self, text) # provided by math plugin block_math(self, text) inline_math(self, text) reStructuredText Renderer ------------------------- Use ``RSTRenderer`` to convert Markdown text to reStructuredText. .. code-block:: python from mistune.renderers.rst import RSTRenderer convert_rst = mistune.create_markdown(renderer=RSTRenderer()) convert_rst(your_markdown_text) Markdown Renderer ----------------- Use ``MarkdownRenderer`` to reformat Markdown text. .. code-block:: python from mistune.renderers.markdown import MarkdownRenderer format_markdown = mistune.create_markdown(renderer=MarkdownRenderer()) format_markdown(your_markdown_text) With plugins ~~~~~~~~~~~~ The default ``MarkdownRenderer`` renders only basic Markdown syntax. If you use plugins, add render methods for the plugin tokens. This example adds the :ref:`strikethrough` plugin: .. code-block:: python import mistune from mistune.renderers.markdown import MarkdownRenderer class MyRenderer(MarkdownRenderer): def strikethrough(self, token, state): return '~~' + self.render_children(token, state) + '~~' format_markdown = mistune.create_markdown(renderer=MyRenderer(), plugins=['strikethrough']) print(format_markdown('~~text~~')) # ~~text~~ Pass the custom renderer instance so that its plugin methods are used. Default methods ~~~~~~~~~~~~~~~ This list shows the default renderer methods for ``MarkdownRenderer``: .. code-block:: # inline level text(self, token, state) link(self, token, state) image(self, token, state) emphasis(self, token, state) strong(self, token, state) codespan(self, token, state) linebreak(self, token, state) softbreak(self, token, state) inline_html(self, token, state) # block level paragraph(self, token, state) heading(self, token, state) blank_line(self, token, state) thematic_break(self, token, state) block_text(self, token, state) block_code(self, token, state) block_quote(self, token, state) block_html(self, token, state) block_error(self, token, state) list(self, token, state) lepture-mistune-f19057f/docs/security.rst000066400000000000000000000074271526537167500206030ustar00rootroot00000000000000Security model ============== Mistune parses text supplied by its caller. Applications should choose a trust mode deliberately and keep application resource controls outside the parser. Safe defaults ------------- ``mistune.create_markdown()`` and ``mistune.HTMLRenderer()`` escape raw HTML and reject unsafe URL schemes by default. Reuse the returned parser when processing multiple documents:: import mistune markdown = mistune.create_markdown() html = markdown(untrusted_markdown_text) The global ``mistune.html`` object is a legacy convenience parser created with ``escape=False``. It permits raw HTML and must not process untrusted input unless an external HTML sanitizer processes the rendered result. Trust boundaries ---------------- ``escape=True`` encodes raw HTML tokens. It is not a general HTML sanitizer, and it does not replace application-level request-size limits, execution isolation, or other resource controls. A custom renderer that deliberately emits raw HTML establishes its own trust boundary. HTML plugins and renderers should use the public helper matching each output context: * ``escape_raw`` for raw HTML tokens; * ``escape_attribute`` for a single attribute value; * ``render_attrs`` for generated, fixed-name attributes; * ``sanitize_url`` before placing a URL in an attribute. Do not treat ``escape=False`` as permission to skip attribute encoding or URL filtering. Parser bounds and recovery -------------------------- ``BlockParser.max_nested_level`` and ``InlineParser.max_nested_level`` default to 20. Inline containers share one budget: alternating images, emphasis, links, and formatting plugins does not grant each syntax its own allowance. When ``Markdown`` creates a missing block or inline parser, it uses the supplied parser's limit:: from mistune import BlockParser, HTMLRenderer, Markdown markdown = Markdown( renderer=HTMLRenderer(), block=BlockParser(max_nested_level=12), ) assert markdown.inline.max_nested_level == 12 The older inline settings ``max_emphasis_depth`` and ``max_image_depth`` are aliases for the shared limit. Limits must be positive; they cannot disable nesting bounds. Link reference labels follow CommonMark's maximum of 999 source characters, including backslashes used for escapes. Bare link destinations must have balanced parentheses, bounded by the parser's nesting limit, and cannot contain ASCII control characters. Parenthesized titles cannot contain an unescaped opening parenthesis. A failed candidate becomes ordinary text. Parsing resumes after the failed marker, so later valid links, emphasis, and code spans remain recognizable. Reaching a nesting limit does not turn the remainder of the document into unparsed text. Links use an opening-bracket stack. Code spans and inline extensions use source-local indexes of closing delimiters; they do not retain parse-failure caches across nested sources or documents. Inline HTML terminators use the same scanner, so repeated unclosed comments do not repeatedly scan the remaining document. Extension performance --------------------- Custom inline extensions may pass an exhaustive ``start_chars`` hint to ``InlineParser.register()``. Omitting the hint is correct and uses the combined regular-expression scanner. An incomplete hint can skip valid matches, so declare one only when every possible starting character is known. Applications accepting untrusted documents should still set appropriate input size and execution limits. Mistune does not impose a universal document-size limit or interrupt parsing with a timeout. Reporting vulnerabilities ------------------------- Do not open a public issue for a suspected vulnerability. Follow the repository's `security policy `_ to report it privately. lepture-mistune-f19057f/docs/sponsors.rst000066400000000000000000000013411526537167500206070ustar00rootroot00000000000000:orphan: :layout: simple Sponsored by ============ .. rst-class:: lead People and organizations supporting Hsiaoming Yang. ------ The Shibuya theme is open source, licensed under BSD-3-Clause, and completely free to use. If you'd like to support my work, consider becoming a `GitHub Sponsor`_. .. _`GitHub Sponsor`: https://github.com/sponsors/lepture .. sponsors:: Gold Sponsors :amount: 100 :size: 2xl :show-name: .. sponsors:: Silver Sponsors :amount: 50, 100 :size: xl .. sponsors:: Sponsors :amount: 25, 50 :size: md .. sponsors:: Backers :amount: 10, 25 :size: sm .. sponsors:: Supporter :amount: 1, 10 :size: sm .. sponsors:: Past Sponsors :amount: 0 :size: xs lepture-mistune-f19057f/docs/upgrade.rst000066400000000000000000000027031526537167500203530ustar00rootroot00000000000000Upgrade Guide ============= Upgrade from v2 to v3 --------------------- HTMLRenderer ~~~~~~~~~~~~ When customizing renderers, these methods' parameters are changed: .. code-block:: diff - link(self, link, text=None, title=None) + link(self, text, url, title=None) - image(self, src, alt="", title=None) + image(self, text, url, title=None) - heading(self, text, level) + heading(self, text, level, **attrs) - list(self, text, ordered, level, start=None) + list(self, text, ordered, **attrs) - list_item(self, text, level) + list_item(self, text) - table_cell(self, text, align=None, is_head=False) + table_cell(self, text, align=None, head=False) For plugins: .. code-block:: diff - abbr(self, key, definition) + abbr(self, text: str, title: str) - task_list_item(self, text: str, level: int, checked: bool) + task_list_item(self, text: str, checked: bool) AstRenderer ~~~~~~~~~~~ There is no ``AstRenderer`` in v3, just pass ``None`` or ``'ast'`` to ``create_markdown``:: import mistune md = mistune.create_markdown(renderer='ast') # or render=None md('...markdown text...') Plugins ~~~~~~~ Please check the advanced guide and built-in plugins source code to find out how to write a mistune plugin. Directives ~~~~~~~~~~ Find out all the details in :ref:`directives`. In v3, there is one more style of directive -- fenced style directive. lepture-mistune-f19057f/pyproject.toml000066400000000000000000000046351526537167500201640ustar00rootroot00000000000000[project] name = "mistune" description = "A sane and fast Markdown parser with useful plugins and renderers" authors = [{name = "Hsiaoming Yang", email="me@lepture.com"}] dependencies = [ "typing-extensions; python_version<'3.11'", ] license = {text = "BSD-3-Clause"} dynamic = ["version"] requires-python = ">=3.10" readme = "README.rst" classifiers = [ "Development Status :: 4 - Beta", "Environment :: Console", "Environment :: Web Environment", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", "Programming Language :: Python :: 3.15", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Text Processing :: Markup", ] [project.urls] Documentation = "https://mistune.lepture.com/" Source = "https://github.com/lepture/mistune" Donate = "https://github.com/sponsors/lepture" [project.scripts] mistune = "mistune.__main__:cli" [build-system] requires = ["setuptools"] build-backend = "setuptools.build_meta" [dependency-groups] lint = [ "mypy", "ruff", ] test = [ "mypy", "pytest", "pytest-cov", "ruff", ] docs = [ "shibuya", "sphinx", "sphinx-copybutton", "sphinx-design", ] [tool.setuptools.dynamic] version = {attr = "mistune.__version__"} [tool.setuptools.packages.find] where = ["src"] [tool.setuptools.package-data] mistune = ["py.typed"] [tool.ruff] target-version = "py310" line-length = 120 [tool.ruff.lint] select = [ "I", "F", ] [tool.ruff.lint.isort] split-on-trailing-comma=false [tool.mypy] strict = true python_version = "3.10" files = ["src/mistune"] show_error_codes = true pretty = true [tool.pytest.ini_options] pythonpath = ["src", "."] testpaths = ["tests"] filterwarnings = ["error"] [tool.coverage.run] branch = true source = ["mistune"] [tool.coverage.paths] source = ["src"] [tool.coverage.report] exclude_lines = [ "pragma: no cover", "def __repr__", "raise NotImplementedError", "@(abc\\.)?abstractmethod", ] lepture-mistune-f19057f/serve-doc.py000066400000000000000000000002111526537167500174730ustar00rootroot00000000000000from livereload import Server, shell app = Server() app.watch("docs", shell("make build-docs"), delay=2) app.serve(root="build/_html/") lepture-mistune-f19057f/setup.py000066400000000000000000000000641526537167500167520ustar00rootroot00000000000000from setuptools import setup setup(name="mistune") lepture-mistune-f19057f/sonar-project.properties000066400000000000000000000004311526537167500221420ustar00rootroot00000000000000sonar.projectKey=lepture_mistune sonar.organization=lepture sonar.sources=src sonar.sourceEncoding=UTF-8 sonar.test.inclusions=tests/**/test_*.py sonar.python.version=3.10, 3.11, 3.12, 3.13, 3.14 sonar.python.coverage.reportPaths=coverage.xml sonar.githubactions.activate=false lepture-mistune-f19057f/src/000077500000000000000000000000001526537167500160275ustar00rootroot00000000000000lepture-mistune-f19057f/src/mistune/000077500000000000000000000000001526537167500175135ustar00rootroot00000000000000lepture-mistune-f19057f/src/mistune/__init__.py000066400000000000000000000065571526537167500216410ustar00rootroot00000000000000""" mistune ~~~~~~~ A fast yet powerful Python Markdown parser with renderers and plugins, compatible with CommonMark 0.31.2. Documentation: https://mistune.lepture.com/ """ from functools import lru_cache from typing import Any, Dict, Iterable, List, Literal, Optional, Tuple, Union from .block_parser import BlockParser from .core import BaseRenderer, BlockState, InlineState from .inline_parser import InlineParser from .markdown import Markdown from .plugins import Plugin, PluginRef, import_plugin from .renderers.html import HTMLRenderer from .util import escape, escape_url, safe_entity, unikey RendererRef = Union[Literal["html", "ast"], BaseRenderer] def create_markdown( escape: Optional[bool] = None, hard_wrap: bool = False, renderer: Optional[RendererRef] = "html", plugins: Optional[Iterable[PluginRef]] = None, ) -> Markdown: """Create a Markdown instance based on the given condition. :param escape: Boolean. If using html renderer, escape html. When it is ``None``, the renderer keeps its own escape setting. :param hard_wrap: Boolean. Break every new line into ``
    ``. :param renderer: renderer instance, default is HTMLRenderer. :param plugins: List of plugins. This method is used when you want to re-use a Markdown instance:: markdown = create_markdown( escape=False, hard_wrap=True, ) # re-use markdown function markdown('.... your text ...') """ if renderer == "ast": # explicit and more similar to 2.x's API renderer = None elif renderer == "html": renderer = HTMLRenderer(escape=True if escape is None else escape) elif escape is not None and isinstance(renderer, HTMLRenderer): # a renderer instance was given, honor the explicit escape flag renderer.escape_enabled = escape inline = InlineParser(hard_wrap=hard_wrap) real_plugins: Optional[Iterable[Plugin]] = None if plugins is not None: real_plugins = [import_plugin(n) for n in plugins if n != "speedup"] return Markdown(renderer=renderer, inline=inline, plugins=real_plugins) html: Markdown = create_markdown(escape=False, plugins=["strikethrough", "footnotes", "table"]) _BuiltinRendererRef = Optional[Literal["html", "ast"]] @lru_cache(maxsize=128) def _cached_markdown(escape: bool, renderer: _BuiltinRendererRef, plugins: Tuple[str, ...]) -> Markdown: return create_markdown(escape=escape, renderer=renderer, plugins=plugins) def markdown( text: str, escape: bool = True, renderer: Optional[RendererRef] = "html", plugins: Optional[Iterable[Any]] = None, ) -> Union[str, List[Dict[str, Any]]]: plugin_refs = tuple(plugins) if plugins is not None else () if (renderer is None or (isinstance(renderer, str) and renderer in ("html", "ast"))) and all( isinstance(plugin, str) for plugin in plugin_refs ): md = _cached_markdown(escape, renderer, plugin_refs) else: md = create_markdown(escape=escape, renderer=renderer, plugins=plugin_refs) return md(text) __all__ = [ "Markdown", "HTMLRenderer", "BlockParser", "BlockState", "BaseRenderer", "InlineParser", "InlineState", "escape", "escape_url", "safe_entity", "unikey", "html", "create_markdown", "markdown", ] __version__ = "3.4.0" __homepage__ = "https://mistune.lepture.com/" lepture-mistune-f19057f/src/mistune/__main__.py000066400000000000000000000064571526537167500216210ustar00rootroot00000000000000import argparse import sys from typing import TYPE_CHECKING, Optional from . import __version__ as version from . import create_markdown from .renderers.markdown import MarkdownRenderer from .renderers.rst import RSTRenderer if TYPE_CHECKING: from .core import BaseRenderer from .markdown import Markdown def _md(args: argparse.Namespace) -> "Markdown": if args.plugin: plugins = args.plugin else: # default plugins plugins = ["strikethrough", "footnotes", "table"] if args.renderer == "rst": renderer: "BaseRenderer" = RSTRenderer() elif args.renderer == "markdown": renderer = MarkdownRenderer() else: renderer = args.renderer return create_markdown( escape=args.escape, hard_wrap=args.hardwrap, renderer=renderer, plugins=plugins, ) def _output(text: str, args: argparse.Namespace) -> None: if args.output: with open(args.output, "w", encoding="utf-8") as f: f.write(text) else: _ensure_stdout_utf8() print(text) CMD_HELP = """Mistune, a sane and fast Python Markdown parser. Examples: $ python -m mistune -m "Hi **Markdown**"

    Hi Markdown

    $ python -m mistune -f README.md

    ... $ cat README.md | python -m mistune

    ... """ def cli() -> None: parser = argparse.ArgumentParser( prog="python -m mistune", description=CMD_HELP, formatter_class=argparse.RawDescriptionHelpFormatter, ) parser.add_argument( "-m", "--message", help="the Markdown message to convert", ) parser.add_argument( "-f", "--file", help="the Markdown file to convert", ) parser.add_argument( "-p", "--plugin", metavar="NAME", action="extend", nargs="+", help="specify a plugin to use", ) parser.add_argument( "--escape", action="store_true", help="enable the escape option", ) parser.add_argument( "--hardwrap", action="store_true", help="enable the hardwrap option", ) parser.add_argument( "-o", "--output", help="write the rendered result into file", ) parser.add_argument( "-r", "--renderer", default="html", help="specify the output renderer", ) parser.add_argument("--version", action="version", version="mistune " + version) args = parser.parse_args() message = args.message if not message and not args.file: message = read_stdin() if message: md = _md(args) text = md(message) assert isinstance(text, str) _output(text, args) elif args.file: md = _md(args) text = md.read(args.file)[0] assert isinstance(text, str) _output(text, args) else: print("You must specify a message or file") sys.exit(1) def _ensure_stdout_utf8() -> None: reconfigure = getattr(sys.stdout, "reconfigure", None) if reconfigure is not None: reconfigure(encoding="utf-8") def read_stdin() -> Optional[str]: is_stdin_pipe = not sys.stdin.isatty() if is_stdin_pipe: return sys.stdin.read() else: return None if __name__ == "__main__": cli() lepture-mistune-f19057f/src/mistune/_inline/000077500000000000000000000000001526537167500211305ustar00rootroot00000000000000lepture-mistune-f19057f/src/mistune/_inline/__init__.py000066400000000000000000000000641526537167500232410ustar00rootroot00000000000000"""Internal helpers for inline Markdown parsing.""" lepture-mistune-f19057f/src/mistune/_inline/delimiters.py000066400000000000000000000050371526537167500236500ustar00rootroot00000000000000"""Indexes of closing delimiters for one inline source. Each delimiter family scans its source once. These are lexical positions, not memoized parse failures, and are never shared with copied or sliced sources. """ import re from bisect import bisect_left, bisect_right from typing import Dict, List, Optional, Tuple _BACKTICKS = re.compile(r"`+") class DelimiterScanner: def __init__(self, src: str) -> None: self.src = src self._code: Optional[Dict[int, List[int]]] = None self._ends: Dict[Tuple[str, bool], List[int]] = {} def code_end(self, marker: str, pos: int) -> Optional[int]: size = len(marker) if self._code is None: end = self.src.find(marker, pos) if end >= 0 and (end == 0 or self.src[end - 1] != "`"): after = end + size if after == len(self.src) or self.src[after] != "`": return end self._code = {} for match in _BACKTICKS.finditer(self.src): self._code.setdefault(match.end() - match.start(), []).append(match.start()) positions = self._code.get(size, []) index = bisect_left(positions, pos) return positions[index] if index < len(positions) else None def find(self, marker: str, pos: int, *, formatting: bool = False) -> Optional[int]: key = (marker, formatting) positions = self._ends.get(key) if positions is None: positions = [] start = self.src.find(marker) while start >= 0: if not formatting or _formatting_closer(self.src, start, marker): positions.append(start) start = self.src.find(marker, start + 1) self._ends[key] = positions index = bisect_right(positions, pos) if formatting else bisect_left(positions, pos) return positions[index] if index < len(positions) else None def _formatting_closer(src: str, start: int, marker: str) -> bool: char = marker[0] end = start + len(marker) if end < len(src) and src[end] == char and not src.startswith(marker, end): return False if not start: return False previous = src[start - 1] if previous != char: return not previous.isspace() # A literal escaped first character can precede a closing pair in a run. if start < 2 or src[start - 2] != "\\": return False backslashes = 0 pos = start - 2 while pos >= 0 and src[pos] == "\\": backslashes += 1 pos -= 1 return backslashes % 2 == 1 lepture-mistune-f19057f/src/mistune/_inline/emphasis.py000066400000000000000000000352121526537167500233160ustar00rootroot00000000000000from __future__ import annotations import re from dataclasses import dataclass from typing import Any, Dict, List, Optional, Tuple, cast from ..core import token_depth _CHARREF_PREFIX = re.compile(r"(#[0-9]{1,7};|#[xX][0-9a-fA-F]+;|[^\t\n\f <&#;]{1,32};)") def is_entity_boundary(left: str, right: str) -> bool: return left.endswith("&") and _CHARREF_PREFIX.match(right) is not None @dataclass(slots=True) class _Delimiter: index: int marker: str length: int can_open: bool can_close: bool #: original run length, used by the CommonMark multiple-of-3 rule even #: after the run has been partially consumed orig_length: int = 0 order: int = 0 class _DelimiterIndex: """Track part positions without rewriting every delimiter after a splice.""" def __init__(self, delimiters: List[_Delimiter], part_count: int) -> None: self._tree = [0] * (part_count + 1) self._next = list(range(len(delimiters) + 1)) def current(self, delimiter: _Delimiter) -> int: index = delimiter.index total = 0 cursor = index + 1 while cursor: total += self._tree[cursor] cursor -= cursor & -cursor return index - total def collapse(self, closer: _Delimiter, removed: int) -> None: if not removed: return cursor = closer.index + 1 while cursor < len(self._tree): self._tree[cursor] += removed cursor += cursor & -cursor def deactivate(self, order: int) -> None: self._next[order] = self._find(order + 1) def deactivate_range(self, delimiters: List[_Delimiter], start: int, end: int) -> None: order = self._find(start) while order < end: delimiters[order].length = 0 self._next[order] = self._find(order + 1) order = self._find(order) def _find(self, order: int) -> int: root = order while self._next[root] != root: root = self._next[root] while self._next[order] != order: parent = self._next[order] self._next[order] = root order = parent return root def finalize_emphasis_tokens( tokens: List[Dict[str, Any]], enabled: bool, max_depth: int, ) -> List[Dict[str, Any]]: if len(tokens) > 1: tokens = _coalesce_emphasis_text(tokens) if not enabled or not _contains_emphasis_marker(tokens): return [_clean_emphasis_token(token) for token in tokens] parts: List[Dict[str, Any]] = [] delimiters: List[_Delimiter] = [] source = _emphasis_source_text(tokens) source_pos = 0 for token in tokens: if token["type"] == "text" and token.get("_emphasis", True): _split_text_token(token, source, source_pos, parts, delimiters) else: parts.append(_clean_emphasis_token(token)) source_pos += _emphasis_source_length(token) if _process_dense_emphasis(parts, delimiters): return _merge_text_tokens(parts) _process_emphasis_delimiters(parts, delimiters, max_depth) return _merge_text_tokens(parts) def _coalesce_emphasis_text(tokens: List[Dict[str, Any]]) -> List[Dict[str, Any]]: result: List[Dict[str, Any]] = [] chunks: List[str] = [] enabled = True def flush() -> None: if chunks: token: Dict[str, Any] = {"type": "text", "raw": "".join(chunks)} if not enabled: token["_emphasis"] = False result.append(token) chunks.clear() for token in tokens: if token["type"] != "text": flush() result.append(token) else: mode = token.get("_emphasis", True) if mode != enabled or (chunks and is_entity_boundary(chunks[-1], token["raw"])): flush() enabled = mode chunks.append(token["raw"]) flush() return result def _process_dense_emphasis(parts: List[Dict[str, Any]], delimiters: List[_Delimiter]) -> bool: """Process a flat run such as ``*a*a*a`` without repeated list scans.""" if len(delimiters) < 4: return False marker = delimiters[0].marker if marker not in ("*", "_") or len(parts) != len(delimiters) * 2: return False for index, delimiter in enumerate(delimiters): if ( delimiter.marker != marker or delimiter.length != 1 or delimiter.index != index * 2 or parts[delimiter.index]["type"] != "text" or parts[delimiter.index + 1]["type"] != "text" ): return False pair_count = len(delimiters) // 2 processed: List[Dict[str, Any]] = [] for pair_index in range(pair_count): opener = delimiters[pair_index * 2] closer = delimiters[pair_index * 2 + 1] if ( not opener.can_open or not closer.can_close or not _can_match_emphasis_delimiters(opener, closer) or not _has_emphasis_content(parts, opener.index + 1, closer.index) ): return False if pair_index: processed.append(parts[opener.index - 1]) processed.append( { "type": "emphasis", "children": [parts[opener.index + 1]], } ) if pair_count: last_close = delimiters[pair_count * 2 - 1].index parts[:] = processed + parts[last_close + 1 :] return True def _contains_emphasis_marker(tokens: List[Dict[str, Any]]) -> bool: for token in tokens: if token["type"] == "text" and token.get("_emphasis", True): raw = token["raw"] if "*" in raw or "_" in raw: return True return False def _clean_emphasis_token(token: Dict[str, Any]) -> Dict[str, Any]: if "_emphasis" not in token and "_autolink" not in token: return token token = token.copy() token.pop("_emphasis", None) token.pop("_autolink", None) return token def _emphasis_source_text(tokens: List[Dict[str, Any]]) -> str: values = [] for token in tokens: if token["type"] == "text": values.append(token["raw"]) elif token["type"] in ("softbreak", "linebreak"): values.append("\n") else: values.append("\ufffc") return "".join(values) def _emphasis_source_length(token: Dict[str, Any]) -> int: if token["type"] == "text": return len(token["raw"]) return 1 def _split_text_token( token: Dict[str, Any], source: str, source_start: int, parts: List[Dict[str, Any]], delimiters: List[_Delimiter], ) -> None: text = token["raw"] pos = 0 while pos < len(text): if text[pos] not in "*_": end = _next_delimiter_run(text, pos) parts.append({"type": "text", "raw": text[pos:end]}) pos = end continue marker = text[pos] end = pos while end < len(text) and text[end] == marker: end += 1 length = end - pos absolute = source_start + pos can_open = _can_open_emphasis(source, absolute, length, marker) can_close = _can_close_emphasis(source, absolute, length, marker) index = len(parts) parts.append({"type": "text", "raw": text[pos:end]}) if can_open or can_close: delimiters.append(_Delimiter(index, marker, length, can_open, can_close, length, len(delimiters))) pos = end def _next_delimiter_run(text: str, pos: int) -> int: while pos < len(text) and text[pos] not in "*_": pos += 1 return pos def _process_emphasis_delimiters( parts: List[Dict[str, Any]], delimiters: List[_Delimiter], max_depth: int, ) -> None: index_map = _DelimiterIndex(delimiters, len(parts)) closer_pos = 0 openers_bottom: Dict[Tuple[str, int, bool], int] = {} while closer_pos < len(delimiters): closer = delimiters[closer_pos] if not closer.can_close or closer.length == 0: closer_pos += 1 continue opener_key = (closer.marker, closer.length % 3, closer.can_open) opener_bottom = openers_bottom.get(opener_key, 0) match = _find_emphasis_opener(delimiters, closer_pos, closer, opener_bottom) if match is None: openers_bottom[opener_key] = closer_pos closer_pos += 1 continue opener_pos, opener = match opener_index = index_map.current(opener) closer_index = index_map.current(closer) use_length = _get_emphasis_use_length(parts, opener, closer, opener_index, closer_index) children = _get_emphasis_children(parts, opener_index, closer_index, max_depth) if use_length is None or children is None: closer_pos += 1 continue _apply_emphasis_match( parts, delimiters, index_map, opener, closer, opener_pos, closer_pos, opener_index, closer_index, use_length, children, ) if opener.can_open or closer.can_close: closer_pos = max(opener_pos, openers_bottom.get(opener_key, 0)) else: closer_pos += 1 def _find_emphasis_opener( delimiters: List[_Delimiter], closer_pos: int, closer: _Delimiter, opener_bottom: int, ) -> Optional[Tuple[int, _Delimiter]]: opener_pos = closer_pos - 1 while opener_pos >= opener_bottom: opener = delimiters[opener_pos] if ( opener.marker == closer.marker and opener.can_open and opener.length > 0 and _can_match_emphasis_delimiters(opener, closer) ): return opener_pos, opener opener_pos -= 1 return None def _get_emphasis_use_length( parts: List[Dict[str, Any]], opener: _Delimiter, closer: _Delimiter, opener_index: int, closer_index: int, ) -> Optional[int]: use_length = 2 if opener.length >= 2 and closer.length >= 2 else 1 if use_length == 2 and not _has_strong_enabled(parts, opener_index, closer_index): use_length = 1 if use_length == 1 and not _has_emphasis_enabled(parts, opener_index, closer_index): return None return use_length def _get_emphasis_children( parts: List[Dict[str, Any]], opener_index: int, closer_index: int, max_depth: int, ) -> Optional[List[Dict[str, Any]]]: if not _has_emphasis_content(parts, opener_index + 1, closer_index): return None opener_text = parts[opener_index] closer_text = parts[closer_index] if opener_text["type"] != "text" or closer_text["type"] != "text": return None children = parts[opener_index + 1 : closer_index] if max_depth > 0 and token_depth(children) >= max_depth: return None return children def _apply_emphasis_match( parts: List[Dict[str, Any]], delimiters: List[_Delimiter], index_map: _DelimiterIndex, opener: _Delimiter, closer: _Delimiter, opener_pos: int, closer_pos: int, opener_index: int, closer_index: int, use_length: int, children: List[Dict[str, Any]], ) -> None: opener_text = parts[opener_index] closer_text = parts[closer_index] opener_text["raw"] = opener_text["raw"][:-use_length] closer_text["raw"] = closer_text["raw"][use_length:] node_type = "strong" if use_length == 2 else "emphasis" parts[opener_index + 1 : closer_index] = [{"type": node_type, "children": children}] removed = closer_index - opener_index - 2 if removed: index_map.deactivate_range(delimiters, opener_pos + 1, closer_pos) index_map.collapse(closer, removed) opener.length -= use_length closer.length -= use_length if opener.length == 0: opener.can_open = False index_map.deactivate(opener.order) if closer.length == 0: closer.can_close = False index_map.deactivate(closer.order) def _has_strong_enabled(parts: List[Dict[str, Any]], opener_index: int, closer_index: int) -> bool: return len(_text_raw(parts[opener_index])) >= 2 and len(_text_raw(parts[closer_index])) >= 2 def _has_emphasis_enabled(parts: List[Dict[str, Any]], opener_index: int, closer_index: int) -> bool: return bool(_text_raw(parts[opener_index]) and _text_raw(parts[closer_index])) def _text_raw(token: Dict[str, Any]) -> str: if token["type"] == "text": return cast(str, token["raw"]) return "" def _has_emphasis_content(parts: List[Dict[str, Any]], start: int, end: int) -> bool: for part in parts[start:end]: if part["type"] != "text" or part["raw"] != "": return True return False def _can_match_emphasis_delimiters(opener: _Delimiter, closer: _Delimiter) -> bool: if opener.can_close or closer.can_open: open_len = opener.orig_length close_len = closer.orig_length return (open_len + close_len) % 3 != 0 or open_len % 3 == 0 and close_len % 3 == 0 return True def _can_open_emphasis(text: str, start: int, size: int, marker: str) -> bool: previous = text[start - 1] if start > 0 else "\n" next_char = text[start + size] if start + size < len(text) else "\n" if marker == "_" and previous.isalnum() and next_char.isalnum(): return False if next_char.isspace(): return False if _is_punctuation(next_char) and not previous.isspace() and not _is_punctuation(previous): return False return True def _can_close_emphasis(text: str, start: int, size: int, marker: str) -> bool: previous = text[start - 1] if start > 0 else "\n" next_char = text[start + size] if start + size < len(text) else "\n" if marker == "_" and previous.isalnum() and next_char.isalnum(): return False if previous.isspace(): return False if _is_punctuation(previous) and not next_char.isspace() and not _is_punctuation(next_char): return False return True def _is_punctuation(char: str) -> bool: return not char.isspace() and not char.isalnum() def _merge_text_tokens(tokens: List[Dict[str, Any]]) -> List[Dict[str, Any]]: result: List[Dict[str, Any]] = [] chunks: List[str] = [] for token in tokens: if token["type"] == "text": raw = token["raw"] if not raw: continue if chunks and is_entity_boundary(chunks[-1], raw): result.append({"type": "text", "raw": "".join(chunks)}) chunks = [] chunks.append(raw) else: if chunks: result.append({"type": "text", "raw": "".join(chunks)}) chunks = [] result.append(_clean_emphasis_token(token)) if chunks: result.append({"type": "text", "raw": "".join(chunks)}) return result lepture-mistune-f19057f/src/mistune/_inline/links.py000066400000000000000000000120541526537167500226240ustar00rootroot00000000000000from __future__ import annotations from dataclasses import dataclass from typing import TYPE_CHECKING, Any, Dict, Match, Optional, Tuple from ..core import InlineState from ..helpers import MAX_LINK_LABEL_LENGTH, parse_link, parse_link_label from ..util import unikey if TYPE_CHECKING: from ..inline_parser import InlineParser @dataclass(slots=True) class Bracket: start: int token_index: int image: bool previous_link: Optional[Bracket] = None active: bool = True nested: bool = False child_depth: int = 0 def parse_link_open(inline: InlineParser, m: Match[str], state: InlineState) -> int: if state.brackets: state.brackets[-1].nested = True bracket = Bracket(m.end(), len(state.tokens), m.group(0).startswith("!"), state.last_link) if not bracket.image: state.last_link = bracket state.append_token({"type": "text", "raw": m.group(0)}) state.brackets.append(bracket) return m.end() def parse_link_close(inline: InlineParser, m: Match[str], state: InlineState) -> int: pos = m.start() if not state.env.get("ref_links"): # Without references, only a ']' immediately followed by '(' can # produce a link. Retire the other openers without parsing candidates. literal_end = m.end() - int(state.src.startswith("(", m.end())) if literal_end > pos: _discard_brackets(state, literal_end - pos) inline.process_text(state.src[pos:literal_end], state) pos = literal_end while pos < m.end(): if not state.brackets: inline.process_text(state.src[pos : m.end()], state) return m.end() pos = _close_bracket(inline, state, pos) return pos def _discard_brackets(state: InlineState, count: int) -> None: if count >= len(state.brackets): state.brackets.clear() state.last_link = None return discarded = state.brackets[-count:] del state.brackets[-count:] parent = state.brackets[-1] found_link = False for bracket in discarded: parent.child_depth = max(parent.child_depth, bracket.child_depth) if not bracket.image and not found_link: state.last_link = bracket.previous_link found_link = True def _close_bracket(inline: InlineParser, state: InlineState, close: int) -> int: opener = state.brackets.pop() if not opener.image: state.last_link = opener.previous_link if state.brackets: state.brackets[-1].child_depth = max(state.brackets[-1].child_depth, opener.child_depth) if not opener.active or (state.in_link and not opener.image): inline.process_text("]", state) return close + 1 # A rejected outer wrapper must not repeatedly copy an already deep subtree. if state.depth + opener.child_depth >= inline.max_nested_level: inline.process_text("]", state) return close + 1 attrs: Optional[Dict[str, Any]] = None end = close + 1 label: Optional[str] = None if state.src.startswith("(", end): attrs, next_pos = parse_link(state.src, end + 1, max_nested_level=inline.max_nested_level) if next_pos is not None: end = next_pos if attrs is None: reference = _parse_reference(state, opener, close, close + 1) if reference is None: inline.process_text("]", state) return close + 1 attrs, label, end = reference children = state.tokens[opener.token_index + 1 :] if not opener.image: # Automatic links inside explicit link text retain their literal text. children = [ {"type": "text", "raw": child["_autolink"], "_emphasis": False} if "_autolink" in child else child for child in children ] children = inline.finalize_tokens(children, state.depth + 1) token: Dict[str, Any] = {"type": "image" if opener.image else "link", "children": children, "attrs": attrs} if label is not None: token.update(ref=unikey(label), label=label) del state.tokens[opener.token_index :] state.append_token(token) if not opener.image: # CommonMark: a successful link deactivates preceding link openers. # Each opener is deactivated at most once; images remain eligible. bracket = state.last_link while bracket is not None and bracket.active: bracket.active = False bracket = bracket.previous_link return end def _parse_reference( state: InlineState, opener: Bracket, close: int, end: int ) -> Optional[Tuple[Dict[str, Any], str, int]]: refs = state.env.get("ref_links") if not refs: return None label = None next_pos = None if state.src.startswith("[", end): label, next_pos = parse_link_label(state.src, end + 1) if label is None or label == "": if opener.nested or close - opener.start > MAX_LINK_LABEL_LENGTH: return None label = state.src[opener.start : close] ref = refs.get(unikey(label)) if ref is None: return None return {"url": ref["url"], "title": ref.get("title")}, label, next_pos or end lepture-mistune-f19057f/src/mistune/block_parser.py000066400000000000000000000501661526537167500225430ustar00rootroot00000000000000import re import string from bisect import bisect_left from typing import List, Match, Optional, Pattern, Set, Tuple from .core import DEFAULT_MAX_NESTED_LEVEL, BlockState, Parser from .helpers import ( BLOCK_TAGS, HTML_ATTRIBUTES, HTML_TAGNAME, LINK_LABEL, PRE_TAGS, parse_link_href, parse_link_title, unescape_char, ) from .list_parser import LIST_PATTERN, parse_list from .util import escape_url, expand_leading_tab, expand_tab, unikey _INDENT_CODE_TRIM = re.compile(r"^ {1,4}", flags=re.M) _ATX_HEADING_TRIM = re.compile(r"(\s+|^)#+\s*$") _BLOCK_QUOTE_TRIM = re.compile(r"^ ?", flags=re.M) _BLANK_TO_LINE = re.compile(r"[ \t]*\n") _BLOCK_TAGS_PATTERN = "(" + "|".join(BLOCK_TAGS) + "|" + "|".join(PRE_TAGS) + ")" _OPEN_TAG_END = re.compile(HTML_ATTRIBUTES + r"[ \t]*>[ \t]*(?:\n|$)") _CLOSE_TAG_END = re.compile(r"[ \t]*>[ \t]*(?:\n|$)") _BLOCK_QUOTE_LINE = re.compile(r"^ {0,3}>([^\n]*(?:\n|$))") class BlockParser(Parser[BlockState]): state_cls = BlockState BLANK_LINE = re.compile(r"(^[ \t\v\f]*\n)+", re.M) RAW_HTML = ( r"^ {0,3}(" r"#{1,6})(?!#+)(?P[ \t]*|[ \t]+.*?)$", "setex_heading": r"^ {0,3}(?P=|-){1,}[ \t]*$", "fenced_code": ( r"^(?P {0,3})(?P`{3,}|~{3,})" r"[ \t]*(?P.*?)$" ), "indent_code": ( r"^(?: {4}| *\t)[^\n]+(?:\n+|$)" r"((?:(?: {4}| *\t)[^\n]+(?:\n+|$))|\s)*" ), "thematic_break": r"^ {0,3}((?:-[ \t]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})$", "ref_link": r"^ {0,3}\[(?P" + LINK_LABEL + r")\]:", "block_quote": r"^ {0,3}>(?P.*?)$", "list": LIST_PATTERN, "block_html": BLOCK_HTML, "raw_html": RAW_HTML, } DEFAULT_RULES = ( "fenced_code", "indent_code", "atx_heading", "setex_heading", "thematic_break", "block_quote", "list", "ref_link", "raw_html", "blank_line", ) def __init__( self, block_quote_rules: Optional[List[str]] = None, list_rules: Optional[List[str]] = None, max_nested_level: int = DEFAULT_MAX_NESTED_LEVEL, ): super(BlockParser, self).__init__() if block_quote_rules is None: block_quote_rules = list(self.DEFAULT_RULES) if list_rules is None: list_rules = list(self.DEFAULT_RULES) if max_nested_level < 1: raise ValueError("max_nested_level must be positive") self.block_quote_rules = block_quote_rules self.list_rules = list_rules self.max_nested_level = max_nested_level # register default parse methods self._methods = {name: getattr(self, "parse_" + name) for name in self.SPECIFICATION} def parse_blank_line(self, m: Match[str], state: BlockState) -> int: """Parse token for blank lines.""" if state.cursor == 0: state.append_token({"type": "blank_line", "newlines": m.group(0).count("\n")}) else: state.append_token({"type": "blank_line"}) return m.end() def parse_thematic_break(self, m: Match[str], state: BlockState) -> int: """Parse token for thematic break, e.g. ``


    `` tag in HTML.""" state.append_token({"type": "thematic_break"}) # $ does not count '\n' return m.end() + 1 def parse_indent_code(self, m: Match[str], state: BlockState) -> int: """Parse token for code block which is indented by 4 spaces.""" # it is a part of the paragraph end_pos = state.append_paragraph() if end_pos: return end_pos code = m.group(0) end_pos = _trim_partial_next_line_indent(code, m.end()) if end_pos != m.end(): code = state.get_text(end_pos) code = expand_leading_tab(code) code = _INDENT_CODE_TRIM.sub("", code) code = code.strip("\n") state.append_token({"type": "block_code", "raw": code, "style": "indent"}) return end_pos def parse_fenced_code(self, m: Match[str], state: BlockState) -> Optional[int]: """Parse token for fenced code block. A fenced code block is started with 3 or more backtick(`) or tilde(~). An example of a fenced code block: .. code-block:: markdown ```python def markdown(text): return mistune.html(text) ``` """ spaces = m.group("fenced_1") marker = m.group("fenced_2") info = m.group("fenced_3") c = marker[0] if info and c == "`": # CommonMark Example 145 # Info strings for backtick code blocks cannot contain backticks if info.find(c) != -1: return None _end = re.compile(r"^ {0,3}" + c + "{" + str(len(marker)) + r",}[ \t]*(?:\n|$)", re.M) cursor_start = m.end() + 1 m2 = _end.search(state.src, cursor_start) if m2: code = state.src[cursor_start : m2.start()] end_pos = m2.end() else: code = state.src[cursor_start:] end_pos = state.cursor_max if spaces and code: _trim_pattern = re.compile("^ {0," + str(len(spaces)) + "}", re.M) code = _trim_pattern.sub("", code) token = {"type": "block_code", "raw": code, "style": "fenced", "marker": marker} if info: info = unescape_char(info) token["attrs"] = {"info": info.strip()} state.append_token(token) return end_pos def parse_atx_heading(self, m: Match[str], state: BlockState) -> int: """Parse token for ATX heading. An ATX heading is started with 1 to 6 symbol of ``#``.""" level = len(m.group("atx_1")) text = m.group("atx_2").strip(string.whitespace) # remove last # if text: text = _ATX_HEADING_TRIM.sub("", text) token = {"type": "heading", "text": text, "attrs": {"level": level}, "style": "atx"} state.append_token(token) return m.end() + 1 def parse_setex_heading(self, m: Match[str], state: BlockState) -> Optional[int]: """Parse token for setex style heading. A setex heading syntax looks like: .. code-block:: markdown H1 title ======== """ if state.cursor in state.lazy_line_starts: return None last_token = state.last_token() if last_token and last_token["type"] == "paragraph": level = 1 if m.group("setext_1") == "=" else 2 last_token["type"] = "heading" last_token["style"] = "setext" last_token["attrs"] = {"level": level} return m.end() + 1 sc = self.compile_sc(["thematic_break", "list"]) m2 = sc.match(state.src, state.cursor) if m2: return self.parse_method(m2, state) return None def parse_ref_link(self, m: Match[str], state: BlockState) -> Optional[int]: """Parse link references and save the link information into ``state.env``. Here is an example of a link reference: .. code-block:: markdown a [link][example] [example]: https://example.com "Optional title" This method will save the link reference into ``state.env`` as:: state.env['ref_links']['example'] = { 'url': 'https://example.com', 'title': "Optional title", } """ end_pos = state.append_paragraph() if end_pos: return end_pos label = m.group("reflink_1") key = unikey(label) if not key: return None href, href_pos = parse_link_href(state.src, m.end(), block=True, max_nested_level=self.max_nested_level) if href is None: return None assert href_pos is not None blank_pos = _find_next_blank_line(state, href_pos, self.BLANK_LINE) if blank_pos is None: max_pos = state.cursor_max else: max_pos = blank_pos title, title_pos = parse_link_title(state.src, href_pos, max_pos) if title_pos: m2 = _BLANK_TO_LINE.match(state.src, title_pos) if m2: title_pos = m2.end() else: title_pos = None title = None if title_pos is None: m3 = _BLANK_TO_LINE.match(state.src, href_pos) if m3: href_pos = m3.end() else: href_pos = None href = None end_pos = title_pos or href_pos if not end_pos: return None if key not in state.env["ref_links"]: assert href is not None href = unescape_char(href) data = {"url": escape_url(href), "label": label} if title: data["title"] = title state.env["ref_links"][key] = data return end_pos def extract_block_quote(self, m: Match[str], state: BlockState) -> Tuple[str, Optional[int], Set[int]]: """Extract text and cursor end position of a block quote.""" text = _parse_block_quote_line(state.get_line(state.cursor)) assert text is not None lazy_line_starts: Set[int] = set() sc = self.compile_sc(["blank_line", "indent_code", "fenced_code"]) require_marker = bool(sc.match(text)) state.cursor += len(state.get_line(state.cursor)) end_pos: Optional[int] = None if require_marker: while state.cursor < state.cursor_max: quote = _parse_block_quote_line(state.get_line(state.cursor)) if quote is None: break text += quote state.cursor += len(state.get_line(state.cursor)) else: prev_blank_line = False break_sc = self.compile_sc( [ "blank_line", "thematic_break", "fenced_code", "list", "block_html", ] ) while state.cursor < state.cursor_max: quote = _parse_block_quote_line(state.get_line(state.cursor)) if quote is not None: text += quote state.cursor += len(state.get_line(state.cursor)) if not quote.strip(): prev_blank_line = True else: prev_blank_line = False continue if prev_blank_line: # CommonMark Example 249 # because of laziness, a blank line is needed between # a block quote and a following paragraph break m4 = break_sc.match(state.src, state.cursor) if m4: end_pos = self.parse_method(m4, state) if end_pos: break # lazy continuation line line = state.get_line(state.cursor) lazy_line_starts.add(len(text)) text += expand_leading_tab(line, 3) state.cursor += len(line) # according to CommonMark Example 6, the second tab should be # treated as 4 spaces return expand_tab(text), end_pos, lazy_line_starts def parse_block_quote(self, m: Match[str], state: BlockState) -> int: """Parse token for block quote. Here is an example of the syntax: .. code-block:: markdown > a block quote starts > with right arrows """ text, end_pos, lazy_line_starts = self.extract_block_quote(m, state) # scan children state child = state.child_state(text, lazy_line_starts=lazy_line_starts) if state.depth() >= self.max_nested_level - 1: # At the nesting limit, stop descending into any further container # blocks. Trimming only "block_quote" still allowed block quotes and # lists to recurse into each other without bound (RecursionError). rules = [rule for rule in self.block_quote_rules if rule not in ("block_quote", "list")] else: rules = self.block_quote_rules self.parse(child, rules) token = {"type": "block_quote", "children": child.tokens} if end_pos: state.prepend_token(token) return end_pos state.append_token(token) return state.cursor def parse_list(self, m: Match[str], state: BlockState) -> int: """Parse tokens for ordered and unordered list.""" return parse_list(self, m, state) def parse_block_html(self, m: Match[str], state: BlockState) -> Optional[int]: return self.parse_raw_html(m, state) def parse_raw_html(self, m: Match[str], state: BlockState) -> Optional[int]: marker = m.group(0).strip() # rule 2 if marker == "", m.end()) # rule 3 if marker == "", m.end()) # rule 5 if marker == "", m.end()) # rule 4 if marker.startswith("", m.end()) close_tag = None open_tag = None if marker.startswith("" return _parse_html_to_end(state, end_tag, m.end()) # rule 6 if open_tag in BLOCK_TAGS: return _parse_html_to_newline(state, self.BLANK_LINE) # Blocks of type 7 may not interrupt a paragraph. end_pos = state.append_paragraph() if end_pos: return end_pos # rule 7 start_pos = m.end() end_pos = state.find_line_end() if (open_tag and _OPEN_TAG_END.match(state.src, start_pos, end_pos)) or ( close_tag and _CLOSE_TAG_END.match(state.src, start_pos, end_pos) ): return _parse_html_to_newline(state, self.BLANK_LINE) return None def parse(self, state: BlockState, rules: Optional[List[str]] = None) -> None: if rules is None: rules = self.rules sc = self.compile_sc(rules) while state.cursor < state.cursor_max: if "indent_code" in rules: end_pos = self._parse_indent_code_fast(state) if end_pos is not None: state.cursor = end_pos continue m = sc.match(state.src, state.cursor) if not m and self._parse_plain_paragraph(state, sc): continue if not m: m = sc.search(state.src, state.cursor) if not m: break end_pos = m.start() if end_pos > state.cursor: text = state.get_text(end_pos) state.add_paragraph(text) state.cursor = end_pos end_pos2 = self.parse_method(m, state) if end_pos2: state.cursor = end_pos2 else: end_pos3 = state.find_line_end() text = state.get_text(end_pos3) state.add_paragraph(text) state.cursor = end_pos3 if state.cursor < state.cursor_max: text = state.src[state.cursor :] state.add_paragraph(text) state.cursor = state.cursor_max def _parse_indent_code_fast(self, state: BlockState) -> Optional[int]: line_end = state.find_line_end() line = state.get_text(line_end) if not _is_indent_code_line(line): return None if state.last_token() and state.last_token()["type"] == "paragraph": return state.append_paragraph() end_pos = _find_indent_code_end(state.src, line_end, state.cursor_max) code = state.get_text(end_pos) code = expand_leading_tab(code) code = _INDENT_CODE_TRIM.sub("", code) code = code.strip("\n") state.append_token({"type": "block_code", "raw": code, "style": "indent"}) return end_pos def _parse_plain_paragraph(self, state: BlockState, sc: Pattern[str]) -> bool: if not _is_plain_paragraph_start(state.src, state.cursor): return False pos = state.cursor while pos < state.cursor_max: if pos > state.cursor and sc.match(state.src, pos): break line = state.get_line(pos) if not line.strip(): break pos += len(line) if pos <= state.cursor: return False state.add_paragraph(state.get_text(pos)) state.cursor = pos return True def _parse_html_to_end(state: BlockState, end_marker: str, start_pos: int) -> int: marker_pos = state.src.find(end_marker, start_pos) if marker_pos == -1: text = state.src[state.cursor :] end_pos = state.cursor_max else: text = state.get_text(marker_pos) state.cursor = marker_pos end_pos = state.find_line_end() text += state.get_text(end_pos) state.append_token({"type": "block_html", "raw": text}) return end_pos def _parse_html_to_newline(state: BlockState, newline: Pattern[str]) -> int: m = newline.search(state.src, state.cursor) if m: end_pos = m.start() text = state.get_text(end_pos) else: text = state.src[state.cursor :] end_pos = state.cursor_max state.append_token({"type": "block_html", "raw": text}) return end_pos def _parse_block_quote_line(line: str) -> Optional[str]: m = _BLOCK_QUOTE_LINE.match(line) if not m: return None text = expand_leading_tab(m.group(1), 3) return _BLOCK_QUOTE_TRIM.sub("", text) def _find_next_blank_line(state: BlockState, pos: int, pattern: Pattern[str]) -> Optional[int]: cache = state.env.get("__blank_line_starts__") if cache is None or cache[0] is not state.src: cache = (state.src, [m.start() for m in pattern.finditer(state.src)]) state.env["__blank_line_starts__"] = cache positions = cache[1] index = bisect_left(positions, pos) if index < len(positions): return positions[index] return None def _trim_partial_next_line_indent(text: str, end_pos: int) -> int: line_start = text.rfind("\n") + 1 if line_start == 0: return end_pos suffix = text[line_start:] if suffix and suffix.strip(" \t") == "" and len(suffix.expandtabs(4)) < 4: return end_pos - len(suffix) return end_pos def _is_indent_code_line(line: str) -> bool: if line.endswith("\n"): line = line[:-1] if len(line) > 4 and line.startswith(" "): return True index = 0 while index < len(line) and line[index] == " ": index += 1 return index + 1 < len(line) and line[index] == "\t" def _find_indent_code_end(src: str, start: int, end: int) -> int: pos = start while pos < end: newline = src.find("\n", pos, end) line_end = end if newline < 0 else newline + 1 line = src[pos:line_end] if _is_indent_code_line(line) or not line.strip(): pos = line_end continue break return pos def _is_plain_paragraph_start(src: str, pos: int) -> bool: if pos >= len(src): return False c = src[pos] return not c.isspace() and not c.isdigit() and c not in string.punctuation lepture-mistune-f19057f/src/mistune/core.py000066400000000000000000000216761526537167500210310ustar00rootroot00000000000000import re import sys from typing import ( TYPE_CHECKING, Any, Callable, ClassVar, Dict, Generic, Iterable, List, Match, MutableMapping, Optional, Pattern, Set, Type, TypeVar, Union, cast, ) from ._inline.delimiters import DelimiterScanner if TYPE_CHECKING: from ._inline.links import Bracket DEFAULT_MAX_NESTED_LEVEL = 20 if sys.version_info >= (3, 11): from typing import Self else: from typing_extensions import Self class BlockState: """The state to save block parser's cursor and tokens.""" src: str tokens: List[Dict[str, Any]] cursor: int cursor_max: int list_tight: bool parent: Any env: MutableMapping[str, Any] lazy_line_starts: Set[int] def __init__(self, parent: Optional[Any] = None) -> None: self.src = "" self.tokens = [] # current cursor position self.cursor = 0 self.cursor_max = 0 # for list and block quote chain self.list_tight = True self.parent = parent self.lazy_line_starts = set() # for saving def references if parent: self.env = parent.env else: self.env = {"ref_links": {}} def child_state(self, src: str, lazy_line_starts: Optional[Set[int]] = None) -> "BlockState": child = self.__class__(self) child.process(src) if lazy_line_starts: child.lazy_line_starts = lazy_line_starts return child def process(self, src: str) -> None: self.src = src self.cursor_max = len(src) def find_line_end(self) -> int: return self.find_line_end_at(self.cursor) def find_line_end_at(self, pos: int) -> int: end = self.src.find("\n", pos) if end < 0: return len(self.src) return end + 1 def get_text(self, end_pos: int) -> str: return self.src[self.cursor : end_pos] def get_line(self, start_pos: int) -> str: return self.src[start_pos : self.find_line_end_at(start_pos)] def last_token(self) -> Any: if self.tokens: return self.tokens[-1] def prepend_token(self, token: Dict[str, Any]) -> None: """Insert token before the last token.""" self.tokens.insert(len(self.tokens) - 1, token) def append_token(self, token: Dict[str, Any]) -> None: """Add token to the end of token list.""" self.tokens.append(token) def add_paragraph(self, text: str) -> None: last_token = self.last_token() if last_token and last_token["type"] == "paragraph": last_token["text"] += text else: self.tokens.append({"type": "paragraph", "text": text}) def append_paragraph(self) -> Optional[int]: last_token = self.last_token() if last_token and last_token["type"] == "paragraph": pos = self.find_line_end() last_token["text"] += self.get_text(pos) return pos return None def depth(self) -> int: d = 0 parent = self.parent while parent: d += 1 parent = parent.parent return d class InlineState: """The state to save inline parser's tokens.""" def __init__(self, env: MutableMapping[str, Any]): self.env = env self.src = "" self.tokens: List[Dict[str, Any]] = [] self.in_image = False self.depth = 0 self.in_link = False self.brackets: List["Bracket"] = [] self.last_link: Optional["Bracket"] = None self._delimiters: Optional[DelimiterScanner] = None def prepend_token(self, token: Dict[str, Any]) -> None: """Insert token before the last token.""" self.tokens.insert(len(self.tokens) - 1, token) def append_token(self, token: Dict[str, Any]) -> None: """Add token to the end of token list.""" self.tokens.append(token) if self.brackets and "children" in token: bracket = self.brackets[-1] if "_autolink" not in token or bracket.image: bracket.child_depth = max(bracket.child_depth, token_depth([token])) def copy(self) -> "InlineState": """Create a copy of current state.""" state = self.__class__(self.env) state.in_image = self.in_image state.depth = self.depth + 1 state.in_link = self.in_link return state @property def delimiters(self) -> DelimiterScanner: if self._delimiters is None or self._delimiters.src is not self.src: self._delimiters = DelimiterScanner(self.src) return self._delimiters def token_depth(tokens: List[Dict[str, Any]]) -> int: """Count all inline containers, including mixed plugin and core syntax.""" maximum = 0 stack = [(token, 0) for token in tokens] while stack: token, depth = stack.pop() if "children" in token: depth += 1 maximum = max(maximum, depth) stack.extend((child, depth) for child in token["children"]) return maximum ST = TypeVar("ST", InlineState, BlockState) class Parser(Generic[ST]): sc_flag: "re._FlagsType" = re.M state_cls: Type[ST] SPECIFICATION: ClassVar[Dict[str, str]] = {} DEFAULT_RULES: ClassVar[Iterable[str]] = [] def __init__(self) -> None: self.specification = self.SPECIFICATION.copy() self.rules = list(self.DEFAULT_RULES) self._methods: Dict[ str, Callable[[Match[str], ST], Optional[int]], ] = {} self.__sc: Dict[str, Pattern[str]] = {} def compile_sc(self, rules: Optional[List[str]] = None) -> Pattern[str]: if rules is None: key = "$" rules = self.rules else: key = "|".join(rules) sc = self.__sc.get(key) if sc: return sc regex = "|".join(r"(?P<%s>%s)" % (k, self.specification[k]) for k in rules) sc = re.compile(regex, self.sc_flag) self.__sc[key] = sc return sc def register( self, name: str, pattern: Union[str, None], func: Callable[[Self, Match[str], ST], Optional[int]], before: Optional[str] = None, ) -> None: """Register a new rule to parse the token. This method is usually used to create a new plugin. :param name: name of the new grammar :param pattern: regex pattern in string :param func: the parsing function :param before: insert this rule before a built-in rule """ self._methods[name] = lambda m, state: func(self, m, state) self.__sc.clear() if pattern: self.specification[name] = pattern if name not in self.rules: self.insert_rule(self.rules, name, before=before) def register_rule(self, name: str, pattern: str, func: Any) -> None: raise DeprecationWarning("This plugin is not compatible with mistune v3.") @staticmethod def insert_rule(rules: List[str], name: str, before: Optional[str] = None) -> None: if before: try: index = rules.index(before) rules.insert(index, name) except ValueError: rules.append(name) else: rules.append(name) def parse_method(self, m: Match[str], state: ST) -> Optional[int]: lastgroup = m.lastgroup assert lastgroup func = self._methods[lastgroup] return func(m, state) class BaseRenderer(object): NAME: ClassVar[str] = "base" def __init__(self) -> None: self.__methods: Dict[str, Callable[..., str]] = {} def register(self, name: str, method: Callable[..., str]) -> None: """Register a render method for the named token. For example:: def render_wiki(renderer, key, title): return f'{title}' renderer.register('wiki', render_wiki) """ # bind self into renderer method self.__methods[name] = lambda *arg, **kwargs: method(self, *arg, **kwargs) def _get_method(self, name: str) -> Callable[..., str]: try: return cast("Callable[..., str]", object.__getattribute__(self, name)) except AttributeError: method = self.__methods.get(name) if not method: raise AttributeError('No renderer "{!r}"'.format(name)) return method def render_token(self, token: Dict[str, Any], state: BlockState) -> str: func = self._get_method(token["type"]) return func(token, state) def iter_tokens(self, tokens: Iterable[Dict[str, Any]], state: BlockState) -> Iterable[str]: for tok in tokens: yield self.render_token(tok, state) def render_tokens(self, tokens: Iterable[Dict[str, Any]], state: BlockState) -> str: return "".join(self.iter_tokens(tokens, state)) def __call__(self, tokens: Iterable[Dict[str, Any]], state: BlockState) -> str: return self.render_tokens(tokens, state) lepture-mistune-f19057f/src/mistune/directives/000077500000000000000000000000001526537167500216545ustar00rootroot00000000000000lepture-mistune-f19057f/src/mistune/directives/__init__.py000066400000000000000000000015431526537167500237700ustar00rootroot00000000000000from typing import List from ._base import BaseDirective, DirectiveParser, DirectivePlugin from ._fenced import FencedDirective from ._rst import RSTDirective from .admonition import Admonition from .image import Figure, Image from .include import Include from .toc import TableOfContents class RstDirective(RSTDirective): # pragma: no cover def __init__(self, plugins: List[DirectivePlugin]) -> None: super(RstDirective, self).__init__(plugins) import warnings warnings.warn( "'RstDirective' is deprecated, please use 'RSTDirective' instead.", DeprecationWarning, stacklevel=2, ) __all__ = [ "DirectiveParser", "BaseDirective", "DirectivePlugin", "RSTDirective", "FencedDirective", "Admonition", "TableOfContents", "Include", "Image", "Figure", ] lepture-mistune-f19057f/src/mistune/directives/_base.py000066400000000000000000000107141526537167500233020ustar00rootroot00000000000000import re from abc import ABCMeta, abstractmethod from typing import TYPE_CHECKING, Any, Callable, Dict, Iterable, List, Match, Optional, Tuple, Type, Union if TYPE_CHECKING: from ..block_parser import BlockParser from ..core import BlockState from ..markdown import Markdown class DirectiveParser(ABCMeta): name = "directive" @staticmethod @abstractmethod def parse_type(m: Match[str]) -> str: raise NotImplementedError() @staticmethod @abstractmethod def parse_title(m: Match[str]) -> str: raise NotImplementedError() @staticmethod @abstractmethod def parse_content(m: Match[str]) -> str: raise NotImplementedError() @classmethod def parse_tokens(cls, block: "BlockParser", text: str, state: "BlockState") -> Iterable[Dict[str, Any]]: if state.depth() >= block.max_nested_level - 1 and cls.name in block.rules: rules = list(block.rules) rules.remove(cls.name) else: rules = block.rules child = state.child_state(text) block.parse(child, rules) return child.tokens @staticmethod def parse_options(m: Match[str]) -> List[Tuple[str, str]]: text = m.group("options") if not text.strip(): return [] options = [] for line in re.split(r"\n+", text): line = line.strip()[1:] if not line: continue i = line.find(":") k = line[:i] v = line[i + 1 :].strip() options.append((k, v)) return options class BaseDirective(metaclass=ABCMeta): parser: Type[DirectiveParser] directive_pattern: Optional[str] = None def __init__(self, plugins: List["DirectivePlugin"]): self._methods: Dict[ str, Callable[ ["BlockParser", Match[str], "BlockState"], Union[Dict[str, Any], List[Dict[str, Any]]], ], ] = {} self.__plugins = plugins def register( self, name: str, fn: Callable[ ["BlockParser", Match[str], "BlockState"], Union[Dict[str, Any], List[Dict[str, Any]]], ], ) -> None: self._methods[name] = fn def parse_method( self, block: "BlockParser", m: Match[str], state: "BlockState" ) -> Union[Dict[str, Any], List[Dict[str, Any]]]: _type = self.parser.parse_type(m) method = self._methods.get(_type) if method: try: token = method(block, m, state) except ValueError as e: token = {"type": "block_error", "raw": str(e)} else: text = m.group(0) token = { "type": "block_error", "raw": text, } if isinstance(token, list): for tok in token: state.append_token(tok) else: state.append_token(token) return token @abstractmethod def parse_directive(self, block: "BlockParser", m: Match[str], state: "BlockState") -> Optional[int]: raise NotImplementedError() def register_block_parser(self, md: "Markdown", before: Optional[str] = None) -> None: md.block.register( self.parser.name, self.directive_pattern, self.parse_directive, before=before, ) def __call__(self, markdown: "Markdown") -> None: for plugin in self.__plugins: plugin.parser = self.parser plugin(self, markdown) class DirectivePlugin: parser: Type[DirectiveParser] def __init__(self) -> None: ... def parse_options(self, m: Match[str]) -> List[Tuple[str, str]]: return self.parser.parse_options(m) def parse_type(self, m: Match[str]) -> str: return self.parser.parse_type(m) def parse_title(self, m: Match[str]) -> str: return self.parser.parse_title(m) def parse_content(self, m: Match[str]) -> str: return self.parser.parse_content(m) def parse_tokens(self, block: "BlockParser", text: str, state: "BlockState") -> Iterable[Dict[str, Any]]: return self.parser.parse_tokens(block, text, state) def parse( self, block: "BlockParser", m: Match[str], state: "BlockState" ) -> Union[Dict[str, Any], List[Dict[str, Any]]]: raise NotImplementedError() def __call__(self, directive: BaseDirective, md: "Markdown") -> None: raise NotImplementedError() lepture-mistune-f19057f/src/mistune/directives/_fenced.py000066400000000000000000000113321526537167500236110ustar00rootroot00000000000000import re from typing import TYPE_CHECKING, List, Match, Optional from ._base import BaseDirective, DirectiveParser, DirectivePlugin if TYPE_CHECKING: from ..block_parser import BlockParser from ..core import BlockState from ..markdown import Markdown __all__ = ["FencedDirective"] _type_re = re.compile(r"^ *\{[a-zA-Z0-9_-]+\}") _directive_re = re.compile( r"\{(?P[a-zA-Z0-9_-]+)\} *(?P[^\n]*)(?:\n|$)" r"(?P<options>(?:\:[a-zA-Z0-9_-]+\: *[^\n]*\n+)*)" r"\n*(?P<text>(?:[^\n]*\n+)*)" ) class FencedParser(DirectiveParser): name = "fenced_directive" @staticmethod def parse_type(m: Match[str]) -> str: return m.group("type") @staticmethod def parse_title(m: Match[str]) -> str: return m.group("title") @staticmethod def parse_content(m: Match[str]) -> str: return m.group("text") class FencedDirective(BaseDirective): """A **fenced** style of directive looks like a fenced code block, it is inspired by markdown-it-docutils. The syntax looks like: .. code-block:: text ```{directive-type} title :option-key: option value :option-key: option value content text here ``` To use ``FencedDirective``, developers can add it into plugin list in the :class:`Markdown` instance: .. code-block:: python import mistune from mistune.directives import FencedDirective, Admonition md = mistune.create_markdown(plugins=[ # ... FencedDirective([Admonition()]), ]) FencedDirective is using >= 3 backticks or curly-brackets for the fenced syntax. Developers can change it to other characters, e.g. colon: .. code-block:: python directive = FencedDirective([Admonition()], ':') And then the directive syntax would look like: .. code-block:: text ::::{note} Nesting directives You can nest directives by ensuring the start and end fence matching the length. For instance, in this example, the admonition is started with 4 colons, then it should end with 4 colons. You can nest another admonition with other length of colons except 4. :::{tip} Longer outermost fence It would be better that you put longer markers for the outer fence, and shorter markers for the inner fence. In this example, we put 4 colons outsie, and 3 colons inside. ::: :::: :param plugins: list of directive plugins :param markers: characters to determine the fence, default is backtick and curly-bracket """ parser = FencedParser def __init__(self, plugins: List[DirectivePlugin], markers: str = "`~") -> None: super(FencedDirective, self).__init__(plugins) self.markers = markers _marker_pattern = "|".join(re.escape(c) for c in markers) self.directive_pattern = ( r"^(?P<fenced_directive_mark>(?:" + _marker_pattern + r"){3,})" r"\{[a-zA-Z0-9_-]+\}" ) def _process_directive(self, block: "BlockParser", marker: str, start: int, state: "BlockState") -> Optional[int]: mlen = len(marker) cursor_start = start + len(marker) _end_pattern = ( r"^ {0,3}" + marker[0] + "{" + str(mlen) + r",}" r"[ \t]*(?:\n|$)" ) _end_re = re.compile(_end_pattern, re.M) _end_m = _end_re.search(state.src, cursor_start) if _end_m: text = state.src[cursor_start : _end_m.start()] end_pos = _end_m.end() else: text = state.src[cursor_start:] end_pos = state.cursor_max m = _directive_re.match(text) if not m: return None self.parse_method(block, m, state) return end_pos def parse_directive(self, block: "BlockParser", m: Match[str], state: "BlockState") -> Optional[int]: marker = m.group("fenced_directive_mark") return self._process_directive(block, marker, m.start(), state) def parse_fenced_code(self, block: "BlockParser", m: Match[str], state: "BlockState") -> Optional[int]: info = m.group("fenced_3") if not info or not _type_re.match(info): return block.parse_fenced_code(m, state) if state.depth() >= block.max_nested_level: return block.parse_fenced_code(m, state) marker = m.group("fenced_2") return self._process_directive(block, marker, m.start(), state) def __call__(self, md: "Markdown") -> None: super(FencedDirective, self).__call__(md) if self.markers == "`~": md.block.register("fenced_code", None, self.parse_fenced_code) else: self.register_block_parser(md, "fenced_code") ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/src/mistune/directives/_rst.py����������������������������������������������0000664�0000000�0000000�00000004233�15265371675�0023177�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import re from typing import TYPE_CHECKING, Match, Optional from ._base import BaseDirective, DirectiveParser if TYPE_CHECKING: from ..block_parser import BlockParser from ..core import BlockState from ..markdown import Markdown __all__ = ["RSTDirective"] _directive_re = re.compile( r"\.\.( +)(?P<type>[a-zA-Z0-9_-]+)\:\: *(?P<title>[^\n]*)(?:\n|$)" r"(?P<options>(?: \1 {0,3}\:[a-zA-Z0-9_-]+\: *[^\n]*\n+)*)" r"\n*(?P<text>(?: \1 {0,3}[^\n]*\n+)*)" ) class RSTParser(DirectiveParser): name = "rst_directive" @staticmethod def parse_type(m: Match[str]) -> str: return m.group("type") @staticmethod def parse_title(m: Match[str]) -> str: return m.group("title") @staticmethod def parse_content(m: Match[str]) -> str: text = m.group("text") leading = len(m.group(1)) + 2 return "\n".join(line[leading:] for line in text.splitlines()) + "\n" class RSTDirective(BaseDirective): """A RST style of directive syntax is inspired by reStructuredText. The syntax is very powerful that you can define a lot of custom features on your own. The syntax looks like: .. code-block:: text .. directive-type:: directive value :option-key: option value :option-key: option value content text here To use ``RSTDirective``, developers can add it into plugin list in the :class:`Markdown` instance: .. code-block:: python import mistune from mistune.directives import RSTDirective, Admonition md = mistune.create_markdown(plugins=[ # ... RSTDirective([Admonition()]), ]) """ parser = RSTParser directive_pattern = r"^\.\. +[a-zA-Z0-9_-]+\:\:" def parse_directive(self, block: "BlockParser", m: Match[str], state: "BlockState") -> Optional[int]: m2 = _directive_re.match(state.src, state.cursor) if not m2: return None self.parse_method(block, m2, state) return m2.end() def __call__(self, markdown: "Markdown") -> None: super(RSTDirective, self).__call__(markdown) self.register_block_parser(markdown) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/src/mistune/directives/admonition.py����������������������������������������0000664�0000000�0000000�00000004325�15265371675�0024373�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from typing import TYPE_CHECKING, Any, Dict, Match from ..util import escape as escape_text from ._base import BaseDirective, DirectivePlugin if TYPE_CHECKING: from ..block_parser import BlockParser from ..core import BlockState from ..markdown import Markdown class Admonition(DirectivePlugin): SUPPORTED_NAMES = { "attention", "caution", "danger", "error", "hint", "important", "note", "tip", "warning", } def parse(self, block: "BlockParser", m: Match[str], state: "BlockState") -> Dict[str, Any]: name = self.parse_type(m) attrs = {"name": name} options = dict(self.parse_options(m)) if "class" in options: attrs["class"] = options["class"] title = self.parse_title(m) if not title: title = name.capitalize() content = self.parse_content(m) children = [ { "type": "admonition_title", "text": title, }, { "type": "admonition_content", "children": self.parse_tokens(block, content, state), }, ] return { "type": "admonition", "children": children, "attrs": attrs, } def __call__(self, directive: "BaseDirective", md: "Markdown") -> None: for name in self.SUPPORTED_NAMES: directive.register(name, self.parse) assert md.renderer is not None if md.renderer.NAME == "html": md.renderer.register("admonition", render_admonition) md.renderer.register("admonition_title", render_admonition_title) md.renderer.register("admonition_content", render_admonition_content) def render_admonition(self: Any, text: str, name: str, **attrs: Any) -> str: html = '<section class="admonition ' + name _cls = attrs.get("class") if _cls: html += " " + escape_text(_cls) return html + '">\n' + text + "</section>\n" def render_admonition_title(self: Any, text: str) -> str: return '<p class="admonition-title">' + text + "</p>\n" def render_admonition_content(self: Any, text: str) -> str: return text �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/src/mistune/directives/image.py���������������������������������������������0000664�0000000�0000000�00000013010�15265371675�0023303�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import re from typing import TYPE_CHECKING, Any, Dict, List, Match, Optional from ..util import escape_url from ._base import BaseDirective, DirectivePlugin if TYPE_CHECKING: from ..block_parser import BlockParser from ..core import BlockState from ..markdown import Markdown from ..renderers.html import HTMLRenderer __all__ = ["Image", "Figure"] _num_re = re.compile(r"^\d+(?:\.\d+)?(?:px|ch|em|rem|ex|rex|vw|vh|%)?$") _allowed_aligns = ["top", "middle", "bottom", "left", "center", "right"] def _parse_attrs(options: Dict[str, Any]) -> Dict[str, Any]: attrs = {} if "alt" in options: attrs["alt"] = options["alt"] # validate align align = options.get("align") if align and align in _allowed_aligns: attrs["align"] = align height = options.get("height") width = options.get("width") if height and _num_re.fullmatch(height): attrs["height"] = height if width and _num_re.fullmatch(width): attrs["width"] = width if "target" in options: attrs["target"] = escape_url(options["target"]) return attrs class Image(DirectivePlugin): NAME = "image" def parse(self, block: "BlockParser", m: Match[str], state: "BlockState") -> Dict[str, Any]: options = dict(self.parse_options(m)) attrs = _parse_attrs(options) attrs["src"] = self.parse_title(m) return {"type": "block_image", "attrs": attrs} def __call__(self, directive: "BaseDirective", md: "Markdown") -> None: directive.register(self.NAME, self.parse) assert md.renderer is not None if md.renderer.NAME == "html": md.renderer.register("block_image", render_block_image) def render_block_image( self: "HTMLRenderer", src: str, alt: Optional[str] = None, width: Optional[str] = None, height: Optional[str] = None, **attrs: Any, ) -> str: image_attrs: Dict[str, object] = {"src": self.sanitize_url(src)} style = "" if alt: image_attrs["alt"] = alt if width and _num_re.fullmatch(width): if width.isdigit(): image_attrs["width"] = width else: style += "width:" + width + ";" if height and _num_re.fullmatch(height): if height.isdigit(): image_attrs["height"] = height else: style += "height:" + height + ";" if style: image_attrs["style"] = style img = "<img" + self.render_attrs(image_attrs) + " />" _cls = "block-image" align = attrs.get("align") if align: _cls += " align-" + align target = attrs.get("target") if target: outer = "<a" + self.render_attrs({"class": _cls, "href": self.sanitize_url(target)}) + ">" return outer + img + "</a>\n" else: return "<div" + self.render_attrs({"class": _cls}) + ">" + img + "</div>\n" class Figure(DirectivePlugin): NAME = "figure" def parse_directive_content( self, block: "BlockParser", m: Match[str], state: "BlockState" ) -> Optional[List[Dict[str, Any]]]: content = self.parse_content(m) if not content: return None tokens = list(self.parse_tokens(block, content, state)) caption = tokens[0] if caption["type"] == "paragraph": caption["type"] = "figcaption" children = [caption] if len(tokens) > 1: children.append({"type": "legend", "children": tokens[1:]}) return children return None def parse(self, block: "BlockParser", m: Match[str], state: "BlockState") -> Dict[str, Any]: options = dict(self.parse_options(m)) image_attrs = _parse_attrs(options) image_attrs["src"] = self.parse_title(m) align = image_attrs.pop("align", None) fig_attrs = {} if align: fig_attrs["align"] = align figwidth = options.get("figwidth") if figwidth and _num_re.fullmatch(figwidth): fig_attrs["figwidth"] = figwidth if "figclass" in options: fig_attrs["figclass"] = options["figclass"] children = [{"type": "block_image", "attrs": image_attrs}] content = self.parse_directive_content(block, m, state) if content: children.extend(content) return { "type": "figure", "attrs": fig_attrs, "children": children, } def __call__(self, directive: "BaseDirective", md: "Markdown") -> None: directive.register(self.NAME, self.parse) assert md.renderer is not None if md.renderer.NAME == "html": md.renderer.register("figure", render_figure) md.renderer.register("block_image", render_block_image) md.renderer.register("figcaption", render_figcaption) md.renderer.register("legend", render_legend) def render_figure( self: "HTMLRenderer", text: str, align: Optional[str] = None, figwidth: Optional[str] = None, figclass: Optional[str] = None, ) -> str: _cls = "figure" if align: _cls += " align-" + align if figclass: _cls += " " + figclass figure_attrs: Dict[str, object] = {"class": _cls} if figwidth and _num_re.fullmatch(figwidth): figure_attrs["style"] = "width:" + figwidth return "<figure" + self.render_attrs(figure_attrs) + ">\n" + text + "</figure>\n" def render_figcaption(self: Any, text: str) -> str: return "<figcaption>" + text + "</figcaption>\n" def render_legend(self: Any, text: str) -> str: return '<div class="legend">\n' + text + "</div>\n" ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/src/mistune/directives/include.py�������������������������������������������0000664�0000000�0000000�00000007350�15265371675�0023656�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import os from typing import TYPE_CHECKING, Any, Dict, List, Match, Union from ._base import BaseDirective, DirectivePlugin if TYPE_CHECKING: from ..block_parser import BlockParser from ..core import BlockState from ..markdown import Markdown from ..renderers.html import HTMLRenderer class Include(DirectivePlugin): def parse( self, block: "BlockParser", m: Match[str], state: "BlockState" ) -> Union[Dict[str, Any], List[Dict[str, Any]]]: source_file = state.env.get("__file__") if not source_file: return {"type": "block_error", "raw": "Missing source file"} encoding = "utf-8" options = self.parse_options(m) if options: attrs = dict(options) if "encoding" in attrs: encoding = attrs["encoding"] else: attrs = {} relpath = self.parse_title(m) source_file = os.path.realpath(source_file) source_dir = os.path.dirname(source_file) dest = os.path.realpath(os.path.join(source_dir, relpath)) if os.path.isabs(relpath) or os.path.commonpath([source_dir, dest]) != source_dir: return { "type": "block_error", "raw": "Could not include outside source dir: " + relpath, } if dest == source_file: return { "type": "block_error", "raw": "Could not include self: " + relpath, } include_stack = state.env.setdefault("__include_stack__", []) source_added = False if source_file not in include_stack: include_stack.append(source_file) source_added = True if dest in include_stack: if source_added: include_stack.pop() return { "type": "block_error", "raw": "Could not include circular reference: " + relpath, } if not os.path.isfile(dest): if source_added: include_stack.pop() return { "type": "block_error", "raw": "Could not find file: " + relpath, } include_stack.append(dest) try: with open(dest, "rb") as f: content = f.read().decode(encoding) ext = os.path.splitext(dest)[1] if ext in {".md", ".markdown", ".mkd"}: content = content.replace("\r\n", "\n").replace("\r", "\n") new_state = state.child_state(content) previous_file = new_state.env.get("__file__") new_state.env["__file__"] = dest try: block.parse(new_state) finally: if previous_file is None: new_state.env.pop("__file__", None) else: new_state.env["__file__"] = previous_file return new_state.tokens elif ext in {".html", ".xhtml", ".htm"}: return {"type": "block_html", "raw": content} attrs["filepath"] = dest return { "type": "include", "raw": content, "attrs": attrs, } finally: include_stack.pop() if source_added: include_stack.pop() def __call__(self, directive: BaseDirective, md: "Markdown") -> None: directive.register("include", self.parse) if md.renderer and md.renderer.NAME == "html": md.renderer.register("include", render_html_include) def render_html_include(renderer: "HTMLRenderer", text: str, **attrs: Any) -> str: return '<pre class="directive-include">\n' + renderer.escape_raw(text) + "</pre>\n" ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/src/mistune/directives/toc.py�����������������������������������������������0000664�0000000�0000000�00000007747�15265371675�0023032�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" TOC directive ~~~~~~~~~~~~~ The TOC directive syntax looks like:: .. toc:: Title :min-level: 1 :max-level: 3 "Title", "min-level", and "max-level" option can be empty. "min-level" and "max-level" are integers >= 1 and <= 6, which define the allowed heading levels writers want to include in the table of contents. """ from typing import TYPE_CHECKING, Any, Dict, Match from ..toc import _HeadingIdAllocator, normalize_toc_item, render_toc_ul from ._base import BaseDirective, DirectivePlugin if TYPE_CHECKING: from ..block_parser import BlockParser from ..core import BaseRenderer, BlockState from ..markdown import Markdown class TableOfContents(DirectivePlugin): def __init__(self, min_level: int = 1, max_level: int = 3) -> None: self.min_level = min_level self.max_level = max_level def generate_heading_id(self, token: Dict[str, Any], index: int) -> str: return "toc_" + str(index + 1) def parse(self, block: "BlockParser", m: Match[str], state: "BlockState") -> Dict[str, Any]: title = self.parse_title(m) options = self.parse_options(m) if options: d_options = dict(options) collapse = "collapse" in d_options min_level = _normalize_level(d_options, "min-level", self.min_level) max_level = _normalize_level(d_options, "max-level", self.max_level) if min_level < self.min_level: raise ValueError(f'"min-level" option MUST be >= {self.min_level}') if max_level > self.max_level: raise ValueError(f'"max-level" option MUST be <= {self.max_level}') if min_level > max_level: raise ValueError('"min-level" option MUST be less than "max-level" option') else: collapse = False min_level = self.min_level max_level = self.max_level attrs = { "min_level": min_level, "max_level": max_level, "collapse": collapse, } return {"type": "toc", "text": title or "", "attrs": attrs} def toc_hook(self, md: "Markdown", state: "BlockState") -> None: sections = [] headings = [] for tok in state.tokens: if tok["type"] == "toc": sections.append(tok) elif tok["type"] == "heading": headings.append(tok) if sections: id_allocator = _HeadingIdAllocator(state, headings) toc_items = [] # adding ID for each heading for i, tok in enumerate(headings): if not tok["attrs"].get("id"): id_allocator.assign(tok, self.generate_heading_id(tok, i)) toc_items.append(normalize_toc_item(md, tok, parent=state)) for sec in sections: _min = sec["attrs"]["min_level"] _max = sec["attrs"]["max_level"] toc = [item for item in toc_items if _min <= item[0] <= _max] sec["attrs"]["toc"] = toc def __call__(self, directive: BaseDirective, md: "Markdown") -> None: if md.renderer and md.renderer.NAME == "html": # only works with HTML renderer directive.register("toc", self.parse) md.before_render_hooks.append(self.toc_hook) md.renderer.register("toc", render_html_toc) def render_html_toc(renderer: "BaseRenderer", title: str, collapse: bool = False, **attrs: Any) -> str: if not title: title = "Table of Contents" content = render_toc_ul(attrs["toc"]) html = '<details class="toc"' if not collapse: html += " open" html += ">\n<summary>" + title + "</summary>\n" return html + content + "</details>\n" def _normalize_level(options: Dict[str, Any], name: str, default: Any) -> Any: level = options.get(name) if not level: return default try: return int(level) except (ValueError, TypeError): raise ValueError(f'"{name}" option MUST be integer') �������������������������lepture-mistune-f19057f/src/mistune/helpers.py������������������������������������������������������0000664�0000000�0000000�00000016577�15265371675�0021547�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import re import string from typing import Any, Dict, Tuple, Union from .core import DEFAULT_MAX_NESTED_LEVEL from .util import escape_url PREVENT_BACKSLASH = r"(?<!\\)(?:\\\\)*" PUNCTUATION = r"[" + re.escape(string.punctuation) + r"]" MAX_LINK_LABEL_LENGTH = 999 LINK_LABEL = r"(?=[\s\S]{0,999}\])(?:[^\\\[\]]|\\.){0,999}" ASCII_WHITESPACE = " \t\n\r\f" HTML_TAGNAME = r"[A-Za-z][A-Za-z0-9-]*" HTML_ATTRIBUTES = ( r"(?:\s+[A-Za-z_:][A-Za-z0-9_.:-]*" r'(?:\s*=\s*(?:[^ !"\'=<>`]+|\'[^\']*?\'|"[^\"]*?"))?)*' ) BLOCK_TAGS = ( "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", "meta", "nav", "noframes", "ol", "optgroup", "option", "p", "param", "section", "source", "summary", "table", "tbody", "td", "tfoot", "th", "thead", "title", "tr", "track", "ul", ) PRE_TAGS = ("pre", "script", "style", "textarea") _INLINE_LINK_LABEL_RE = re.compile(LINK_LABEL + r"\]") _INLINE_SQUARE_BRACKET_RE = re.compile(PREVENT_BACKSLASH + r"[\[\]]") _ESCAPE_CHAR_RE = re.compile(r"\\(" + PUNCTUATION + r")") _BLANK_LINE_RE = re.compile(r"\n[ \t]*\n") def unescape_char(text: str) -> str: return _ESCAPE_CHAR_RE.sub(r"\1", text) def parse_link_text(src: str, pos: int) -> Union[Tuple[str, int], Tuple[None, int]]: level = 1 found = False start_pos = pos while pos < len(src): m = _INLINE_SQUARE_BRACKET_RE.search(src, pos) if not m: pos = len(src) # FIX: record we scanned to end break pos = m.end() marker = m.group(0) if marker == "]": level -= 1 if level == 0: found = True break else: level += 1 if found: text = src[start_pos : pos - 1] return text, pos return None, pos # FIX: return pos instead of None def parse_link_label(src: str, start_pos: int) -> Union[Tuple[str, int], Tuple[None, None]]: m = _INLINE_LINK_LABEL_RE.match(src, start_pos, start_pos + MAX_LINK_LABEL_LENGTH + 1) if m: label = m.group(0)[:-1] return label, m.end() return None, None def parse_link_href( src: str, start_pos: int, block: bool = False, *, max_nested_level: int = DEFAULT_MAX_NESTED_LEVEL ) -> Union[Tuple[str, int], Tuple[None, None]]: href, href_pos, _end_pos = _parse_link_href(src, start_pos, block=block, max_nested_level=max_nested_level) if href is None: return None, None assert href_pos is not None return href, href_pos def _parse_link_href( src: str, start_pos: int, block: bool = False, *, max_nested_level: int = DEFAULT_MAX_NESTED_LEVEL ) -> Tuple[Union[str, None], Union[int, None], int]: pos = _skip_link_start_whitespace(src, start_pos) if pos >= len(src): return None, None, pos if src[pos] == "<": href, href_pos = _parse_angle_link_href(src, pos) if href is None: return None, None, pos assert href_pos is not None return href, href_pos, href_pos if block and src[pos] in ASCII_WHITESPACE: return None, None, pos start = pos level = 0 while pos < len(src): c = src[pos] if c in ASCII_WHITESPACE: break if ord(c) < 32 or c == "\x7f": return None, None, pos if c == "\\" and pos + 1 < len(src) and src[pos + 1] in string.punctuation: pos = min(pos + 2, len(src)) continue if c == "(": level += 1 if level > max_nested_level: return None, None, pos elif c == ")": if level == 0: break level -= 1 pos += 1 if level != 0: return None, None, pos return src[start:pos], pos, pos def parse_link_title(src: str, start_pos: int, max_pos: int) -> Union[Tuple[str, int], Tuple[None, None]]: pos = start_pos if pos >= max_pos or src[pos] not in ASCII_WHITESPACE: return None, None pos = _skip_ascii_whitespace(src, pos, max_pos) if pos >= max_pos: return None, None opener = src[pos] closer = {"'": "'", '"': '"', "(": ")"}.get(opener) if closer is None: return None, None pos += 1 title = [] while pos < max_pos: c = src[pos] if c == "\x00" or (opener == "(" and c == "("): return None, None if c == "\n" and _BLANK_LINE_RE.match(src, pos, max_pos): return None, None if c == "\\": if pos + 1 < max_pos and src[pos + 1] in string.punctuation: title.append(src[pos : pos + 2]) pos += 2 continue if c == closer: return unescape_char("".join(title)), pos + 1 title.append(src[pos]) pos += 1 return None, None def parse_link( src: str, pos: int, *, max_nested_level: int = DEFAULT_MAX_NESTED_LEVEL ) -> Union[Tuple[Dict[str, Any], int], Tuple[None, None]]: attrs, next_pos, _end_pos = parse_link_with_end(src, pos, max_nested_level=max_nested_level) if attrs is None: return None, None assert next_pos is not None return attrs, next_pos def parse_link_with_end( src: str, pos: int, *, max_nested_level: int = DEFAULT_MAX_NESTED_LEVEL ) -> Tuple[Union[Dict[str, Any], None], Union[int, None], int]: href, href_pos, scan_end = _parse_link_href(src, pos, max_nested_level=max_nested_level) if href is None: return None, None, scan_end assert href_pos is not None title, title_pos = parse_link_title(src, href_pos, len(src)) next_pos = title_pos or href_pos next_pos = _skip_ascii_whitespace(src, next_pos) if next_pos >= len(src) or src[next_pos] != ")": return None, None, next_pos href = unescape_char(href) attrs = {"url": escape_url(href)} if title: attrs["title"] = title return attrs, next_pos + 1, next_pos + 1 def _skip_ascii_whitespace(src: str, pos: int, max_pos: Union[int, None] = None) -> int: if max_pos is None: max_pos = len(src) while pos < max_pos and src[pos] in ASCII_WHITESPACE: pos += 1 return pos def _skip_link_start_whitespace(src: str, pos: int) -> int: while pos < len(src) and src[pos] in " \t": pos += 1 if pos < len(src) and src[pos] in "\n\r": if src[pos] == "\r" and pos + 1 < len(src) and src[pos + 1] == "\n": pos += 2 else: pos += 1 while pos < len(src) and src[pos] in " \t": pos += 1 return pos def _parse_angle_link_href(src: str, pos: int) -> Union[Tuple[str, int], Tuple[None, None]]: start = pos + 1 pos = start while pos < len(src): c = src[pos] if c == ">": return src[start:pos], pos + 1 if c == "\\" and pos + 1 < len(src) and src[pos + 1] in string.punctuation: pos += 2 continue if c in "<\n\r\x00": return None, None pos += 1 return None, None ���������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/src/mistune/inline_parser.py������������������������������������������������0000664�0000000�0000000�00000035246�15265371675�0022731�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations import re from typing import Any, Dict, Iterable, List, Match, MutableMapping, Optional, Set, Tuple, Union from ._inline.emphasis import finalize_emphasis_tokens from ._inline.links import parse_link_close, parse_link_open from .core import DEFAULT_MAX_NESTED_LEVEL, InlineState, Parser from .helpers import HTML_ATTRIBUTES, HTML_TAGNAME, PUNCTUATION, unescape_char from .util import escape_url DEFAULT_MAX_EMPHASIS_DEPTH = DEFAULT_MAX_NESTED_LEVEL DEFAULT_MAX_IMAGE_DEPTH = DEFAULT_MAX_NESTED_LEVEL _KNOWN_RULE_START_CHARS = { "escape": {"\\"}, "codespan": {"`"}, "emphasis": {"*", "_"}, "link": {"!", "["}, "link_close": {"]"}, "auto_link": {"<"}, "auto_email": {"<"}, "inline_html": {"<"}, "linebreak": {"\n"}, "softbreak": {"\n"}, "prec_auto_link": {"<"}, "prec_inline_html": {"<"}, # built-in plugins "url_link": {"h"}, "strikethrough": {"~"}, "mark": {"="}, "insert": {"^"}, "superscript": {"^"}, "subscript": {"~"}, "footnote": {"["}, "inline_math": {"$"}, "ruby": {"["}, "inline_spoiler": {">"}, } AUTO_EMAIL = ( r"""<[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9]""" r"(?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?" r"(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*>" ) _HTML_DECLARATION_START = re.compile(r"<![A-Z]+[ \t\n\r\f]") _INLINE_HTML_TAG = re.compile(r"<" + HTML_TAGNAME + HTML_ATTRIBUTES + r"\s*/?>|</" + HTML_TAGNAME + r"\s*>") class InlineParser(Parser[InlineState]): sc_flag = 0 state_cls = InlineState #: linebreak leaves two spaces at the end of line STD_LINEBREAK = r"(?:\\| {2,})\n\s*" #: every new line becomes <br> HARD_LINEBREAK = r" *\n\s*" # we only need to find the start pattern of an inline token SPECIFICATION = { # e.g. \`, \$ "escape": r"(?:\\" + PUNCTUATION + ")+", # `code, ```code "codespan": r"`{1,}", # *w, **w, _w, __w "emphasis": r"[*_]+", # [link], ![img] "link": r"!?\[", "link_close": r"\]+", # <https://example.com>. regex copied from commonmark.js "auto_link": r"<[A-Za-z][A-Za-z0-9.+-]{1,31}:[^<>\x00-\x20]*>", "auto_email": AUTO_EMAIL, "inline_html": r"<(?:/?[A-Za-z]|!|\?)", "linebreak": STD_LINEBREAK, "softbreak": HARD_LINEBREAK, "prec_auto_link": r"<[A-Za-z][A-Za-z\d.+-]{1,31}:", "prec_inline_html": r"</?" + HTML_TAGNAME + r"|<!|<\?", } DEFAULT_RULES = ( "escape", "codespan", "emphasis", "link", "link_close", "auto_link", "auto_email", "inline_html", "linebreak", ) def __init__( self, hard_wrap: bool = False, max_emphasis_depth: Optional[int] = None, max_image_depth: Optional[int] = None, *, max_nested_level: int = DEFAULT_MAX_NESTED_LEVEL, ) -> None: super(InlineParser, self).__init__() self.hard_wrap = hard_wrap # Older keyword names configure the same bound, rather than independent # per-token budgets that can be bypassed by alternating syntax types. limits = [max_nested_level] + [value for value in (max_emphasis_depth, max_image_depth) if value is not None] self.max_nested_level = min(limits) self._fast_trigger_chars: Optional[Set[str]] = None self._fast_trigger_re: Optional[re.Pattern[str]] = None self._fast_trigger_re_chars: Optional[Tuple[str, ...]] = None self._rule_start_chars: Dict[str, Set[str]] = {} # lazy add linebreak if hard_wrap: self.specification["linebreak"] = self.HARD_LINEBREAK else: self.rules.append("softbreak") self._methods = {name: getattr(self, "parse_" + name) for name in self.rules} @property def max_nested_level(self) -> int: return self._max_nested_level @max_nested_level.setter def max_nested_level(self, value: int) -> None: if value < 1: raise ValueError("max_nested_level must be positive") self._max_nested_level = value @property def max_emphasis_depth(self) -> int: return self.max_nested_level @max_emphasis_depth.setter def max_emphasis_depth(self, value: int) -> None: self.max_nested_level = value @property def max_image_depth(self) -> int: return self.max_nested_level @max_image_depth.setter def max_image_depth(self, value: int) -> None: self.max_nested_level = value def register( self, name: str, pattern: Optional[str], func: Any, before: Optional[str] = None, *, start_chars: Optional[Union[str, Iterable[str]]] = None, ) -> None: """Register an inline rule with optional exhaustive start characters.""" self._rule_start_chars.pop(name, None) if start_chars is not None: self._rule_start_chars[name] = _normalize_start_chars(start_chars) super().register(name, pattern, func, before=before) self._fast_trigger_chars = None self._fast_trigger_re = None self._fast_trigger_re_chars = None def parse_escape(self, m: Match[str], state: InlineState) -> int: text = m.group(0) text = unescape_char(text) self.process_text(text, state, parse_emphasis=False) return m.end() def parse_link(self, m: Match[str], state: InlineState) -> Optional[int]: return parse_link_open(self, m, state) def parse_link_close(self, m: Match[str], state: InlineState) -> int: return parse_link_close(self, m, state) def parse_auto_link(self, m: Match[str], state: InlineState) -> int: text = m.group(0) pos = m.end() if state.in_link or state.depth >= self.max_nested_level: self.process_text(text, state) return pos text = text[1:-1] self._add_auto_link(text, text, state) return pos def parse_auto_email(self, m: Match[str], state: InlineState) -> int: text = m.group(0) pos = m.end() if state.in_link or state.depth >= self.max_nested_level: self.process_text(text, state) return pos text = text[1:-1] url = "mailto:" + text self._add_auto_link(url, text, state) return pos def _add_auto_link(self, url: str, text: str, state: InlineState) -> None: state.append_token( { "type": "link", "children": [{"type": "text", "raw": text}], "attrs": {"url": escape_url(url)}, "_autolink": "<" + text + ">", } ) def parse_emphasis(self, m: Match[str], state: InlineState) -> int: # Delimiter flanking and matching are resolved together after scanning. self.process_text(m.group(0), state) return m.end() def parse_codespan(self, m: Match[str], state: InlineState) -> int: marker = m.group(0) pos = m.end() end = state.delimiters.code_end(marker, pos) if end is None: state.append_token({"type": "text", "raw": marker}) return pos code = state.src[pos:end].replace("\n", " ") if code.strip(" ") and code.startswith(" ") and code.endswith(" "): code = code[1:-1] state.append_token({"type": "codespan", "raw": code}) return end + len(marker) def parse_linebreak(self, m: Match[str], state: InlineState) -> int: state.append_token({"type": "linebreak"}) return m.end() def parse_softbreak(self, m: Match[str], state: InlineState) -> int: state.append_token({"type": "softbreak"}) return m.end() def parse_inline_html(self, m: Match[str], state: InlineState) -> Optional[int]: start = m.start() src = state.src if src.startswith("<!-->", start): end_pos = start + 5 elif src.startswith("<!--->", start): end_pos = start + 6 else: marker = None offset = 0 if src.startswith("<!--", start): marker, offset = "-->", 4 elif src.startswith("<?", start): marker, offset = "?>", 2 elif src.startswith("<![CDATA[", start): marker, offset = "]]>", 9 elif src.startswith("<!", start): declaration = _HTML_DECLARATION_START.match(src, start) if declaration is None: return None marker, offset = ">", declaration.end() - start if marker is not None: close = state.delimiters.find(marker, start + offset) if close is None: return None end_pos = close + len(marker) else: tag = _INLINE_HTML_TAG.match(src, start) if tag is None: return None end_pos = tag.end() html = src[start:end_pos] state.append_token({"type": "inline_html", "raw": html}) if html.startswith(("<a ", "<a>", "<A ", "<A>")): state.in_link = True elif html.startswith(("</a ", "</a>", "</A ", "</A>")): state.in_link = False return end_pos def process_text(self, text: str, state: InlineState, parse_emphasis: bool = True) -> None: token: Dict[str, Any] = {"type": "text", "raw": text} if not parse_emphasis: token["_emphasis"] = False state.append_token(token) def parse(self, state: InlineState) -> List[Dict[str, Any]]: pos = 0 sc = self.compile_sc() while pos < len(state.src): fast_end = self._find_fast_text_end(state.src, pos) if fast_end is None: m = sc.search(state.src, pos) else: if fast_end > pos: self.process_text(state.src[pos:fast_end], state) pos = fast_end if pos >= len(state.src): break m = sc.match(state.src, pos) if not m: if fast_end is not None: self.process_text(state.src[pos : pos + 1], state) pos += 1 continue break end_pos = m.start() if end_pos > pos: hole = state.src[pos:end_pos] self.process_text(hole, state) new_pos = self.parse_method(m, state) if not new_pos: # move cursor 1 character forward pos = end_pos + 1 hole = state.src[end_pos:pos] self.process_text(hole, state) else: pos = new_pos if pos == 0: # special case, just pure text self.process_text(state.src, state) elif pos < len(state.src): self.process_text(state.src[pos:], state) state.tokens = self.finalize_tokens(state.tokens, state.depth) return state.tokens def finalize_tokens(self, tokens: List[Dict[str, Any]], depth: int) -> List[Dict[str, Any]]: remaining = self.max_nested_level - depth return finalize_emphasis_tokens(tokens, "emphasis" in self.rules and remaining > 0, remaining) def _find_fast_text_end(self, src: str, pos: int) -> Optional[int]: chars = self._get_fast_trigger_chars() if chars is None: return None trigger_re = self._get_fast_trigger_re(chars) m = trigger_re.search(src, pos) if m is None: return len(src) if m.group(0) == "\n": return self._find_linebreak_start(src, pos, m.start()) return m.start() def _get_fast_trigger_re(self, chars: Set[str]) -> re.Pattern[str]: key = tuple(sorted(chars)) if self._fast_trigger_re is None or self._fast_trigger_re_chars != key: pattern = "[" + re.escape("".join(key)) + "]" self._fast_trigger_re = re.compile(pattern) self._fast_trigger_re_chars = key assert self._fast_trigger_re is not None return self._fast_trigger_re def _find_linebreak_start(self, src: str, min_pos: int, newline_pos: int) -> int: pos = newline_pos while pos > min_pos and src[pos - 1] == " ": pos -= 1 if pos == newline_pos and pos > min_pos and src[pos - 1] == "\\": return pos - 1 return pos def _get_fast_trigger_chars(self) -> Optional[Set[str]]: chars = self._fast_trigger_chars if chars is not None: return chars chars = set() for name in self.rules: rule_chars = self._rule_start_chars.get(name, _KNOWN_RULE_START_CHARS.get(name)) if rule_chars is None: self._fast_trigger_chars = None return None chars.update(rule_chars) self._fast_trigger_chars = chars return chars def precedence_scan( self, m: Match[str], state: InlineState, end_pos: int, rules: Optional[List[str]] = None, ) -> Optional[int]: if rules is None: rules = ["codespan", "link", "prec_auto_link", "prec_inline_html"] mark_pos = m.end() sc = self.compile_sc(rules) m1 = sc.search(state.src, mark_pos, end_pos) if not m1: return None lastgroup = m1.lastgroup if not lastgroup: return None rule_name = lastgroup.replace("prec_", "") sc = self.compile_sc([rule_name]) m2 = sc.match(state.src, m1.start()) if not m2: return None func = self._methods[rule_name] new_state = state.copy() new_state.src = state.src m2_pos = func(m2, new_state) if not m2_pos or m2_pos < end_pos: return None raw_text = state.src[m.start() : m2.start()] state.append_token({"type": "text", "raw": raw_text}) for token in new_state.tokens: state.append_token(token) return m2_pos def render(self, state: InlineState) -> List[Dict[str, Any]]: self.parse(state) return state.tokens def __call__(self, s: str, env: MutableMapping[str, Any]) -> List[Dict[str, Any]]: state = self.state_cls(env) state.src = s return self.render(state) def _normalize_start_chars(start_chars: Union[str, Iterable[str]]) -> Set[str]: if isinstance(start_chars, str): values = [start_chars] else: values = list(start_chars) if not values or any(not isinstance(value, str) or len(value) != 1 for value in values): raise ValueError("start_chars must contain one or more single-character strings") return set(values) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/src/mistune/list_parser.py��������������������������������������������������0000664�0000000�0000000�00000026634�15265371675�0022427�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������"""because list is complex, split list parser in a new file""" from __future__ import annotations import re from dataclasses import dataclass from typing import TYPE_CHECKING, Any, Iterable, Match, Optional, Pattern, cast from .util import strip_end if TYPE_CHECKING: from .block_parser import BlockParser from .core import BlockState LIST_PATTERN = ( r"^(?P<list_1> {0,3})" r"(?P<list_2>[\*\+-]|\d{1,9}[.)])" r"(?P<list_3>[ \t]*|[ \t].+)$" ) _LINE_HAS_TEXT = re.compile(r"(\s*)\S") @dataclass class _ListMarker: spaces: str marker: str text: str @property def leading_width(self) -> int: return len(self.spaces) + len(self.marker) @property def bullet(self) -> str: return self.marker[-1] @property def ordered(self) -> bool: return len(self.marker) > 1 @dataclass class _ListItemLines: src: str next_item: Optional[_ListMarker] = None loose: bool = False end_pos: Optional[int] = None token_index: Optional[int] = None def parse_list(block: "BlockParser", m: Match[str], state: "BlockState") -> int: """Parse tokens for ordered and unordered list.""" item = _create_list_marker(m, "list") text = item.text if not text.strip(): # Example 285 # an empty list item cannot interrupt a paragraph end_pos = state.append_paragraph() if end_pos: return end_pos marker = item.marker depth = state.depth() token: dict[str, Any] = { "type": "list", "children": [], "tight": True, "bullet": item.bullet, "attrs": { "depth": depth, "ordered": item.ordered, }, } if item.ordered: start = int(marker[:-1]) if start != 1: # Example 304 # we allow only lists starting with 1 to interrupt paragraphs end_pos = state.append_paragraph() if end_pos: return end_pos token["attrs"]["start"] = start state.cursor = m.end() + 1 item_or_none: Optional[_ListMarker] = item if depth >= block.max_nested_level - 1: # At the nesting limit, stop descending into any further container # blocks. Trimming only "list" still allowed lists and block quotes to # recurse into each other without bound (RecursionError). rules = [rule for rule in block.list_rules if rule not in ("list", "block_quote")] else: rules = block.list_rules bullet = _get_list_bullet(item.bullet) while item_or_none: item_or_none = _parse_list_item(block, bullet, item_or_none, token, state, rules) end_pos = cast(Optional[int], token.pop("_end_pos", None)) _transform_tight_list(token) if end_pos: index = cast(int, token.pop("_tok_index")) state.tokens.insert(index, token) return end_pos state.append_token(token) return state.cursor def _transform_tight_list(token: dict[str, Any]) -> None: if token["tight"]: # reset tight list item for list_item in token["children"]: for tok in list_item["children"]: if tok["type"] == "paragraph": tok["type"] = "block_text" elif tok["type"] == "list": _transform_tight_list(tok) def _parse_list_item( block: "BlockParser", bullet: str, item: _ListMarker, token: dict[str, Any], state: "BlockState", rules: list[str], ) -> _ListMarker | None: text = item.text leading_width = item.leading_width text, continue_width = _compile_continue_width(text, leading_width) list_item_re = re.compile(_compile_list_item_pattern(bullet, leading_width)) break_sc = _compile_list_break_sc(block, leading_width) lines = _collect_list_item_lines(block, list_item_re, break_sc, state, text, continue_width) if lines.loose: token["tight"] = False if lines.end_pos is not None: token["_tok_index"] = lines.token_index token["_end_pos"] = lines.end_pos child = state.child_state(_build_list_item_source(text, lines.src, continue_width)) block.parse(child, rules) if token["tight"] and _is_loose_list(child.tokens): token["tight"] = False token["children"].append( { "type": "list_item", "children": child.tokens, } ) if lines.next_item: return lines.next_item return None def _collect_list_item_lines( block: "BlockParser", list_item_re: Pattern[str], break_sc: Pattern[str], state: "BlockState", text: str, continue_width: int, ) -> _ListItemLines: src = "" next_item = None prev_blank_line = False while state.cursor < state.cursor_max: raw_line = state.get_line(state.cursor) next_pos = state.cursor + len(raw_line) if block.BLANK_LINE.match(raw_line): src += "\n" prev_blank_line = True state.cursor = next_pos continue has_continuation = _has_continuation_indent(raw_line, continue_width) if has_continuation: if prev_blank_line and not text and not src.strip(): # Example 280 # A list item can begin with at most one blank line break src += raw_line prev_blank_line = False state.cursor = next_pos continue line = _expand_leading_tabs(raw_line) line_break = _match_list_item_break(list_item_re, break_sc, state, line) if line_break: tok_type, m = line_break if tok_type == "list_item": next_item = _create_list_marker(m, "listitem") state.cursor = next_pos return _ListItemLines(src, next_item=next_item, loose=prev_blank_line) if tok_type == "list": break tok_index = len(state.tokens) end_pos = block.parse_method(m, state) if end_pos: return _ListItemLines(src, end_pos=end_pos, token_index=tok_index) if prev_blank_line and not has_continuation: # not a continue line, and previous line is blank break src += raw_line state.cursor = next_pos return _ListItemLines(src) def _create_list_marker(m: Match[str], prefix: str) -> _ListMarker: return _ListMarker( spaces=m.group(prefix + "_1"), marker=m.group(prefix + "_2"), text=m.group(prefix + "_3"), ) def _build_list_item_source(text: str, src: str, continue_width: int) -> str: text += _clean_list_item_text(src, continue_width) return strip_end(text) def _compile_list_break_sc(block: "BlockParser", leading_width: int) -> Pattern[str]: pairs = [(name, block.specification[name]) for name in _get_list_break_rules(block)] if leading_width < 3: # Relax the leading indent bound only. Matching on a bare "3" would # rewrite the first quantifier of any rule that has no indent prefix -- # e.g. a fenced directive's "{3,}" marker run. _repl = " {0,%d}" % leading_width pairs = [(n, p.replace(" {0,3}", _repl, 1)) for n, p in pairs] regex = "|".join(r"(?P<%s>(?<=\n)%s)" % pair for pair in pairs) return re.compile(regex, re.M) def _get_list_break_rules(block: "BlockParser") -> list[str]: rules = [ "thematic_break", "fenced_code", "atx_heading", "block_quote", "block_html", "list", ] if "fenced_directive" in block.specification: rules.insert(1, "fenced_directive") return rules def _match_list_item_break( list_item_re: Pattern[str], break_sc: Pattern[str], state: "BlockState", line: str, ) -> tuple[str, Match[str]] | None: m = break_sc.match(state.src, state.cursor) if m and m.lastgroup == "thematic_break": return "thematic_break", m m2 = list_item_re.match(line) if m2: return "list_item", m2 if m: tok_type = m.lastgroup assert tok_type is not None return tok_type, m return None def _get_list_bullet(c: str) -> str: if c == ".": bullet = r"\d{1,9}\." elif c == ")": bullet = r"\d{1,9}\)" elif c == "*": bullet = r"\*" elif c == "+": bullet = r"\+" else: bullet = "-" return bullet def _compile_list_item_pattern(bullet: str, leading_width: int) -> str: if leading_width > 3: leading_width = 3 return ( r"^(?P<listitem_1> {0," + str(leading_width) + "})" r"(?P<listitem_2>" + bullet + ")" r"(?P<listitem_3>[ \t]*|[ \t][^\n]+)$" ) def _compile_continue_width(text: str, leading_width: int) -> tuple[str, int]: text = _expand_leading_tabs(text, leading_width) m2 = _LINE_HAS_TEXT.match(text) if m2: # indent code, startswith 5 spaces indent = _count_indent(text) if indent >= 5: space_width = 1 else: space_width = indent text = text[space_width:] + "\n" else: space_width = 1 text = "" continue_width = leading_width + space_width return text, continue_width def _clean_list_item_text(src: str, continue_width: int) -> str: rv = [] lines = src.split("\n") for line in lines: if _has_continuation_indent(line, continue_width): rv.append(_strip_continuation_indent(line, continue_width)) else: rv.append(_expand_leading_tabs(line)) return "\n".join(rv) def _has_continuation_indent(line: str, columns: int) -> bool: width = 0 for char in line: if char == " ": width += 1 elif char == "\t": width += 4 - width % 4 else: break if width >= columns: return True return False def _strip_continuation_indent(line: str, columns: int) -> str: width = 0 index = 0 while index < len(line) and width < columns: char = line[index] if char == " ": width += 1 elif char == "\t": width += 4 - width % 4 else: break index += 1 if width < columns: return "" prefix = " " * (width - columns) if index < len(line) and line[index] == " ": if "\t" not in line[index:]: return prefix + line[index:] elif index == len(line) or line[index] != "\t": return prefix + line[index:] return prefix + _expand_leading_tabs(line[index:], width) def _expand_leading_tabs(line: str, start_column: int = 0) -> str: column = start_column parts = [] index = 0 while index < len(line): c = line[index] if c == " ": parts.append(" ") column += 1 elif c == "\t": size = 4 - column % 4 parts.append(" " * size) column += size else: break index += 1 return "".join(parts) + line[index:] def _count_indent(text: str) -> int: column = 0 for c in text: if c == " ": column += 1 elif c == "\t": column += 4 - column % 4 else: break return column def _is_loose_list(tokens: Iterable[dict[str, Any]]) -> bool: paragraph_count = 0 for tok in tokens: if tok["type"] == "blank_line": return True if tok["type"] == "paragraph": paragraph_count += 1 if paragraph_count > 1: return True return False ����������������������������������������������������������������������������������������������������lepture-mistune-f19057f/src/mistune/markdown.py�����������������������������������������������������0000664�0000000�0000000�00000010047�15265371675�0021711�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Union from .block_parser import BlockParser from .core import BaseRenderer, BlockState from .inline_parser import InlineParser from .plugins import Plugin class Markdown: """Markdown instance to convert markdown text into HTML or other formats. Here is an example with the HTMLRenderer:: from mistune import HTMLRenderer md = Markdown(renderer=HTMLRenderer(escape=False)) md('hello **world**') :param renderer: a renderer to convert parsed tokens :param block: block level syntax parser :param inline: inline level syntax parser :param plugins: mistune plugins to use """ def __init__( self, renderer: Optional[BaseRenderer] = None, block: Optional[BlockParser] = None, inline: Optional[InlineParser] = None, plugins: Optional[Iterable[Plugin]] = None, ): if block is None: block = BlockParser() if inline is None else BlockParser(max_nested_level=inline.max_nested_level) if inline is None: inline = InlineParser(max_nested_level=block.max_nested_level) self.renderer = renderer self.block: BlockParser = block self.inline: InlineParser = inline self.before_parse_hooks: List[Callable[["Markdown", BlockState], None]] = [] self.before_render_hooks: List[Callable[["Markdown", BlockState], Any]] = [] self.after_render_hooks: List[ Callable[["Markdown", Union[str, List[Dict[str, Any]]], BlockState], Union[str, List[Dict[str, Any]]]] ] = [] if plugins: for plugin in plugins: plugin(self) def use(self, plugin: Plugin) -> None: plugin(self) def render_state(self, state: BlockState) -> Union[str, List[Dict[str, Any]]]: data = self._iter_render(state.tokens, state) if self.renderer: return self.renderer(data, state) return list(data) def _iter_render(self, tokens: Iterable[Dict[str, Any]], state: BlockState) -> Iterable[Dict[str, Any]]: for tok in tokens: if "children" in tok: children = self._iter_render(tok["children"], state) tok["children"] = list(children) elif "text" in tok: text = tok.pop("text") # process inline text # avoid striping emsp or other unicode spaces tok["children"] = self.inline(text.strip(" \r\n\t\f"), state.env) yield tok def parse(self, s: str, state: Optional[BlockState] = None) -> Tuple[Union[str, List[Dict[str, Any]]], BlockState]: """Parse and convert the given markdown string. If renderer is None, the returned **result** will be parsed markdown tokens. :param s: markdown string :param state: instance of BlockState :returns: result, state """ if state is None: state = self.block.state_cls() # normalize line separator s = s.replace("\r\n", "\n") s = s.replace("\r", "\n") if not s.endswith("\n"): s += "\n" state.process(s) for hook in self.before_parse_hooks: hook(self, state) self.block.parse(state) for hook2 in self.before_render_hooks: hook2(self, state) result = self.render_state(state) for hook3 in self.after_render_hooks: result = hook3(self, result, state) return result, state def read( self, filepath: str, encoding: str = "utf-8", state: Optional[BlockState] = None ) -> Tuple[Union[str, List[Dict[str, Any]]], BlockState]: if state is None: state = self.block.state_cls() state.env["__file__"] = filepath with open(filepath, "rb") as f: s = f.read() s2 = s.decode(encoding) return self.parse(s2, state) def __call__(self, s: str) -> Union[str, List[Dict[str, Any]]]: if s is None: s = "\n" return self.parse(s)[0] �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/src/mistune/plugins/��������������������������������������������������������0000775�0000000�0000000�00000000000�15265371675�0021174�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/src/mistune/plugins/__init__.py���������������������������������������������0000664�0000000�0000000�00000003042�15265371675�0023304�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from importlib import import_module from typing import TYPE_CHECKING, Dict, Protocol, Union, cast if TYPE_CHECKING: from ..markdown import Markdown _plugins = { "speedup": "mistune.plugins.speedup.speedup", "strikethrough": "mistune.plugins.formatting.strikethrough", "mark": "mistune.plugins.formatting.mark", "insert": "mistune.plugins.formatting.insert", "superscript": "mistune.plugins.formatting.superscript", "subscript": "mistune.plugins.formatting.subscript", "footnotes": "mistune.plugins.footnotes.footnotes", "table": "mistune.plugins.table.table", "url": "mistune.plugins.url.url", "abbr": "mistune.plugins.abbr.abbr", "def_list": "mistune.plugins.def_list.def_list", "math": "mistune.plugins.math.math", "ruby": "mistune.plugins.ruby.ruby", "task_lists": "mistune.plugins.task_lists.task_lists", "spoiler": "mistune.plugins.spoiler.spoiler", } class Plugin(Protocol): def __call__(self, md: "Markdown") -> None: ... _cached_modules: Dict[str, Plugin] = {} PluginRef = Union[str, Plugin] # reference to register a plugin def import_plugin(name: PluginRef) -> Plugin: if callable(name): return name if name in _cached_modules: return _cached_modules[name] if name in _plugins: module_path, func_name = _plugins[name].rsplit(".", 1) else: module_path, func_name = name.rsplit(".", 1) module = import_module(module_path) plugin = cast(Plugin, getattr(module, func_name)) _cached_modules[name] = plugin return plugin ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/src/mistune/plugins/abbr.py�������������������������������������������������0000664�0000000�0000000�00000010374�15265371675�0022461�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import re import types from typing import TYPE_CHECKING, List, Match, Tuple from ..helpers import PREVENT_BACKSLASH from ..util import escape if TYPE_CHECKING: from ..block_parser import BlockParser from ..core import BaseRenderer, BlockState, InlineState from ..inline_parser import InlineParser from ..markdown import Markdown __all__ = ["abbr"] TextSegment = Tuple[str, bool] # https://michelf.ca/projects/php-markdown/extra/#abbr REF_ABBR = ( r"^ {0,3}\*\[(?P<abbr_key>[^\]]+)" + PREVENT_BACKSLASH + r"\]:" r"(?P<abbr_text>(?:[ \t]*\n(?: {3,}|\t)[^\n]+)|(?:[^\n]*))$" ) def parse_ref_abbr(block: "BlockParser", m: Match[str], state: "BlockState") -> int: ref = state.env.get("ref_abbrs") if not ref: ref = {} key = m.group("abbr_key") text = m.group("abbr_text") ref[key] = text.strip() state.env["ref_abbrs"] = ref # abbr definition can split paragraph state.append_token({"type": "blank_line"}) return m.end() + 1 def _append_text( inline: "InlineParser", text: str, state: "InlineState", parse_emphasis: bool, ) -> None: type(inline).process_text(inline, text, state, parse_emphasis=parse_emphasis) def _append_text_segments( inline: "InlineParser", segments: List[TextSegment], state: "InlineState", start: int, end: int, ) -> None: offset = 0 for value, parse_emphasis in segments: next_offset = offset + len(value) if start < next_offset and end > offset: part_start = max(start - offset, 0) part_end = min(end - offset, len(value)) _append_text(inline, value[part_start:part_end], state, parse_emphasis) offset = next_offset def process_text( inline: "InlineParser", text: str, state: "InlineState", parse_emphasis: bool = True, ) -> None: ref = state.env.get("ref_abbrs") if not ref or state.depth >= inline.max_nested_level: return _append_text(inline, text, state, parse_emphasis) segments: List[TextSegment] = [] if state.tokens: last = state.tokens[-1] if last["type"] == "text": state.tokens.pop() segments.append((last["raw"], last.get("_emphasis", True))) segments.append((text, parse_emphasis)) text = "".join(value for value, _ in segments) abbrs_re = state.env.get("abbrs_re") if not abbrs_re: abbrs_re = re.compile(r"|".join(re.escape(k) for k in sorted(ref, key=len, reverse=True))) state.env["abbrs_re"] = abbrs_re pos = 0 while pos < len(text): m = abbrs_re.search(text, pos) if not m: break end_pos = m.start() if end_pos > pos: _append_text_segments(inline, segments, state, pos, end_pos) label = m.group(0) state.append_token( {"type": "abbr", "children": [{"type": "text", "raw": label}], "attrs": {"title": ref[label]}} ) pos = m.end() if pos == 0: # special case, just pure text _append_text_segments(inline, segments, state, 0, len(text)) elif pos < len(text): _append_text_segments(inline, segments, state, pos, len(text)) def render_abbr(renderer: "BaseRenderer", text: str, title: str) -> str: if not title: return "<abbr>" + text + "</abbr>" return '<abbr title="' + escape(title) + '">' + text + "</abbr>" def abbr(md: "Markdown") -> None: """A mistune plugin to support abbreviations, spec defined at https://michelf.ca/projects/php-markdown/extra/#abbr Here is an example: .. code-block:: text The HTML specification is maintained by the W3C. *[HTML]: Hyper Text Markup Language *[W3C]: World Wide Web Consortium It will be converted into HTML: .. code-block:: html The <abbr title="Hyper Text Markup Language">HTML</abbr> specification is maintained by the <abbr title="World Wide Web Consortium">W3C</abbr>. :param md: Markdown instance """ md.block.register("ref_abbr", REF_ABBR, parse_ref_abbr, before="paragraph") # replace process_text md.inline.process_text = types.MethodType(process_text, md.inline) # type: ignore[method-assign] if md.renderer and md.renderer.NAME == "html": md.renderer.register("abbr", render_abbr) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/src/mistune/plugins/def_list.py���������������������������������������������0000664�0000000�0000000�00000013225�15265371675�0023342�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import re from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Match, Optional, Tuple from ..util import strip_end if TYPE_CHECKING: from ..block_parser import BlockParser from ..core import BaseRenderer, BlockState from ..markdown import Markdown __all__ = ["def_list"] # https://michelf.ca/projects/php-markdown/extra/#def-list DEF_PATTERN = r"^ {0,3}:[ \t]+.*(?:\n|$)" DD_START_RE = re.compile(r"^ {0,3}:[ \t]+", re.M) DD_MARKER_RE = re.compile(r"^ {0,3}:[ \t]") TRIM_RE = re.compile(r"^ {0,4}", re.M) HAS_BLANK_LINE_RE = re.compile(r"\n[ \t]*\n$") def parse_def_list(block: "BlockParser", m: Match[str], state: "BlockState") -> Optional[int]: head = _get_previous_paragraph(state) if head is None: return None definitions, end_pos = _collect_definitions(state.src, state.cursor, state.cursor_max, head[1]) if not definitions: return None children = list(_parse_def_item(block, head[0], definitions)) _replace_previous_paragraph(state, children) return end_pos def _parse_def_item( block: "BlockParser", head: str, definitions: List[Tuple[str, bool]], ) -> Iterable[Dict[str, Any]]: for line in head.splitlines(): yield { "type": "def_list_head", "text": line, } for text, loose in definitions: children = _process_text(block, text, loose) yield { "type": "def_list_item", "children": children, } def _process_text(block: "BlockParser", text: str, loose: bool) -> List[Any]: text = TRIM_RE.sub("", text) state = block.state_cls() state.process(strip_end(text)) # use default list rules block.parse(state, block.list_rules) tokens = state.tokens if not loose and len(tokens) == 1 and tokens[0]["type"] == "paragraph": tokens[0]["type"] = "block_text" return tokens def _get_previous_paragraph(state: "BlockState") -> Optional[Tuple[str, bool]]: if not state.tokens: return None last_token = state.tokens[-1] if last_token["type"] == "paragraph": return last_token["text"], False if last_token["type"] == "blank_line" and len(state.tokens) > 1: prev_token = state.tokens[-2] if prev_token["type"] == "paragraph": return prev_token["text"], True return None def _replace_previous_paragraph(state: "BlockState", children: List[Dict[str, Any]]) -> None: if state.tokens[-1]["type"] == "blank_line": state.tokens.pop() state.tokens.pop() if state.tokens and state.tokens[-1]["type"] == "def_list": state.tokens[-1]["children"].extend(children) else: state.append_token( { "type": "def_list", "children": children, } ) def _collect_definitions(src: str, pos: int, max_pos: int, loose: bool) -> Tuple[List[Tuple[str, bool]], int]: definitions = [] while pos < max_pos: line = _get_line(src, pos, max_pos) if not DD_START_RE.match(line): break start = pos pos += len(line) pos = _scan_definition_tail(src, pos, max_pos) # drop marker indentation and ':' plus its trailing space or tab; a tab here would # otherwise survive TRIM_RE (spaces only) and make the line a code block text = DD_MARKER_RE.sub(" ", src[start:pos], count=1) definitions.append((text, loose)) loose = bool(HAS_BLANK_LINE_RE.search(text)) return definitions, pos def _scan_definition_tail(src: str, pos: int, max_pos: int) -> int: while pos < max_pos: line = _get_line(src, pos, max_pos) if DD_START_RE.match(line): break if line.strip(): pos += len(line) continue while pos < max_pos: line = _get_line(src, pos, max_pos) if line.strip(): break pos += len(line) if pos >= max_pos: break line = _get_line(src, pos, max_pos) if DD_START_RE.match(line): break if line.startswith((" ", "\t")): continue return pos return pos def _get_line(src: str, pos: int, max_pos: int) -> str: end = src.find("\n", pos, max_pos) if end == -1: return src[pos:max_pos] return src[pos : end + 1] def render_def_list(renderer: "BaseRenderer", text: str) -> str: return "<dl>\n" + text + "</dl>\n" def render_def_list_head(renderer: "BaseRenderer", text: str) -> str: return "<dt>" + text + "</dt>\n" def render_def_list_item(renderer: "BaseRenderer", text: str) -> str: return "<dd>" + text + "</dd>\n" def def_list(md: "Markdown") -> None: """A mistune plugin to support def list, spec defined at https://michelf.ca/projects/php-markdown/extra/#def-list Here is an example: .. code-block:: text Apple : Pomaceous fruit of plants of the genus Malus in the family Rosaceae. Orange : The fruit of an evergreen tree of the genus Citrus. It will be converted into HTML: .. code-block:: html <dl> <dt>Apple</dt> <dd>Pomaceous fruit of plants of the genus Malus in the family Rosaceae.</dd> <dt>Orange</dt> <dd>The fruit of an evergreen tree of the genus Citrus.</dd> </dl> :param md: Markdown instance """ md.block.register("def_list", DEF_PATTERN, parse_def_list, before="paragraph") if md.renderer and md.renderer.NAME == "html": md.renderer.register("def_list", render_def_list) md.renderer.register("def_list_head", render_def_list_head) md.renderer.register("def_list_item", render_def_list_item) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/src/mistune/plugins/footnotes.py��������������������������������������������0000664�0000000�0000000�00000012507�15265371675�0023573�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import re from typing import TYPE_CHECKING, Any, Dict, List, Match, Union from ..core import BlockState from ..util import unikey if TYPE_CHECKING: from ..block_parser import BlockParser from ..core import BaseRenderer, InlineState from ..inline_parser import InlineParser from ..markdown import Markdown __all__ = ["footnotes"] _PARAGRAPH_SPLIT = re.compile(r"\n{2,}") # Like LINK_LABEL but disallows whitespace in footnote identifiers # https://michelf.ca/projects/php-markdown/extra/#footnotes _FOOTNOTE_LABEL = r"(?:[^\\\[\]\s]|\\.){1,500}" REF_FOOTNOTE = ( r"^(?P<footnote_lead> {0,4})" r"\[\^(?P<footnote_key>" + _FOOTNOTE_LABEL + r")]:[ \t\n]" r"(?P<footnote_text>[^\n]*(?:\n+|$)" r"(?:(?P=footnote_lead) {1,4}(?! )[^\n]*\n+)*" r")" ) INLINE_FOOTNOTE = r"\[\^(?P<footnote_key>" + _FOOTNOTE_LABEL + r")\]" def parse_inline_footnote(inline: "InlineParser", m: Match[str], state: "InlineState") -> int: key = unikey(m.group("footnote_key")) ref = state.env.get("ref_footnotes") if ref and key in ref: notes = state.env.get("footnotes") if not notes: notes = [] indexes = state.env.get("footnote_indexes") if not indexes: indexes = {note_key: index for index, note_key in enumerate(notes)} state.env["footnote_indexes"] = indexes if key not in indexes: notes.append(key) indexes[key] = len(notes) - 1 state.env["footnotes"] = notes state.append_token({"type": "footnote_ref", "raw": key, "attrs": {"index": indexes[key] + 1}}) else: state.append_token({"type": "text", "raw": m.group(0)}) return m.end() def parse_ref_footnote(block: "BlockParser", m: Match[str], state: BlockState) -> int: ref = state.env.get("ref_footnotes") if not ref: ref = {} key = unikey(m.group("footnote_key")) if key not in ref: ref[key] = m.group("footnote_text") state.env["ref_footnotes"] = ref return m.end() def parse_footnote_item(block: "BlockParser", key: str, index: int, state: BlockState) -> Dict[str, Any]: ref = state.env.get("ref_footnotes") if not ref: raise ValueError("Missing 'ref_footnotes'.") text = ref[key] lines = text.splitlines() second_line = None for second_line in lines[1:]: if second_line: break if second_line: spaces = len(second_line) - len(second_line.lstrip()) pattern = re.compile(r"^ {" + str(spaces) + r",}", flags=re.M) text = pattern.sub("", text).strip() footer_state = state.child_state(text + "\n") block.parse(footer_state) children = footer_state.tokens else: text = text.strip() children = [{"type": "paragraph", "text": text}] return {"type": "footnote_item", "children": children, "attrs": {"key": key, "index": index}} def md_footnotes_hook( md: "Markdown", result: Union[str, List[Dict[str, Any]]], state: BlockState ) -> Union[str, List[Dict[str, Any]]]: notes = state.env.get("footnotes") if not notes: return result children = [parse_footnote_item(md.block, k, i + 1, state) for i, k in enumerate(notes)] state = BlockState(parent=state) state.tokens = [{"type": "footnotes", "children": children}] output = md.render_state(state) return result + output # type: ignore[operator] def render_footnote_ref(renderer: "BaseRenderer", key: str, index: int) -> str: i = str(index) html = '<sup class="footnote-ref" id="fnref-' + i + '">' return html + '<a href="#fn-' + i + '">' + i + "</a></sup>" def render_footnotes(renderer: "BaseRenderer", text: str) -> str: return '<section class="footnotes">\n<ol>\n' + text + "</ol>\n</section>\n" def render_footnote_item(renderer: "BaseRenderer", text: str, key: str, index: int) -> str: i = str(index) back = '<a href="#fnref-' + i + '" class="footnote">↩</a>' text = text.rstrip() if text.endswith("</p>"): text = text[:-4] + back + "</p>" else: text = text + "\n" + back return '<li id="fn-' + i + '">' + text + "</li>\n" def footnotes(md: "Markdown") -> None: """A mistune plugin to support footnotes, spec defined at https://michelf.ca/projects/php-markdown/extra/#footnotes Here is an example: .. code-block:: text That's some text with a footnote.[^1] [^1]: And that's the footnote. It will be converted into HTML: .. code-block:: html <p>That's some text with a footnote.<sup class="footnote-ref" id="fnref-1"><a href="#fn-1">1</a></sup></p> <section class="footnotes"> <ol> <li id="fn-1"><p>And that's the footnote.<a href="#fnref-1" class="footnote">↩</a></p></li> </ol> </section> :param md: Markdown instance """ md.inline.register( "footnote", INLINE_FOOTNOTE, parse_inline_footnote, before="link", ) md.block.register( "ref_footnote", REF_FOOTNOTE, parse_ref_footnote, before="ref_link", ) md.after_render_hooks.append(md_footnotes_hook) if md.renderer and md.renderer.NAME == "html": md.renderer.register("footnote_ref", render_footnote_ref) md.renderer.register("footnote_item", render_footnote_item) md.renderer.register("footnotes", render_footnotes) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/src/mistune/plugins/formatting.py�������������������������������������������0000664�0000000�0000000�00000012337�15265371675�0023726�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from typing import TYPE_CHECKING, Match, Optional from ..helpers import PREVENT_BACKSLASH if TYPE_CHECKING: from ..core import BaseRenderer, InlineState from ..inline_parser import InlineParser from ..markdown import Markdown __all__ = ["strikethrough", "mark", "insert", "superscript", "subscript"] SUPERSCRIPT_PATTERN = r"\^(?:" + PREVENT_BACKSLASH + r"\\\^|\S|\\ )+?\^" SUBSCRIPT_PATTERN = r"~(?:" + PREVENT_BACKSLASH + r"\\~|\S|\\ )+?~" def parse_strikethrough(inline: "InlineParser", m: Match[str], state: "InlineState") -> Optional[int]: return _parse_to_end(inline, m, state, "strikethrough", "~~") def render_strikethrough(renderer: "BaseRenderer", text: str) -> str: return "<del>" + text + "</del>" def parse_mark(inline: "InlineParser", m: Match[str], state: "InlineState") -> Optional[int]: return _parse_to_end(inline, m, state, "mark", "==") def render_mark(renderer: "BaseRenderer", text: str) -> str: return "<mark>" + text + "</mark>" def parse_insert(inline: "InlineParser", m: Match[str], state: "InlineState") -> Optional[int]: return _parse_to_end(inline, m, state, "insert", "^^") def render_insert(renderer: "BaseRenderer", text: str) -> str: return "<ins>" + text + "</ins>" def parse_superscript(inline: "InlineParser", m: Match[str], state: "InlineState") -> Optional[int]: return _parse_script(inline, m, state, "superscript") def render_superscript(renderer: "BaseRenderer", text: str) -> str: return "<sup>" + text + "</sup>" def parse_subscript(inline: "InlineParser", m: Match[str], state: "InlineState") -> Optional[int]: return _parse_script(inline, m, state, "subscript") def render_subscript(renderer: "BaseRenderer", text: str) -> str: return "<sub>" + text + "</sub>" def _parse_to_end( inline: "InlineParser", m: Match[str], state: "InlineState", tok_type: str, marker: str, ) -> Optional[int]: if state.depth >= inline.max_nested_level: return None pos = m.end() close = state.delimiters.find(marker, pos, formatting=True) if close is None: return None end_pos = close + len(marker) text = state.src[pos:close] new_state = state.copy() new_state.src = text children = inline.render(new_state) state.append_token({"type": tok_type, "children": children}) return end_pos def _parse_script(inline: "InlineParser", m: Match[str], state: "InlineState", tok_type: str) -> Optional[int]: if state.depth >= inline.max_nested_level: return None text = m.group(0) new_state = state.copy() new_state.src = text[1:-1].replace("\\ ", " ") children = inline.render(new_state) state.append_token({"type": tok_type, "children": children}) return m.end() def strikethrough(md: "Markdown") -> None: """A mistune plugin to support strikethrough. Spec defined by GitHub flavored Markdown and commonly used by many parsers: .. code-block:: text ~~This was mistaken text~~ It will be converted into HTML: .. code-block:: html <del>This was mistaken text</del> :param md: Markdown instance """ md.inline.register( "strikethrough", r"~~(?=[^\s~])", parse_strikethrough, before="link", ) if md.renderer and md.renderer.NAME == "html": md.renderer.register("strikethrough", render_strikethrough) def mark(md: "Markdown") -> None: """A mistune plugin to add ``<mark>`` tag. Spec defined at https://facelessuser.github.io/pymdown-extensions/extensions/mark/: .. code-block:: text ==mark me== ==mark \\=\\= equal== :param md: Markdown instance """ md.inline.register( "mark", r"==(?=[^\s=])", parse_mark, before="link", ) if md.renderer and md.renderer.NAME == "html": md.renderer.register("mark", render_mark) def insert(md: "Markdown") -> None: """A mistune plugin to add ``<ins>`` tag. Spec defined at https://facelessuser.github.io/pymdown-extensions/extensions/caret/#insert: .. code-block:: text ^^insert me^^ :param md: Markdown instance """ md.inline.register( "insert", r"\^\^(?=[^\s\^])", parse_insert, before="link", ) if md.renderer and md.renderer.NAME == "html": md.renderer.register("insert", render_insert) def superscript(md: "Markdown") -> None: """A mistune plugin to add ``<sup>`` tag. Spec defined at https://pandoc.org/MANUAL.html#superscripts-and-subscripts: .. code-block:: text 2^10^ is 1024. :param md: Markdown instance """ md.inline.register("superscript", SUPERSCRIPT_PATTERN, parse_superscript, before="linebreak") if md.renderer and md.renderer.NAME == "html": md.renderer.register("superscript", render_superscript) def subscript(md: "Markdown") -> None: """A mistune plugin to add ``<sub>`` tag. Spec defined at https://pandoc.org/MANUAL.html#superscripts-and-subscripts: .. code-block:: text H~2~O is a liquid. :param md: Markdown instance """ md.inline.register("subscript", SUBSCRIPT_PATTERN, parse_subscript, before="linebreak") if md.renderer and md.renderer.NAME == "html": md.renderer.register("subscript", render_subscript) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/src/mistune/plugins/math.py�������������������������������������������������0000664�0000000�0000000�00000005470�15265371675�0022505�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from typing import TYPE_CHECKING, Match if TYPE_CHECKING: from ..block_parser import BlockParser from ..core import BlockState, InlineState from ..inline_parser import InlineParser from ..markdown import Markdown from ..renderers.html import HTMLRenderer __all__ = ["math", "math_in_quote", "math_in_list"] BLOCK_MATH_PATTERN = ( r"^ {0,3}\$\$(?P<math_text_single>[^\n]*?)\$\$[ \t]*(?:\n|$)|" r"^ {0,3}\$\$[ \t]*\n(?P<math_text_multi>[\s\S]*?)\n\$\$[ \t]*(?:\n|$)" ) INLINE_MATH_PATTERN = ( r"\$\$(?P<display_math_text>(?:[^$\\]|\\.)*?)\$\$|" r"\$(?P<backtick_math_marker>`+)(?P<backtick_math_text>[\s\S]*?)(?P=backtick_math_marker)\$|" r"\$(?!\$)(?!\s)(?P<math_text>(?:[^$\\\n]|\\.)+?)\$(?!\d)" ) def parse_block_math(block: "BlockParser", m: Match[str], state: "BlockState") -> int: text = m.group("math_text_single") if text is None: text = m.group("math_text_multi") assert text is not None state.append_token({"type": "block_math", "raw": text}) return m.end() def parse_inline_math(inline: "InlineParser", m: Match[str], state: "InlineState") -> int: display_text = m.group("display_math_text") if display_text is not None: state.append_token({"type": "block_math", "raw": display_text}) return m.end() text = m.group("backtick_math_text") if text is None: text = m.group("math_text") assert text is not None state.append_token({"type": "inline_math", "raw": text}) return m.end() def render_block_math(renderer: "HTMLRenderer", text: str) -> str: return '<div class="math">$$\n' + renderer.escape_attribute(text) + "\n$$</div>\n" def render_inline_math(renderer: "HTMLRenderer", text: str) -> str: return r'<span class="math">\(' + renderer.escape_attribute(text) + r"\)</span>" def math(md: "Markdown") -> None: """A mistune plugin to support math. The syntax is used by many markdown extensions: .. code-block:: text Block math is surrounded by $$: $$ f(a)=f(b) $$ Inline math is surrounded by `$`, such as $f(a)=f(b)$ :param md: Markdown instance """ md.block.register("block_math", BLOCK_MATH_PATTERN, parse_block_math, before="list") md.inline.register("inline_math", INLINE_MATH_PATTERN, parse_inline_math, before="codespan") if md.renderer and md.renderer.NAME == "html": md.renderer.register("block_math", render_block_math) md.renderer.register("inline_math", render_inline_math) def math_in_quote(md: "Markdown") -> None: """Enable block math plugin in block quote.""" md.block.insert_rule(md.block.block_quote_rules, "block_math", before="list") def math_in_list(md: "Markdown") -> None: """Enable block math plugin in list.""" md.block.insert_rule(md.block.list_rules, "block_math", before="list") ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/src/mistune/plugins/ruby.py�������������������������������������������������0000664�0000000�0000000�00000006617�15265371675�0022541�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import re from typing import TYPE_CHECKING, Any, Dict, List, Match, Optional from ..helpers import parse_link, parse_link_label from ..util import unikey if TYPE_CHECKING: from ..core import BaseRenderer, InlineState from ..inline_parser import InlineParser from ..markdown import Markdown RUBY_PATTERN = r"\[(?:\w+\([\w ]+\))+\]" _ruby_re = re.compile(RUBY_PATTERN) def parse_ruby(inline: "InlineParser", m: Match[str], state: "InlineState") -> int: while True: tokens = _parse_ruby_tokens(m) end_pos = m.end() next_match = _ruby_re.match(state.src, end_pos) if not next_match: break for tok in tokens: state.append_token(tok) m = next_match # repeat link logic if end_pos < len(state.src): link_pos = _parse_ruby_link(inline, state, end_pos, tokens) if link_pos: return link_pos for tok in tokens: state.append_token(tok) return end_pos def _parse_ruby_tokens(m: Match[str]) -> List[Dict[str, Any]]: text = m.group(0)[1:-2] tokens = [] for item in text.split(")"): rb, rt = item.split("(") tokens.append({"type": "ruby", "raw": rb, "attrs": {"rt": rt}}) return tokens def _parse_ruby_link( inline: "InlineParser", state: "InlineState", pos: int, tokens: List[Dict[str, Any]] ) -> Optional[int]: if state.depth >= inline.max_nested_level: return None c = state.src[pos] if c == "(": # standard link [text](<url> "title") attrs, link_pos = parse_link(state.src, pos + 1) if link_pos: state.append_token( { "type": "link", "children": tokens, "attrs": attrs, } ) return link_pos elif c == "[": # standard ref link [text][label] label, link_pos = parse_link_label(state.src, pos + 1) if label and link_pos: ref_links = state.env["ref_links"] key = unikey(label) env = ref_links.get(key) if env: attrs = {"url": env["url"], "title": env.get("title")} state.append_token( { "type": "link", "children": tokens, "attrs": attrs, } ) else: for tok in tokens: state.append_token(tok) state.append_token( { "type": "text", "raw": "[" + label + "]", } ) return link_pos return None def render_ruby(renderer: "BaseRenderer", text: str, rt: str) -> str: return "<ruby>" + text + "<rt>" + rt + "</rt></ruby>" def ruby(md: "Markdown") -> None: """A mistune plugin to support ``<ruby>`` tag. The syntax is defined at https://lepture.com/en/2022/markdown-ruby-markup: .. code-block:: text [漢字(ㄏㄢˋㄗˋ)] [漢(ㄏㄢˋ)字(ㄗˋ)] [漢字(ㄏㄢˋㄗˋ)][link] [漢字(ㄏㄢˋㄗˋ)](/url "title") [link]: /url "title" :param md: Markdown instance """ md.inline.register("ruby", RUBY_PATTERN, parse_ruby, before="link") if md.renderer and md.renderer.NAME == "html": md.renderer.register("ruby", render_ruby) �����������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/src/mistune/plugins/speedup.py����������������������������������������������0000664�0000000�0000000�00000000622�15265371675�0023213�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from typing import TYPE_CHECKING if TYPE_CHECKING: from ..markdown import Markdown __all__ = ["speedup"] def speedup(md: "Markdown") -> None: """Compatibility plugin for the former parser speedups. The paragraph and inline text fast paths are now part of the core parsers, so installing this plugin intentionally leaves the Markdown instance unchanged. """ return None ��������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/src/mistune/plugins/spoiler.py����������������������������������������������0000664�0000000�0000000�00000006070�15265371675�0023226�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import re from typing import TYPE_CHECKING, Match, Optional if TYPE_CHECKING: from ..block_parser import BlockParser from ..core import BaseRenderer, BlockState, InlineState from ..inline_parser import InlineParser from ..markdown import Markdown __all__ = ["spoiler"] _BLOCK_SPOILER_START = re.compile(r"^ {0,3}! ?", re.M) _BLOCK_SPOILER_MATCH = re.compile(r"^( {0,3}![^\n]*\n)+$") INLINE_SPOILER_PATTERN = r">!" def parse_block_spoiler(block: "BlockParser", m: Match[str], state: "BlockState") -> int: text, end_pos, lazy_line_starts = block.extract_block_quote(m, state) if not text.endswith("\n"): # ensure it endswith \n to make sure # _BLOCK_SPOILER_MATCH.match works text += "\n" depth = state.depth() if not depth and _BLOCK_SPOILER_MATCH.match(text): text = _BLOCK_SPOILER_START.sub("", text) tok_type = "block_spoiler" else: tok_type = "block_quote" # scan children state child = state.child_state(text, lazy_line_starts=lazy_line_starts) if state.depth() >= block.max_nested_level - 1: rules = list(block.block_quote_rules) rules.remove("block_quote") else: rules = block.block_quote_rules block.parse(child, rules) token = {"type": tok_type, "children": child.tokens} if end_pos: state.prepend_token(token) return end_pos state.append_token(token) return state.cursor def parse_inline_spoiler(inline: "InlineParser", m: Match[str], state: "InlineState") -> Optional[int]: if state.depth >= inline.max_nested_level: return None pos = m.end() close = state.delimiters.find("!<", pos + 1) if close is None or state.src.find("\n", pos, close) >= 0: return None text = state.src[pos:close].strip() if not text: return None new_state = state.copy() new_state.src = text children = inline.render(new_state) state.append_token({"type": "inline_spoiler", "children": children}) return close + 2 def render_block_spoiler(renderer: "BaseRenderer", text: str) -> str: return '<div class="spoiler">\n' + text + "</div>\n" def render_inline_spoiler(renderer: "BaseRenderer", text: str) -> str: return '<span class="spoiler">' + text + "</span>" def spoiler(md: "Markdown") -> None: """A mistune plugin to support block and inline spoiler. The syntax is inspired by stackexchange: .. code-block:: text Block level spoiler looks like block quote, but with `>!`: >! this is spoiler >! >! the content will be hidden Inline spoiler is surrounded by `>!` and `!<`, such as >! hide me !<. :param md: Markdown instance """ # reset block quote parser with block spoiler parser md.block.register("block_quote", None, parse_block_spoiler) md.inline.register("inline_spoiler", INLINE_SPOILER_PATTERN, parse_inline_spoiler) if md.renderer and md.renderer.NAME == "html": md.renderer.register("block_spoiler", render_block_spoiler) md.renderer.register("inline_spoiler", render_inline_spoiler) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/src/mistune/plugins/table.py������������������������������������������������0000664�0000000�0000000�00000016620�15265371675�0022642�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import re from typing import TYPE_CHECKING, Any, Dict, List, Match, Optional, Tuple, Union if TYPE_CHECKING: from ..block_parser import BlockParser from ..core import BaseRenderer, BlockState from ..markdown import Markdown # https://michelf.ca/projects/php-markdown/extra/#table __all__ = ["table", "table_in_quote", "table_in_list"] TABLE_PATTERN = r"^ {0,3}\|[^\n]*\|[ \t]*(?:\n|$)" NP_TABLE_PATTERN = r"^ {0,3}\S[^\n]*\|[^\n]*(?:\n|$)" ALIGN_CENTER = re.compile(r"^ *:-+: *$") ALIGN_LEFT = re.compile(r"^ *:-+ *$") ALIGN_RIGHT = re.compile(r"^ *-+: *$") ALIGN_NONE = re.compile(r"^ *-+ *$") def parse_table(block: "BlockParser", m: Match[str], state: "BlockState") -> Optional[int]: pos = m.end() header = _strip_pipe_table_row(m.group(0)) if header is None: return None align_line = state.get_line(pos) align = _strip_pipe_table_row(align_line) if align is None: return None thead, aligns = _process_thead(header, align) if not thead: return _parse_invalid_pipe_table(state, pos + len(align_line)) assert aligns is not None pos += len(align_line) rows = [] while pos < state.cursor_max: line = state.get_line(pos) text = _strip_pipe_table_row(line) if text is None: break row = _process_row(text, aligns) if not row: return _parse_invalid_pipe_table(state, pos + len(line)) rows.append(row) pos += len(line) children = [thead, {"type": "table_body", "children": rows}] state.append_token({"type": "table", "children": children}) return pos def parse_nptable(block: "BlockParser", m: Match[str], state: "BlockState") -> Optional[int]: pos = m.end() header = _strip_table_line(m.group(0)) if header is None: return None align_line = state.get_line(pos) align = _strip_table_line(align_line) if align is None: return None thead, aligns = _process_thead(header, align) if not thead: return None assert aligns is not None pos += len(align_line) rows = [] while pos < state.cursor_max: line = state.get_line(pos) text = _strip_table_line(line) if text is None: break row = _process_row(text, aligns) if not row: return None rows.append(row) pos += len(line) children = [thead, {"type": "table_body", "children": rows}] state.append_token({"type": "table", "children": children}) return pos def _process_thead(header: str, align: str) -> Union[Tuple[None, None], Tuple[Dict[str, Any], List[Optional[str]]]]: headers = _split_table_cells(header) raw_aligns = _split_table_cells(align) if len(headers) != len(raw_aligns): return None, None aligns: List[Optional[str]] = [] for v in raw_aligns: if ALIGN_CENTER.match(v): aligns.append("center") elif ALIGN_LEFT.match(v): aligns.append("left") elif ALIGN_RIGHT.match(v): aligns.append("right") elif ALIGN_NONE.match(v) or not v.strip(): aligns.append(None) else: # a delimiter cell must be dashes (optionally colon-flanked) or empty; # anything else means this is not a delimiter row, so not a table return None, None children: List[Dict[str, Any]] = [ {"type": "table_cell", "text": text.strip(), "attrs": {"align": aligns[i], "head": True}} for i, text in enumerate(headers) ] thead: Dict[str, Any] = {"type": "table_head", "children": children} return thead, aligns def _process_row(text: str, aligns: List[Optional[str]]) -> Optional[Dict[str, Any]]: cells = _split_table_cells(text) if len(cells) != len(aligns): return None children: List[Dict[str, Any]] = [ {"type": "table_cell", "text": text.strip(), "attrs": {"align": aligns[i], "head": False}} for i, text in enumerate(cells) ] return {"type": "table_row", "children": children} def _strip_pipe_table_row(line: str) -> Optional[str]: text = line.rstrip("\n").rstrip(" \t") if not text.startswith("|") and text.startswith((" ", "\t")): text = text.lstrip(" ") if not text.startswith("|") or not text.endswith("|"): return None return text[1:-1] def _parse_invalid_pipe_table(state: "BlockState", pos: int) -> int: while pos < state.cursor_max: line = state.get_line(pos) if _strip_pipe_table_row(line) is None: break pos += len(line) state.add_paragraph(state.src[state.cursor : pos]) return pos def _strip_table_line(line: str) -> Optional[str]: text = line.rstrip("\n").rstrip(" \t") if not text or "|" not in text: return None return text def _split_table_cells(text: str) -> List[str]: cells = [] start = 0 pos = 0 while pos < len(text): if text[pos] == "|" and not _is_escaped_pipe(text, pos): cells.append(text[start:pos].strip()) start = pos + 1 pos += 1 cells.append(text[start:].strip()) return cells def _is_escaped_pipe(text: str, pos: int) -> bool: backslashes = 0 pos -= 1 while pos >= 0 and text[pos] == "\\": backslashes += 1 pos -= 1 return backslashes % 2 == 1 def render_table(renderer: "BaseRenderer", text: str) -> str: return "<table>\n" + text + "</table>\n" def render_table_head(renderer: "BaseRenderer", text: str) -> str: return "<thead>\n<tr>\n" + text + "</tr>\n</thead>\n" def render_table_body(renderer: "BaseRenderer", text: str) -> str: return "<tbody>\n" + text + "</tbody>\n" def render_table_row(renderer: "BaseRenderer", text: str) -> str: return "<tr>\n" + text + "</tr>\n" def render_table_cell(renderer: "BaseRenderer", text: str, align: Optional[str] = None, head: bool = False) -> str: if head: tag = "th" else: tag = "td" html = " <" + tag if align: html += ' style="text-align:' + align + '"' return html + ">" + text + "</" + tag + ">\n" def table(md: "Markdown") -> None: """A mistune plugin to support table, spec defined at https://michelf.ca/projects/php-markdown/extra/#table Here is an example: .. code-block:: text First Header | Second Header ------------- | ------------- Content Cell | Content Cell Content Cell | Content Cell :param md: Markdown instance """ md.block.register("table", TABLE_PATTERN, parse_table, before="paragraph") md.block.register("nptable", NP_TABLE_PATTERN, parse_nptable, before="paragraph") if md.renderer and md.renderer.NAME == "html": md.renderer.register("table", render_table) md.renderer.register("table_head", render_table_head) md.renderer.register("table_body", render_table_body) md.renderer.register("table_row", render_table_row) md.renderer.register("table_cell", render_table_cell) def table_in_quote(md: "Markdown") -> None: """Enable table plugin in block quotes.""" md.block.insert_rule(md.block.block_quote_rules, "table", before="paragraph") md.block.insert_rule(md.block.block_quote_rules, "nptable", before="paragraph") def table_in_list(md: "Markdown") -> None: """Enable table plugin in list.""" md.block.insert_rule(md.block.list_rules, "table", before="paragraph") md.block.insert_rule(md.block.list_rules, "nptable", before="paragraph") ����������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/src/mistune/plugins/task_lists.py�������������������������������������������0000664�0000000�0000000�00000004046�15265371675�0023732�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import re from typing import TYPE_CHECKING, Any, Dict, Iterable if TYPE_CHECKING: from ..core import BaseRenderer, BlockState from ..markdown import Markdown __all__ = ["task_lists"] TASK_LIST_ITEM = re.compile(r"^(\[[ xX]\])\s+") def task_lists_hook(md: "Markdown", state: "BlockState") -> Iterable[Dict[str, Any]]: return _rewrite_all_list_items(state.tokens) def render_task_list_item(renderer: "BaseRenderer", text: str, checked: bool = False) -> str: checkbox = '<input class="task-list-item-checkbox" type="checkbox" disabled' if checked: checkbox += " checked/>" else: checkbox += "/>" if text.startswith("<p>"): text = text.replace("<p>", "<p>" + checkbox, 1) else: text = checkbox + text return '<li class="task-list-item">' + text + "</li>\n" def task_lists(md: "Markdown") -> None: """A mistune plugin to support task lists. Spec defined by GitHub flavored Markdown and commonly used by many parsers: .. code-block:: text - [ ] unchecked task - [x] checked task :param md: Markdown instance """ md.before_render_hooks.append(task_lists_hook) if md.renderer and md.renderer.NAME == "html": md.renderer.register("task_list_item", render_task_list_item) def _rewrite_all_list_items(tokens: Iterable[Dict[str, Any]]) -> Iterable[Dict[str, Any]]: for tok in tokens: if tok["type"] == "list_item": _rewrite_list_item(tok) if "children" in tok: _rewrite_all_list_items(tok["children"]) return tokens def _rewrite_list_item(tok: Dict[str, Any]) -> None: children = tok["children"] if children: first_child = children[0] if first_child["type"] not in ("paragraph", "block_text"): return text = first_child.get("text", "") m = TASK_LIST_ITEM.match(text) if m: mark = m.group(1) first_child["text"] = text[m.end() :] tok["type"] = "task_list_item" tok["attrs"] = {"checked": mark != "[ ]"} ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/src/mistune/plugins/url.py��������������������������������������������������0000664�0000000�0000000�00000001772�15265371675�0022357�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from typing import TYPE_CHECKING, Match from ..util import escape_url if TYPE_CHECKING: from ..core import InlineState from ..inline_parser import InlineParser from ..markdown import Markdown __all__ = ["url"] URL_LINK_PATTERN = r"""https?:\/\/[^\s<]+[^<.,:;"')\]\s]""" def parse_url_link(inline: "InlineParser", m: Match[str], state: "InlineState") -> int: text = m.group(0) pos = m.end() if state.brackets: close = text.find("]") if close >= 0: text = text[:close] pos = m.start() + close if state.in_link or state.depth >= inline.max_nested_level: inline.process_text(text, state) return pos state.append_token( { "type": "link", "children": [{"type": "text", "raw": text}], "attrs": {"url": escape_url(text)}, "_autolink": text, } ) return pos def url(md: "Markdown") -> None: md.inline.register("url_link", URL_LINK_PATTERN, parse_url_link) ������lepture-mistune-f19057f/src/mistune/py.typed��������������������������������������������������������0000664�0000000�0000000�00000000265�15265371675�0021215�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# when type checking dependents, tell type checkers, e.g. mypy, to use this package's types # without this file, mypy will write a warning and ignore type annotations from mistune. �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/src/mistune/renderers/������������������������������������������������������0000775�0000000�0000000�00000000000�15265371675�0021504�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/src/mistune/renderers/__init__.py�������������������������������������������0000664�0000000�0000000�00000000000�15265371675�0023603�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/src/mistune/renderers/_list.py����������������������������������������������0000664�0000000�0000000�00000004665�15265371675�0023203�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from typing import TYPE_CHECKING, Any, Dict, Iterable, cast from ..util import strip_end if TYPE_CHECKING: from ..core import BaseRenderer, BlockState def render_list(renderer: "BaseRenderer", token: Dict[str, Any], state: "BlockState") -> str: attrs = token["attrs"] if attrs["ordered"]: children = _render_ordered_list(renderer, token, state) else: children = _render_unordered_list(renderer, token, state) text = "".join(children) parent = token.get("parent") if parent: if parent["tight"]: return text return text + "\n" return strip_end(text) + "\n" def render_list_item( renderer: "BaseRenderer", item: Dict[str, Any], state: "BlockState", marker: str = "", ) -> str: parent = item.get("parent") if not parent: parent = {"leading": "- ", "tight": False} leading = cast(str, parent["leading"]) + marker text = "" prev = None for tok in item["children"]: if tok["type"] == "list": tok["parent"] = parent elif tok["type"] == "blank_line": continue tok["prev"] = prev prev = tok text += renderer.render_token(tok, state) # Markdown normalizes line endings to LF; other separators are content. lines = text.removesuffix("\n").split("\n") text = (lines[0] if lines else "") + "\n" prefix = " " * len(leading) for line in lines[1:]: if line: text += prefix + line + "\n" else: text += "\n" return leading + text def _render_ordered_list(renderer: "BaseRenderer", token: Dict[str, Any], state: "BlockState") -> Iterable[str]: attrs = token["attrs"] start = attrs.get("start", 1) for item in token["children"]: leading = str(start) + token["bullet"] + " " item["parent"] = { "leading": leading, "tight": token["tight"], } try: yield renderer.render_token(item, state) finally: item.pop("parent", None) start += 1 def _render_unordered_list(renderer: "BaseRenderer", token: Dict[str, Any], state: "BlockState") -> Iterable[str]: parent = { "leading": token["bullet"] + " ", "tight": token["tight"], } for item in token["children"]: item["parent"] = parent try: yield renderer.render_token(item, state) finally: item.pop("parent", None) ���������������������������������������������������������������������������lepture-mistune-f19057f/src/mistune/renderers/html.py�����������������������������������������������0000664�0000000�0000000�00000015775�15265371675�0023041�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import re from typing import Any, ClassVar, Dict, Iterable, Literal, Mapping, Optional, Tuple, Union from urllib.parse import unquote from ..core import BaseRenderer, BlockState from ..util import escape as escape_text from ..util import safe_entity, striptags class HTMLRenderer(BaseRenderer): """A renderer for converting Markdown to HTML.""" _escape: bool _allow_harmful_protocols: Optional[Union[bool, Iterable[str]]] NAME: ClassVar[Literal["html"]] = "html" SAFE_PROTOCOLS: ClassVar[Tuple[str, ...]] = ( "http:", "https:", "mailto:", "tel:", "ftp:", "ftps:", "irc:", "ircs:", ) GOOD_DATA_PROTOCOLS: ClassVar[Tuple[str, ...]] = ( "data:image/gif;", "data:image/png;", "data:image/jpeg;", "data:image/webp;", ) _attribute_name_re = re.compile(r"^[A-Za-z_:][A-Za-z0-9_.:-]*$") def __init__( self, escape: bool = True, allow_harmful_protocols: Optional[Union[bool, Iterable[str]]] = None, ) -> None: super(HTMLRenderer, self).__init__() self._allow_harmful_protocols = allow_harmful_protocols self._escape = escape @property def escape_enabled(self) -> bool: """Whether raw HTML nodes are escaped.""" return self._escape @escape_enabled.setter def escape_enabled(self, enabled: bool) -> None: self._escape = enabled def escape_raw(self, value: str) -> str: """Escape raw HTML when raw HTML output is disabled.""" if self.escape_enabled: return escape_text(value) return value def escape_attribute(self, value: object) -> str: """Escape a value for use in a generated HTML attribute.""" return safe_entity(str(value)) def render_attrs(self, attrs: Mapping[str, object]) -> str: """Render generated HTML attributes with escaped values.""" rendered = [] for name, value in attrs.items(): if not self._attribute_name_re.fullmatch(name): raise ValueError("invalid HTML attribute name: " + name) if value is None or value is False: continue if value is True: rendered.append(" " + name) else: rendered.append(' ' + name + '="' + self.escape_attribute(value) + '"') return "".join(rendered) def sanitize_url(self, url: str) -> str: """Return a URL allowed by this renderer's protocol policy.""" allow_harmful_protocols = self._allow_harmful_protocols if allow_harmful_protocols is True: return url normalized_url = _unquote_url(url).lower().lstrip() if allow_harmful_protocols and normalized_url.startswith(tuple(allow_harmful_protocols)): return url if _is_safe_url(normalized_url, self.SAFE_PROTOCOLS, self.GOOD_DATA_PROTOCOLS): return url return "#harmful-link" def render_token(self, token: Dict[str, Any], state: BlockState) -> str: # backward compitable with v2 func = self._get_method(token["type"]) attrs = token.get("attrs") if "raw" in token: text = token["raw"] elif "children" in token: text = self.render_tokens(token["children"], state) else: if attrs: return func(**attrs) else: return func() if attrs: return func(text, **attrs) else: return func(text) def safe_url(self, url: str) -> str: """Ensure the given URL is safe. This method is used for rendering links, images, and etc. """ return self.escape_attribute(self.sanitize_url(url)) def text(self, text: str) -> str: if self.escape_enabled: return escape_text(text) return safe_entity(text) def emphasis(self, text: str) -> str: return "<em>" + text + "</em>" def strong(self, text: str) -> str: return "<strong>" + text + "</strong>" def link(self, text: str, url: str, title: Optional[str] = None) -> str: attrs: Dict[str, object] = {"href": self.sanitize_url(url)} if title: attrs["title"] = title return "<a" + self.render_attrs(attrs) + ">" + text + "</a>" def image(self, text: str, url: str, title: Optional[str] = None) -> str: alt = striptags(text) attrs: Dict[str, object] = {"src": self.sanitize_url(url), "alt": alt} if title: attrs["title"] = title return "<img" + self.render_attrs(attrs) + " />" def codespan(self, text: str) -> str: return "<code>" + escape_text(text) + "</code>" def linebreak(self) -> str: return "<br />\n" def softbreak(self) -> str: return "\n" def inline_html(self, html: str) -> str: return self.escape_raw(html) def paragraph(self, text: str) -> str: return "<p>" + text + "</p>\n" def heading(self, text: str, level: int, **attrs: Any) -> str: tag = "h" + str(level) _id = attrs.get("id") rendered_attrs = self.render_attrs({"id": _id}) if _id else "" return "<" + tag + rendered_attrs + ">" + text + "</" + tag + ">\n" def blank_line(self) -> str: return "" def thematic_break(self) -> str: return "<hr />\n" def block_text(self, text: str) -> str: return text def block_code(self, code: str, info: Optional[str] = None) -> str: attrs: Dict[str, object] = {} if info is not None: info = safe_entity(info.strip()) if info: lang = info.split(None, 1)[0] attrs["class"] = "language-" + lang return "<pre><code" + self.render_attrs(attrs) + ">" + escape_text(code) + "</code></pre>\n" def block_quote(self, text: str) -> str: return "<blockquote>\n" + text + "</blockquote>\n" def block_html(self, html: str) -> str: if self.escape_enabled: return "<p>" + self.escape_raw(html.strip()) + "</p>\n" return html + "\n" def block_error(self, text: str) -> str: return '<div class="error"><pre>' + escape_text(text) + "</pre></div>\n" def list(self, text: str, ordered: bool, **attrs: Any) -> str: if ordered: start = attrs.get("start") return "<ol" + self.render_attrs({"start": start}) + ">\n" + text + "</ol>\n" return "<ul>\n" + text + "</ul>\n" def list_item(self, text: str) -> str: return "<li>" + text + "</li>\n" def _unquote_url(url: str) -> str: for _ in range(3): decoded = unquote(url) if decoded == url: break url = decoded return url def _is_safe_url(url: str, safe_protocols: Tuple[str, ...], good_data_protocols: Tuple[str, ...]) -> bool: if url.startswith(safe_protocols): return True if url.startswith(good_data_protocols): return True if url.startswith(("/", "#", "?")): return True return ":" not in url.split("/", 1)[0] ���lepture-mistune-f19057f/src/mistune/renderers/markdown.py�������������������������������������������0000664�0000000�0000000�00000030463�15265371675�0023706�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import re from textwrap import indent from typing import Any, Dict, Iterable, cast from ..core import BaseRenderer, BlockState from ..util import strip_end from ._list import render_list, render_list_item fenced_re = re.compile(r"^ {0,3}([`~]+)", re.M) _backtick_run_re = re.compile(r"`+") _literal_inline_markers_re = re.compile(r"&(?:#[0-9]+|#[xX][0-9a-fA-F]+|[a-zA-Z][a-zA-Z0-9]+);|([\\`<!&])") #: leading markers that would be parsed as a new block (list, heading, block #: quote) if they appear unescaped at the start of a line. _block_prefix_re = re.compile(r"^(\s*)(>|[-+*]|#{1,6}|\d{1,9}[.)])(\s|$)") class MarkdownRenderer(BaseRenderer): """A renderer to re-format Markdown text.""" NAME = "markdown" def __call__(self, tokens: Iterable[Dict[str, Any]], state: BlockState) -> str: tokens = list(tokens) leading = "" i = 0 while i < len(tokens) and tokens[i]["type"] == "blank_line" and "newlines" in tokens[i]: leading += "\n" * tokens[i]["newlines"] i += 1 out = self.render_tokens(tokens[i:], state) # special handle for line breaks out += "\n\n".join(self.render_referrences(state)) + "\n" return strip_end(leading + out) def render_referrences(self, state: BlockState) -> Iterable[str]: ref_links = state.env["ref_links"] for key in ref_links: attrs = ref_links[key] # An empty destination must be explicit in a reference definition. url = attrs["url"] or "<>" text = "[" + attrs["label"] + "]: " + url title = attrs.get("title") if title: text += ' "' + _escape_title(title) + '"' yield text def render_children(self, token: Dict[str, Any], state: BlockState) -> str: children = token["children"] return self.render_tokens(children, state) def text(self, token: Dict[str, Any], state: BlockState) -> str: raw = cast(str, token["raw"]) # a text token that is made up entirely of "*"/"_" is a literal # emphasis delimiter -- either an escaped marker from the source # (``\*``) or an unmatched leftover -- so every character must stay # escaped, or it would re-parse as emphasis on the round-trip. Prose # punctuation such as ``2 * 3`` or ``snake_case`` arrives mixed with # other characters and is left untouched. if raw and all(c in "*_" for c in raw): return "".join("\\" + c for c in raw) # Keep literal escapes, code delimiters, image introducers, HTML # delimiters and entity prefixes from becoming markup on re-parse. # Complete entity references already in this token keep their meaning; # escaped ampersands arrive in a separate text token. return _literal_inline_markers_re.sub(lambda m: "\\" + m[1] if m[1] else m[0], raw) def emphasis(self, token: Dict[str, Any], state: BlockState) -> str: return "*" + self.render_children(token, state) + "*" def strong(self, token: Dict[str, Any], state: BlockState) -> str: return "**" + self.render_children(token, state) + "**" # Inline formatting plugins (strikethrough, mark, insert) def strikethrough(self, token: Dict[str, Any], state: BlockState) -> str: return "~~" + self.render_children(token, state) + "~~" def mark(self, token: Dict[str, Any], state: BlockState) -> str: return "==" + self.render_children(token, state) + "==" def insert(self, token: Dict[str, Any], state: BlockState) -> str: return "^^" + self.render_children(token, state) + "^^" def link(self, token: Dict[str, Any], state: BlockState) -> str: label = cast(str, token.get("label")) text = self.render_children(token, state) out = "[" + text + "]" if label: return out + "[" + label + "]" attrs = token["attrs"] url: str = attrs["url"] title = attrs.get("title") if token["type"] == "link" and text == url and not title: return "<" + text + ">" elif token["type"] == "link" and "mailto:" + text == url and not title: return "<" + text + ">" out += "(" if "(" in url or ")" in url: out += "<" + url + ">" else: out += url if title: out += ' "' + _escape_title(title) + '"' return out + ")" def image(self, token: Dict[str, Any], state: BlockState) -> str: return "!" + self.link(token, state) def codespan(self, token: Dict[str, Any], state: BlockState) -> str: code = cast(str, token["raw"]) # The delimiter must be a run of backticks longer than any backtick run # inside the content, otherwise the content would close the span early. longest = max((len(run) for run in _backtick_run_re.findall(code)), default=0) fence = "`" * (longest + 1) # Padding separates edge backticks from the delimiter and protects # meaningful spaces at both ends from the parser's space normalization. # All-space content is exempt from that normalization. if ( code.startswith("`") or code.endswith("`") or (code.startswith(" ") and code.endswith(" ") and code.strip(" ")) ): return fence + " " + code + " " + fence return fence + code + fence def linebreak(self, token: Dict[str, Any], state: BlockState) -> str: return " \n" def softbreak(self, token: Dict[str, Any], state: BlockState) -> str: return "\n" def blank_line(self, token: Dict[str, Any], state: BlockState) -> str: return "" def inline_html(self, token: Dict[str, Any], state: BlockState) -> str: return cast(str, token["raw"]) def paragraph(self, token: Dict[str, Any], state: BlockState) -> str: text = self.render_children(token, state) return _escape_block_prefix(text) + "\n\n" def heading(self, token: Dict[str, Any], state: BlockState) -> str: level = cast(int, token["attrs"]["level"]) text = self.render_children(token, state) # An ATX heading ("# ...") occupies a single line, so a heading whose # rendered text spans several lines -- a multi-line setext heading -- # must be re-emitted in setext form. As ATX the continuation lines # would fall out of the heading and become a paragraph on a re-parse. # Only levels 1 and 2 reach this branch, since an ATX heading never # contains a line break. if "\n" in text and level in (1, 2): underline = "=" if level == 1 else "-" return text + "\n" + underline * 3 + "\n\n" marker = "#" * level text = re.sub(r"(^|[ \t])(#+)$", r"\1\\\2", text) return marker + " " + text + "\n\n" def thematic_break(self, token: Dict[str, Any], state: BlockState) -> str: return "***\n\n" def block_text(self, token: Dict[str, Any], state: BlockState) -> str: return _escape_block_prefix(self.render_children(token, state)) + "\n" def block_code(self, token: Dict[str, Any], state: BlockState) -> str: attrs = token.get("attrs", {}) info = cast(str, attrs.get("info", "")) code = cast(str, token["raw"]) if code and code[-1] != "\n": code += "\n" marker = token.get("marker") if not marker: marker = _get_fenced_marker(code) marker2 = cast(str, marker) return marker2 + info + "\n" + code + marker2 + "\n\n" def block_quote(self, token: Dict[str, Any], state: BlockState) -> str: # strip the children's trailing blank lines first so the quote marker is # not added to a dangling empty line; stripping it back off afterwards # would also eat a ">" that ends the content (an autolink or HTML tag). text = self.render_children(token, state).rstrip("\n") text = indent(text, "> ", lambda _: True) return text + "\n\n" def block_html(self, token: Dict[str, Any], state: BlockState) -> str: return cast(str, token["raw"]) + "\n\n" def block_error(self, token: Dict[str, Any], state: BlockState) -> str: return "" def list(self, token: Dict[str, Any], state: BlockState) -> str: return render_list(self, token, state) def list_item(self, token: Dict[str, Any], state: BlockState) -> str: return render_list_item(self, token, state) def task_list_item(self, token: Dict[str, Any], state: BlockState) -> str: checked = token.get("attrs", {}).get("checked") marker = "[x] " if checked else "[ ] " return render_list_item(self, token, state, marker) def table(self, token: Dict[str, Any], state: BlockState) -> str: children = token.get("children", []) if not children: return "\n" head = children[0] body = children[1] if len(children) > 1 else None head_cells = head.get("children", []) align = [_table_cell_align(cell) for cell in head_cells] lines = [ _render_table_row(self, head_cells, state), _render_table_delimiter(align), ] if body: for row in body.get("children", []): lines.append(_render_table_row(self, row.get("children", []), state)) return "\n".join(lines) + "\n\n" def table_head(self, token: Dict[str, Any], state: BlockState) -> str: cells = token.get("children", []) return ( _render_table_row(self, cells, state) + "\n" + _render_table_delimiter([_table_cell_align(c) for c in cells]) ) def table_body(self, token: Dict[str, Any], state: BlockState) -> str: return "\n".join(self.render_token(row, state).rstrip("\n") for row in token.get("children", [])) def table_row(self, token: Dict[str, Any], state: BlockState) -> str: return _render_table_row(self, token.get("children", []), state) + "\n" def table_cell(self, token: Dict[str, Any], state: BlockState) -> str: return _render_table_cell(self, token, state) def _escape_title(title: str) -> str: """Escape a link/image title for emission inside double quotes. The closing quote would otherwise end the title early on a re-parse; a backslash is escaped first so it can't combine with the following character.""" return title.replace("\\", "\\\\").replace('"', '\\"') def _escape_block_prefix(text: str) -> str: """Backslash-escape a leading block marker on each line so that literal text is not re-parsed as a list, heading or block quote.""" return "\n".join(_escape_line_prefix(line) for line in text.split("\n")) def _escape_line_prefix(line: str) -> str: m = _block_prefix_re.match(line) if not m: return line indent_, marker = m.group(1), m.group(2) return indent_ + marker[:-1] + "\\" + marker[-1] + line[m.end(2) :] def _get_fenced_marker(code: str) -> str: found = fenced_re.findall(code) if not found: return "```" ticks = [] # ` waves = [] # ~ for s in found: if s[0] == "`": ticks.append(len(s)) else: waves.append(len(s)) if not ticks: return "```" if not waves: return "~~~" return "`" * (max(ticks) + 1) def _render_table_row(renderer: MarkdownRenderer, cells: Iterable[Dict[str, Any]], state: BlockState) -> str: return "| " + " | ".join(_render_table_cell(renderer, cell, state) for cell in cells) + " |" def _render_table_delimiter(aligns: Iterable[Any]) -> str: cells = [] for align in aligns: if align == "left": cells.append(":---") elif align == "center": cells.append(":---:") elif align == "right": cells.append("---:") else: cells.append("---") return "| " + " | ".join(cells) + " |" def _render_table_cell(renderer: MarkdownRenderer, token: Dict[str, Any], state: BlockState) -> str: if "children" in token: text = renderer.render_children(token, state) else: text = cast(str, token.get("raw", "")) # Code spans can already contain escaped pipes; keep an odd escape count. text = re.sub(r"\\.|[|]", lambda m: r"\|" if m[0] == "|" else m[0], text) return text.replace("\n", " ").strip() def _table_cell_align(token: Dict[str, Any]) -> Any: return token.get("attrs", {}).get("align") �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/src/mistune/renderers/rst.py������������������������������������������������0000664�0000000�0000000�00000013712�15265371675�0022672�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from textwrap import indent from typing import Any, Dict, Iterable, List, cast from ..core import BaseRenderer, BlockState from ..util import strip_end from ._list import render_list, render_list_item class RSTRenderer(BaseRenderer): """A renderer for converting Markdown to ReST.""" NAME = "rst" #: marker symbols for heading HEADING_MARKERS = { 1: "=", 2: "-", 3: "~", 4: "^", 5: '"', 6: "'", } INLINE_IMAGE_PREFIX = "img-" def iter_tokens(self, tokens: Iterable[Dict[str, Any]], state: BlockState) -> Iterable[str]: prev = None for tok in tokens: # ignore blank line if tok["type"] == "blank_line": continue tok["prev"] = prev prev = tok yield self.render_token(tok, state) def __call__(self, tokens: Iterable[Dict[str, Any]], state: BlockState) -> str: state.env["inline_images"] = [] out = self.render_tokens(tokens, state) # special handle for line breaks out += "\n\n".join(self.render_referrences(state)) + "\n" return strip_end(out) def render_referrences(self, state: BlockState) -> Iterable[str]: images = state.env["inline_images"] for index, token in enumerate(images): attrs = token["attrs"] alt = self.render_children(token, state) ident = self.INLINE_IMAGE_PREFIX + str(index) yield ".. |" + ident + "| image:: " + attrs["url"] + "\n :alt: " + alt def render_children(self, token: Dict[str, Any], state: BlockState) -> str: children = token["children"] return self.render_tokens(children, state) def text(self, token: Dict[str, Any], state: BlockState) -> str: text = cast(str, token["raw"]) return text.replace("|", r"\|") def emphasis(self, token: Dict[str, Any], state: BlockState) -> str: return "*" + self.render_children(token, state) + "*" def strong(self, token: Dict[str, Any], state: BlockState) -> str: return "**" + self.render_children(token, state) + "**" def link(self, token: Dict[str, Any], state: BlockState) -> str: attrs = token["attrs"] text = self.render_children(token, state) return "`" + text + " <" + cast(str, attrs["url"]) + ">`__" def image(self, token: Dict[str, Any], state: BlockState) -> str: refs: List[Dict[str, Any]] = state.env["inline_images"] index = len(refs) refs.append(token) return "|" + self.INLINE_IMAGE_PREFIX + str(index) + "|" def codespan(self, token: Dict[str, Any], state: BlockState) -> str: return "``" + cast(str, token["raw"]) + "``" def linebreak(self, token: Dict[str, Any], state: BlockState) -> str: return "<linebreak>" def softbreak(self, token: Dict[str, Any], state: BlockState) -> str: return " " def inline_html(self, token: Dict[str, Any], state: BlockState) -> str: # rst does not support inline html return "" def paragraph(self, token: Dict[str, Any], state: BlockState) -> str: children = token["children"] if len(children) == 1 and children[0]["type"] == "image": image = children[0] attrs = image["attrs"] title = cast(str, attrs.get("title")) alt = self.render_children(image, state) text = ".. figure:: " + cast(str, attrs["url"]) if title: text += "\n :alt: " + title text += "\n\n" + indent(alt, " ") else: text = self.render_tokens(children, state) lines = text.split("<linebreak>") if len(lines) > 1: text = "\n".join("| " + line for line in lines) return text + "\n\n" def heading(self, token: Dict[str, Any], state: BlockState) -> str: attrs = token["attrs"] text = self.render_children(token, state) marker = self.HEADING_MARKERS[attrs["level"]] return text + "\n" + marker * len(text) + "\n\n" def thematic_break(self, token: Dict[str, Any], state: BlockState) -> str: return "--------------\n\n" def block_text(self, token: Dict[str, Any], state: BlockState) -> str: text = self.render_children(token, state) lines = text.split("<linebreak>") if len(lines) > 1: text = "\n".join("| " + line for line in lines) return text + "\n" def block_code(self, token: Dict[str, Any], state: BlockState) -> str: attrs = token.get("attrs", {}) info = cast(str, attrs.get("info")) code = indent(cast(str, token["raw"]), " ") if info: lang = info.split()[0] return ".. code:: " + lang + "\n\n" + code + "\n" else: return "::\n\n" + code + "\n\n" def block_quote(self, token: Dict[str, Any], state: BlockState) -> str: text = indent(self.render_children(token, state), " ") prev = token.get("prev") ignore_blocks = ( "paragraph", "block_text", "thematic_break", "linebreak", "heading", ) if prev and prev["type"] not in ignore_blocks: text = "..\n\n" + text return text def block_html(self, token: Dict[str, Any], state: BlockState) -> str: raw = token["raw"] return ".. raw:: html\n\n" + indent(raw, " ") + "\n\n" def block_error(self, token: Dict[str, Any], state: BlockState) -> str: return "" def list(self, token: Dict[str, Any], state: BlockState) -> str: return render_list(self, token, state) def list_item(self, token: Dict[str, Any], state: BlockState) -> str: return render_list_item(self, token, state) def task_list_item(self, token: Dict[str, Any], state: BlockState) -> str: checked = token.get("attrs", {}).get("checked") marker = "[x] " if checked else "[ ] " return render_list_item(self, token, state, marker) ������������������������������������������������������lepture-mistune-f19057f/src/mistune/toc.py����������������������������������������������������������0000664�0000000�0000000�00000011474�15265371675�0020661�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import re from typing import TYPE_CHECKING, Any, Callable, Dict, Iterable, List, Optional, Set, Tuple from .core import BlockState from .util import escape, striptags if TYPE_CHECKING: from .markdown import Markdown _HTML_ID_RE = re.compile(r"""\bid\s*=\s*(?:"([^"]*)"|'([^']*)')""", re.I) def add_toc_hook( md: "Markdown", min_level: int = 1, max_level: int = 3, heading_id: Optional[Callable[[Dict[str, Any], int], str]] = None, ) -> None: """Add a hook to save toc items into ``state.env``. This is usually helpful for doc generator:: import mistune from mistune.toc import add_toc_hook, render_toc_ul md = mistune.create_markdown(...) add_toc_hook(md) html, state = md.parse(text) toc_items = state.env['toc_items'] toc_html = render_toc_ul(toc_items) :param md: Markdown instance :param min_level: min heading level :param max_level: max heading level :param heading_id: a function to generate heading_id """ if heading_id is None: auto_heading_id = True def heading_id(token: Dict[str, Any], index: int) -> str: return "toc_" + str(index + 1) else: auto_heading_id = False def toc_hook(md: "Markdown", state: "BlockState") -> None: headings = [] for tok in state.tokens: if tok["type"] == "heading": level = tok["attrs"]["level"] if min_level <= level <= max_level: headings.append(tok) id_allocator = _HeadingIdAllocator(state, headings) toc_items = [] for i, tok in enumerate(headings): if not tok["attrs"].get("id"): value = heading_id(tok, i) id_allocator.assign(tok, value, ensure_unique=auto_heading_id) toc_items.append(normalize_toc_item(md, tok, parent=state)) # save items into state state.env["toc_items"] = toc_items md.before_render_hooks.append(toc_hook) class _HeadingIdAllocator: def __init__(self, state: "BlockState", headings: Iterable[Dict[str, Any]]) -> None: self.used_ids: Set[str] = {m.group(1) or m.group(2) for m in _HTML_ID_RE.finditer(state.src)} for token in headings: value = token.get("attrs", {}).get("id") if value: self.used_ids.add(value) def assign(self, token: Dict[str, Any], value: str, ensure_unique: bool = True) -> str: if ensure_unique: value = self._unique(value) self.used_ids.add(value) token["attrs"]["id"] = value return value def _unique(self, value: str) -> str: if value not in self.used_ids: return value index = 1 while value + "_" + str(index) in self.used_ids: index += 1 return value + "_" + str(index) def normalize_toc_item(md: "Markdown", token: Dict[str, Any], parent: Optional[Any] = None) -> Tuple[int, str, str]: text = token["text"] tokens = md.inline(text, parent.env if parent else {}) assert md.renderer is not None html = md.renderer(tokens, BlockState()) text = striptags(html) attrs = token["attrs"] return attrs["level"], attrs["id"], text def render_toc_ul(toc: Iterable[Tuple[int, str, str]]) -> str: """Render a <ul> table of content HTML. The param "toc" should be formatted into this structure:: [ (level, id, text), ] For example:: [ (1, 'toc-intro', 'Introduction'), (2, 'toc-install', 'Install'), (2, 'toc-upgrade', 'Upgrade'), (1, 'toc-license', 'License'), ] """ if not toc: return "" s = "" levels: List[int] = [] for level, k, text in toc: item = '<a href="#{}">{}</a>'.format(escape(k), text) if not levels: s += "<li>" + item levels.append(level) elif level == levels[-1]: s += "</li>\n<li>" + item elif level > levels[-1]: s += "\n<ul>\n<li>" + item levels.append(level) else: levels.pop() while levels: last_level = levels.pop() if level == last_level: s += "</li>\n</ul>\n</li>\n<li>" + item levels.append(level) break elif level > last_level: s += "</li>\n<li>" + item levels.append(last_level) levels.append(level) break else: s += "</li>\n</ul>\n" else: levels.append(level) s += "</li>\n<li>" + item while len(levels) > 1: s += "</li>\n</ul>\n" levels.pop() if not s: return "" return "<ul>\n" + s + "</li>\n</ul>\n" ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/src/mistune/util.py���������������������������������������������������������0000664�0000000�0000000�00000005146�15265371675�0021050�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import html import re from typing import Callable, Match, cast from urllib.parse import quote _expand_tab_re = re.compile(r"^( {0,3})\t", flags=re.M) _replace_charref = cast(Callable[[Match[str]], str], getattr(html, "_replace_charref")) def expand_leading_tab(text: str, width: int = 4) -> str: def repl(m: Match[str]) -> str: s = m.group(1) return s + " " * (width - len(s)) return _expand_tab_re.sub(repl, text) def expand_tab(text: str, space: str = " ") -> str: repl = r"\1" + space return _expand_tab_re.sub(repl, text) def escape(s: str, quote: bool = True) -> str: """Escape characters of ``&<>``. If quote=True, ``"`` will be converted to ``"e;``.""" s = s.replace("&", "&") s = s.replace("<", "<") s = s.replace(">", ">") if quote: s = s.replace('"', """) return s def escape_url(link: str) -> str: """Escape URL for safety.""" safe = ( ":/?#@" # gen-delims - '[]' (rfc3986) "!$&()*+,;=" # sub-delims - "'" (rfc3986) "%" # leave already-encoded octets alone ) return quote(unescape(link), safe=safe) def safe_entity(s: str) -> str: """Escape characters for safety.""" return escape(unescape(s)) def unikey(s: str) -> str: """Generate a unique key for links and footnotes.""" key = " ".join(s.split()).strip() return key.lower().upper() _charref_re = re.compile( r"&(#[0-9]{1,7};" r"|#[xX][0-9a-fA-F]+;" r"|[^\t\n\f <&#;]{1,32};)" ) def unescape(s: str) -> str: """ Copy from `html.unescape`, but `_charref` is different. CommonMark does not accept entity references without a trailing semicolon """ if "&" not in s: return s return _charref_re.sub(_replace_charref, s) _striptags_re = re.compile(r"(<!--.*?-->|<[^>]*>)") _strip_image_re = re.compile(r"<img\b[^>]*\balt=(\"([^\"]*)\"|'([^']*)')[^>]*>") def striptags(s: str) -> str: s = _strip_image_re.sub(lambda m: m.group(2) or m.group(3) or "", s) return _striptags_re.sub("", s) def strip_end(src: str) -> str: r"""Strip trailing whitespace after the final line break. This used to be implemented as ``re.sub(r"\n\s+$", "\n", src)``. For a long run of blank lines followed by a non-whitespace continuation, the regex retries ``\s+`` from every preceding newline and becomes quadratic. Scanning the suffix once keeps the same behavior in linear time. """ end = len(src) while end and src[end - 1].isspace(): end -= 1 newline = src.find("\n", end) if newline >= 0: return src[:newline] + "\n" return src ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/����������������������������������������������������������������������0000775�0000000�0000000�00000000000�15265371675�0016402�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/__init__.py�����������������������������������������������������������0000664�0000000�0000000�00000002171�15265371675�0020514�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import re from abc import abstractmethod from unittest import TestCase from tests import fixtures class BaseTestCase(TestCase): @classmethod def load_fixtures(cls, case_file: str) -> None: def attach_case(n: str, text: str, html: str) -> None: def method(self: "BaseTestCase") -> None: self.assert_case(n, text, html) name = "test_{}".format(n) method.__name__ = name method.__doc__ = "Run fixture {} - {}".format(case_file, n) setattr(cls, name, method) for n, text, html in fixtures.load_examples(case_file): if cls.ignore_case(n): continue attach_case(n, text, html) @classmethod def ignore_case(cls, name: str) -> bool: return False @abstractmethod def parse(self, text: str) -> str: ... def assert_case(self, name: str, text: str, html: str) -> None: result = self.parse(text) self.assertEqual(result, html) def normalize_html(html: str) -> str: html = re.sub(r">\n+", ">", html) html = re.sub(r"\n+<", "<", html) return html.strip() �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/fixtures/�������������������������������������������������������������0000775�0000000�0000000�00000000000�15265371675�0020253�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/fixtures/__init__.py��������������������������������������������������0000664�0000000�0000000�00000003000�15265371675�0022355�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import json import os import re from typing import Any, Iterable, Tuple ROOT = os.path.join(os.path.dirname(__file__)) EXAMPLE_PATTERN = re.compile( r"^`{32} example\n([\s\S]*?)" r"^\.\n([\s\S]*?)" r"^`{32}$|^#{1,6} *(.*)$", flags=re.M, ) def load_ast(filename: str) -> Any: with open(os.path.join(ROOT, "ast", filename), encoding="utf-8") as f: return json.load(f) def load_json(filename: str) -> Any: with open(os.path.join(ROOT, filename), encoding="utf-8") as f: return json.load(f) def load_examples(filename: str) -> Iterable[Tuple[str, str, str]]: if filename.endswith(".json"): data = load_json(filename) for item in data: section = item["section"].lower().replace(" ", "_") n = "%s_%03d" % (section, item["example"]) yield n, item["markdown"], item["html"] else: with open(os.path.join(ROOT, filename), "rb") as f: content = f.read() s = content.decode("utf-8") yield from parse_examples(s) def parse_examples(text: str) -> Iterable[Tuple[str, str, str]]: data = EXAMPLE_PATTERN.findall(text) section = None count = 0 for md, html, title in data: if title: count = 0 section = title.lower().replace(" ", "_") if md and html: count += 1 n = "%s_%03d" % (section, count) md = md.replace("\u2192", "\t") html = html.replace("\u2192", "\t") yield n, md, html lepture-mistune-f19057f/tests/fixtures/abbr.txt�����������������������������������������������������0000664�0000000�0000000�00000007511�15265371675�0021726�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Abbreviation ## abbreviation ```````````````````````````````` example HTML . <p>HTML</p> ```````````````````````````````` ```````````````````````````````` example \*a* . <p>*a*</p> ```````````````````````````````` ```````````````````````````````` example HTML *[HTML]: Hyper Text Markup Language . <p><abbr title="Hyper Text Markup Language">HTML</abbr></p> ```````````````````````````````` ```````````````````````````````` example The HTML specification is maintained by the W3C. *[HTML]: Hyper Text Markup Language *[W3C]: World Wide Web Consortium . <p>The <abbr title="Hyper Text Markup Language">HTML</abbr> specification is maintained by the <abbr title="World Wide Web Consortium">W3C</abbr>.</p> ```````````````````````````````` ```````````````````````````````` example The HTML specification is maintained by the W3C. *[HTML]: Hyper Text Markup Language *[W3C]: World Wide Web Consortium . <p>The <abbr title="Hyper Text Markup Language">HTML</abbr> specification is maintained by the <abbr title="World Wide Web Consortium">W3C</abbr>.</p> ```````````````````````````````` ```````````````````````````````` example The HTML specification is maintained by the W3C. *[HTML]: Hyper Text Markup Language *[W3C]: World Wide Web Consortium There is more text below this one. . <p>The <abbr title="Hyper Text Markup Language">HTML</abbr> specification is maintained by the <abbr title="World Wide Web Consortium">W3C</abbr>.</p> <p>There is more text below this one.</p> ```````````````````````````````` ```````````````````````````````` example The latest spec of HTML is HTML5. *[HTML]: Hyper Text Markup Language . <p>The latest spec of <abbr title="Hyper Text Markup Language">HTML</abbr> is <abbr title="Hyper Text Markup Language">HTML</abbr>5.</p> ```````````````````````````````` ```````````````````````````````` example HTML should always be spelt with capital letters and not spelt html. *[HTML]: Hyper Text Markup Language . <p><abbr title="Hyper Text Markup Language">HTML</abbr> should always be spelt with capital letters and not spelt html.</p> ```````````````````````````````` ```````````````````````````````` example HTML is an abbreviation but nobody knows what it stands for. *[HTML]: . <p><abbr>HTML</abbr> is an abbreviation but nobody knows what it stands for.</p> ```````````````````````````````` ```````````````````````````````` example \*HTML *[HTML]: Hyper Text Markup Language . <p>*<abbr title="Hyper Text Markup Language">HTML</abbr></p> ```````````````````````````````` ```````````````````````````````` example \*a* *[HTML]: Hyper Text Markup Language . <p>*a*</p> ```````````````````````````````` ```````````````````````````````` example Foo.* looks like a regular expression. *[Foo.*]: Just foo . <p><abbr title="Just foo">Foo.*</abbr> looks like a regular expression.</p> ```````````````````````````````` ```````````````````````````````` example Untrusted HTML should be escaped. *[HTML]: <p>This is some HTML</p> . <p>Untrusted <abbr title="<p>This is some HTML</p>">HTML</abbr> should be escaped.</p> ```````````````````````````````` ```````````````````````````````` example HTML5 and HTML *[HTML]: Hyper Text Markup Language *[HTML5]: Hyper Text Markup Language 5 . <p><abbr title="Hyper Text Markup Language 5">HTML5</abbr> and <abbr title="Hyper Text Markup Language">HTML</abbr></p> ```````````````````````````````` ```````````````````````````````` example New York City and New York *[New York]: State *[New York City]: City . <p><abbr title="City">New York City</abbr> and <abbr title="State">New York</abbr></p> ```````````````````````````````` ```````````````````````````````` example HTML5 and HTML *[HTML5]: Hyper Text Markup Language 5 *[HTML]: Hyper Text Markup Language . <p><abbr title="Hyper Text Markup Language 5">HTML5</abbr> and <abbr title="Hyper Text Markup Language">HTML</abbr></p> ```````````````````````````````` ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/fixtures/cli.txt������������������������������������������������������0000664�0000000�0000000�00000000570�15265371675�0021565�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Command Line ```````````````````````````````` example Hi **Markdown** . <p>Hi <strong>Markdown</strong></p> ```````````````````````````````` ```````````````````````````````` example | A | B | | - | - | | 1 | 2 | . <table> <thead> <tr> <th>A</th> <th>B</th> </tr> </thead> <tbody> <tr> <td>1</td> <td>2</td> </tr> </tbody> </table> ```````````````````````````````` ����������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/fixtures/commonmark.json����������������������������������������������0000664�0000000�0000000�00000422166�15265371675�0023324�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������[ { "markdown": "\tfoo\tbaz\t\tbim\n", "html": "<pre><code>foo\tbaz\t\tbim\n</code></pre>\n", "example": 1, "start_line": 356, "end_line": 361, "section": "Tabs" }, { "markdown": " \tfoo\tbaz\t\tbim\n", "html": "<pre><code>foo\tbaz\t\tbim\n</code></pre>\n", "example": 2, "start_line": 363, "end_line": 368, "section": "Tabs" }, { "markdown": " a\ta\n ὐ\ta\n", "html": "<pre><code>a\ta\nὐ\ta\n</code></pre>\n", "example": 3, "start_line": 370, "end_line": 377, "section": "Tabs" }, { "markdown": " - foo\n\n\tbar\n", "html": "<ul>\n<li>\n<p>foo</p>\n<p>bar</p>\n</li>\n</ul>\n", "example": 4, "start_line": 383, "end_line": 394, "section": "Tabs" }, { "markdown": "- foo\n\n\t\tbar\n", "html": "<ul>\n<li>\n<p>foo</p>\n<pre><code> bar\n</code></pre>\n</li>\n</ul>\n", "example": 5, "start_line": 396, "end_line": 408, "section": "Tabs" }, { "markdown": ">\t\tfoo\n", "html": "<blockquote>\n<pre><code> foo\n</code></pre>\n</blockquote>\n", "example": 6, "start_line": 419, "end_line": 426, "section": "Tabs" }, { "markdown": "-\t\tfoo\n", "html": "<ul>\n<li>\n<pre><code> foo\n</code></pre>\n</li>\n</ul>\n", "example": 7, "start_line": 428, "end_line": 437, "section": "Tabs" }, { "markdown": " foo\n\tbar\n", "html": "<pre><code>foo\nbar\n</code></pre>\n", "example": 8, "start_line": 440, "end_line": 447, "section": "Tabs" }, { "markdown": " - foo\n - bar\n\t - baz\n", "html": "<ul>\n<li>foo\n<ul>\n<li>bar\n<ul>\n<li>baz</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n", "example": 9, "start_line": 449, "end_line": 465, "section": "Tabs" }, { "markdown": "#\tFoo\n", "html": "<h1>Foo</h1>\n", "example": 10, "start_line": 467, "end_line": 471, "section": "Tabs" }, { "markdown": "*\t*\t*\t\n", "html": "<hr />\n", "example": 11, "start_line": 473, "end_line": 477, "section": "Tabs" }, { "markdown": "\\!\\\"\\#\\$\\%\\&\\'\\(\\)\\*\\+\\,\\-\\.\\/\\:\\;\\<\\=\\>\\?\\@\\[\\\\\\]\\^\\_\\`\\{\\|\\}\\~\n", "html": "<p>!"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~</p>\n", "example": 12, "start_line": 490, "end_line": 494, "section": "Backslash escapes" }, { "markdown": "\\\t\\A\\a\\ \\3\\φ\\«\n", "html": "<p>\\\t\\A\\a\\ \\3\\φ\\«</p>\n", "example": 13, "start_line": 500, "end_line": 504, "section": "Backslash escapes" }, { "markdown": "\\*not emphasized*\n\\<br/> not a tag\n\\[not a link](/foo)\n\\`not code`\n1\\. not a list\n\\* not a list\n\\# not a heading\n\\[foo]: /url \"not a reference\"\n\\ö not a character entity\n", "html": "<p>*not emphasized*\n<br/> not a tag\n[not a link](/foo)\n`not code`\n1. not a list\n* not a list\n# not a heading\n[foo]: /url "not a reference"\n&ouml; not a character entity</p>\n", "example": 14, "start_line": 510, "end_line": 530, "section": "Backslash escapes" }, { "markdown": "\\\\*emphasis*\n", "html": "<p>\\<em>emphasis</em></p>\n", "example": 15, "start_line": 535, "end_line": 539, "section": "Backslash escapes" }, { "markdown": "foo\\\nbar\n", "html": "<p>foo<br />\nbar</p>\n", "example": 16, "start_line": 544, "end_line": 550, "section": "Backslash escapes" }, { "markdown": "`` \\[\\` ``\n", "html": "<p><code>\\[\\`</code></p>\n", "example": 17, "start_line": 556, "end_line": 560, "section": "Backslash escapes" }, { "markdown": " \\[\\]\n", "html": "<pre><code>\\[\\]\n</code></pre>\n", "example": 18, "start_line": 563, "end_line": 568, "section": "Backslash escapes" }, { "markdown": "~~~\n\\[\\]\n~~~\n", "html": "<pre><code>\\[\\]\n</code></pre>\n", "example": 19, "start_line": 571, "end_line": 578, "section": "Backslash escapes" }, { "markdown": "<http://example.com?find=\\*>\n", "html": "<p><a href=\"http://example.com?find=%5C*\">http://example.com?find=\\*</a></p>\n", "example": 20, "start_line": 581, "end_line": 585, "section": "Backslash escapes" }, { "markdown": "<a href=\"/bar\\/)\">\n", "html": "<a href=\"/bar\\/)\">\n", "example": 21, "start_line": 588, "end_line": 592, "section": "Backslash escapes" }, { "markdown": "[foo](/bar\\* \"ti\\*tle\")\n", "html": "<p><a href=\"/bar*\" title=\"ti*tle\">foo</a></p>\n", "example": 22, "start_line": 598, "end_line": 602, "section": "Backslash escapes" }, { "markdown": "[foo]\n\n[foo]: /bar\\* \"ti\\*tle\"\n", "html": "<p><a href=\"/bar*\" title=\"ti*tle\">foo</a></p>\n", "example": 23, "start_line": 605, "end_line": 611, "section": "Backslash escapes" }, { "markdown": "``` foo\\+bar\nfoo\n```\n", "html": "<pre><code class=\"language-foo+bar\">foo\n</code></pre>\n", "example": 24, "start_line": 614, "end_line": 621, "section": "Backslash escapes" }, { "markdown": "  & © Æ Ď\n¾ ℋ ⅆ\n∲ ≧̸\n", "html": "<p>  & © Æ Ď\n¾ ℋ ⅆ\n∲ ≧̸</p>\n", "example": 25, "start_line": 650, "end_line": 658, "section": "Entity and numeric character references" }, { "markdown": "# Ӓ Ϡ �\n", "html": "<p># Ӓ Ϡ �</p>\n", "example": 26, "start_line": 669, "end_line": 673, "section": "Entity and numeric character references" }, { "markdown": "" ആ ಫ\n", "html": "<p>" ആ ಫ</p>\n", "example": 27, "start_line": 682, "end_line": 686, "section": "Entity and numeric character references" }, { "markdown": "  &x; &#; &#x;\n�\n&#abcdef0;\n&ThisIsNotDefined; &hi?;\n", "html": "<p>&nbsp &x; &#; &#x;\n&#87654321;\n&#abcdef0;\n&ThisIsNotDefined; &hi?;</p>\n", "example": 28, "start_line": 691, "end_line": 701, "section": "Entity and numeric character references" }, { "markdown": "©\n", "html": "<p>&copy</p>\n", "example": 29, "start_line": 708, "end_line": 712, "section": "Entity and numeric character references" }, { "markdown": "&MadeUpEntity;\n", "html": "<p>&MadeUpEntity;</p>\n", "example": 30, "start_line": 718, "end_line": 722, "section": "Entity and numeric character references" }, { "markdown": "<a href=\"öö.html\">\n", "html": "<a href=\"öö.html\">\n", "example": 31, "start_line": 729, "end_line": 733, "section": "Entity and numeric character references" }, { "markdown": "[foo](/föö \"föö\")\n", "html": "<p><a href=\"/f%C3%B6%C3%B6\" title=\"föö\">foo</a></p>\n", "example": 32, "start_line": 736, "end_line": 740, "section": "Entity and numeric character references" }, { "markdown": "[foo]\n\n[foo]: /föö \"föö\"\n", "html": "<p><a href=\"/f%C3%B6%C3%B6\" title=\"föö\">foo</a></p>\n", "example": 33, "start_line": 743, "end_line": 749, "section": "Entity and numeric character references" }, { "markdown": "``` föö\nfoo\n```\n", "html": "<pre><code class=\"language-föö\">foo\n</code></pre>\n", "example": 34, "start_line": 752, "end_line": 759, "section": "Entity and numeric character references" }, { "markdown": "`föö`\n", "html": "<p><code>f&ouml;&ouml;</code></p>\n", "example": 35, "start_line": 765, "end_line": 769, "section": "Entity and numeric character references" }, { "markdown": " föfö\n", "html": "<pre><code>f&ouml;f&ouml;\n</code></pre>\n", "example": 36, "start_line": 772, "end_line": 777, "section": "Entity and numeric character references" }, { "markdown": "*foo*\n*foo*\n", "html": "<p>*foo*\n<em>foo</em></p>\n", "example": 37, "start_line": 784, "end_line": 790, "section": "Entity and numeric character references" }, { "markdown": "* foo\n\n* foo\n", "html": "<p>* foo</p>\n<ul>\n<li>foo</li>\n</ul>\n", "example": 38, "start_line": 792, "end_line": 801, "section": "Entity and numeric character references" }, { "markdown": "foo bar\n", "html": "<p>foo\n\nbar</p>\n", "example": 39, "start_line": 803, "end_line": 809, "section": "Entity and numeric character references" }, { "markdown": " foo\n", "html": "<p>\tfoo</p>\n", "example": 40, "start_line": 811, "end_line": 815, "section": "Entity and numeric character references" }, { "markdown": "[a](url "tit")\n", "html": "<p>[a](url "tit")</p>\n", "example": 41, "start_line": 818, "end_line": 822, "section": "Entity and numeric character references" }, { "markdown": "- `one\n- two`\n", "html": "<ul>\n<li>`one</li>\n<li>two`</li>\n</ul>\n", "example": 42, "start_line": 841, "end_line": 849, "section": "Precedence" }, { "markdown": "***\n---\n___\n", "html": "<hr />\n<hr />\n<hr />\n", "example": 43, "start_line": 880, "end_line": 888, "section": "Thematic breaks" }, { "markdown": "+++\n", "html": "<p>+++</p>\n", "example": 44, "start_line": 893, "end_line": 897, "section": "Thematic breaks" }, { "markdown": "===\n", "html": "<p>===</p>\n", "example": 45, "start_line": 900, "end_line": 904, "section": "Thematic breaks" }, { "markdown": "--\n**\n__\n", "html": "<p>--\n**\n__</p>\n", "example": 46, "start_line": 909, "end_line": 917, "section": "Thematic breaks" }, { "markdown": " ***\n ***\n ***\n", "html": "<hr />\n<hr />\n<hr />\n", "example": 47, "start_line": 922, "end_line": 930, "section": "Thematic breaks" }, { "markdown": " ***\n", "html": "<pre><code>***\n</code></pre>\n", "example": 48, "start_line": 935, "end_line": 940, "section": "Thematic breaks" }, { "markdown": "Foo\n ***\n", "html": "<p>Foo\n***</p>\n", "example": 49, "start_line": 943, "end_line": 949, "section": "Thematic breaks" }, { "markdown": "_____________________________________\n", "html": "<hr />\n", "example": 50, "start_line": 954, "end_line": 958, "section": "Thematic breaks" }, { "markdown": " - - -\n", "html": "<hr />\n", "example": 51, "start_line": 963, "end_line": 967, "section": "Thematic breaks" }, { "markdown": " ** * ** * ** * **\n", "html": "<hr />\n", "example": 52, "start_line": 970, "end_line": 974, "section": "Thematic breaks" }, { "markdown": "- - - -\n", "html": "<hr />\n", "example": 53, "start_line": 977, "end_line": 981, "section": "Thematic breaks" }, { "markdown": "- - - - \n", "html": "<hr />\n", "example": 54, "start_line": 986, "end_line": 990, "section": "Thematic breaks" }, { "markdown": "_ _ _ _ a\n\na------\n\n---a---\n", "html": "<p>_ _ _ _ a</p>\n<p>a------</p>\n<p>---a---</p>\n", "example": 55, "start_line": 995, "end_line": 1005, "section": "Thematic breaks" }, { "markdown": " *-*\n", "html": "<p><em>-</em></p>\n", "example": 56, "start_line": 1011, "end_line": 1015, "section": "Thematic breaks" }, { "markdown": "- foo\n***\n- bar\n", "html": "<ul>\n<li>foo</li>\n</ul>\n<hr />\n<ul>\n<li>bar</li>\n</ul>\n", "example": 57, "start_line": 1020, "end_line": 1032, "section": "Thematic breaks" }, { "markdown": "Foo\n***\nbar\n", "html": "<p>Foo</p>\n<hr />\n<p>bar</p>\n", "example": 58, "start_line": 1037, "end_line": 1045, "section": "Thematic breaks" }, { "markdown": "Foo\n---\nbar\n", "html": "<h2>Foo</h2>\n<p>bar</p>\n", "example": 59, "start_line": 1054, "end_line": 1061, "section": "Thematic breaks" }, { "markdown": "* Foo\n* * *\n* Bar\n", "html": "<ul>\n<li>Foo</li>\n</ul>\n<hr />\n<ul>\n<li>Bar</li>\n</ul>\n", "example": 60, "start_line": 1067, "end_line": 1079, "section": "Thematic breaks" }, { "markdown": "- Foo\n- * * *\n", "html": "<ul>\n<li>Foo</li>\n<li>\n<hr />\n</li>\n</ul>\n", "example": 61, "start_line": 1084, "end_line": 1094, "section": "Thematic breaks" }, { "markdown": "# foo\n## foo\n### foo\n#### foo\n##### foo\n###### foo\n", "html": "<h1>foo</h1>\n<h2>foo</h2>\n<h3>foo</h3>\n<h4>foo</h4>\n<h5>foo</h5>\n<h6>foo</h6>\n", "example": 62, "start_line": 1113, "end_line": 1127, "section": "ATX headings" }, { "markdown": "####### foo\n", "html": "<p>####### foo</p>\n", "example": 63, "start_line": 1132, "end_line": 1136, "section": "ATX headings" }, { "markdown": "#5 bolt\n\n#hashtag\n", "html": "<p>#5 bolt</p>\n<p>#hashtag</p>\n", "example": 64, "start_line": 1147, "end_line": 1154, "section": "ATX headings" }, { "markdown": "\\## foo\n", "html": "<p>## foo</p>\n", "example": 65, "start_line": 1159, "end_line": 1163, "section": "ATX headings" }, { "markdown": "# foo *bar* \\*baz\\*\n", "html": "<h1>foo <em>bar</em> *baz*</h1>\n", "example": 66, "start_line": 1168, "end_line": 1172, "section": "ATX headings" }, { "markdown": "# foo \n", "html": "<h1>foo</h1>\n", "example": 67, "start_line": 1177, "end_line": 1181, "section": "ATX headings" }, { "markdown": " ### foo\n ## foo\n # foo\n", "html": "<h3>foo</h3>\n<h2>foo</h2>\n<h1>foo</h1>\n", "example": 68, "start_line": 1186, "end_line": 1194, "section": "ATX headings" }, { "markdown": " # foo\n", "html": "<pre><code># foo\n</code></pre>\n", "example": 69, "start_line": 1199, "end_line": 1204, "section": "ATX headings" }, { "markdown": "foo\n # bar\n", "html": "<p>foo\n# bar</p>\n", "example": 70, "start_line": 1207, "end_line": 1213, "section": "ATX headings" }, { "markdown": "## foo ##\n ### bar ###\n", "html": "<h2>foo</h2>\n<h3>bar</h3>\n", "example": 71, "start_line": 1218, "end_line": 1224, "section": "ATX headings" }, { "markdown": "# foo ##################################\n##### foo ##\n", "html": "<h1>foo</h1>\n<h5>foo</h5>\n", "example": 72, "start_line": 1229, "end_line": 1235, "section": "ATX headings" }, { "markdown": "### foo ### \n", "html": "<h3>foo</h3>\n", "example": 73, "start_line": 1240, "end_line": 1244, "section": "ATX headings" }, { "markdown": "### foo ### b\n", "html": "<h3>foo ### b</h3>\n", "example": 74, "start_line": 1251, "end_line": 1255, "section": "ATX headings" }, { "markdown": "# foo#\n", "html": "<h1>foo#</h1>\n", "example": 75, "start_line": 1260, "end_line": 1264, "section": "ATX headings" }, { "markdown": "### foo \\###\n## foo #\\##\n# foo \\#\n", "html": "<h3>foo ###</h3>\n<h2>foo ###</h2>\n<h1>foo #</h1>\n", "example": 76, "start_line": 1270, "end_line": 1278, "section": "ATX headings" }, { "markdown": "****\n## foo\n****\n", "html": "<hr />\n<h2>foo</h2>\n<hr />\n", "example": 77, "start_line": 1284, "end_line": 1292, "section": "ATX headings" }, { "markdown": "Foo bar\n# baz\nBar foo\n", "html": "<p>Foo bar</p>\n<h1>baz</h1>\n<p>Bar foo</p>\n", "example": 78, "start_line": 1295, "end_line": 1303, "section": "ATX headings" }, { "markdown": "## \n#\n### ###\n", "html": "<h2></h2>\n<h1></h1>\n<h3></h3>\n", "example": 79, "start_line": 1308, "end_line": 1316, "section": "ATX headings" }, { "markdown": "Foo *bar*\n=========\n\nFoo *bar*\n---------\n", "html": "<h1>Foo <em>bar</em></h1>\n<h2>Foo <em>bar</em></h2>\n", "example": 80, "start_line": 1351, "end_line": 1360, "section": "Setext headings" }, { "markdown": "Foo *bar\nbaz*\n====\n", "html": "<h1>Foo <em>bar\nbaz</em></h1>\n", "example": 81, "start_line": 1365, "end_line": 1372, "section": "Setext headings" }, { "markdown": " Foo *bar\nbaz*\t\n====\n", "html": "<h1>Foo <em>bar\nbaz</em></h1>\n", "example": 82, "start_line": 1379, "end_line": 1386, "section": "Setext headings" }, { "markdown": "Foo\n-------------------------\n\nFoo\n=\n", "html": "<h2>Foo</h2>\n<h1>Foo</h1>\n", "example": 83, "start_line": 1391, "end_line": 1400, "section": "Setext headings" }, { "markdown": " Foo\n---\n\n Foo\n-----\n\n Foo\n ===\n", "html": "<h2>Foo</h2>\n<h2>Foo</h2>\n<h1>Foo</h1>\n", "example": 84, "start_line": 1406, "end_line": 1419, "section": "Setext headings" }, { "markdown": " Foo\n ---\n\n Foo\n---\n", "html": "<pre><code>Foo\n---\n\nFoo\n</code></pre>\n<hr />\n", "example": 85, "start_line": 1424, "end_line": 1437, "section": "Setext headings" }, { "markdown": "Foo\n ---- \n", "html": "<h2>Foo</h2>\n", "example": 86, "start_line": 1443, "end_line": 1448, "section": "Setext headings" }, { "markdown": "Foo\n ---\n", "html": "<p>Foo\n---</p>\n", "example": 87, "start_line": 1453, "end_line": 1459, "section": "Setext headings" }, { "markdown": "Foo\n= =\n\nFoo\n--- -\n", "html": "<p>Foo\n= =</p>\n<p>Foo</p>\n<hr />\n", "example": 88, "start_line": 1464, "end_line": 1475, "section": "Setext headings" }, { "markdown": "Foo \n-----\n", "html": "<h2>Foo</h2>\n", "example": 89, "start_line": 1480, "end_line": 1485, "section": "Setext headings" }, { "markdown": "Foo\\\n----\n", "html": "<h2>Foo\\</h2>\n", "example": 90, "start_line": 1490, "end_line": 1495, "section": "Setext headings" }, { "markdown": "`Foo\n----\n`\n\n<a title=\"a lot\n---\nof dashes\"/>\n", "html": "<h2>`Foo</h2>\n<p>`</p>\n<h2><a title="a lot</h2>\n<p>of dashes"/></p>\n", "example": 91, "start_line": 1501, "end_line": 1514, "section": "Setext headings" }, { "markdown": "> Foo\n---\n", "html": "<blockquote>\n<p>Foo</p>\n</blockquote>\n<hr />\n", "example": 92, "start_line": 1520, "end_line": 1528, "section": "Setext headings" }, { "markdown": "> foo\nbar\n===\n", "html": "<blockquote>\n<p>foo\nbar\n===</p>\n</blockquote>\n", "example": 93, "start_line": 1531, "end_line": 1541, "section": "Setext headings" }, { "markdown": "- Foo\n---\n", "html": "<ul>\n<li>Foo</li>\n</ul>\n<hr />\n", "example": 94, "start_line": 1544, "end_line": 1552, "section": "Setext headings" }, { "markdown": "Foo\nBar\n---\n", "html": "<h2>Foo\nBar</h2>\n", "example": 95, "start_line": 1559, "end_line": 1566, "section": "Setext headings" }, { "markdown": "---\nFoo\n---\nBar\n---\nBaz\n", "html": "<hr />\n<h2>Foo</h2>\n<h2>Bar</h2>\n<p>Baz</p>\n", "example": 96, "start_line": 1572, "end_line": 1584, "section": "Setext headings" }, { "markdown": "\n====\n", "html": "<p>====</p>\n", "example": 97, "start_line": 1589, "end_line": 1594, "section": "Setext headings" }, { "markdown": "---\n---\n", "html": "<hr />\n<hr />\n", "example": 98, "start_line": 1601, "end_line": 1607, "section": "Setext headings" }, { "markdown": "- foo\n-----\n", "html": "<ul>\n<li>foo</li>\n</ul>\n<hr />\n", "example": 99, "start_line": 1610, "end_line": 1618, "section": "Setext headings" }, { "markdown": " foo\n---\n", "html": "<pre><code>foo\n</code></pre>\n<hr />\n", "example": 100, "start_line": 1621, "end_line": 1628, "section": "Setext headings" }, { "markdown": "> foo\n-----\n", "html": "<blockquote>\n<p>foo</p>\n</blockquote>\n<hr />\n", "example": 101, "start_line": 1631, "end_line": 1639, "section": "Setext headings" }, { "markdown": "\\> foo\n------\n", "html": "<h2>> foo</h2>\n", "example": 102, "start_line": 1645, "end_line": 1650, "section": "Setext headings" }, { "markdown": "Foo\n\nbar\n---\nbaz\n", "html": "<p>Foo</p>\n<h2>bar</h2>\n<p>baz</p>\n", "example": 103, "start_line": 1676, "end_line": 1686, "section": "Setext headings" }, { "markdown": "Foo\nbar\n\n---\n\nbaz\n", "html": "<p>Foo\nbar</p>\n<hr />\n<p>baz</p>\n", "example": 104, "start_line": 1692, "end_line": 1704, "section": "Setext headings" }, { "markdown": "Foo\nbar\n* * *\nbaz\n", "html": "<p>Foo\nbar</p>\n<hr />\n<p>baz</p>\n", "example": 105, "start_line": 1710, "end_line": 1720, "section": "Setext headings" }, { "markdown": "Foo\nbar\n\\---\nbaz\n", "html": "<p>Foo\nbar\n---\nbaz</p>\n", "example": 106, "start_line": 1725, "end_line": 1735, "section": "Setext headings" }, { "markdown": " a simple\n indented code block\n", "html": "<pre><code>a simple\n indented code block\n</code></pre>\n", "example": 107, "start_line": 1753, "end_line": 1760, "section": "Indented code blocks" }, { "markdown": " - foo\n\n bar\n", "html": "<ul>\n<li>\n<p>foo</p>\n<p>bar</p>\n</li>\n</ul>\n", "example": 108, "start_line": 1767, "end_line": 1778, "section": "Indented code blocks" }, { "markdown": "1. foo\n\n - bar\n", "html": "<ol>\n<li>\n<p>foo</p>\n<ul>\n<li>bar</li>\n</ul>\n</li>\n</ol>\n", "example": 109, "start_line": 1781, "end_line": 1794, "section": "Indented code blocks" }, { "markdown": " <a/>\n *hi*\n\n - one\n", "html": "<pre><code><a/>\n*hi*\n\n- one\n</code></pre>\n", "example": 110, "start_line": 1801, "end_line": 1812, "section": "Indented code blocks" }, { "markdown": " chunk1\n\n chunk2\n \n \n \n chunk3\n", "html": "<pre><code>chunk1\n\nchunk2\n\n\n\nchunk3\n</code></pre>\n", "example": 111, "start_line": 1817, "end_line": 1834, "section": "Indented code blocks" }, { "markdown": " chunk1\n \n chunk2\n", "html": "<pre><code>chunk1\n \n chunk2\n</code></pre>\n", "example": 112, "start_line": 1840, "end_line": 1849, "section": "Indented code blocks" }, { "markdown": "Foo\n bar\n\n", "html": "<p>Foo\nbar</p>\n", "example": 113, "start_line": 1855, "end_line": 1862, "section": "Indented code blocks" }, { "markdown": " foo\nbar\n", "html": "<pre><code>foo\n</code></pre>\n<p>bar</p>\n", "example": 114, "start_line": 1869, "end_line": 1876, "section": "Indented code blocks" }, { "markdown": "# Heading\n foo\nHeading\n------\n foo\n----\n", "html": "<h1>Heading</h1>\n<pre><code>foo\n</code></pre>\n<h2>Heading</h2>\n<pre><code>foo\n</code></pre>\n<hr />\n", "example": 115, "start_line": 1882, "end_line": 1897, "section": "Indented code blocks" }, { "markdown": " foo\n bar\n", "html": "<pre><code> foo\nbar\n</code></pre>\n", "example": 116, "start_line": 1902, "end_line": 1909, "section": "Indented code blocks" }, { "markdown": "\n \n foo\n \n\n", "html": "<pre><code>foo\n</code></pre>\n", "example": 117, "start_line": 1915, "end_line": 1924, "section": "Indented code blocks" }, { "markdown": " foo \n", "html": "<pre><code>foo \n</code></pre>\n", "example": 118, "start_line": 1929, "end_line": 1934, "section": "Indented code blocks" }, { "markdown": "```\n<\n >\n```\n", "html": "<pre><code><\n >\n</code></pre>\n", "example": 119, "start_line": 1984, "end_line": 1993, "section": "Fenced code blocks" }, { "markdown": "~~~\n<\n >\n~~~\n", "html": "<pre><code><\n >\n</code></pre>\n", "example": 120, "start_line": 1998, "end_line": 2007, "section": "Fenced code blocks" }, { "markdown": "``\nfoo\n``\n", "html": "<p><code>foo</code></p>\n", "example": 121, "start_line": 2011, "end_line": 2017, "section": "Fenced code blocks" }, { "markdown": "```\naaa\n~~~\n```\n", "html": "<pre><code>aaa\n~~~\n</code></pre>\n", "example": 122, "start_line": 2022, "end_line": 2031, "section": "Fenced code blocks" }, { "markdown": "~~~\naaa\n```\n~~~\n", "html": "<pre><code>aaa\n```\n</code></pre>\n", "example": 123, "start_line": 2034, "end_line": 2043, "section": "Fenced code blocks" }, { "markdown": "````\naaa\n```\n``````\n", "html": "<pre><code>aaa\n```\n</code></pre>\n", "example": 124, "start_line": 2048, "end_line": 2057, "section": "Fenced code blocks" }, { "markdown": "~~~~\naaa\n~~~\n~~~~\n", "html": "<pre><code>aaa\n~~~\n</code></pre>\n", "example": 125, "start_line": 2060, "end_line": 2069, "section": "Fenced code blocks" }, { "markdown": "```\n", "html": "<pre><code></code></pre>\n", "example": 126, "start_line": 2075, "end_line": 2079, "section": "Fenced code blocks" }, { "markdown": "`````\n\n```\naaa\n", "html": "<pre><code>\n```\naaa\n</code></pre>\n", "example": 127, "start_line": 2082, "end_line": 2092, "section": "Fenced code blocks" }, { "markdown": "> ```\n> aaa\n\nbbb\n", "html": "<blockquote>\n<pre><code>aaa\n</code></pre>\n</blockquote>\n<p>bbb</p>\n", "example": 128, "start_line": 2095, "end_line": 2106, "section": "Fenced code blocks" }, { "markdown": "```\n\n \n```\n", "html": "<pre><code>\n \n</code></pre>\n", "example": 129, "start_line": 2111, "end_line": 2120, "section": "Fenced code blocks" }, { "markdown": "```\n```\n", "html": "<pre><code></code></pre>\n", "example": 130, "start_line": 2125, "end_line": 2130, "section": "Fenced code blocks" }, { "markdown": " ```\n aaa\naaa\n```\n", "html": "<pre><code>aaa\naaa\n</code></pre>\n", "example": 131, "start_line": 2137, "end_line": 2146, "section": "Fenced code blocks" }, { "markdown": " ```\naaa\n aaa\naaa\n ```\n", "html": "<pre><code>aaa\naaa\naaa\n</code></pre>\n", "example": 132, "start_line": 2149, "end_line": 2160, "section": "Fenced code blocks" }, { "markdown": " ```\n aaa\n aaa\n aaa\n ```\n", "html": "<pre><code>aaa\n aaa\naaa\n</code></pre>\n", "example": 133, "start_line": 2163, "end_line": 2174, "section": "Fenced code blocks" }, { "markdown": " ```\n aaa\n ```\n", "html": "<pre><code>```\naaa\n```\n</code></pre>\n", "example": 134, "start_line": 2179, "end_line": 2188, "section": "Fenced code blocks" }, { "markdown": "```\naaa\n ```\n", "html": "<pre><code>aaa\n</code></pre>\n", "example": 135, "start_line": 2194, "end_line": 2201, "section": "Fenced code blocks" }, { "markdown": " ```\naaa\n ```\n", "html": "<pre><code>aaa\n</code></pre>\n", "example": 136, "start_line": 2204, "end_line": 2211, "section": "Fenced code blocks" }, { "markdown": "```\naaa\n ```\n", "html": "<pre><code>aaa\n ```\n</code></pre>\n", "example": 137, "start_line": 2216, "end_line": 2224, "section": "Fenced code blocks" }, { "markdown": "``` ```\naaa\n", "html": "<p><code> </code>\naaa</p>\n", "example": 138, "start_line": 2230, "end_line": 2236, "section": "Fenced code blocks" }, { "markdown": "~~~~~~\naaa\n~~~ ~~\n", "html": "<pre><code>aaa\n~~~ ~~\n</code></pre>\n", "example": 139, "start_line": 2239, "end_line": 2247, "section": "Fenced code blocks" }, { "markdown": "foo\n```\nbar\n```\nbaz\n", "html": "<p>foo</p>\n<pre><code>bar\n</code></pre>\n<p>baz</p>\n", "example": 140, "start_line": 2253, "end_line": 2264, "section": "Fenced code blocks" }, { "markdown": "foo\n---\n~~~\nbar\n~~~\n# baz\n", "html": "<h2>foo</h2>\n<pre><code>bar\n</code></pre>\n<h1>baz</h1>\n", "example": 141, "start_line": 2270, "end_line": 2282, "section": "Fenced code blocks" }, { "markdown": "```ruby\ndef foo(x)\n return 3\nend\n```\n", "html": "<pre><code class=\"language-ruby\">def foo(x)\n return 3\nend\n</code></pre>\n", "example": 142, "start_line": 2292, "end_line": 2303, "section": "Fenced code blocks" }, { "markdown": "~~~~ ruby startline=3 $%@#$\ndef foo(x)\n return 3\nend\n~~~~~~~\n", "html": "<pre><code class=\"language-ruby\">def foo(x)\n return 3\nend\n</code></pre>\n", "example": 143, "start_line": 2306, "end_line": 2317, "section": "Fenced code blocks" }, { "markdown": "````;\n````\n", "html": "<pre><code class=\"language-;\"></code></pre>\n", "example": 144, "start_line": 2320, "end_line": 2325, "section": "Fenced code blocks" }, { "markdown": "``` aa ```\nfoo\n", "html": "<p><code>aa</code>\nfoo</p>\n", "example": 145, "start_line": 2330, "end_line": 2336, "section": "Fenced code blocks" }, { "markdown": "~~~ aa ``` ~~~\nfoo\n~~~\n", "html": "<pre><code class=\"language-aa\">foo\n</code></pre>\n", "example": 146, "start_line": 2341, "end_line": 2348, "section": "Fenced code blocks" }, { "markdown": "```\n``` aaa\n```\n", "html": "<pre><code>``` aaa\n</code></pre>\n", "example": 147, "start_line": 2353, "end_line": 2360, "section": "Fenced code blocks" }, { "markdown": "<table><tr><td>\n<pre>\n**Hello**,\n\n_world_.\n</pre>\n</td></tr></table>\n", "html": "<table><tr><td>\n<pre>\n**Hello**,\n<p><em>world</em>.\n</pre></p>\n</td></tr></table>\n", "example": 148, "start_line": 2432, "end_line": 2447, "section": "HTML blocks" }, { "markdown": "<table>\n <tr>\n <td>\n hi\n </td>\n </tr>\n</table>\n\nokay.\n", "html": "<table>\n <tr>\n <td>\n hi\n </td>\n </tr>\n</table>\n<p>okay.</p>\n", "example": 149, "start_line": 2461, "end_line": 2480, "section": "HTML blocks" }, { "markdown": " <div>\n *hello*\n <foo><a>\n", "html": " <div>\n *hello*\n <foo><a>\n", "example": 150, "start_line": 2483, "end_line": 2491, "section": "HTML blocks" }, { "markdown": "</div>\n*foo*\n", "html": "</div>\n*foo*\n", "example": 151, "start_line": 2496, "end_line": 2502, "section": "HTML blocks" }, { "markdown": "<DIV CLASS=\"foo\">\n\n*Markdown*\n\n</DIV>\n", "html": "<DIV CLASS=\"foo\">\n<p><em>Markdown</em></p>\n</DIV>\n", "example": 152, "start_line": 2507, "end_line": 2517, "section": "HTML blocks" }, { "markdown": "<div id=\"foo\"\n class=\"bar\">\n</div>\n", "html": "<div id=\"foo\"\n class=\"bar\">\n</div>\n", "example": 153, "start_line": 2523, "end_line": 2531, "section": "HTML blocks" }, { "markdown": "<div id=\"foo\" class=\"bar\n baz\">\n</div>\n", "html": "<div id=\"foo\" class=\"bar\n baz\">\n</div>\n", "example": 154, "start_line": 2534, "end_line": 2542, "section": "HTML blocks" }, { "markdown": "<div>\n*foo*\n\n*bar*\n", "html": "<div>\n*foo*\n<p><em>bar</em></p>\n", "example": 155, "start_line": 2546, "end_line": 2555, "section": "HTML blocks" }, { "markdown": "<div id=\"foo\"\n*hi*\n", "html": "<div id=\"foo\"\n*hi*\n", "example": 156, "start_line": 2562, "end_line": 2568, "section": "HTML blocks" }, { "markdown": "<div class\nfoo\n", "html": "<div class\nfoo\n", "example": 157, "start_line": 2571, "end_line": 2577, "section": "HTML blocks" }, { "markdown": "<div *???-&&&-<---\n*foo*\n", "html": "<div *???-&&&-<---\n*foo*\n", "example": 158, "start_line": 2583, "end_line": 2589, "section": "HTML blocks" }, { "markdown": "<div><a href=\"bar\">*foo*</a></div>\n", "html": "<div><a href=\"bar\">*foo*</a></div>\n", "example": 159, "start_line": 2595, "end_line": 2599, "section": "HTML blocks" }, { "markdown": "<table><tr><td>\nfoo\n</td></tr></table>\n", "html": "<table><tr><td>\nfoo\n</td></tr></table>\n", "example": 160, "start_line": 2602, "end_line": 2610, "section": "HTML blocks" }, { "markdown": "<div></div>\n``` c\nint x = 33;\n```\n", "html": "<div></div>\n``` c\nint x = 33;\n```\n", "example": 161, "start_line": 2619, "end_line": 2629, "section": "HTML blocks" }, { "markdown": "<a href=\"foo\">\n*bar*\n</a>\n", "html": "<a href=\"foo\">\n*bar*\n</a>\n", "example": 162, "start_line": 2636, "end_line": 2644, "section": "HTML blocks" }, { "markdown": "<Warning>\n*bar*\n</Warning>\n", "html": "<Warning>\n*bar*\n</Warning>\n", "example": 163, "start_line": 2649, "end_line": 2657, "section": "HTML blocks" }, { "markdown": "<i class=\"foo\">\n*bar*\n</i>\n", "html": "<i class=\"foo\">\n*bar*\n</i>\n", "example": 164, "start_line": 2660, "end_line": 2668, "section": "HTML blocks" }, { "markdown": "</ins>\n*bar*\n", "html": "</ins>\n*bar*\n", "example": 165, "start_line": 2671, "end_line": 2677, "section": "HTML blocks" }, { "markdown": "<del>\n*foo*\n</del>\n", "html": "<del>\n*foo*\n</del>\n", "example": 166, "start_line": 2686, "end_line": 2694, "section": "HTML blocks" }, { "markdown": "<del>\n\n*foo*\n\n</del>\n", "html": "<del>\n<p><em>foo</em></p>\n</del>\n", "example": 167, "start_line": 2701, "end_line": 2711, "section": "HTML blocks" }, { "markdown": "<del>*foo*</del>\n", "html": "<p><del><em>foo</em></del></p>\n", "example": 168, "start_line": 2719, "end_line": 2723, "section": "HTML blocks" }, { "markdown": "<pre language=\"haskell\"><code>\nimport Text.HTML.TagSoup\n\nmain :: IO ()\nmain = print $ parseTags tags\n</code></pre>\nokay\n", "html": "<pre language=\"haskell\"><code>\nimport Text.HTML.TagSoup\n\nmain :: IO ()\nmain = print $ parseTags tags\n</code></pre>\n<p>okay</p>\n", "example": 169, "start_line": 2735, "end_line": 2751, "section": "HTML blocks" }, { "markdown": "<script type=\"text/javascript\">\n// JavaScript example\n\ndocument.getElementById(\"demo\").innerHTML = \"Hello JavaScript!\";\n</script>\nokay\n", "html": "<script type=\"text/javascript\">\n// JavaScript example\n\ndocument.getElementById(\"demo\").innerHTML = \"Hello JavaScript!\";\n</script>\n<p>okay</p>\n", "example": 170, "start_line": 2756, "end_line": 2770, "section": "HTML blocks" }, { "markdown": "<textarea>\n\n*foo*\n\n_bar_\n\n</textarea>\n", "html": "<textarea>\n\n*foo*\n\n_bar_\n\n</textarea>\n", "example": 171, "start_line": 2775, "end_line": 2791, "section": "HTML blocks" }, { "markdown": "<style\n type=\"text/css\">\nh1 {color:red;}\n\np {color:blue;}\n</style>\nokay\n", "html": "<style\n type=\"text/css\">\nh1 {color:red;}\n\np {color:blue;}\n</style>\n<p>okay</p>\n", "example": 172, "start_line": 2795, "end_line": 2811, "section": "HTML blocks" }, { "markdown": "<style\n type=\"text/css\">\n\nfoo\n", "html": "<style\n type=\"text/css\">\n\nfoo\n", "example": 173, "start_line": 2818, "end_line": 2828, "section": "HTML blocks" }, { "markdown": "> <div>\n> foo\n\nbar\n", "html": "<blockquote>\n<div>\nfoo\n</blockquote>\n<p>bar</p>\n", "example": 174, "start_line": 2831, "end_line": 2842, "section": "HTML blocks" }, { "markdown": "- <div>\n- foo\n", "html": "<ul>\n<li>\n<div>\n</li>\n<li>foo</li>\n</ul>\n", "example": 175, "start_line": 2845, "end_line": 2855, "section": "HTML blocks" }, { "markdown": "<style>p{color:red;}</style>\n*foo*\n", "html": "<style>p{color:red;}</style>\n<p><em>foo</em></p>\n", "example": 176, "start_line": 2860, "end_line": 2866, "section": "HTML blocks" }, { "markdown": "<!-- foo -->*bar*\n*baz*\n", "html": "<!-- foo -->*bar*\n<p><em>baz</em></p>\n", "example": 177, "start_line": 2869, "end_line": 2875, "section": "HTML blocks" }, { "markdown": "<script>\nfoo\n</script>1. *bar*\n", "html": "<script>\nfoo\n</script>1. *bar*\n", "example": 178, "start_line": 2881, "end_line": 2889, "section": "HTML blocks" }, { "markdown": "<!-- Foo\n\nbar\n baz -->\nokay\n", "html": "<!-- Foo\n\nbar\n baz -->\n<p>okay</p>\n", "example": 179, "start_line": 2894, "end_line": 2906, "section": "HTML blocks" }, { "markdown": "<?php\n\n echo '>';\n\n?>\nokay\n", "html": "<?php\n\n echo '>';\n\n?>\n<p>okay</p>\n", "example": 180, "start_line": 2912, "end_line": 2926, "section": "HTML blocks" }, { "markdown": "<!DOCTYPE html>\n", "html": "<!DOCTYPE html>\n", "example": 181, "start_line": 2931, "end_line": 2935, "section": "HTML blocks" }, { "markdown": "<![CDATA[\nfunction matchwo(a,b)\n{\n if (a < b && a < 0) then {\n return 1;\n\n } else {\n\n return 0;\n }\n}\n]]>\nokay\n", "html": "<![CDATA[\nfunction matchwo(a,b)\n{\n if (a < b && a < 0) then {\n return 1;\n\n } else {\n\n return 0;\n }\n}\n]]>\n<p>okay</p>\n", "example": 182, "start_line": 2940, "end_line": 2968, "section": "HTML blocks" }, { "markdown": " <!-- foo -->\n\n <!-- foo -->\n", "html": " <!-- foo -->\n<pre><code><!-- foo -->\n</code></pre>\n", "example": 183, "start_line": 2974, "end_line": 2982, "section": "HTML blocks" }, { "markdown": " <div>\n\n <div>\n", "html": " <div>\n<pre><code><div>\n</code></pre>\n", "example": 184, "start_line": 2985, "end_line": 2993, "section": "HTML blocks" }, { "markdown": "Foo\n<div>\nbar\n</div>\n", "html": "<p>Foo</p>\n<div>\nbar\n</div>\n", "example": 185, "start_line": 2999, "end_line": 3009, "section": "HTML blocks" }, { "markdown": "<div>\nbar\n</div>\n*foo*\n", "html": "<div>\nbar\n</div>\n*foo*\n", "example": 186, "start_line": 3016, "end_line": 3026, "section": "HTML blocks" }, { "markdown": "Foo\n<a href=\"bar\">\nbaz\n", "html": "<p>Foo\n<a href=\"bar\">\nbaz</p>\n", "example": 187, "start_line": 3031, "end_line": 3039, "section": "HTML blocks" }, { "markdown": "<div>\n\n*Emphasized* text.\n\n</div>\n", "html": "<div>\n<p><em>Emphasized</em> text.</p>\n</div>\n", "example": 188, "start_line": 3072, "end_line": 3082, "section": "HTML blocks" }, { "markdown": "<div>\n*Emphasized* text.\n</div>\n", "html": "<div>\n*Emphasized* text.\n</div>\n", "example": 189, "start_line": 3085, "end_line": 3093, "section": "HTML blocks" }, { "markdown": "<table>\n\n<tr>\n\n<td>\nHi\n</td>\n\n</tr>\n\n</table>\n", "html": "<table>\n<tr>\n<td>\nHi\n</td>\n</tr>\n</table>\n", "example": 190, "start_line": 3107, "end_line": 3127, "section": "HTML blocks" }, { "markdown": "<table>\n\n <tr>\n\n <td>\n Hi\n </td>\n\n </tr>\n\n</table>\n", "html": "<table>\n <tr>\n<pre><code><td>\n Hi\n</td>\n</code></pre>\n </tr>\n</table>\n", "example": 191, "start_line": 3134, "end_line": 3155, "section": "HTML blocks" }, { "markdown": "[foo]: /url \"title\"\n\n[foo]\n", "html": "<p><a href=\"/url\" title=\"title\">foo</a></p>\n", "example": 192, "start_line": 3183, "end_line": 3189, "section": "Link reference definitions" }, { "markdown": " [foo]: \n /url \n 'the title' \n\n[foo]\n", "html": "<p><a href=\"/url\" title=\"the title\">foo</a></p>\n", "example": 193, "start_line": 3192, "end_line": 3200, "section": "Link reference definitions" }, { "markdown": "[Foo*bar\\]]:my_(url) 'title (with parens)'\n\n[Foo*bar\\]]\n", "html": "<p><a href=\"my_(url)\" title=\"title (with parens)\">Foo*bar]</a></p>\n", "example": 194, "start_line": 3203, "end_line": 3209, "section": "Link reference definitions" }, { "markdown": "[Foo bar]:\n<my url>\n'title'\n\n[Foo bar]\n", "html": "<p><a href=\"my%20url\" title=\"title\">Foo bar</a></p>\n", "example": 195, "start_line": 3212, "end_line": 3220, "section": "Link reference definitions" }, { "markdown": "[foo]: /url '\ntitle\nline1\nline2\n'\n\n[foo]\n", "html": "<p><a href=\"/url\" title=\"\ntitle\nline1\nline2\n\">foo</a></p>\n", "example": 196, "start_line": 3225, "end_line": 3239, "section": "Link reference definitions" }, { "markdown": "[foo]: /url 'title\n\nwith blank line'\n\n[foo]\n", "html": "<p>[foo]: /url 'title</p>\n<p>with blank line'</p>\n<p>[foo]</p>\n", "example": 197, "start_line": 3244, "end_line": 3254, "section": "Link reference definitions" }, { "markdown": "[foo]:\n/url\n\n[foo]\n", "html": "<p><a href=\"/url\">foo</a></p>\n", "example": 198, "start_line": 3259, "end_line": 3266, "section": "Link reference definitions" }, { "markdown": "[foo]:\n\n[foo]\n", "html": "<p>[foo]:</p>\n<p>[foo]</p>\n", "example": 199, "start_line": 3271, "end_line": 3278, "section": "Link reference definitions" }, { "markdown": "[foo]: <>\n\n[foo]\n", "html": "<p><a href=\"\">foo</a></p>\n", "example": 200, "start_line": 3283, "end_line": 3289, "section": "Link reference definitions" }, { "markdown": "[foo]: <bar>(baz)\n\n[foo]\n", "html": "<p>[foo]: <bar>(baz)</p>\n<p>[foo]</p>\n", "example": 201, "start_line": 3294, "end_line": 3301, "section": "Link reference definitions" }, { "markdown": "[foo]: /url\\bar\\*baz \"foo\\\"bar\\baz\"\n\n[foo]\n", "html": "<p><a href=\"/url%5Cbar*baz\" title=\"foo"bar\\baz\">foo</a></p>\n", "example": 202, "start_line": 3307, "end_line": 3313, "section": "Link reference definitions" }, { "markdown": "[foo]\n\n[foo]: url\n", "html": "<p><a href=\"url\">foo</a></p>\n", "example": 203, "start_line": 3318, "end_line": 3324, "section": "Link reference definitions" }, { "markdown": "[foo]\n\n[foo]: first\n[foo]: second\n", "html": "<p><a href=\"first\">foo</a></p>\n", "example": 204, "start_line": 3330, "end_line": 3337, "section": "Link reference definitions" }, { "markdown": "[FOO]: /url\n\n[Foo]\n", "html": "<p><a href=\"/url\">Foo</a></p>\n", "example": 205, "start_line": 3343, "end_line": 3349, "section": "Link reference definitions" }, { "markdown": "[ΑΓΩ]: /φου\n\n[αγω]\n", "html": "<p><a href=\"/%CF%86%CE%BF%CF%85\">αγω</a></p>\n", "example": 206, "start_line": 3352, "end_line": 3358, "section": "Link reference definitions" }, { "markdown": "[foo]: /url\n", "html": "", "example": 207, "start_line": 3367, "end_line": 3370, "section": "Link reference definitions" }, { "markdown": "[\nfoo\n]: /url\nbar\n", "html": "<p>bar</p>\n", "example": 208, "start_line": 3375, "end_line": 3382, "section": "Link reference definitions" }, { "markdown": "[foo]: /url \"title\" ok\n", "html": "<p>[foo]: /url "title" ok</p>\n", "example": 209, "start_line": 3388, "end_line": 3392, "section": "Link reference definitions" }, { "markdown": "[foo]: /url\n\"title\" ok\n", "html": "<p>"title" ok</p>\n", "example": 210, "start_line": 3397, "end_line": 3402, "section": "Link reference definitions" }, { "markdown": " [foo]: /url \"title\"\n\n[foo]\n", "html": "<pre><code>[foo]: /url "title"\n</code></pre>\n<p>[foo]</p>\n", "example": 211, "start_line": 3408, "end_line": 3416, "section": "Link reference definitions" }, { "markdown": "```\n[foo]: /url\n```\n\n[foo]\n", "html": "<pre><code>[foo]: /url\n</code></pre>\n<p>[foo]</p>\n", "example": 212, "start_line": 3422, "end_line": 3432, "section": "Link reference definitions" }, { "markdown": "Foo\n[bar]: /baz\n\n[bar]\n", "html": "<p>Foo\n[bar]: /baz</p>\n<p>[bar]</p>\n", "example": 213, "start_line": 3437, "end_line": 3446, "section": "Link reference definitions" }, { "markdown": "# [Foo]\n[foo]: /url\n> bar\n", "html": "<h1><a href=\"/url\">Foo</a></h1>\n<blockquote>\n<p>bar</p>\n</blockquote>\n", "example": 214, "start_line": 3452, "end_line": 3461, "section": "Link reference definitions" }, { "markdown": "[foo]: /url\nbar\n===\n[foo]\n", "html": "<h1>bar</h1>\n<p><a href=\"/url\">foo</a></p>\n", "example": 215, "start_line": 3463, "end_line": 3471, "section": "Link reference definitions" }, { "markdown": "[foo]: /url\n===\n[foo]\n", "html": "<p>===\n<a href=\"/url\">foo</a></p>\n", "example": 216, "start_line": 3473, "end_line": 3480, "section": "Link reference definitions" }, { "markdown": "[foo]: /foo-url \"foo\"\n[bar]: /bar-url\n \"bar\"\n[baz]: /baz-url\n\n[foo],\n[bar],\n[baz]\n", "html": "<p><a href=\"/foo-url\" title=\"foo\">foo</a>,\n<a href=\"/bar-url\" title=\"bar\">bar</a>,\n<a href=\"/baz-url\">baz</a></p>\n", "example": 217, "start_line": 3486, "end_line": 3499, "section": "Link reference definitions" }, { "markdown": "[foo]\n\n> [foo]: /url\n", "html": "<p><a href=\"/url\">foo</a></p>\n<blockquote>\n</blockquote>\n", "example": 218, "start_line": 3507, "end_line": 3515, "section": "Link reference definitions" }, { "markdown": "aaa\n\nbbb\n", "html": "<p>aaa</p>\n<p>bbb</p>\n", "example": 219, "start_line": 3529, "end_line": 3536, "section": "Paragraphs" }, { "markdown": "aaa\nbbb\n\nccc\nddd\n", "html": "<p>aaa\nbbb</p>\n<p>ccc\nddd</p>\n", "example": 220, "start_line": 3541, "end_line": 3552, "section": "Paragraphs" }, { "markdown": "aaa\n\n\nbbb\n", "html": "<p>aaa</p>\n<p>bbb</p>\n", "example": 221, "start_line": 3557, "end_line": 3565, "section": "Paragraphs" }, { "markdown": " aaa\n bbb\n", "html": "<p>aaa\nbbb</p>\n", "example": 222, "start_line": 3570, "end_line": 3576, "section": "Paragraphs" }, { "markdown": "aaa\n bbb\n ccc\n", "html": "<p>aaa\nbbb\nccc</p>\n", "example": 223, "start_line": 3582, "end_line": 3590, "section": "Paragraphs" }, { "markdown": " aaa\nbbb\n", "html": "<p>aaa\nbbb</p>\n", "example": 224, "start_line": 3596, "end_line": 3602, "section": "Paragraphs" }, { "markdown": " aaa\nbbb\n", "html": "<pre><code>aaa\n</code></pre>\n<p>bbb</p>\n", "example": 225, "start_line": 3605, "end_line": 3612, "section": "Paragraphs" }, { "markdown": "aaa \nbbb \n", "html": "<p>aaa<br />\nbbb</p>\n", "example": 226, "start_line": 3619, "end_line": 3625, "section": "Paragraphs" }, { "markdown": " \n\naaa\n \n\n# aaa\n\n \n", "html": "<p>aaa</p>\n<h1>aaa</h1>\n", "example": 227, "start_line": 3636, "end_line": 3648, "section": "Blank lines" }, { "markdown": "> # Foo\n> bar\n> baz\n", "html": "<blockquote>\n<h1>Foo</h1>\n<p>bar\nbaz</p>\n</blockquote>\n", "example": 228, "start_line": 3704, "end_line": 3714, "section": "Block quotes" }, { "markdown": "># Foo\n>bar\n> baz\n", "html": "<blockquote>\n<h1>Foo</h1>\n<p>bar\nbaz</p>\n</blockquote>\n", "example": 229, "start_line": 3719, "end_line": 3729, "section": "Block quotes" }, { "markdown": " > # Foo\n > bar\n > baz\n", "html": "<blockquote>\n<h1>Foo</h1>\n<p>bar\nbaz</p>\n</blockquote>\n", "example": 230, "start_line": 3734, "end_line": 3744, "section": "Block quotes" }, { "markdown": " > # Foo\n > bar\n > baz\n", "html": "<pre><code>> # Foo\n> bar\n> baz\n</code></pre>\n", "example": 231, "start_line": 3749, "end_line": 3758, "section": "Block quotes" }, { "markdown": "> # Foo\n> bar\nbaz\n", "html": "<blockquote>\n<h1>Foo</h1>\n<p>bar\nbaz</p>\n</blockquote>\n", "example": 232, "start_line": 3764, "end_line": 3774, "section": "Block quotes" }, { "markdown": "> bar\nbaz\n> foo\n", "html": "<blockquote>\n<p>bar\nbaz\nfoo</p>\n</blockquote>\n", "example": 233, "start_line": 3780, "end_line": 3790, "section": "Block quotes" }, { "markdown": "> foo\n---\n", "html": "<blockquote>\n<p>foo</p>\n</blockquote>\n<hr />\n", "example": 234, "start_line": 3804, "end_line": 3812, "section": "Block quotes" }, { "markdown": "> - foo\n- bar\n", "html": "<blockquote>\n<ul>\n<li>foo</li>\n</ul>\n</blockquote>\n<ul>\n<li>bar</li>\n</ul>\n", "example": 235, "start_line": 3824, "end_line": 3836, "section": "Block quotes" }, { "markdown": "> foo\n bar\n", "html": "<blockquote>\n<pre><code>foo\n</code></pre>\n</blockquote>\n<pre><code>bar\n</code></pre>\n", "example": 236, "start_line": 3842, "end_line": 3852, "section": "Block quotes" }, { "markdown": "> ```\nfoo\n```\n", "html": "<blockquote>\n<pre><code></code></pre>\n</blockquote>\n<p>foo</p>\n<pre><code></code></pre>\n", "example": 237, "start_line": 3855, "end_line": 3865, "section": "Block quotes" }, { "markdown": "> foo\n - bar\n", "html": "<blockquote>\n<p>foo\n- bar</p>\n</blockquote>\n", "example": 238, "start_line": 3871, "end_line": 3879, "section": "Block quotes" }, { "markdown": ">\n", "html": "<blockquote>\n</blockquote>\n", "example": 239, "start_line": 3895, "end_line": 3900, "section": "Block quotes" }, { "markdown": ">\n> \n> \n", "html": "<blockquote>\n</blockquote>\n", "example": 240, "start_line": 3903, "end_line": 3910, "section": "Block quotes" }, { "markdown": ">\n> foo\n> \n", "html": "<blockquote>\n<p>foo</p>\n</blockquote>\n", "example": 241, "start_line": 3915, "end_line": 3923, "section": "Block quotes" }, { "markdown": "> foo\n\n> bar\n", "html": "<blockquote>\n<p>foo</p>\n</blockquote>\n<blockquote>\n<p>bar</p>\n</blockquote>\n", "example": 242, "start_line": 3928, "end_line": 3939, "section": "Block quotes" }, { "markdown": "> foo\n> bar\n", "html": "<blockquote>\n<p>foo\nbar</p>\n</blockquote>\n", "example": 243, "start_line": 3950, "end_line": 3958, "section": "Block quotes" }, { "markdown": "> foo\n>\n> bar\n", "html": "<blockquote>\n<p>foo</p>\n<p>bar</p>\n</blockquote>\n", "example": 244, "start_line": 3963, "end_line": 3972, "section": "Block quotes" }, { "markdown": "foo\n> bar\n", "html": "<p>foo</p>\n<blockquote>\n<p>bar</p>\n</blockquote>\n", "example": 245, "start_line": 3977, "end_line": 3985, "section": "Block quotes" }, { "markdown": "> aaa\n***\n> bbb\n", "html": "<blockquote>\n<p>aaa</p>\n</blockquote>\n<hr />\n<blockquote>\n<p>bbb</p>\n</blockquote>\n", "example": 246, "start_line": 3991, "end_line": 4003, "section": "Block quotes" }, { "markdown": "> bar\nbaz\n", "html": "<blockquote>\n<p>bar\nbaz</p>\n</blockquote>\n", "example": 247, "start_line": 4009, "end_line": 4017, "section": "Block quotes" }, { "markdown": "> bar\n\nbaz\n", "html": "<blockquote>\n<p>bar</p>\n</blockquote>\n<p>baz</p>\n", "example": 248, "start_line": 4020, "end_line": 4029, "section": "Block quotes" }, { "markdown": "> bar\n>\nbaz\n", "html": "<blockquote>\n<p>bar</p>\n</blockquote>\n<p>baz</p>\n", "example": 249, "start_line": 4032, "end_line": 4041, "section": "Block quotes" }, { "markdown": "> > > foo\nbar\n", "html": "<blockquote>\n<blockquote>\n<blockquote>\n<p>foo\nbar</p>\n</blockquote>\n</blockquote>\n</blockquote>\n", "example": 250, "start_line": 4048, "end_line": 4060, "section": "Block quotes" }, { "markdown": ">>> foo\n> bar\n>>baz\n", "html": "<blockquote>\n<blockquote>\n<blockquote>\n<p>foo\nbar\nbaz</p>\n</blockquote>\n</blockquote>\n</blockquote>\n", "example": 251, "start_line": 4063, "end_line": 4077, "section": "Block quotes" }, { "markdown": "> code\n\n> not code\n", "html": "<blockquote>\n<pre><code>code\n</code></pre>\n</blockquote>\n<blockquote>\n<p>not code</p>\n</blockquote>\n", "example": 252, "start_line": 4085, "end_line": 4097, "section": "Block quotes" }, { "markdown": "A paragraph\nwith two lines.\n\n indented code\n\n> A block quote.\n", "html": "<p>A paragraph\nwith two lines.</p>\n<pre><code>indented code\n</code></pre>\n<blockquote>\n<p>A block quote.</p>\n</blockquote>\n", "example": 253, "start_line": 4139, "end_line": 4154, "section": "List items" }, { "markdown": "1. A paragraph\n with two lines.\n\n indented code\n\n > A block quote.\n", "html": "<ol>\n<li>\n<p>A paragraph\nwith two lines.</p>\n<pre><code>indented code\n</code></pre>\n<blockquote>\n<p>A block quote.</p>\n</blockquote>\n</li>\n</ol>\n", "example": 254, "start_line": 4161, "end_line": 4180, "section": "List items" }, { "markdown": "- one\n\n two\n", "html": "<ul>\n<li>one</li>\n</ul>\n<p>two</p>\n", "example": 255, "start_line": 4194, "end_line": 4203, "section": "List items" }, { "markdown": "- one\n\n two\n", "html": "<ul>\n<li>\n<p>one</p>\n<p>two</p>\n</li>\n</ul>\n", "example": 256, "start_line": 4206, "end_line": 4217, "section": "List items" }, { "markdown": " - one\n\n two\n", "html": "<ul>\n<li>one</li>\n</ul>\n<pre><code> two\n</code></pre>\n", "example": 257, "start_line": 4220, "end_line": 4230, "section": "List items" }, { "markdown": " - one\n\n two\n", "html": "<ul>\n<li>\n<p>one</p>\n<p>two</p>\n</li>\n</ul>\n", "example": 258, "start_line": 4233, "end_line": 4244, "section": "List items" }, { "markdown": " > > 1. one\n>>\n>> two\n", "html": "<blockquote>\n<blockquote>\n<ol>\n<li>\n<p>one</p>\n<p>two</p>\n</li>\n</ol>\n</blockquote>\n</blockquote>\n", "example": 259, "start_line": 4255, "end_line": 4270, "section": "List items" }, { "markdown": ">>- one\n>>\n > > two\n", "html": "<blockquote>\n<blockquote>\n<ul>\n<li>one</li>\n</ul>\n<p>two</p>\n</blockquote>\n</blockquote>\n", "example": 260, "start_line": 4282, "end_line": 4295, "section": "List items" }, { "markdown": "-one\n\n2.two\n", "html": "<p>-one</p>\n<p>2.two</p>\n", "example": 261, "start_line": 4301, "end_line": 4308, "section": "List items" }, { "markdown": "- foo\n\n\n bar\n", "html": "<ul>\n<li>\n<p>foo</p>\n<p>bar</p>\n</li>\n</ul>\n", "example": 262, "start_line": 4314, "end_line": 4326, "section": "List items" }, { "markdown": "1. foo\n\n ```\n bar\n ```\n\n baz\n\n > bam\n", "html": "<ol>\n<li>\n<p>foo</p>\n<pre><code>bar\n</code></pre>\n<p>baz</p>\n<blockquote>\n<p>bam</p>\n</blockquote>\n</li>\n</ol>\n", "example": 263, "start_line": 4331, "end_line": 4353, "section": "List items" }, { "markdown": "- Foo\n\n bar\n\n\n baz\n", "html": "<ul>\n<li>\n<p>Foo</p>\n<pre><code>bar\n\n\nbaz\n</code></pre>\n</li>\n</ul>\n", "example": 264, "start_line": 4359, "end_line": 4377, "section": "List items" }, { "markdown": "123456789. ok\n", "html": "<ol start=\"123456789\">\n<li>ok</li>\n</ol>\n", "example": 265, "start_line": 4381, "end_line": 4387, "section": "List items" }, { "markdown": "1234567890. not ok\n", "html": "<p>1234567890. not ok</p>\n", "example": 266, "start_line": 4390, "end_line": 4394, "section": "List items" }, { "markdown": "0. ok\n", "html": "<ol start=\"0\">\n<li>ok</li>\n</ol>\n", "example": 267, "start_line": 4399, "end_line": 4405, "section": "List items" }, { "markdown": "003. ok\n", "html": "<ol start=\"3\">\n<li>ok</li>\n</ol>\n", "example": 268, "start_line": 4408, "end_line": 4414, "section": "List items" }, { "markdown": "-1. not ok\n", "html": "<p>-1. not ok</p>\n", "example": 269, "start_line": 4419, "end_line": 4423, "section": "List items" }, { "markdown": "- foo\n\n bar\n", "html": "<ul>\n<li>\n<p>foo</p>\n<pre><code>bar\n</code></pre>\n</li>\n</ul>\n", "example": 270, "start_line": 4442, "end_line": 4454, "section": "List items" }, { "markdown": " 10. foo\n\n bar\n", "html": "<ol start=\"10\">\n<li>\n<p>foo</p>\n<pre><code>bar\n</code></pre>\n</li>\n</ol>\n", "example": 271, "start_line": 4459, "end_line": 4471, "section": "List items" }, { "markdown": " indented code\n\nparagraph\n\n more code\n", "html": "<pre><code>indented code\n</code></pre>\n<p>paragraph</p>\n<pre><code>more code\n</code></pre>\n", "example": 272, "start_line": 4478, "end_line": 4490, "section": "List items" }, { "markdown": "1. indented code\n\n paragraph\n\n more code\n", "html": "<ol>\n<li>\n<pre><code>indented code\n</code></pre>\n<p>paragraph</p>\n<pre><code>more code\n</code></pre>\n</li>\n</ol>\n", "example": 273, "start_line": 4493, "end_line": 4509, "section": "List items" }, { "markdown": "1. indented code\n\n paragraph\n\n more code\n", "html": "<ol>\n<li>\n<pre><code> indented code\n</code></pre>\n<p>paragraph</p>\n<pre><code>more code\n</code></pre>\n</li>\n</ol>\n", "example": 274, "start_line": 4515, "end_line": 4531, "section": "List items" }, { "markdown": " foo\n\nbar\n", "html": "<p>foo</p>\n<p>bar</p>\n", "example": 275, "start_line": 4542, "end_line": 4549, "section": "List items" }, { "markdown": "- foo\n\n bar\n", "html": "<ul>\n<li>foo</li>\n</ul>\n<p>bar</p>\n", "example": 276, "start_line": 4552, "end_line": 4561, "section": "List items" }, { "markdown": "- foo\n\n bar\n", "html": "<ul>\n<li>\n<p>foo</p>\n<p>bar</p>\n</li>\n</ul>\n", "example": 277, "start_line": 4569, "end_line": 4580, "section": "List items" }, { "markdown": "-\n foo\n-\n ```\n bar\n ```\n-\n baz\n", "html": "<ul>\n<li>foo</li>\n<li>\n<pre><code>bar\n</code></pre>\n</li>\n<li>\n<pre><code>baz\n</code></pre>\n</li>\n</ul>\n", "example": 278, "start_line": 4596, "end_line": 4617, "section": "List items" }, { "markdown": "- \n foo\n", "html": "<ul>\n<li>foo</li>\n</ul>\n", "example": 279, "start_line": 4622, "end_line": 4629, "section": "List items" }, { "markdown": "-\n\n foo\n", "html": "<ul>\n<li></li>\n</ul>\n<p>foo</p>\n", "example": 280, "start_line": 4636, "end_line": 4645, "section": "List items" }, { "markdown": "- foo\n-\n- bar\n", "html": "<ul>\n<li>foo</li>\n<li></li>\n<li>bar</li>\n</ul>\n", "example": 281, "start_line": 4650, "end_line": 4660, "section": "List items" }, { "markdown": "- foo\n- \n- bar\n", "html": "<ul>\n<li>foo</li>\n<li></li>\n<li>bar</li>\n</ul>\n", "example": 282, "start_line": 4665, "end_line": 4675, "section": "List items" }, { "markdown": "1. foo\n2.\n3. bar\n", "html": "<ol>\n<li>foo</li>\n<li></li>\n<li>bar</li>\n</ol>\n", "example": 283, "start_line": 4680, "end_line": 4690, "section": "List items" }, { "markdown": "*\n", "html": "<ul>\n<li></li>\n</ul>\n", "example": 284, "start_line": 4695, "end_line": 4701, "section": "List items" }, { "markdown": "foo\n*\n\nfoo\n1.\n", "html": "<p>foo\n*</p>\n<p>foo\n1.</p>\n", "example": 285, "start_line": 4705, "end_line": 4716, "section": "List items" }, { "markdown": " 1. A paragraph\n with two lines.\n\n indented code\n\n > A block quote.\n", "html": "<ol>\n<li>\n<p>A paragraph\nwith two lines.</p>\n<pre><code>indented code\n</code></pre>\n<blockquote>\n<p>A block quote.</p>\n</blockquote>\n</li>\n</ol>\n", "example": 286, "start_line": 4727, "end_line": 4746, "section": "List items" }, { "markdown": " 1. A paragraph\n with two lines.\n\n indented code\n\n > A block quote.\n", "html": "<ol>\n<li>\n<p>A paragraph\nwith two lines.</p>\n<pre><code>indented code\n</code></pre>\n<blockquote>\n<p>A block quote.</p>\n</blockquote>\n</li>\n</ol>\n", "example": 287, "start_line": 4751, "end_line": 4770, "section": "List items" }, { "markdown": " 1. A paragraph\n with two lines.\n\n indented code\n\n > A block quote.\n", "html": "<ol>\n<li>\n<p>A paragraph\nwith two lines.</p>\n<pre><code>indented code\n</code></pre>\n<blockquote>\n<p>A block quote.</p>\n</blockquote>\n</li>\n</ol>\n", "example": 288, "start_line": 4775, "end_line": 4794, "section": "List items" }, { "markdown": " 1. A paragraph\n with two lines.\n\n indented code\n\n > A block quote.\n", "html": "<pre><code>1. A paragraph\n with two lines.\n\n indented code\n\n > A block quote.\n</code></pre>\n", "example": 289, "start_line": 4799, "end_line": 4814, "section": "List items" }, { "markdown": " 1. A paragraph\nwith two lines.\n\n indented code\n\n > A block quote.\n", "html": "<ol>\n<li>\n<p>A paragraph\nwith two lines.</p>\n<pre><code>indented code\n</code></pre>\n<blockquote>\n<p>A block quote.</p>\n</blockquote>\n</li>\n</ol>\n", "example": 290, "start_line": 4829, "end_line": 4848, "section": "List items" }, { "markdown": " 1. A paragraph\n with two lines.\n", "html": "<ol>\n<li>A paragraph\nwith two lines.</li>\n</ol>\n", "example": 291, "start_line": 4853, "end_line": 4861, "section": "List items" }, { "markdown": "> 1. > Blockquote\ncontinued here.\n", "html": "<blockquote>\n<ol>\n<li>\n<blockquote>\n<p>Blockquote\ncontinued here.</p>\n</blockquote>\n</li>\n</ol>\n</blockquote>\n", "example": 292, "start_line": 4866, "end_line": 4880, "section": "List items" }, { "markdown": "> 1. > Blockquote\n> continued here.\n", "html": "<blockquote>\n<ol>\n<li>\n<blockquote>\n<p>Blockquote\ncontinued here.</p>\n</blockquote>\n</li>\n</ol>\n</blockquote>\n", "example": 293, "start_line": 4883, "end_line": 4897, "section": "List items" }, { "markdown": "- foo\n - bar\n - baz\n - boo\n", "html": "<ul>\n<li>foo\n<ul>\n<li>bar\n<ul>\n<li>baz\n<ul>\n<li>boo</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n", "example": 294, "start_line": 4911, "end_line": 4932, "section": "List items" }, { "markdown": "- foo\n - bar\n - baz\n - boo\n", "html": "<ul>\n<li>foo</li>\n<li>bar</li>\n<li>baz</li>\n<li>boo</li>\n</ul>\n", "example": 295, "start_line": 4937, "end_line": 4949, "section": "List items" }, { "markdown": "10) foo\n - bar\n", "html": "<ol start=\"10\">\n<li>foo\n<ul>\n<li>bar</li>\n</ul>\n</li>\n</ol>\n", "example": 296, "start_line": 4954, "end_line": 4965, "section": "List items" }, { "markdown": "10) foo\n - bar\n", "html": "<ol start=\"10\">\n<li>foo</li>\n</ol>\n<ul>\n<li>bar</li>\n</ul>\n", "example": 297, "start_line": 4970, "end_line": 4980, "section": "List items" }, { "markdown": "- - foo\n", "html": "<ul>\n<li>\n<ul>\n<li>foo</li>\n</ul>\n</li>\n</ul>\n", "example": 298, "start_line": 4985, "end_line": 4995, "section": "List items" }, { "markdown": "1. - 2. foo\n", "html": "<ol>\n<li>\n<ul>\n<li>\n<ol start=\"2\">\n<li>foo</li>\n</ol>\n</li>\n</ul>\n</li>\n</ol>\n", "example": 299, "start_line": 4998, "end_line": 5012, "section": "List items" }, { "markdown": "- # Foo\n- Bar\n ---\n baz\n", "html": "<ul>\n<li>\n<h1>Foo</h1>\n</li>\n<li>\n<h2>Bar</h2>\nbaz</li>\n</ul>\n", "example": 300, "start_line": 5017, "end_line": 5031, "section": "List items" }, { "markdown": "- foo\n- bar\n+ baz\n", "html": "<ul>\n<li>foo</li>\n<li>bar</li>\n</ul>\n<ul>\n<li>baz</li>\n</ul>\n", "example": 301, "start_line": 5253, "end_line": 5265, "section": "Lists" }, { "markdown": "1. foo\n2. bar\n3) baz\n", "html": "<ol>\n<li>foo</li>\n<li>bar</li>\n</ol>\n<ol start=\"3\">\n<li>baz</li>\n</ol>\n", "example": 302, "start_line": 5268, "end_line": 5280, "section": "Lists" }, { "markdown": "Foo\n- bar\n- baz\n", "html": "<p>Foo</p>\n<ul>\n<li>bar</li>\n<li>baz</li>\n</ul>\n", "example": 303, "start_line": 5287, "end_line": 5297, "section": "Lists" }, { "markdown": "The number of windows in my house is\n14. The number of doors is 6.\n", "html": "<p>The number of windows in my house is\n14. The number of doors is 6.</p>\n", "example": 304, "start_line": 5364, "end_line": 5370, "section": "Lists" }, { "markdown": "The number of windows in my house is\n1. The number of doors is 6.\n", "html": "<p>The number of windows in my house is</p>\n<ol>\n<li>The number of doors is 6.</li>\n</ol>\n", "example": 305, "start_line": 5374, "end_line": 5382, "section": "Lists" }, { "markdown": "- foo\n\n- bar\n\n\n- baz\n", "html": "<ul>\n<li>\n<p>foo</p>\n</li>\n<li>\n<p>bar</p>\n</li>\n<li>\n<p>baz</p>\n</li>\n</ul>\n", "example": 306, "start_line": 5388, "end_line": 5407, "section": "Lists" }, { "markdown": "- foo\n - bar\n - baz\n\n\n bim\n", "html": "<ul>\n<li>foo\n<ul>\n<li>bar\n<ul>\n<li>\n<p>baz</p>\n<p>bim</p>\n</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n", "example": 307, "start_line": 5409, "end_line": 5431, "section": "Lists" }, { "markdown": "- foo\n- bar\n\n<!-- -->\n\n- baz\n- bim\n", "html": "<ul>\n<li>foo</li>\n<li>bar</li>\n</ul>\n<!-- -->\n<ul>\n<li>baz</li>\n<li>bim</li>\n</ul>\n", "example": 308, "start_line": 5439, "end_line": 5457, "section": "Lists" }, { "markdown": "- foo\n\n notcode\n\n- foo\n\n<!-- -->\n\n code\n", "html": "<ul>\n<li>\n<p>foo</p>\n<p>notcode</p>\n</li>\n<li>\n<p>foo</p>\n</li>\n</ul>\n<!-- -->\n<pre><code>code\n</code></pre>\n", "example": 309, "start_line": 5460, "end_line": 5483, "section": "Lists" }, { "markdown": "- a\n - b\n - c\n - d\n - e\n - f\n- g\n", "html": "<ul>\n<li>a</li>\n<li>b</li>\n<li>c</li>\n<li>d</li>\n<li>e</li>\n<li>f</li>\n<li>g</li>\n</ul>\n", "example": 310, "start_line": 5491, "end_line": 5509, "section": "Lists" }, { "markdown": "1. a\n\n 2. b\n\n 3. c\n", "html": "<ol>\n<li>\n<p>a</p>\n</li>\n<li>\n<p>b</p>\n</li>\n<li>\n<p>c</p>\n</li>\n</ol>\n", "example": 311, "start_line": 5512, "end_line": 5530, "section": "Lists" }, { "markdown": "- a\n - b\n - c\n - d\n - e\n", "html": "<ul>\n<li>a</li>\n<li>b</li>\n<li>c</li>\n<li>d\n- e</li>\n</ul>\n", "example": 312, "start_line": 5536, "end_line": 5550, "section": "Lists" }, { "markdown": "1. a\n\n 2. b\n\n 3. c\n", "html": "<ol>\n<li>\n<p>a</p>\n</li>\n<li>\n<p>b</p>\n</li>\n</ol>\n<pre><code>3. c\n</code></pre>\n", "example": 313, "start_line": 5556, "end_line": 5573, "section": "Lists" }, { "markdown": "- a\n- b\n\n- c\n", "html": "<ul>\n<li>\n<p>a</p>\n</li>\n<li>\n<p>b</p>\n</li>\n<li>\n<p>c</p>\n</li>\n</ul>\n", "example": 314, "start_line": 5579, "end_line": 5596, "section": "Lists" }, { "markdown": "* a\n*\n\n* c\n", "html": "<ul>\n<li>\n<p>a</p>\n</li>\n<li></li>\n<li>\n<p>c</p>\n</li>\n</ul>\n", "example": 315, "start_line": 5601, "end_line": 5616, "section": "Lists" }, { "markdown": "- a\n- b\n\n c\n- d\n", "html": "<ul>\n<li>\n<p>a</p>\n</li>\n<li>\n<p>b</p>\n<p>c</p>\n</li>\n<li>\n<p>d</p>\n</li>\n</ul>\n", "example": 316, "start_line": 5623, "end_line": 5642, "section": "Lists" }, { "markdown": "- a\n- b\n\n [ref]: /url\n- d\n", "html": "<ul>\n<li>\n<p>a</p>\n</li>\n<li>\n<p>b</p>\n</li>\n<li>\n<p>d</p>\n</li>\n</ul>\n", "example": 317, "start_line": 5645, "end_line": 5663, "section": "Lists" }, { "markdown": "- a\n- ```\n b\n\n\n ```\n- c\n", "html": "<ul>\n<li>a</li>\n<li>\n<pre><code>b\n\n\n</code></pre>\n</li>\n<li>c</li>\n</ul>\n", "example": 318, "start_line": 5668, "end_line": 5687, "section": "Lists" }, { "markdown": "- a\n - b\n\n c\n- d\n", "html": "<ul>\n<li>a\n<ul>\n<li>\n<p>b</p>\n<p>c</p>\n</li>\n</ul>\n</li>\n<li>d</li>\n</ul>\n", "example": 319, "start_line": 5694, "end_line": 5712, "section": "Lists" }, { "markdown": "* a\n > b\n >\n* c\n", "html": "<ul>\n<li>a\n<blockquote>\n<p>b</p>\n</blockquote>\n</li>\n<li>c</li>\n</ul>\n", "example": 320, "start_line": 5718, "end_line": 5732, "section": "Lists" }, { "markdown": "- a\n > b\n ```\n c\n ```\n- d\n", "html": "<ul>\n<li>a\n<blockquote>\n<p>b</p>\n</blockquote>\n<pre><code>c\n</code></pre>\n</li>\n<li>d</li>\n</ul>\n", "example": 321, "start_line": 5738, "end_line": 5756, "section": "Lists" }, { "markdown": "- a\n", "html": "<ul>\n<li>a</li>\n</ul>\n", "example": 322, "start_line": 5761, "end_line": 5767, "section": "Lists" }, { "markdown": "- a\n - b\n", "html": "<ul>\n<li>a\n<ul>\n<li>b</li>\n</ul>\n</li>\n</ul>\n", "example": 323, "start_line": 5770, "end_line": 5781, "section": "Lists" }, { "markdown": "1. ```\n foo\n ```\n\n bar\n", "html": "<ol>\n<li>\n<pre><code>foo\n</code></pre>\n<p>bar</p>\n</li>\n</ol>\n", "example": 324, "start_line": 5787, "end_line": 5801, "section": "Lists" }, { "markdown": "* foo\n * bar\n\n baz\n", "html": "<ul>\n<li>\n<p>foo</p>\n<ul>\n<li>bar</li>\n</ul>\n<p>baz</p>\n</li>\n</ul>\n", "example": 325, "start_line": 5806, "end_line": 5821, "section": "Lists" }, { "markdown": "- a\n - b\n - c\n\n- d\n - e\n - f\n", "html": "<ul>\n<li>\n<p>a</p>\n<ul>\n<li>b</li>\n<li>c</li>\n</ul>\n</li>\n<li>\n<p>d</p>\n<ul>\n<li>e</li>\n<li>f</li>\n</ul>\n</li>\n</ul>\n", "example": 326, "start_line": 5824, "end_line": 5849, "section": "Lists" }, { "markdown": "`hi`lo`\n", "html": "<p><code>hi</code>lo`</p>\n", "example": 327, "start_line": 5858, "end_line": 5862, "section": "Inlines" }, { "markdown": "`foo`\n", "html": "<p><code>foo</code></p>\n", "example": 328, "start_line": 5890, "end_line": 5894, "section": "Code spans" }, { "markdown": "`` foo ` bar ``\n", "html": "<p><code>foo ` bar</code></p>\n", "example": 329, "start_line": 5901, "end_line": 5905, "section": "Code spans" }, { "markdown": "` `` `\n", "html": "<p><code>``</code></p>\n", "example": 330, "start_line": 5911, "end_line": 5915, "section": "Code spans" }, { "markdown": "` `` `\n", "html": "<p><code> `` </code></p>\n", "example": 331, "start_line": 5919, "end_line": 5923, "section": "Code spans" }, { "markdown": "` a`\n", "html": "<p><code> a</code></p>\n", "example": 332, "start_line": 5928, "end_line": 5932, "section": "Code spans" }, { "markdown": "` b `\n", "html": "<p><code> b </code></p>\n", "example": 333, "start_line": 5937, "end_line": 5941, "section": "Code spans" }, { "markdown": "` `\n` `\n", "html": "<p><code> </code>\n<code> </code></p>\n", "example": 334, "start_line": 5945, "end_line": 5951, "section": "Code spans" }, { "markdown": "``\nfoo\nbar \nbaz\n``\n", "html": "<p><code>foo bar baz</code></p>\n", "example": 335, "start_line": 5956, "end_line": 5964, "section": "Code spans" }, { "markdown": "``\nfoo \n``\n", "html": "<p><code>foo </code></p>\n", "example": 336, "start_line": 5966, "end_line": 5972, "section": "Code spans" }, { "markdown": "`foo bar \nbaz`\n", "html": "<p><code>foo bar baz</code></p>\n", "example": 337, "start_line": 5977, "end_line": 5982, "section": "Code spans" }, { "markdown": "`foo\\`bar`\n", "html": "<p><code>foo\\</code>bar`</p>\n", "example": 338, "start_line": 5994, "end_line": 5998, "section": "Code spans" }, { "markdown": "``foo`bar``\n", "html": "<p><code>foo`bar</code></p>\n", "example": 339, "start_line": 6005, "end_line": 6009, "section": "Code spans" }, { "markdown": "` foo `` bar `\n", "html": "<p><code>foo `` bar</code></p>\n", "example": 340, "start_line": 6011, "end_line": 6015, "section": "Code spans" }, { "markdown": "*foo`*`\n", "html": "<p>*foo<code>*</code></p>\n", "example": 341, "start_line": 6023, "end_line": 6027, "section": "Code spans" }, { "markdown": "[not a `link](/foo`)\n", "html": "<p>[not a <code>link](/foo</code>)</p>\n", "example": 342, "start_line": 6032, "end_line": 6036, "section": "Code spans" }, { "markdown": "`<a href=\"`\">`\n", "html": "<p><code><a href="</code>">`</p>\n", "example": 343, "start_line": 6042, "end_line": 6046, "section": "Code spans" }, { "markdown": "<a href=\"`\">`\n", "html": "<p><a href=\"`\">`</p>\n", "example": 344, "start_line": 6051, "end_line": 6055, "section": "Code spans" }, { "markdown": "`<http://foo.bar.`baz>`\n", "html": "<p><code><http://foo.bar.</code>baz>`</p>\n", "example": 345, "start_line": 6060, "end_line": 6064, "section": "Code spans" }, { "markdown": "<http://foo.bar.`baz>`\n", "html": "<p><a href=\"http://foo.bar.%60baz\">http://foo.bar.`baz</a>`</p>\n", "example": 346, "start_line": 6069, "end_line": 6073, "section": "Code spans" }, { "markdown": "```foo``\n", "html": "<p>```foo``</p>\n", "example": 347, "start_line": 6079, "end_line": 6083, "section": "Code spans" }, { "markdown": "`foo\n", "html": "<p>`foo</p>\n", "example": 348, "start_line": 6086, "end_line": 6090, "section": "Code spans" }, { "markdown": "`foo``bar``\n", "html": "<p>`foo<code>bar</code></p>\n", "example": 349, "start_line": 6095, "end_line": 6099, "section": "Code spans" }, { "markdown": "*foo bar*\n", "html": "<p><em>foo bar</em></p>\n", "example": 350, "start_line": 6312, "end_line": 6316, "section": "Emphasis and strong emphasis" }, { "markdown": "a * foo bar*\n", "html": "<p>a * foo bar*</p>\n", "example": 351, "start_line": 6322, "end_line": 6326, "section": "Emphasis and strong emphasis" }, { "markdown": "a*\"foo\"*\n", "html": "<p>a*"foo"*</p>\n", "example": 352, "start_line": 6333, "end_line": 6337, "section": "Emphasis and strong emphasis" }, { "markdown": "* a *\n", "html": "<p>* a *</p>\n", "example": 353, "start_line": 6342, "end_line": 6346, "section": "Emphasis and strong emphasis" }, { "markdown": "foo*bar*\n", "html": "<p>foo<em>bar</em></p>\n", "example": 354, "start_line": 6351, "end_line": 6355, "section": "Emphasis and strong emphasis" }, { "markdown": "5*6*78\n", "html": "<p>5<em>6</em>78</p>\n", "example": 355, "start_line": 6358, "end_line": 6362, "section": "Emphasis and strong emphasis" }, { "markdown": "_foo bar_\n", "html": "<p><em>foo bar</em></p>\n", "example": 356, "start_line": 6367, "end_line": 6371, "section": "Emphasis and strong emphasis" }, { "markdown": "_ foo bar_\n", "html": "<p>_ foo bar_</p>\n", "example": 357, "start_line": 6377, "end_line": 6381, "section": "Emphasis and strong emphasis" }, { "markdown": "a_\"foo\"_\n", "html": "<p>a_"foo"_</p>\n", "example": 358, "start_line": 6387, "end_line": 6391, "section": "Emphasis and strong emphasis" }, { "markdown": "foo_bar_\n", "html": "<p>foo_bar_</p>\n", "example": 359, "start_line": 6396, "end_line": 6400, "section": "Emphasis and strong emphasis" }, { "markdown": "5_6_78\n", "html": "<p>5_6_78</p>\n", "example": 360, "start_line": 6403, "end_line": 6407, "section": "Emphasis and strong emphasis" }, { "markdown": "пристаням_стремятся_\n", "html": "<p>пристаням_стремятся_</p>\n", "example": 361, "start_line": 6410, "end_line": 6414, "section": "Emphasis and strong emphasis" }, { "markdown": "aa_\"bb\"_cc\n", "html": "<p>aa_"bb"_cc</p>\n", "example": 362, "start_line": 6420, "end_line": 6424, "section": "Emphasis and strong emphasis" }, { "markdown": "foo-_(bar)_\n", "html": "<p>foo-<em>(bar)</em></p>\n", "example": 363, "start_line": 6431, "end_line": 6435, "section": "Emphasis and strong emphasis" }, { "markdown": "_foo*\n", "html": "<p>_foo*</p>\n", "example": 364, "start_line": 6443, "end_line": 6447, "section": "Emphasis and strong emphasis" }, { "markdown": "*foo bar *\n", "html": "<p>*foo bar *</p>\n", "example": 365, "start_line": 6453, "end_line": 6457, "section": "Emphasis and strong emphasis" }, { "markdown": "*foo bar\n*\n", "html": "<p>*foo bar\n*</p>\n", "example": 366, "start_line": 6462, "end_line": 6468, "section": "Emphasis and strong emphasis" }, { "markdown": "*(*foo)\n", "html": "<p>*(*foo)</p>\n", "example": 367, "start_line": 6475, "end_line": 6479, "section": "Emphasis and strong emphasis" }, { "markdown": "*(*foo*)*\n", "html": "<p><em>(<em>foo</em>)</em></p>\n", "example": 368, "start_line": 6485, "end_line": 6489, "section": "Emphasis and strong emphasis" }, { "markdown": "*foo*bar\n", "html": "<p><em>foo</em>bar</p>\n", "example": 369, "start_line": 6494, "end_line": 6498, "section": "Emphasis and strong emphasis" }, { "markdown": "_foo bar _\n", "html": "<p>_foo bar _</p>\n", "example": 370, "start_line": 6507, "end_line": 6511, "section": "Emphasis and strong emphasis" }, { "markdown": "_(_foo)\n", "html": "<p>_(_foo)</p>\n", "example": 371, "start_line": 6517, "end_line": 6521, "section": "Emphasis and strong emphasis" }, { "markdown": "_(_foo_)_\n", "html": "<p><em>(<em>foo</em>)</em></p>\n", "example": 372, "start_line": 6526, "end_line": 6530, "section": "Emphasis and strong emphasis" }, { "markdown": "_foo_bar\n", "html": "<p>_foo_bar</p>\n", "example": 373, "start_line": 6535, "end_line": 6539, "section": "Emphasis and strong emphasis" }, { "markdown": "_пристаням_стремятся\n", "html": "<p>_пристаням_стремятся</p>\n", "example": 374, "start_line": 6542, "end_line": 6546, "section": "Emphasis and strong emphasis" }, { "markdown": "_foo_bar_baz_\n", "html": "<p><em>foo_bar_baz</em></p>\n", "example": 375, "start_line": 6549, "end_line": 6553, "section": "Emphasis and strong emphasis" }, { "markdown": "_(bar)_.\n", "html": "<p><em>(bar)</em>.</p>\n", "example": 376, "start_line": 6560, "end_line": 6564, "section": "Emphasis and strong emphasis" }, { "markdown": "**foo bar**\n", "html": "<p><strong>foo bar</strong></p>\n", "example": 377, "start_line": 6569, "end_line": 6573, "section": "Emphasis and strong emphasis" }, { "markdown": "** foo bar**\n", "html": "<p>** foo bar**</p>\n", "example": 378, "start_line": 6579, "end_line": 6583, "section": "Emphasis and strong emphasis" }, { "markdown": "a**\"foo\"**\n", "html": "<p>a**"foo"**</p>\n", "example": 379, "start_line": 6590, "end_line": 6594, "section": "Emphasis and strong emphasis" }, { "markdown": "foo**bar**\n", "html": "<p>foo<strong>bar</strong></p>\n", "example": 380, "start_line": 6599, "end_line": 6603, "section": "Emphasis and strong emphasis" }, { "markdown": "__foo bar__\n", "html": "<p><strong>foo bar</strong></p>\n", "example": 381, "start_line": 6608, "end_line": 6612, "section": "Emphasis and strong emphasis" }, { "markdown": "__ foo bar__\n", "html": "<p>__ foo bar__</p>\n", "example": 382, "start_line": 6618, "end_line": 6622, "section": "Emphasis and strong emphasis" }, { "markdown": "__\nfoo bar__\n", "html": "<p>__\nfoo bar__</p>\n", "example": 383, "start_line": 6626, "end_line": 6632, "section": "Emphasis and strong emphasis" }, { "markdown": "a__\"foo\"__\n", "html": "<p>a__"foo"__</p>\n", "example": 384, "start_line": 6638, "end_line": 6642, "section": "Emphasis and strong emphasis" }, { "markdown": "foo__bar__\n", "html": "<p>foo__bar__</p>\n", "example": 385, "start_line": 6647, "end_line": 6651, "section": "Emphasis and strong emphasis" }, { "markdown": "5__6__78\n", "html": "<p>5__6__78</p>\n", "example": 386, "start_line": 6654, "end_line": 6658, "section": "Emphasis and strong emphasis" }, { "markdown": "пристаням__стремятся__\n", "html": "<p>пристаням__стремятся__</p>\n", "example": 387, "start_line": 6661, "end_line": 6665, "section": "Emphasis and strong emphasis" }, { "markdown": "__foo, __bar__, baz__\n", "html": "<p><strong>foo, <strong>bar</strong>, baz</strong></p>\n", "example": 388, "start_line": 6668, "end_line": 6672, "section": "Emphasis and strong emphasis" }, { "markdown": "foo-__(bar)__\n", "html": "<p>foo-<strong>(bar)</strong></p>\n", "example": 389, "start_line": 6679, "end_line": 6683, "section": "Emphasis and strong emphasis" }, { "markdown": "**foo bar **\n", "html": "<p>**foo bar **</p>\n", "example": 390, "start_line": 6692, "end_line": 6696, "section": "Emphasis and strong emphasis" }, { "markdown": "**(**foo)\n", "html": "<p>**(**foo)</p>\n", "example": 391, "start_line": 6705, "end_line": 6709, "section": "Emphasis and strong emphasis" }, { "markdown": "*(**foo**)*\n", "html": "<p><em>(<strong>foo</strong>)</em></p>\n", "example": 392, "start_line": 6715, "end_line": 6719, "section": "Emphasis and strong emphasis" }, { "markdown": "**Gomphocarpus (*Gomphocarpus physocarpus*, syn.\n*Asclepias physocarpa*)**\n", "html": "<p><strong>Gomphocarpus (<em>Gomphocarpus physocarpus</em>, syn.\n<em>Asclepias physocarpa</em>)</strong></p>\n", "example": 393, "start_line": 6722, "end_line": 6728, "section": "Emphasis and strong emphasis" }, { "markdown": "**foo \"*bar*\" foo**\n", "html": "<p><strong>foo "<em>bar</em>" foo</strong></p>\n", "example": 394, "start_line": 6731, "end_line": 6735, "section": "Emphasis and strong emphasis" }, { "markdown": "**foo**bar\n", "html": "<p><strong>foo</strong>bar</p>\n", "example": 395, "start_line": 6740, "end_line": 6744, "section": "Emphasis and strong emphasis" }, { "markdown": "__foo bar __\n", "html": "<p>__foo bar __</p>\n", "example": 396, "start_line": 6752, "end_line": 6756, "section": "Emphasis and strong emphasis" }, { "markdown": "__(__foo)\n", "html": "<p>__(__foo)</p>\n", "example": 397, "start_line": 6762, "end_line": 6766, "section": "Emphasis and strong emphasis" }, { "markdown": "_(__foo__)_\n", "html": "<p><em>(<strong>foo</strong>)</em></p>\n", "example": 398, "start_line": 6772, "end_line": 6776, "section": "Emphasis and strong emphasis" }, { "markdown": "__foo__bar\n", "html": "<p>__foo__bar</p>\n", "example": 399, "start_line": 6781, "end_line": 6785, "section": "Emphasis and strong emphasis" }, { "markdown": "__пристаням__стремятся\n", "html": "<p>__пристаням__стремятся</p>\n", "example": 400, "start_line": 6788, "end_line": 6792, "section": "Emphasis and strong emphasis" }, { "markdown": "__foo__bar__baz__\n", "html": "<p><strong>foo__bar__baz</strong></p>\n", "example": 401, "start_line": 6795, "end_line": 6799, "section": "Emphasis and strong emphasis" }, { "markdown": "__(bar)__.\n", "html": "<p><strong>(bar)</strong>.</p>\n", "example": 402, "start_line": 6806, "end_line": 6810, "section": "Emphasis and strong emphasis" }, { "markdown": "*foo [bar](/url)*\n", "html": "<p><em>foo <a href=\"/url\">bar</a></em></p>\n", "example": 403, "start_line": 6818, "end_line": 6822, "section": "Emphasis and strong emphasis" }, { "markdown": "*foo\nbar*\n", "html": "<p><em>foo\nbar</em></p>\n", "example": 404, "start_line": 6825, "end_line": 6831, "section": "Emphasis and strong emphasis" }, { "markdown": "_foo __bar__ baz_\n", "html": "<p><em>foo <strong>bar</strong> baz</em></p>\n", "example": 405, "start_line": 6837, "end_line": 6841, "section": "Emphasis and strong emphasis" }, { "markdown": "_foo _bar_ baz_\n", "html": "<p><em>foo <em>bar</em> baz</em></p>\n", "example": 406, "start_line": 6844, "end_line": 6848, "section": "Emphasis and strong emphasis" }, { "markdown": "__foo_ bar_\n", "html": "<p><em><em>foo</em> bar</em></p>\n", "example": 407, "start_line": 6851, "end_line": 6855, "section": "Emphasis and strong emphasis" }, { "markdown": "*foo *bar**\n", "html": "<p><em>foo <em>bar</em></em></p>\n", "example": 408, "start_line": 6858, "end_line": 6862, "section": "Emphasis and strong emphasis" }, { "markdown": "*foo **bar** baz*\n", "html": "<p><em>foo <strong>bar</strong> baz</em></p>\n", "example": 409, "start_line": 6865, "end_line": 6869, "section": "Emphasis and strong emphasis" }, { "markdown": "*foo**bar**baz*\n", "html": "<p><em>foo<strong>bar</strong>baz</em></p>\n", "example": 410, "start_line": 6871, "end_line": 6875, "section": "Emphasis and strong emphasis" }, { "markdown": "*foo**bar*\n", "html": "<p><em>foo**bar</em></p>\n", "example": 411, "start_line": 6895, "end_line": 6899, "section": "Emphasis and strong emphasis" }, { "markdown": "***foo** bar*\n", "html": "<p><em><strong>foo</strong> bar</em></p>\n", "example": 412, "start_line": 6908, "end_line": 6912, "section": "Emphasis and strong emphasis" }, { "markdown": "*foo **bar***\n", "html": "<p><em>foo <strong>bar</strong></em></p>\n", "example": 413, "start_line": 6915, "end_line": 6919, "section": "Emphasis and strong emphasis" }, { "markdown": "*foo**bar***\n", "html": "<p><em>foo<strong>bar</strong></em></p>\n", "example": 414, "start_line": 6922, "end_line": 6926, "section": "Emphasis and strong emphasis" }, { "markdown": "foo***bar***baz\n", "html": "<p>foo<em><strong>bar</strong></em>baz</p>\n", "example": 415, "start_line": 6933, "end_line": 6937, "section": "Emphasis and strong emphasis" }, { "markdown": "foo******bar*********baz\n", "html": "<p>foo<strong><strong><strong>bar</strong></strong></strong>***baz</p>\n", "example": 416, "start_line": 6939, "end_line": 6943, "section": "Emphasis and strong emphasis" }, { "markdown": "*foo **bar *baz* bim** bop*\n", "html": "<p><em>foo <strong>bar <em>baz</em> bim</strong> bop</em></p>\n", "example": 417, "start_line": 6948, "end_line": 6952, "section": "Emphasis and strong emphasis" }, { "markdown": "*foo [*bar*](/url)*\n", "html": "<p><em>foo <a href=\"/url\"><em>bar</em></a></em></p>\n", "example": 418, "start_line": 6955, "end_line": 6959, "section": "Emphasis and strong emphasis" }, { "markdown": "** is not an empty emphasis\n", "html": "<p>** is not an empty emphasis</p>\n", "example": 419, "start_line": 6964, "end_line": 6968, "section": "Emphasis and strong emphasis" }, { "markdown": "**** is not an empty strong emphasis\n", "html": "<p>**** is not an empty strong emphasis</p>\n", "example": 420, "start_line": 6971, "end_line": 6975, "section": "Emphasis and strong emphasis" }, { "markdown": "**foo [bar](/url)**\n", "html": "<p><strong>foo <a href=\"/url\">bar</a></strong></p>\n", "example": 421, "start_line": 6984, "end_line": 6988, "section": "Emphasis and strong emphasis" }, { "markdown": "**foo\nbar**\n", "html": "<p><strong>foo\nbar</strong></p>\n", "example": 422, "start_line": 6991, "end_line": 6997, "section": "Emphasis and strong emphasis" }, { "markdown": "__foo _bar_ baz__\n", "html": "<p><strong>foo <em>bar</em> baz</strong></p>\n", "example": 423, "start_line": 7003, "end_line": 7007, "section": "Emphasis and strong emphasis" }, { "markdown": "__foo __bar__ baz__\n", "html": "<p><strong>foo <strong>bar</strong> baz</strong></p>\n", "example": 424, "start_line": 7010, "end_line": 7014, "section": "Emphasis and strong emphasis" }, { "markdown": "____foo__ bar__\n", "html": "<p><strong><strong>foo</strong> bar</strong></p>\n", "example": 425, "start_line": 7017, "end_line": 7021, "section": "Emphasis and strong emphasis" }, { "markdown": "**foo **bar****\n", "html": "<p><strong>foo <strong>bar</strong></strong></p>\n", "example": 426, "start_line": 7024, "end_line": 7028, "section": "Emphasis and strong emphasis" }, { "markdown": "**foo *bar* baz**\n", "html": "<p><strong>foo <em>bar</em> baz</strong></p>\n", "example": 427, "start_line": 7031, "end_line": 7035, "section": "Emphasis and strong emphasis" }, { "markdown": "**foo*bar*baz**\n", "html": "<p><strong>foo<em>bar</em>baz</strong></p>\n", "example": 428, "start_line": 7038, "end_line": 7042, "section": "Emphasis and strong emphasis" }, { "markdown": "***foo* bar**\n", "html": "<p><strong><em>foo</em> bar</strong></p>\n", "example": 429, "start_line": 7045, "end_line": 7049, "section": "Emphasis and strong emphasis" }, { "markdown": "**foo *bar***\n", "html": "<p><strong>foo <em>bar</em></strong></p>\n", "example": 430, "start_line": 7052, "end_line": 7056, "section": "Emphasis and strong emphasis" }, { "markdown": "**foo *bar **baz**\nbim* bop**\n", "html": "<p><strong>foo <em>bar <strong>baz</strong>\nbim</em> bop</strong></p>\n", "example": 431, "start_line": 7061, "end_line": 7067, "section": "Emphasis and strong emphasis" }, { "markdown": "**foo [*bar*](/url)**\n", "html": "<p><strong>foo <a href=\"/url\"><em>bar</em></a></strong></p>\n", "example": 432, "start_line": 7070, "end_line": 7074, "section": "Emphasis and strong emphasis" }, { "markdown": "__ is not an empty emphasis\n", "html": "<p>__ is not an empty emphasis</p>\n", "example": 433, "start_line": 7079, "end_line": 7083, "section": "Emphasis and strong emphasis" }, { "markdown": "____ is not an empty strong emphasis\n", "html": "<p>____ is not an empty strong emphasis</p>\n", "example": 434, "start_line": 7086, "end_line": 7090, "section": "Emphasis and strong emphasis" }, { "markdown": "foo ***\n", "html": "<p>foo ***</p>\n", "example": 435, "start_line": 7096, "end_line": 7100, "section": "Emphasis and strong emphasis" }, { "markdown": "foo *\\**\n", "html": "<p>foo <em>*</em></p>\n", "example": 436, "start_line": 7103, "end_line": 7107, "section": "Emphasis and strong emphasis" }, { "markdown": "foo *_*\n", "html": "<p>foo <em>_</em></p>\n", "example": 437, "start_line": 7110, "end_line": 7114, "section": "Emphasis and strong emphasis" }, { "markdown": "foo *****\n", "html": "<p>foo *****</p>\n", "example": 438, "start_line": 7117, "end_line": 7121, "section": "Emphasis and strong emphasis" }, { "markdown": "foo **\\***\n", "html": "<p>foo <strong>*</strong></p>\n", "example": 439, "start_line": 7124, "end_line": 7128, "section": "Emphasis and strong emphasis" }, { "markdown": "foo **_**\n", "html": "<p>foo <strong>_</strong></p>\n", "example": 440, "start_line": 7131, "end_line": 7135, "section": "Emphasis and strong emphasis" }, { "markdown": "**foo*\n", "html": "<p>*<em>foo</em></p>\n", "example": 441, "start_line": 7142, "end_line": 7146, "section": "Emphasis and strong emphasis" }, { "markdown": "*foo**\n", "html": "<p><em>foo</em>*</p>\n", "example": 442, "start_line": 7149, "end_line": 7153, "section": "Emphasis and strong emphasis" }, { "markdown": "***foo**\n", "html": "<p>*<strong>foo</strong></p>\n", "example": 443, "start_line": 7156, "end_line": 7160, "section": "Emphasis and strong emphasis" }, { "markdown": "****foo*\n", "html": "<p>***<em>foo</em></p>\n", "example": 444, "start_line": 7163, "end_line": 7167, "section": "Emphasis and strong emphasis" }, { "markdown": "**foo***\n", "html": "<p><strong>foo</strong>*</p>\n", "example": 445, "start_line": 7170, "end_line": 7174, "section": "Emphasis and strong emphasis" }, { "markdown": "*foo****\n", "html": "<p><em>foo</em>***</p>\n", "example": 446, "start_line": 7177, "end_line": 7181, "section": "Emphasis and strong emphasis" }, { "markdown": "foo ___\n", "html": "<p>foo ___</p>\n", "example": 447, "start_line": 7187, "end_line": 7191, "section": "Emphasis and strong emphasis" }, { "markdown": "foo _\\__\n", "html": "<p>foo <em>_</em></p>\n", "example": 448, "start_line": 7194, "end_line": 7198, "section": "Emphasis and strong emphasis" }, { "markdown": "foo _*_\n", "html": "<p>foo <em>*</em></p>\n", "example": 449, "start_line": 7201, "end_line": 7205, "section": "Emphasis and strong emphasis" }, { "markdown": "foo _____\n", "html": "<p>foo _____</p>\n", "example": 450, "start_line": 7208, "end_line": 7212, "section": "Emphasis and strong emphasis" }, { "markdown": "foo __\\___\n", "html": "<p>foo <strong>_</strong></p>\n", "example": 451, "start_line": 7215, "end_line": 7219, "section": "Emphasis and strong emphasis" }, { "markdown": "foo __*__\n", "html": "<p>foo <strong>*</strong></p>\n", "example": 452, "start_line": 7222, "end_line": 7226, "section": "Emphasis and strong emphasis" }, { "markdown": "__foo_\n", "html": "<p>_<em>foo</em></p>\n", "example": 453, "start_line": 7229, "end_line": 7233, "section": "Emphasis and strong emphasis" }, { "markdown": "_foo__\n", "html": "<p><em>foo</em>_</p>\n", "example": 454, "start_line": 7240, "end_line": 7244, "section": "Emphasis and strong emphasis" }, { "markdown": "___foo__\n", "html": "<p>_<strong>foo</strong></p>\n", "example": 455, "start_line": 7247, "end_line": 7251, "section": "Emphasis and strong emphasis" }, { "markdown": "____foo_\n", "html": "<p>___<em>foo</em></p>\n", "example": 456, "start_line": 7254, "end_line": 7258, "section": "Emphasis and strong emphasis" }, { "markdown": "__foo___\n", "html": "<p><strong>foo</strong>_</p>\n", "example": 457, "start_line": 7261, "end_line": 7265, "section": "Emphasis and strong emphasis" }, { "markdown": "_foo____\n", "html": "<p><em>foo</em>___</p>\n", "example": 458, "start_line": 7268, "end_line": 7272, "section": "Emphasis and strong emphasis" }, { "markdown": "**foo**\n", "html": "<p><strong>foo</strong></p>\n", "example": 459, "start_line": 7278, "end_line": 7282, "section": "Emphasis and strong emphasis" }, { "markdown": "*_foo_*\n", "html": "<p><em><em>foo</em></em></p>\n", "example": 460, "start_line": 7285, "end_line": 7289, "section": "Emphasis and strong emphasis" }, { "markdown": "__foo__\n", "html": "<p><strong>foo</strong></p>\n", "example": 461, "start_line": 7292, "end_line": 7296, "section": "Emphasis and strong emphasis" }, { "markdown": "_*foo*_\n", "html": "<p><em><em>foo</em></em></p>\n", "example": 462, "start_line": 7299, "end_line": 7303, "section": "Emphasis and strong emphasis" }, { "markdown": "****foo****\n", "html": "<p><strong><strong>foo</strong></strong></p>\n", "example": 463, "start_line": 7309, "end_line": 7313, "section": "Emphasis and strong emphasis" }, { "markdown": "____foo____\n", "html": "<p><strong><strong>foo</strong></strong></p>\n", "example": 464, "start_line": 7316, "end_line": 7320, "section": "Emphasis and strong emphasis" }, { "markdown": "******foo******\n", "html": "<p><strong><strong><strong>foo</strong></strong></strong></p>\n", "example": 465, "start_line": 7327, "end_line": 7331, "section": "Emphasis and strong emphasis" }, { "markdown": "***foo***\n", "html": "<p><em><strong>foo</strong></em></p>\n", "example": 466, "start_line": 7336, "end_line": 7340, "section": "Emphasis and strong emphasis" }, { "markdown": "_____foo_____\n", "html": "<p><em><strong><strong>foo</strong></strong></em></p>\n", "example": 467, "start_line": 7343, "end_line": 7347, "section": "Emphasis and strong emphasis" }, { "markdown": "*foo _bar* baz_\n", "html": "<p><em>foo _bar</em> baz_</p>\n", "example": 468, "start_line": 7352, "end_line": 7356, "section": "Emphasis and strong emphasis" }, { "markdown": "*foo __bar *baz bim__ bam*\n", "html": "<p><em>foo <strong>bar *baz bim</strong> bam</em></p>\n", "example": 469, "start_line": 7359, "end_line": 7363, "section": "Emphasis and strong emphasis" }, { "markdown": "**foo **bar baz**\n", "html": "<p>**foo <strong>bar baz</strong></p>\n", "example": 470, "start_line": 7368, "end_line": 7372, "section": "Emphasis and strong emphasis" }, { "markdown": "*foo *bar baz*\n", "html": "<p>*foo <em>bar baz</em></p>\n", "example": 471, "start_line": 7375, "end_line": 7379, "section": "Emphasis and strong emphasis" }, { "markdown": "*[bar*](/url)\n", "html": "<p>*<a href=\"/url\">bar*</a></p>\n", "example": 472, "start_line": 7384, "end_line": 7388, "section": "Emphasis and strong emphasis" }, { "markdown": "_foo [bar_](/url)\n", "html": "<p>_foo <a href=\"/url\">bar_</a></p>\n", "example": 473, "start_line": 7391, "end_line": 7395, "section": "Emphasis and strong emphasis" }, { "markdown": "*<img src=\"foo\" title=\"*\"/>\n", "html": "<p>*<img src=\"foo\" title=\"*\"/></p>\n", "example": 474, "start_line": 7398, "end_line": 7402, "section": "Emphasis and strong emphasis" }, { "markdown": "**<a href=\"**\">\n", "html": "<p>**<a href=\"**\"></p>\n", "example": 475, "start_line": 7405, "end_line": 7409, "section": "Emphasis and strong emphasis" }, { "markdown": "__<a href=\"__\">\n", "html": "<p>__<a href=\"__\"></p>\n", "example": 476, "start_line": 7412, "end_line": 7416, "section": "Emphasis and strong emphasis" }, { "markdown": "*a `*`*\n", "html": "<p><em>a <code>*</code></em></p>\n", "example": 477, "start_line": 7419, "end_line": 7423, "section": "Emphasis and strong emphasis" }, { "markdown": "_a `_`_\n", "html": "<p><em>a <code>_</code></em></p>\n", "example": 478, "start_line": 7426, "end_line": 7430, "section": "Emphasis and strong emphasis" }, { "markdown": "**a<http://foo.bar/?q=**>\n", "html": "<p>**a<a href=\"http://foo.bar/?q=**\">http://foo.bar/?q=**</a></p>\n", "example": 479, "start_line": 7433, "end_line": 7437, "section": "Emphasis and strong emphasis" }, { "markdown": "__a<http://foo.bar/?q=__>\n", "html": "<p>__a<a href=\"http://foo.bar/?q=__\">http://foo.bar/?q=__</a></p>\n", "example": 480, "start_line": 7440, "end_line": 7444, "section": "Emphasis and strong emphasis" }, { "markdown": "[link](/uri \"title\")\n", "html": "<p><a href=\"/uri\" title=\"title\">link</a></p>\n", "example": 481, "start_line": 7528, "end_line": 7532, "section": "Links" }, { "markdown": "[link](/uri)\n", "html": "<p><a href=\"/uri\">link</a></p>\n", "example": 482, "start_line": 7538, "end_line": 7542, "section": "Links" }, { "markdown": "[](./target.md)\n", "html": "<p><a href=\"./target.md\"></a></p>\n", "example": 483, "start_line": 7544, "end_line": 7548, "section": "Links" }, { "markdown": "[link]()\n", "html": "<p><a href=\"\">link</a></p>\n", "example": 484, "start_line": 7551, "end_line": 7555, "section": "Links" }, { "markdown": "[link](<>)\n", "html": "<p><a href=\"\">link</a></p>\n", "example": 485, "start_line": 7558, "end_line": 7562, "section": "Links" }, { "markdown": "[]()\n", "html": "<p><a href=\"\"></a></p>\n", "example": 486, "start_line": 7565, "end_line": 7569, "section": "Links" }, { "markdown": "[link](/my uri)\n", "html": "<p>[link](/my uri)</p>\n", "example": 487, "start_line": 7574, "end_line": 7578, "section": "Links" }, { "markdown": "[link](</my uri>)\n", "html": "<p><a href=\"/my%20uri\">link</a></p>\n", "example": 488, "start_line": 7580, "end_line": 7584, "section": "Links" }, { "markdown": "[link](foo\nbar)\n", "html": "<p>[link](foo\nbar)</p>\n", "example": 489, "start_line": 7589, "end_line": 7595, "section": "Links" }, { "markdown": "[link](<foo\nbar>)\n", "html": "<p>[link](<foo\nbar>)</p>\n", "example": 490, "start_line": 7597, "end_line": 7603, "section": "Links" }, { "markdown": "[a](<b)c>)\n", "html": "<p><a href=\"b)c\">a</a></p>\n", "example": 491, "start_line": 7608, "end_line": 7612, "section": "Links" }, { "markdown": "[link](<foo\\>)\n", "html": "<p>[link](<foo>)</p>\n", "example": 492, "start_line": 7616, "end_line": 7620, "section": "Links" }, { "markdown": "[a](<b)c\n[a](<b)c>\n[a](<b>c)\n", "html": "<p>[a](<b)c\n[a](<b)c>\n[a](<b>c)</p>\n", "example": 493, "start_line": 7625, "end_line": 7633, "section": "Links" }, { "markdown": "[link](\\(foo\\))\n", "html": "<p><a href=\"(foo)\">link</a></p>\n", "example": 494, "start_line": 7637, "end_line": 7641, "section": "Links" }, { "markdown": "[link](foo(and(bar)))\n", "html": "<p><a href=\"foo(and(bar))\">link</a></p>\n", "example": 495, "start_line": 7646, "end_line": 7650, "section": "Links" }, { "markdown": "[link](foo(and(bar))\n", "html": "<p>[link](foo(and(bar))</p>\n", "example": 496, "start_line": 7655, "end_line": 7659, "section": "Links" }, { "markdown": "[link](foo\\(and\\(bar\\))\n", "html": "<p><a href=\"foo(and(bar)\">link</a></p>\n", "example": 497, "start_line": 7662, "end_line": 7666, "section": "Links" }, { "markdown": "[link](<foo(and(bar)>)\n", "html": "<p><a href=\"foo(and(bar)\">link</a></p>\n", "example": 498, "start_line": 7669, "end_line": 7673, "section": "Links" }, { "markdown": "[link](foo\\)\\:)\n", "html": "<p><a href=\"foo):\">link</a></p>\n", "example": 499, "start_line": 7679, "end_line": 7683, "section": "Links" }, { "markdown": "[link](#fragment)\n\n[link](http://example.com#fragment)\n\n[link](http://example.com?foo=3#frag)\n", "html": "<p><a href=\"#fragment\">link</a></p>\n<p><a href=\"http://example.com#fragment\">link</a></p>\n<p><a href=\"http://example.com?foo=3#frag\">link</a></p>\n", "example": 500, "start_line": 7688, "end_line": 7698, "section": "Links" }, { "markdown": "[link](foo\\bar)\n", "html": "<p><a href=\"foo%5Cbar\">link</a></p>\n", "example": 501, "start_line": 7704, "end_line": 7708, "section": "Links" }, { "markdown": "[link](foo%20bä)\n", "html": "<p><a href=\"foo%20b%C3%A4\">link</a></p>\n", "example": 502, "start_line": 7720, "end_line": 7724, "section": "Links" }, { "markdown": "[link](\"title\")\n", "html": "<p><a href=\"%22title%22\">link</a></p>\n", "example": 503, "start_line": 7731, "end_line": 7735, "section": "Links" }, { "markdown": "[link](/url \"title\")\n[link](/url 'title')\n[link](/url (title))\n", "html": "<p><a href=\"/url\" title=\"title\">link</a>\n<a href=\"/url\" title=\"title\">link</a>\n<a href=\"/url\" title=\"title\">link</a></p>\n", "example": 504, "start_line": 7740, "end_line": 7748, "section": "Links" }, { "markdown": "[link](/url \"title \\\""\")\n", "html": "<p><a href=\"/url\" title=\"title ""\">link</a></p>\n", "example": 505, "start_line": 7754, "end_line": 7758, "section": "Links" }, { "markdown": "[link](/url \"title\")\n", "html": "<p><a href=\"/url%C2%A0%22title%22\">link</a></p>\n", "example": 506, "start_line": 7765, "end_line": 7769, "section": "Links" }, { "markdown": "[link](/url \"title \"and\" title\")\n", "html": "<p>[link](/url "title "and" title")</p>\n", "example": 507, "start_line": 7774, "end_line": 7778, "section": "Links" }, { "markdown": "[link](/url 'title \"and\" title')\n", "html": "<p><a href=\"/url\" title=\"title "and" title\">link</a></p>\n", "example": 508, "start_line": 7783, "end_line": 7787, "section": "Links" }, { "markdown": "[link]( /uri\n \"title\" )\n", "html": "<p><a href=\"/uri\" title=\"title\">link</a></p>\n", "example": 509, "start_line": 7808, "end_line": 7813, "section": "Links" }, { "markdown": "[link] (/uri)\n", "html": "<p>[link] (/uri)</p>\n", "example": 510, "start_line": 7819, "end_line": 7823, "section": "Links" }, { "markdown": "[link [foo [bar]]](/uri)\n", "html": "<p><a href=\"/uri\">link [foo [bar]]</a></p>\n", "example": 511, "start_line": 7829, "end_line": 7833, "section": "Links" }, { "markdown": "[link] bar](/uri)\n", "html": "<p>[link] bar](/uri)</p>\n", "example": 512, "start_line": 7836, "end_line": 7840, "section": "Links" }, { "markdown": "[link [bar](/uri)\n", "html": "<p>[link <a href=\"/uri\">bar</a></p>\n", "example": 513, "start_line": 7843, "end_line": 7847, "section": "Links" }, { "markdown": "[link \\[bar](/uri)\n", "html": "<p><a href=\"/uri\">link [bar</a></p>\n", "example": 514, "start_line": 7850, "end_line": 7854, "section": "Links" }, { "markdown": "[link *foo **bar** `#`*](/uri)\n", "html": "<p><a href=\"/uri\">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>\n", "example": 515, "start_line": 7859, "end_line": 7863, "section": "Links" }, { "markdown": "[![moon](moon.jpg)](/uri)\n", "html": "<p><a href=\"/uri\"><img src=\"moon.jpg\" alt=\"moon\" /></a></p>\n", "example": 516, "start_line": 7866, "end_line": 7870, "section": "Links" }, { "markdown": "[foo [bar](/uri)](/uri)\n", "html": "<p>[foo <a href=\"/uri\">bar</a>](/uri)</p>\n", "example": 517, "start_line": 7875, "end_line": 7879, "section": "Links" }, { "markdown": "[foo *[bar [baz](/uri)](/uri)*](/uri)\n", "html": "<p>[foo <em>[bar <a href=\"/uri\">baz</a>](/uri)</em>](/uri)</p>\n", "example": 518, "start_line": 7882, "end_line": 7886, "section": "Links" }, { "markdown": "![[[foo](uri1)](uri2)](uri3)\n", "html": "<p><img src=\"uri3\" alt=\"[foo](uri2)\" /></p>\n", "example": 519, "start_line": 7889, "end_line": 7893, "section": "Links" }, { "markdown": "*[foo*](/uri)\n", "html": "<p>*<a href=\"/uri\">foo*</a></p>\n", "example": 520, "start_line": 7899, "end_line": 7903, "section": "Links" }, { "markdown": "[foo *bar](baz*)\n", "html": "<p><a href=\"baz*\">foo *bar</a></p>\n", "example": 521, "start_line": 7906, "end_line": 7910, "section": "Links" }, { "markdown": "*foo [bar* baz]\n", "html": "<p><em>foo [bar</em> baz]</p>\n", "example": 522, "start_line": 7916, "end_line": 7920, "section": "Links" }, { "markdown": "[foo <bar attr=\"](baz)\">\n", "html": "<p>[foo <bar attr=\"](baz)\"></p>\n", "example": 523, "start_line": 7926, "end_line": 7930, "section": "Links" }, { "markdown": "[foo`](/uri)`\n", "html": "<p>[foo<code>](/uri)</code></p>\n", "example": 524, "start_line": 7933, "end_line": 7937, "section": "Links" }, { "markdown": "[foo<http://example.com/?search=](uri)>\n", "html": "<p>[foo<a href=\"http://example.com/?search=%5D(uri)\">http://example.com/?search=](uri)</a></p>\n", "example": 525, "start_line": 7940, "end_line": 7944, "section": "Links" }, { "markdown": "[foo][bar]\n\n[bar]: /url \"title\"\n", "html": "<p><a href=\"/url\" title=\"title\">foo</a></p>\n", "example": 526, "start_line": 7978, "end_line": 7984, "section": "Links" }, { "markdown": "[link [foo [bar]]][ref]\n\n[ref]: /uri\n", "html": "<p><a href=\"/uri\">link [foo [bar]]</a></p>\n", "example": 527, "start_line": 7993, "end_line": 7999, "section": "Links" }, { "markdown": "[link \\[bar][ref]\n\n[ref]: /uri\n", "html": "<p><a href=\"/uri\">link [bar</a></p>\n", "example": 528, "start_line": 8002, "end_line": 8008, "section": "Links" }, { "markdown": "[link *foo **bar** `#`*][ref]\n\n[ref]: /uri\n", "html": "<p><a href=\"/uri\">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>\n", "example": 529, "start_line": 8013, "end_line": 8019, "section": "Links" }, { "markdown": "[![moon](moon.jpg)][ref]\n\n[ref]: /uri\n", "html": "<p><a href=\"/uri\"><img src=\"moon.jpg\" alt=\"moon\" /></a></p>\n", "example": 530, "start_line": 8022, "end_line": 8028, "section": "Links" }, { "markdown": "[foo [bar](/uri)][ref]\n\n[ref]: /uri\n", "html": "<p>[foo <a href=\"/uri\">bar</a>]<a href=\"/uri\">ref</a></p>\n", "example": 531, "start_line": 8033, "end_line": 8039, "section": "Links" }, { "markdown": "[foo *bar [baz][ref]*][ref]\n\n[ref]: /uri\n", "html": "<p>[foo <em>bar <a href=\"/uri\">baz</a></em>]<a href=\"/uri\">ref</a></p>\n", "example": 532, "start_line": 8042, "end_line": 8048, "section": "Links" }, { "markdown": "*[foo*][ref]\n\n[ref]: /uri\n", "html": "<p>*<a href=\"/uri\">foo*</a></p>\n", "example": 533, "start_line": 8057, "end_line": 8063, "section": "Links" }, { "markdown": "[foo *bar][ref]*\n\n[ref]: /uri\n", "html": "<p><a href=\"/uri\">foo *bar</a>*</p>\n", "example": 534, "start_line": 8066, "end_line": 8072, "section": "Links" }, { "markdown": "[foo <bar attr=\"][ref]\">\n\n[ref]: /uri\n", "html": "<p>[foo <bar attr=\"][ref]\"></p>\n", "example": 535, "start_line": 8078, "end_line": 8084, "section": "Links" }, { "markdown": "[foo`][ref]`\n\n[ref]: /uri\n", "html": "<p>[foo<code>][ref]</code></p>\n", "example": 536, "start_line": 8087, "end_line": 8093, "section": "Links" }, { "markdown": "[foo<http://example.com/?search=][ref]>\n\n[ref]: /uri\n", "html": "<p>[foo<a href=\"http://example.com/?search=%5D%5Bref%5D\">http://example.com/?search=][ref]</a></p>\n", "example": 537, "start_line": 8096, "end_line": 8102, "section": "Links" }, { "markdown": "[foo][BaR]\n\n[bar]: /url \"title\"\n", "html": "<p><a href=\"/url\" title=\"title\">foo</a></p>\n", "example": 538, "start_line": 8107, "end_line": 8113, "section": "Links" }, { "markdown": "[ẞ]\n\n[SS]: /url\n", "html": "<p><a href=\"/url\">ẞ</a></p>\n", "example": 539, "start_line": 8118, "end_line": 8124, "section": "Links" }, { "markdown": "[Foo\n bar]: /url\n\n[Baz][Foo bar]\n", "html": "<p><a href=\"/url\">Baz</a></p>\n", "example": 540, "start_line": 8130, "end_line": 8137, "section": "Links" }, { "markdown": "[foo] [bar]\n\n[bar]: /url \"title\"\n", "html": "<p>[foo] <a href=\"/url\" title=\"title\">bar</a></p>\n", "example": 541, "start_line": 8143, "end_line": 8149, "section": "Links" }, { "markdown": "[foo]\n[bar]\n\n[bar]: /url \"title\"\n", "html": "<p>[foo]\n<a href=\"/url\" title=\"title\">bar</a></p>\n", "example": 542, "start_line": 8152, "end_line": 8160, "section": "Links" }, { "markdown": "[foo]: /url1\n\n[foo]: /url2\n\n[bar][foo]\n", "html": "<p><a href=\"/url1\">bar</a></p>\n", "example": 543, "start_line": 8193, "end_line": 8201, "section": "Links" }, { "markdown": "[bar][foo\\!]\n\n[foo!]: /url\n", "html": "<p>[bar][foo!]</p>\n", "example": 544, "start_line": 8208, "end_line": 8214, "section": "Links" }, { "markdown": "[foo][ref[]\n\n[ref[]: /uri\n", "html": "<p>[foo][ref[]</p>\n<p>[ref[]: /uri</p>\n", "example": 545, "start_line": 8220, "end_line": 8227, "section": "Links" }, { "markdown": "[foo][ref[bar]]\n\n[ref[bar]]: /uri\n", "html": "<p>[foo][ref[bar]]</p>\n<p>[ref[bar]]: /uri</p>\n", "example": 546, "start_line": 8230, "end_line": 8237, "section": "Links" }, { "markdown": "[[[foo]]]\n\n[[[foo]]]: /url\n", "html": "<p>[[[foo]]]</p>\n<p>[[[foo]]]: /url</p>\n", "example": 547, "start_line": 8240, "end_line": 8247, "section": "Links" }, { "markdown": "[foo][ref\\[]\n\n[ref\\[]: /uri\n", "html": "<p><a href=\"/uri\">foo</a></p>\n", "example": 548, "start_line": 8250, "end_line": 8256, "section": "Links" }, { "markdown": "[bar\\\\]: /uri\n\n[bar\\\\]\n", "html": "<p><a href=\"/uri\">bar\\</a></p>\n", "example": 549, "start_line": 8261, "end_line": 8267, "section": "Links" }, { "markdown": "[]\n\n[]: /uri\n", "html": "<p>[]</p>\n<p>[]: /uri</p>\n", "example": 550, "start_line": 8273, "end_line": 8280, "section": "Links" }, { "markdown": "[\n ]\n\n[\n ]: /uri\n", "html": "<p>[\n]</p>\n<p>[\n]: /uri</p>\n", "example": 551, "start_line": 8283, "end_line": 8294, "section": "Links" }, { "markdown": "[foo][]\n\n[foo]: /url \"title\"\n", "html": "<p><a href=\"/url\" title=\"title\">foo</a></p>\n", "example": 552, "start_line": 8306, "end_line": 8312, "section": "Links" }, { "markdown": "[*foo* bar][]\n\n[*foo* bar]: /url \"title\"\n", "html": "<p><a href=\"/url\" title=\"title\"><em>foo</em> bar</a></p>\n", "example": 553, "start_line": 8315, "end_line": 8321, "section": "Links" }, { "markdown": "[Foo][]\n\n[foo]: /url \"title\"\n", "html": "<p><a href=\"/url\" title=\"title\">Foo</a></p>\n", "example": 554, "start_line": 8326, "end_line": 8332, "section": "Links" }, { "markdown": "[foo] \n[]\n\n[foo]: /url \"title\"\n", "html": "<p><a href=\"/url\" title=\"title\">foo</a>\n[]</p>\n", "example": 555, "start_line": 8339, "end_line": 8347, "section": "Links" }, { "markdown": "[foo]\n\n[foo]: /url \"title\"\n", "html": "<p><a href=\"/url\" title=\"title\">foo</a></p>\n", "example": 556, "start_line": 8359, "end_line": 8365, "section": "Links" }, { "markdown": "[*foo* bar]\n\n[*foo* bar]: /url \"title\"\n", "html": "<p><a href=\"/url\" title=\"title\"><em>foo</em> bar</a></p>\n", "example": 557, "start_line": 8368, "end_line": 8374, "section": "Links" }, { "markdown": "[[*foo* bar]]\n\n[*foo* bar]: /url \"title\"\n", "html": "<p>[<a href=\"/url\" title=\"title\"><em>foo</em> bar</a>]</p>\n", "example": 558, "start_line": 8377, "end_line": 8383, "section": "Links" }, { "markdown": "[[bar [foo]\n\n[foo]: /url\n", "html": "<p>[[bar <a href=\"/url\">foo</a></p>\n", "example": 559, "start_line": 8386, "end_line": 8392, "section": "Links" }, { "markdown": "[Foo]\n\n[foo]: /url \"title\"\n", "html": "<p><a href=\"/url\" title=\"title\">Foo</a></p>\n", "example": 560, "start_line": 8397, "end_line": 8403, "section": "Links" }, { "markdown": "[foo] bar\n\n[foo]: /url\n", "html": "<p><a href=\"/url\">foo</a> bar</p>\n", "example": 561, "start_line": 8408, "end_line": 8414, "section": "Links" }, { "markdown": "\\[foo]\n\n[foo]: /url \"title\"\n", "html": "<p>[foo]</p>\n", "example": 562, "start_line": 8420, "end_line": 8426, "section": "Links" }, { "markdown": "[foo*]: /url\n\n*[foo*]\n", "html": "<p>*<a href=\"/url\">foo*</a></p>\n", "example": 563, "start_line": 8432, "end_line": 8438, "section": "Links" }, { "markdown": "[foo][bar]\n\n[foo]: /url1\n[bar]: /url2\n", "html": "<p><a href=\"/url2\">foo</a></p>\n", "example": 564, "start_line": 8444, "end_line": 8451, "section": "Links" }, { "markdown": "[foo][]\n\n[foo]: /url1\n", "html": "<p><a href=\"/url1\">foo</a></p>\n", "example": 565, "start_line": 8453, "end_line": 8459, "section": "Links" }, { "markdown": "[foo]()\n\n[foo]: /url1\n", "html": "<p><a href=\"\">foo</a></p>\n", "example": 566, "start_line": 8463, "end_line": 8469, "section": "Links" }, { "markdown": "[foo](not a link)\n\n[foo]: /url1\n", "html": "<p><a href=\"/url1\">foo</a>(not a link)</p>\n", "example": 567, "start_line": 8471, "end_line": 8477, "section": "Links" }, { "markdown": "[foo][bar][baz]\n\n[baz]: /url\n", "html": "<p>[foo]<a href=\"/url\">bar</a></p>\n", "example": 568, "start_line": 8482, "end_line": 8488, "section": "Links" }, { "markdown": "[foo][bar][baz]\n\n[baz]: /url1\n[bar]: /url2\n", "html": "<p><a href=\"/url2\">foo</a><a href=\"/url1\">baz</a></p>\n", "example": 569, "start_line": 8494, "end_line": 8501, "section": "Links" }, { "markdown": "[foo][bar][baz]\n\n[baz]: /url1\n[foo]: /url2\n", "html": "<p>[foo]<a href=\"/url1\">bar</a></p>\n", "example": 570, "start_line": 8507, "end_line": 8514, "section": "Links" }, { "markdown": "![foo](/url \"title\")\n", "html": "<p><img src=\"/url\" alt=\"foo\" title=\"title\" /></p>\n", "example": 571, "start_line": 8530, "end_line": 8534, "section": "Images" }, { "markdown": "![foo *bar*]\n\n[foo *bar*]: train.jpg \"train & tracks\"\n", "html": "<p><img src=\"train.jpg\" alt=\"foo bar\" title=\"train & tracks\" /></p>\n", "example": 572, "start_line": 8537, "end_line": 8543, "section": "Images" }, { "markdown": "![foo ![bar](/url)](/url2)\n", "html": "<p><img src=\"/url2\" alt=\"foo bar\" /></p>\n", "example": 573, "start_line": 8546, "end_line": 8550, "section": "Images" }, { "markdown": "![foo [bar](/url)](/url2)\n", "html": "<p><img src=\"/url2\" alt=\"foo bar\" /></p>\n", "example": 574, "start_line": 8553, "end_line": 8557, "section": "Images" }, { "markdown": "![foo *bar*][]\n\n[foo *bar*]: train.jpg \"train & tracks\"\n", "html": "<p><img src=\"train.jpg\" alt=\"foo bar\" title=\"train & tracks\" /></p>\n", "example": 575, "start_line": 8567, "end_line": 8573, "section": "Images" }, { "markdown": "![foo *bar*][foobar]\n\n[FOOBAR]: train.jpg \"train & tracks\"\n", "html": "<p><img src=\"train.jpg\" alt=\"foo bar\" title=\"train & tracks\" /></p>\n", "example": 576, "start_line": 8576, "end_line": 8582, "section": "Images" }, { "markdown": "![foo](train.jpg)\n", "html": "<p><img src=\"train.jpg\" alt=\"foo\" /></p>\n", "example": 577, "start_line": 8585, "end_line": 8589, "section": "Images" }, { "markdown": "My ![foo bar](/path/to/train.jpg \"title\" )\n", "html": "<p>My <img src=\"/path/to/train.jpg\" alt=\"foo bar\" title=\"title\" /></p>\n", "example": 578, "start_line": 8592, "end_line": 8596, "section": "Images" }, { "markdown": "![foo](<url>)\n", "html": "<p><img src=\"url\" alt=\"foo\" /></p>\n", "example": 579, "start_line": 8599, "end_line": 8603, "section": "Images" }, { "markdown": "![](/url)\n", "html": "<p><img src=\"/url\" alt=\"\" /></p>\n", "example": 580, "start_line": 8606, "end_line": 8610, "section": "Images" }, { "markdown": "![foo][bar]\n\n[bar]: /url\n", "html": "<p><img src=\"/url\" alt=\"foo\" /></p>\n", "example": 581, "start_line": 8615, "end_line": 8621, "section": "Images" }, { "markdown": "![foo][bar]\n\n[BAR]: /url\n", "html": "<p><img src=\"/url\" alt=\"foo\" /></p>\n", "example": 582, "start_line": 8624, "end_line": 8630, "section": "Images" }, { "markdown": "![foo][]\n\n[foo]: /url \"title\"\n", "html": "<p><img src=\"/url\" alt=\"foo\" title=\"title\" /></p>\n", "example": 583, "start_line": 8635, "end_line": 8641, "section": "Images" }, { "markdown": "![*foo* bar][]\n\n[*foo* bar]: /url \"title\"\n", "html": "<p><img src=\"/url\" alt=\"foo bar\" title=\"title\" /></p>\n", "example": 584, "start_line": 8644, "end_line": 8650, "section": "Images" }, { "markdown": "![Foo][]\n\n[foo]: /url \"title\"\n", "html": "<p><img src=\"/url\" alt=\"Foo\" title=\"title\" /></p>\n", "example": 585, "start_line": 8655, "end_line": 8661, "section": "Images" }, { "markdown": "![foo] \n[]\n\n[foo]: /url \"title\"\n", "html": "<p><img src=\"/url\" alt=\"foo\" title=\"title\" />\n[]</p>\n", "example": 586, "start_line": 8667, "end_line": 8675, "section": "Images" }, { "markdown": "![foo]\n\n[foo]: /url \"title\"\n", "html": "<p><img src=\"/url\" alt=\"foo\" title=\"title\" /></p>\n", "example": 587, "start_line": 8680, "end_line": 8686, "section": "Images" }, { "markdown": "![*foo* bar]\n\n[*foo* bar]: /url \"title\"\n", "html": "<p><img src=\"/url\" alt=\"foo bar\" title=\"title\" /></p>\n", "example": 588, "start_line": 8689, "end_line": 8695, "section": "Images" }, { "markdown": "![[foo]]\n\n[[foo]]: /url \"title\"\n", "html": "<p>![[foo]]</p>\n<p>[[foo]]: /url "title"</p>\n", "example": 589, "start_line": 8700, "end_line": 8707, "section": "Images" }, { "markdown": "![Foo]\n\n[foo]: /url \"title\"\n", "html": "<p><img src=\"/url\" alt=\"Foo\" title=\"title\" /></p>\n", "example": 590, "start_line": 8712, "end_line": 8718, "section": "Images" }, { "markdown": "!\\[foo]\n\n[foo]: /url \"title\"\n", "html": "<p>![foo]</p>\n", "example": 591, "start_line": 8724, "end_line": 8730, "section": "Images" }, { "markdown": "\\![foo]\n\n[foo]: /url \"title\"\n", "html": "<p>!<a href=\"/url\" title=\"title\">foo</a></p>\n", "example": 592, "start_line": 8736, "end_line": 8742, "section": "Images" }, { "markdown": "<http://foo.bar.baz>\n", "html": "<p><a href=\"http://foo.bar.baz\">http://foo.bar.baz</a></p>\n", "example": 593, "start_line": 8769, "end_line": 8773, "section": "Autolinks" }, { "markdown": "<http://foo.bar.baz/test?q=hello&id=22&boolean>\n", "html": "<p><a href=\"http://foo.bar.baz/test?q=hello&id=22&boolean\">http://foo.bar.baz/test?q=hello&id=22&boolean</a></p>\n", "example": 594, "start_line": 8776, "end_line": 8780, "section": "Autolinks" }, { "markdown": "<irc://foo.bar:2233/baz>\n", "html": "<p><a href=\"irc://foo.bar:2233/baz\">irc://foo.bar:2233/baz</a></p>\n", "example": 595, "start_line": 8783, "end_line": 8787, "section": "Autolinks" }, { "markdown": "<MAILTO:FOO@BAR.BAZ>\n", "html": "<p><a href=\"MAILTO:FOO@BAR.BAZ\">MAILTO:FOO@BAR.BAZ</a></p>\n", "example": 596, "start_line": 8792, "end_line": 8796, "section": "Autolinks" }, { "markdown": "<a+b+c:d>\n", "html": "<p><a href=\"a+b+c:d\">a+b+c:d</a></p>\n", "example": 597, "start_line": 8804, "end_line": 8808, "section": "Autolinks" }, { "markdown": "<made-up-scheme://foo,bar>\n", "html": "<p><a href=\"made-up-scheme://foo,bar\">made-up-scheme://foo,bar</a></p>\n", "example": 598, "start_line": 8811, "end_line": 8815, "section": "Autolinks" }, { "markdown": "<http://../>\n", "html": "<p><a href=\"http://../\">http://../</a></p>\n", "example": 599, "start_line": 8818, "end_line": 8822, "section": "Autolinks" }, { "markdown": "<localhost:5001/foo>\n", "html": "<p><a href=\"localhost:5001/foo\">localhost:5001/foo</a></p>\n", "example": 600, "start_line": 8825, "end_line": 8829, "section": "Autolinks" }, { "markdown": "<http://foo.bar/baz bim>\n", "html": "<p><http://foo.bar/baz bim></p>\n", "example": 601, "start_line": 8834, "end_line": 8838, "section": "Autolinks" }, { "markdown": "<http://example.com/\\[\\>\n", "html": "<p><a href=\"http://example.com/%5C%5B%5C\">http://example.com/\\[\\</a></p>\n", "example": 602, "start_line": 8843, "end_line": 8847, "section": "Autolinks" }, { "markdown": "<foo@bar.example.com>\n", "html": "<p><a href=\"mailto:foo@bar.example.com\">foo@bar.example.com</a></p>\n", "example": 603, "start_line": 8865, "end_line": 8869, "section": "Autolinks" }, { "markdown": "<foo+special@Bar.baz-bar0.com>\n", "html": "<p><a href=\"mailto:foo+special@Bar.baz-bar0.com\">foo+special@Bar.baz-bar0.com</a></p>\n", "example": 604, "start_line": 8872, "end_line": 8876, "section": "Autolinks" }, { "markdown": "<foo\\+@bar.example.com>\n", "html": "<p><foo+@bar.example.com></p>\n", "example": 605, "start_line": 8881, "end_line": 8885, "section": "Autolinks" }, { "markdown": "<>\n", "html": "<p><></p>\n", "example": 606, "start_line": 8890, "end_line": 8894, "section": "Autolinks" }, { "markdown": "< http://foo.bar >\n", "html": "<p>< http://foo.bar ></p>\n", "example": 607, "start_line": 8897, "end_line": 8901, "section": "Autolinks" }, { "markdown": "<m:abc>\n", "html": "<p><m:abc></p>\n", "example": 608, "start_line": 8904, "end_line": 8908, "section": "Autolinks" }, { "markdown": "<foo.bar.baz>\n", "html": "<p><foo.bar.baz></p>\n", "example": 609, "start_line": 8911, "end_line": 8915, "section": "Autolinks" }, { "markdown": "http://example.com\n", "html": "<p>http://example.com</p>\n", "example": 610, "start_line": 8918, "end_line": 8922, "section": "Autolinks" }, { "markdown": "foo@bar.example.com\n", "html": "<p>foo@bar.example.com</p>\n", "example": 611, "start_line": 8925, "end_line": 8929, "section": "Autolinks" }, { "markdown": "<a><bab><c2c>\n", "html": "<p><a><bab><c2c></p>\n", "example": 612, "start_line": 9006, "end_line": 9010, "section": "Raw HTML" }, { "markdown": "<a/><b2/>\n", "html": "<p><a/><b2/></p>\n", "example": 613, "start_line": 9015, "end_line": 9019, "section": "Raw HTML" }, { "markdown": "<a /><b2\ndata=\"foo\" >\n", "html": "<p><a /><b2\ndata=\"foo\" ></p>\n", "example": 614, "start_line": 9024, "end_line": 9030, "section": "Raw HTML" }, { "markdown": "<a foo=\"bar\" bam = 'baz <em>\"</em>'\n_boolean zoop:33=zoop:33 />\n", "html": "<p><a foo=\"bar\" bam = 'baz <em>\"</em>'\n_boolean zoop:33=zoop:33 /></p>\n", "example": 615, "start_line": 9035, "end_line": 9041, "section": "Raw HTML" }, { "markdown": "Foo <responsive-image src=\"foo.jpg\" />\n", "html": "<p>Foo <responsive-image src=\"foo.jpg\" /></p>\n", "example": 616, "start_line": 9046, "end_line": 9050, "section": "Raw HTML" }, { "markdown": "<33> <__>\n", "html": "<p><33> <__></p>\n", "example": 617, "start_line": 9055, "end_line": 9059, "section": "Raw HTML" }, { "markdown": "<a h*#ref=\"hi\">\n", "html": "<p><a h*#ref="hi"></p>\n", "example": 618, "start_line": 9064, "end_line": 9068, "section": "Raw HTML" }, { "markdown": "<a href=\"hi'> <a href=hi'>\n", "html": "<p><a href="hi'> <a href=hi'></p>\n", "example": 619, "start_line": 9073, "end_line": 9077, "section": "Raw HTML" }, { "markdown": "< a><\nfoo><bar/ >\n<foo bar=baz\nbim!bop />\n", "html": "<p>< a><\nfoo><bar/ >\n<foo bar=baz\nbim!bop /></p>\n", "example": 620, "start_line": 9082, "end_line": 9092, "section": "Raw HTML" }, { "markdown": "<a href='bar'title=title>\n", "html": "<p><a href='bar'title=title></p>\n", "example": 621, "start_line": 9097, "end_line": 9101, "section": "Raw HTML" }, { "markdown": "</a></foo >\n", "html": "<p></a></foo ></p>\n", "example": 622, "start_line": 9106, "end_line": 9110, "section": "Raw HTML" }, { "markdown": "</a href=\"foo\">\n", "html": "<p></a href="foo"></p>\n", "example": 623, "start_line": 9115, "end_line": 9119, "section": "Raw HTML" }, { "markdown": "foo <!-- this is a\ncomment - with hyphen -->\n", "html": "<p>foo <!-- this is a\ncomment - with hyphen --></p>\n", "example": 624, "start_line": 9124, "end_line": 9130, "section": "Raw HTML" }, { "markdown": "foo <!-- not a comment -- two hyphens -->\n", "html": "<p>foo <!-- not a comment -- two hyphens --></p>\n", "example": 625, "start_line": 9133, "end_line": 9137, "section": "Raw HTML" }, { "markdown": "foo <!--> foo -->\n\nfoo <!-- foo--->\n", "html": "<p>foo <!--> foo --></p>\n<p>foo <!-- foo---></p>\n", "example": 626, "start_line": 9142, "end_line": 9149, "section": "Raw HTML" }, { "markdown": "foo <?php echo $a; ?>\n", "html": "<p>foo <?php echo $a; ?></p>\n", "example": 627, "start_line": 9154, "end_line": 9158, "section": "Raw HTML" }, { "markdown": "foo <!ELEMENT br EMPTY>\n", "html": "<p>foo <!ELEMENT br EMPTY></p>\n", "example": 628, "start_line": 9163, "end_line": 9167, "section": "Raw HTML" }, { "markdown": "foo <![CDATA[>&<]]>\n", "html": "<p>foo <![CDATA[>&<]]></p>\n", "example": 629, "start_line": 9172, "end_line": 9176, "section": "Raw HTML" }, { "markdown": "foo <a href=\"ö\">\n", "html": "<p>foo <a href=\"ö\"></p>\n", "example": 630, "start_line": 9182, "end_line": 9186, "section": "Raw HTML" }, { "markdown": "foo <a href=\"\\*\">\n", "html": "<p>foo <a href=\"\\*\"></p>\n", "example": 631, "start_line": 9191, "end_line": 9195, "section": "Raw HTML" }, { "markdown": "<a href=\"\\\"\">\n", "html": "<p><a href="""></p>\n", "example": 632, "start_line": 9198, "end_line": 9202, "section": "Raw HTML" }, { "markdown": "foo \nbaz\n", "html": "<p>foo<br />\nbaz</p>\n", "example": 633, "start_line": 9212, "end_line": 9218, "section": "Hard line breaks" }, { "markdown": "foo\\\nbaz\n", "html": "<p>foo<br />\nbaz</p>\n", "example": 634, "start_line": 9224, "end_line": 9230, "section": "Hard line breaks" }, { "markdown": "foo \nbaz\n", "html": "<p>foo<br />\nbaz</p>\n", "example": 635, "start_line": 9235, "end_line": 9241, "section": "Hard line breaks" }, { "markdown": "foo \n bar\n", "html": "<p>foo<br />\nbar</p>\n", "example": 636, "start_line": 9246, "end_line": 9252, "section": "Hard line breaks" }, { "markdown": "foo\\\n bar\n", "html": "<p>foo<br />\nbar</p>\n", "example": 637, "start_line": 9255, "end_line": 9261, "section": "Hard line breaks" }, { "markdown": "*foo \nbar*\n", "html": "<p><em>foo<br />\nbar</em></p>\n", "example": 638, "start_line": 9267, "end_line": 9273, "section": "Hard line breaks" }, { "markdown": "*foo\\\nbar*\n", "html": "<p><em>foo<br />\nbar</em></p>\n", "example": 639, "start_line": 9276, "end_line": 9282, "section": "Hard line breaks" }, { "markdown": "`code \nspan`\n", "html": "<p><code>code span</code></p>\n", "example": 640, "start_line": 9287, "end_line": 9292, "section": "Hard line breaks" }, { "markdown": "`code\\\nspan`\n", "html": "<p><code>code\\ span</code></p>\n", "example": 641, "start_line": 9295, "end_line": 9300, "section": "Hard line breaks" }, { "markdown": "<a href=\"foo \nbar\">\n", "html": "<p><a href=\"foo \nbar\"></p>\n", "example": 642, "start_line": 9305, "end_line": 9311, "section": "Hard line breaks" }, { "markdown": "<a href=\"foo\\\nbar\">\n", "html": "<p><a href=\"foo\\\nbar\"></p>\n", "example": 643, "start_line": 9314, "end_line": 9320, "section": "Hard line breaks" }, { "markdown": "foo\\\n", "html": "<p>foo\\</p>\n", "example": 644, "start_line": 9327, "end_line": 9331, "section": "Hard line breaks" }, { "markdown": "foo \n", "html": "<p>foo</p>\n", "example": 645, "start_line": 9334, "end_line": 9338, "section": "Hard line breaks" }, { "markdown": "### foo\\\n", "html": "<h3>foo\\</h3>\n", "example": 646, "start_line": 9341, "end_line": 9345, "section": "Hard line breaks" }, { "markdown": "### foo \n", "html": "<h3>foo</h3>\n", "example": 647, "start_line": 9348, "end_line": 9352, "section": "Hard line breaks" }, { "markdown": "foo\nbaz\n", "html": "<p>foo\nbaz</p>\n", "example": 648, "start_line": 9363, "end_line": 9369, "section": "Soft line breaks" }, { "markdown": "foo \n baz\n", "html": "<p>foo\nbaz</p>\n", "example": 649, "start_line": 9375, "end_line": 9381, "section": "Soft line breaks" }, { "markdown": "hello $.;'there\n", "html": "<p>hello $.;'there</p>\n", "example": 650, "start_line": 9395, "end_line": 9399, "section": "Textual content" }, { "markdown": "Foo χρῆν\n", "html": "<p>Foo χρῆν</p>\n", "example": 651, "start_line": 9402, "end_line": 9406, "section": "Textual content" }, { "markdown": "Multiple spaces\n", "html": "<p>Multiple spaces</p>\n", "example": 652, "start_line": 9411, "end_line": 9415, "section": "Textual content" } ] ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/fixtures/def_list.txt�������������������������������������������������0000664�0000000�0000000�00000007007�15265371675�0022611�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Definition Lists ```````````````````````````````` example Term : definition . <dl> <dt>Term</dt> <dd>definition</dd> </dl> ```````````````````````````````` ## Invalid Definition List ```````````````````````````````` example : orphan . <p>: orphan</p> ```````````````````````````````` ```````````````````````````````` example # Term : definition . <h1>Term</h1> <p>: definition</p> ```````````````````````````````` ## Definition Separated By Blank Lines ```````````````````````````````` example Term : foo : bar . <dl> <dt>Term</dt> <dd>foo</dd> <dd><p>bar</p> </dd> </dl> ```````````````````````````````` ```````````````````````````````` example Term : foo . <dl> <dt>Term</dt> <dd>foo</dd> </dl> ```````````````````````````````` ```````````````````````````````` example Term : definition1 : definition2 . <dl> <dt>Term</dt> <dd>definition1</dd> <dd>definition2</dd> </dl> ```````````````````````````````` ```````````````````````````````` example Term : definition1 : definition2 paragraph . <dl> <dt>Term</dt> <dd>definition1</dd> <dd>definition2</dd> </dl> <p>paragraph</p> ```````````````````````````````` ```````````````````````````````` example First Term : This is the definition of the first term. Second Term : This is one definition of the second term. : This is another definition of the second term. . <dl> <dt>First Term</dt> <dd>This is the definition of the first term.</dd> <dt>Second Term</dt> <dd>This is one definition of the second term.</dd> <dd>This is another definition of the second term.</dd> </dl> ```````````````````````````````` ```````````````````````````````` example First Term : This is the definition of the first term. Second Term : This is one definition of the second term. : This is another definition of the second term. paragraph . <dl> <dt>First Term</dt> <dd>This is the definition of the first term.</dd> <dt>Second Term</dt> <dd>This is one definition of the second term.</dd> <dd>This is another definition of the second term.</dd> </dl> <p>paragraph</p> ```````````````````````````````` ```````````````````````````````` example First Term : This is the definition of the first term. Not Second Term : This is one definition of the second term. : This is another definition of the second term. paragraph . <dl> <dt>First Term</dt> <dd>This is the definition of the first term. Not Second Term</dd> <dd>This is one definition of the second term.</dd> <dd>This is another definition of the second term.</dd> </dl> <p>paragraph</p> ```````````````````````````````` ## Definition with Multiple Lines ```````````````````````````````` example Term : definition . <dl> <dt>Term</dt> <dd><p>definition</p> </dd> </dl> ```````````````````````````````` ```````````````````````````````` example Term : foo bar . <dl> <dt>Term</dt> <dd><p>foo</p> <p>bar</p> </dd> </dl> ```````````````````````````````` Leading 4 white spaces ```````````````````````````````` example Term : foo bar . <dl> <dt>Term</dt> <dd><p>foo</p> <p>bar</p> </dd> </dl> ```````````````````````````````` ```````````````````````````````` example Term : foo bar . <dl> <dt>Term</dt> <dd><p>foo</p> <pre><code>bar</code></pre> </dd> </dl> ```````````````````````````````` ```````````````````````````````` example Term : foo - bar - baz . <dl> <dt>Term</dt> <dd><p>foo</p> <ul> <li>bar</li> <li>baz</li> </ul> </dd> </dl> ```````````````````````````````` ## Tab-Marked Definition ```````````````````````````````` example Term : Tab-marked def . <dl> <dt>Term</dt> <dd>Tab-marked def</dd> </dl> ```````````````````````````````` �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/fixtures/fenced_admonition.txt����������������������������������������0000664�0000000�0000000�00000004732�15265371675�0024467�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Admonition ```````````````````````````````` example ```{unknown} Hi this is **strong** world ``` . <div class="error"><pre>{unknown} Hi this is **strong** world </pre></div> ```````````````````````````````` ```````````````````````````````` example ``` this is code ``` . <pre><code>this is code </code></pre> ```````````````````````````````` ```````````````````````````````` example ~~~{note} Warning message ~~~ . <section class="admonition note"> <p class="admonition-title">Warning</p> <p>message</p> </section> ```````````````````````````````` ```````````````````````````````` example ~~~{note} A **strong** title _message_ ~~~ . <section class="admonition note"> <p class="admonition-title">A <strong>strong</strong> title</p> <p><em>message</em></p> </section> ```````````````````````````````` Test with code block. ```````````````````````````````` example ```{note} print() ``` . <section class="admonition note"> <p class="admonition-title">Note</p> <pre><code>print()</code></pre> </section> ```````````````````````````````` Test with no message. ```````````````````````````````` example ~~~{note} Warning ~~~ . <section class="admonition note"> <p class="admonition-title">Warning</p> </section> ```````````````````````````````` Test with no ending fence ```````````````````````````````` example ~~~{note} Warning . <section class="admonition note"> <p class="admonition-title">Warning</p> </section> ```````````````````````````````` Test with nested admonition ```````````````````````````````` example ~~~~~~~{note} ~~~~~~{warning} ~~~~~{tip} ~~~~{caution} ~~~{hint} ``````{danger} `````{attention} ````{important} ```{error} ``` ```` ````` `````` ~~~ ~~~~ ~~~~~ ~~~~~~ ~~~~~~~ . <section class="admonition note"> <p class="admonition-title">Note</p> <section class="admonition warning"> <p class="admonition-title">Warning</p> <section class="admonition tip"> <p class="admonition-title">Tip</p> <section class="admonition caution"> <p class="admonition-title">Caution</p> <section class="admonition hint"> <p class="admonition-title">Hint</p> <section class="admonition danger"> <p class="admonition-title">Danger</p> <section class="admonition attention"> <p class="admonition-title">Attention</p> <section class="admonition important"> <p class="admonition-title">Important</p> <section class="admonition error"> <p class="admonition-title">Error</p> </section> </section> </section> </section> </section> </section> </section> </section> </section> ```````````````````````````````` ��������������������������������������lepture-mistune-f19057f/tests/fixtures/fenced_figure.txt��������������������������������������������0000664�0000000�0000000�00000006631�15265371675�0023607�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Figure ## No options ```````````````````````````````` example ~~~{figure} picture.png ~~~ . <figure class="figure"> <div class="block-image"><img src="picture.png" /></div> </figure> ```````````````````````````````` ## Align options ```````````````````````````````` example ~~~{figure} picture.png :align: left ~~~ . <figure class="figure align-left"> <div class="block-image"><img src="picture.png" /></div> </figure> ```````````````````````````````` ```````````````````````````````` example ~~~{figure} picture.png :align: invalid ~~~ . <figure class="figure"> <div class="block-image"><img src="picture.png" /></div> </figure> ```````````````````````````````` ## width and height ```````````````````````````````` example ~~~{figure} picture.png :width: 100 :height: 50 ~~~ . <figure class="figure"> <div class="block-image"><img src="picture.png" width="100" height="50" /></div> </figure> ```````````````````````````````` ```````````````````````````````` example ~~~{figure} picture.png :width: 100px :height: 50px ~~~ . <figure class="figure"> <div class="block-image"><img src="picture.png" style="width:100px;height:50px;" /></div> </figure> ```````````````````````````````` ```````````````````````````````` example ~~~{figure} picture.png :figwidth: 400px ~~~ . <figure class="figure" style="width:400px"> <div class="block-image"><img src="picture.png" /></div> </figure> ```````````````````````````````` ## alt option ```````````````````````````````` example ~~~{figure} picture.png :alt: description text ~~~ . <figure class="figure"> <div class="block-image"><img src="picture.png" alt="description text" /></div> </figure> ```````````````````````````````` ## target option ```````````````````````````````` example ~~~{figure} picture.png :target: https://lepture.com ~~~ . <figure class="figure"> <a class="block-image" href="https://lepture.com"><img src="picture.png" /></a> </figure> ```````````````````````````````` ## caption ```````````````````````````````` example ~~~{figure} picture.png a caption with **emphasis** text ~~~ . <figure class="figure"> <div class="block-image"><img src="picture.png" /></div> <figcaption>a caption with <strong>emphasis</strong> text</figcaption> </figure> ```````````````````````````````` ## legend ```````````````````````````````` example ~~~{figure} picture.png a caption with **emphasis** text > quote ~~~ . <figure class="figure"> <div class="block-image"><img src="picture.png" /></div> <figcaption>a caption with <strong>emphasis</strong> text</figcaption> <div class="legend"> <blockquote> <p>quote</p> </blockquote> </div> </figure> ```````````````````````````````` ```````````````````````````````` example ~~~{figure} picture.png > quote ~~~ . <figure class="figure"> <div class="block-image"><img src="picture.png" /></div> </figure> ```````````````````````````````` ## all options ```````````````````````````````` example ~~~{figure} picture.png :figwidth: 400px :figclass: all-options :target: https://lepture.com :alt: description :align: left :width: 100 :height: 50 a caption with **emphasis** text > quote ~~~ . <figure class="figure align-left all-options" style="width:400px"> <a class="block-image" href="https://lepture.com"><img src="picture.png" alt="description" width="100" height="50" /></a> <figcaption>a caption with <strong>emphasis</strong> text</figcaption> <div class="legend"> <blockquote> <p>quote</p> </blockquote> </div> </figure> ```````````````````````````````` �������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/fixtures/fenced_image.txt���������������������������������������������0000664�0000000�0000000�00000004447�15265371675�0023413�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Image ## No options ```````````````````````````````` example ~~~{image} picture.png ~~~ . <div class="block-image"><img src="picture.png" /></div> ```````````````````````````````` ## Align options ```````````````````````````````` example ~~~{image} picture.png :align: left ~~~ . <div class="block-image align-left"><img src="picture.png" /></div> ```````````````````````````````` ```````````````````````````````` example ~~~{image} picture.png :align: invalid ~~~ . <div class="block-image"><img src="picture.png" /></div> ```````````````````````````````` ## width and height ```````````````````````````````` example ~~~{image} picture.png :width: 100 :height: 50 ~~~ . <div class="block-image"><img src="picture.png" width="100" height="50" /></div> ```````````````````````````````` ```````````````````````````````` example ~~~{image} picture.png :width: 100px :height: 50px ~~~ . <div class="block-image"><img src="picture.png" style="width:100px;height:50px;" /></div> ```````````````````````````````` ## alt option ```````````````````````````````` example ~~~{image} picture.png :alt: description text ~~~ . <div class="block-image"><img src="picture.png" alt="description text" /></div> ```````````````````````````````` ## target option ```````````````````````````````` example ~~~{image} picture.png :target: https://lepture.com ~~~ . <a class="block-image" href="https://lepture.com"><img src="picture.png" /></a> ```````````````````````````````` ## all options ```````````````````````````````` example ~~~{image} picture.png :target: https://lepture.com :alt: description :align: left :width: 100 :height: 50 ~~~ . <a class="block-image align-left" href="https://lepture.com"><img src="picture.png" alt="description" width="100" height="50" /></a> ```````````````````````````````` ## ampersand in source ```````````````````````````````` example ~~~{image} https://example.com/picture.png?foo=qux&test=me ~~~ . <div class="block-image"><img src="https://example.com/picture.png?foo=qux&test=me" /></div> ```````````````````````````````` ## ampersand in target ```````````````````````````````` example ~~~{image} picture.png :target: https://example.com/rickroll?a=1&b=2 ~~~ . <a class="block-image" href="https://example.com/rickroll?a=1&b=2"><img src="picture.png" /></a> ```````````````````````````````` �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/fixtures/fenced_toc.txt�����������������������������������������������0000664�0000000�0000000�00000007333�15265371675�0023113�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Table of Contents ## No TOC ```````````````````````````````` example none . <p>none</p> ```````````````````````````````` ```````````````````````````````` example # H1 ## H2 . <h1>H1</h1> <h2>H2</h2> ```````````````````````````````` ## Simple TOC ```````````````````````````````` example ~~~{toc} ~~~ # H1 ## H2 . <details class="toc" open> <summary>Table of Contents</summary> <ul> <li><a href="#toc_1">H1</a> <ul> <li><a href="#toc_2">H2</a></li> </ul> </li> </ul> </details> <h1 id="toc_1">H1</h1> <h2 id="toc_2">H2</h2> ```````````````````````````````` ## Invalid Option ```````````````````````````````` example # H1 ## H2 ~~~{toc} :max-level: s ~~~ . <h1>H1</h1> <h2>H2</h2> <div class="error"><pre>"max-level" option MUST be integer</pre></div> ```````````````````````````````` ```````````````````````````````` example # H1 ## H2 ~~~{toc} :max-level: 9 ~~~ . <h1>H1</h1> <h2>H2</h2> <div class="error"><pre>"max-level" option MUST be <= 3</pre></div> ```````````````````````````````` ```````````````````````````````` example # H1 ## H2 ~~~{toc} :min-level: 2 :max-level: 1 ~~~ . <h1>H1</h1> <h2>H2</h2> <div class="error"><pre>"min-level" option MUST be less than "max-level" option</pre></div> ```````````````````````````````` ## Complex ```````````````````````````````` example # H1 ## H2 ### H3 #### H4 # H1 B # H1 `C` ```{toc} Contents ``` . <h1 id="toc_1">H1</h1> <h2 id="toc_2">H2</h2> <h3 id="toc_3">H3</h3> <h4 id="toc_4">H4</h4> <h1 id="toc_5">H1 B</h1> <h1 id="toc_6">H1 <code>C</code></h1> <details class="toc" open> <summary>Contents</summary> <ul> <li><a href="#toc_1">H1</a> <ul> <li><a href="#toc_2">H2</a> <ul> <li><a href="#toc_3">H3</a></li> </ul> </li> </ul> </li> <li><a href="#toc_5">H1 B</a></li> <li><a href="#toc_6">H1 C</a></li> </ul> </details> ```````````````````````````````` ## Insane ```````````````````````````````` example # H1 ### H3 ## H2 #### H4 ### H3 B # H1 B ```{toc} ``` . <h1 id="toc_1">H1</h1> <h3 id="toc_2">H3</h3> <h2 id="toc_3">H2</h2> <h4 id="toc_4">H4</h4> <h3 id="toc_5">H3 B</h3> <h1 id="toc_6">H1 B</h1> <details class="toc" open> <summary>Table of Contents</summary> <ul> <li><a href="#toc_1">H1</a> <ul> <li><a href="#toc_2">H3</a></li> <li><a href="#toc_3">H2</a> <ul> <li><a href="#toc_5">H3 B</a></li> </ul> </li> </ul> </li> <li><a href="#toc_6">H1 B</a></li> </ul> </details> ```````````````````````````````` ```````````````````````````````` example ### H3 ## H2 # H1 ```{toc} ``` . <h3 id="toc_1">H3</h3> <h2 id="toc_2">H2</h2> <h1 id="toc_3">H1</h1> <details class="toc" open> <summary>Table of Contents</summary> <ul> <li><a href="#toc_1">H3</a></li> <li><a href="#toc_2">H2</a></li> <li><a href="#toc_3">H1</a></li> </ul> </details> ```````````````````````````````` ## Link in Heading ```````````````````````````````` example # [foo](/bar) # [baz][ref] [ref]: /quux ```{toc} ``` . <h1 id="toc_1"><a href="/bar">foo</a></h1> <h1 id="toc_2"><a href="/quux">baz</a></h1> <details class="toc" open> <summary>Table of Contents</summary> <ul> <li><a href="#toc_1">foo</a></li> <li><a href="#toc_2">baz</a></li> </ul> </details> ```````````````````````````````` ## HTML in Heading ```````````````````````````````` example # <em>H1</em> ```{toc} ``` . <h1 id="toc_1"><em>H1</em></h1> <details class="toc" open> <summary>Table of Contents</summary> <ul> <li><a href="#toc_1">H1</a></li> </ul> </details> ```````````````````````````````` ## Collapse TOC ```````````````````````````````` example ```{toc} :collapse: ``` # H1 ## H2 . <details class="toc"> <summary>Table of Contents</summary> <ul> <li><a href="#toc_1">H1</a> <ul> <li><a href="#toc_2">H2</a></li> </ul> </li> </ul> </details> <h1 id="toc_1">H1</h1> <h2 id="toc_2">H2</h2> ```````````````````````````````` �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/fixtures/fix-commonmark.txt�������������������������������������������0000664�0000000�0000000�00000005250�15265371675�0023745�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������Historical CommonMark edge cases. ## Links Autolinks in link text stay literal. ```````````````````````````````` example [<https://example.com>](/foo) . <p><a href="/foo"><https://example.com></a></p> ```````````````````````````````` ```````````````````````````````` example [<name@example.com>](/foo) . <p><a href="/foo"><name@example.com></a></p> ```````````````````````````````` ```````````````````````````````` example [[foo][]][bar] [foo]: /foo [bar]: /bar . <p>[<a href="/foo">foo</a>]<a href="/bar">bar</a></p> ```````````````````````````````` The label of a full reference image is not a link of its own. ```````````````````````````````` example [![moon][img]](/uri) [img]: moon.jpg . <p><a href="/uri"><img src="moon.jpg" alt="moon" /></a></p> ```````````````````````````````` ```````````````````````````````` example [![moon][img]][ref] [img]: moon.jpg [ref]: /uri . <p><a href="/uri"><img src="moon.jpg" alt="moon" /></a></p> ```````````````````````````````` ## Emphasis CommonMark delimiter handling is the default. ```````````````````````````````` example *_em_* __**strong**__ ______m______ . <p><em><em>em</em></em> <strong><strong>strong</strong></strong> <strong><strong><strong>m</strong></strong></strong></p> ```````````````````````````````` ```````````````````````````````` example *a **b c* d** . <p><em>a <em><em>b c</em> d</em></em></p> ```````````````````````````````` ```````````````````````````````` example *a **b c* d** . <p><em>a <em><em>b c</em> d</em></em></p> ```````````````````````````````` ```````````````````````````````` example *a **b c* d . <p>*a *<em>b c</em> d</p> ```````````````````````````````` The multiple-of-3 rule uses the original delimiter run length, so the remainder of a partially consumed run can still match a later delimiter. ```````````````````````````````` example *a***a* . <p><em>a</em>*<em>a</em></p> ```````````````````````````````` ```````````````````````````````` example *foo***bar* . <p><em>foo</em>*<em>bar</em></p> ```````````````````````````````` ## Max depth ```````````````````````````````` example > > > > > > > > b . <blockquote> <blockquote> <blockquote> <blockquote> <blockquote> <blockquote> <blockquote> <blockquote> <p>b</p> </blockquote> </blockquote> </blockquote> </blockquote> </blockquote> </blockquote> </blockquote> </blockquote> ```````````````````````````````` ```````````````````````````````` example - a - b - c - d - e - f - g - h . <ul> <li>a<ul> <li>b<ul> <li>c<ul> <li>d<ul> <li>e<ul> <li>f<ul> <li>g<ul> <li>h</li> </ul> </li> </ul> </li> </ul> </li> </ul> </li> </ul> </li> </ul> </li> </ul> </li> </ul> ```````````````````````````````` ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/fixtures/footnotes.txt������������������������������������������������0000664�0000000�0000000�00000010342�15265371675�0023034�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Footnotes ```````````````````````````````` example none [^1] . <p>none [^1]</p> ```````````````````````````````` ```````````````````````````````` example oneline [^1] [^1]: foo . <p>oneline <sup class="footnote-ref" id="fnref-1"><a href="#fn-1">1</a></sup></p> <section class="footnotes"> <ol> <li id="fn-1"><p>foo<a href="#fnref-1" class="footnote">↩</a></p></li> </ol> </section> ```````````````````````````````` ```````````````````````````````` example multiple lines [^1] [^1]: foo one two three four five . <p>multiple lines <sup class="footnote-ref" id="fnref-1"><a href="#fn-1">1</a></sup></p> <pre><code> five</code></pre> <section class="footnotes"> <ol> <li id="fn-1"><p>foo</p> <p>one</p> <p>two</p> <p>three</p> <p>four<a href="#fnref-1" class="footnote">↩</a></p></li> </ol> </section> ```````````````````````````````` ```````````````````````````````` example multi-line footnote[^1] [^1]: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. . <p>multi-line footnote<sup class="footnote-ref" id="fnref-1"><a href="#fn-1">1</a></sup></p> <section class="footnotes"> <ol> <li id="fn-1"><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.<a href="#fnref-1" class="footnote">↩</a></p></li> </ol> </section> ```````````````````````````````` ```````````````````````````````` example fenced code block in footnote[^1] [^1]: first ```sh second third ``` fourth . <p>fenced code block in footnote<sup class="footnote-ref" id="fnref-1"><a href="#fn-1">1</a></sup></p> <section class="footnotes"> <ol> <li id="fn-1"><p>first</p> <pre><code class="language-sh">second third </code></pre> <p>fourth<a href="#fnref-1" class="footnote">↩</a></p></li> </ol> </section> ```````````````````````````````` https://github.com/lepture/mistune/issues/378 ```````````````````````````````` example This is a foo [^foo]. This is a bar [^bar]. [^foo]: A foo is beautiful. This is in contrast to a bar [^bar]. [^bar]: A bar is very common. . <p>This is a foo <sup class="footnote-ref" id="fnref-1"><a href="#fn-1">1</a></sup>.</p> <p>This is a bar <sup class="footnote-ref" id="fnref-2"><a href="#fn-2">2</a></sup>.</p> <section class="footnotes"> <ol> <li id="fn-1"><p>A foo is beautiful. This is in contrast to a bar <sup class="footnote-ref" id="fnref-2"><a href="#fn-2">2</a></sup>.<a href="#fnref-1" class="footnote">↩</a></p></li> <li id="fn-2"><p>A bar is very common.<a href="#fnref-2" class="footnote">↩</a></p></li> </ol> </section> ```````````````````````````````` https://github.com/lepture/mistune/issues/378 ```````````````````````````````` example This is body text, and a footnote.[^f] [^f]: The footnote includes [a link][1]. [1]: https://example.com . <p>This is body text, and a footnote.<sup class="footnote-ref" id="fnref-1"><a href="#fn-1">1</a></sup></p> <section class="footnotes"> <ol> <li id="fn-1"><p>The footnote includes <a href="https://example.com">a link</a>.<a href="#fnref-1" class="footnote">↩</a></p></li> </ol> </section> ```````````````````````````````` https://github.com/lepture/mistune/issues/428 ```````````````````````````````` example paragraph [^fn] [^fn]: *emph* > aaa . <p>paragraph <sup class="footnote-ref" id="fnref-1"><a href="#fn-1">1</a></sup></p> <section class="footnotes"> <ol> <li id="fn-1"><p><em>emph</em></p> <blockquote> <p>aaa</p> </blockquote> <a href="#fnref-1" class="footnote">↩</a></li> </ol> </section> ```````````````````````````````` ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/fixtures/hook_toc.txt�������������������������������������������������0000664�0000000�0000000�00000003720�15265371675�0022623�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Table of Contents ## Simple TOC ```````````````````````````````` example # H1 content ## H2 . <h1 id="toc_1">H1</h1> <p>content</p> <h2 id="toc_2">H2</h2> <ul> <li><a href="#toc_1">H1</a> <ul> <li><a href="#toc_2">H2</a></li> </ul> </li> </ul> ```````````````````````````````` ## Complex TOC ```````````````````````````````` example # H1 ## H2 ### H3 #### H4 # H1 B # H1 `C` . <h1 id="toc_1">H1</h1> <h2 id="toc_2">H2</h2> <h3 id="toc_3">H3</h3> <h4>H4</h4> <h1 id="toc_4">H1 B</h1> <h1 id="toc_5">H1 <code>C</code></h1> <ul> <li><a href="#toc_1">H1</a> <ul> <li><a href="#toc_2">H2</a> <ul> <li><a href="#toc_3">H3</a></li> </ul> </li> </ul> </li> <li><a href="#toc_4">H1 B</a></li> <li><a href="#toc_5">H1 C</a></li> </ul> ```````````````````````````````` ## Insane TOC ```````````````````````````````` example # H1 ### H3 ## H2 #### H4 ### H3 B # H1 B . <h1 id="toc_1">H1</h1> <h3 id="toc_2">H3</h3> <h2 id="toc_3">H2</h2> <h4>H4</h4> <h3 id="toc_4">H3 B</h3> <h1 id="toc_5">H1 B</h1> <ul> <li><a href="#toc_1">H1</a> <ul> <li><a href="#toc_2">H3</a></li> <li><a href="#toc_3">H2</a> <ul> <li><a href="#toc_4">H3 B</a></li> </ul> </li> </ul> </li> <li><a href="#toc_5">H1 B</a></li> </ul> ```````````````````````````````` ```````````````````````````````` example ### H3 ## H2 # H1 . <h3 id="toc_1">H3</h3> <h2 id="toc_2">H2</h2> <h1 id="toc_3">H1</h1> <ul> <li><a href="#toc_1">H3</a></li> <li><a href="#toc_2">H2</a></li> <li><a href="#toc_3">H1</a></li> </ul> ```````````````````````````````` ## Link in Heading ```````````````````````````````` example # [foo](/bar) # [baz][ref] [ref]: /quux . <h1 id="toc_1"><a href="/bar">foo</a></h1> <h1 id="toc_2"><a href="/quux">baz</a></h1> <ul> <li><a href="#toc_1">foo</a></li> <li><a href="#toc_2">baz</a></li> </ul> ```````````````````````````````` ## HTML in Heading ```````````````````````````````` example # <em>H1</em> . <h1 id="toc_1"><em>H1</em></h1> <ul> <li><a href="#toc_1">H1</a></li> </ul> ```````````````````````````````` ������������������������������������������������lepture-mistune-f19057f/tests/fixtures/include/�����������������������������������������������������0000775�0000000�0000000�00000000000�15265371675�0021676�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/fixtures/include/hello.md���������������������������������������������0000664�0000000�0000000�00000000010�15265371675�0023312�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������> hello ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/fixtures/include/hello.txt��������������������������������������������0000664�0000000�0000000�00000000006�15265371675�0023536�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������hello ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/fixtures/include/text.html��������������������������������������������0000664�0000000�0000000�00000000030�15265371675�0023541�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<div>include html</div> ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/fixtures/include/text.md����������������������������������������������0000664�0000000�0000000�00000000243�15265371675�0023203�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Include .. include:: ./text.md .. include:: ./not-exist.md .. include:: ./text.html :encoding: utf-8 .. include:: ./hello.md .. include:: ../rst_toc.txt �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/fixtures/insert.txt���������������������������������������������������0000664�0000000�0000000�00000002215�15265371675�0022320�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Insert ```````````````````````````````` example ^^insert me . <p>^^insert me</p> ```````````````````````````````` ## normal insert ```````````````````````````````` example ^^insert me^^ . <p><ins>insert me</ins></p> ```````````````````````````````` ```````````````````````````````` example foo ^^insert me^^ . <p>foo <ins>insert me</ins></p> ```````````````````````````````` ```````````````````````````````` example ^^insert me^^foo . <p><ins>insert me</ins>foo</p> ```````````````````````````````` ```````````````````````````````` example ^^insert me^^^ . <p>^^insert me^^^</p> ```````````````````````````````` ## escape insert ```````````````````````````````` example ^^insert me\^^^ . <p><ins>insert me^</ins></p> ```````````````````````````````` ```````````````````````````````` example ^^insert \^\^ me^^ . <p><ins>insert ^^ me</ins></p> ```````````````````````````````` ## insert link ```````````````````````````````` example ^^insert [me^^](/) . <p><ins>insert [me</ins>](/)</p> ```````````````````````````````` ```````````````````````````````` example ^^[hello](/)^^ . <p><ins><a href="/">hello</a></ins></p> ```````````````````````````````` �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/fixtures/mark.txt�����������������������������������������������������0000664�0000000�0000000�00000002162�15265371675�0021747�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Mark ```````````````````````````````` example ==mark me . <p>==mark me</p> ```````````````````````````````` ## normal mark ```````````````````````````````` example ==mark me== . <p><mark>mark me</mark></p> ```````````````````````````````` ```````````````````````````````` example foo ==mark me== . <p>foo <mark>mark me</mark></p> ```````````````````````````````` ```````````````````````````````` example ==mark me==foo . <p><mark>mark me</mark>foo</p> ```````````````````````````````` ```````````````````````````````` example ==mark me=== . <p>==mark me===</p> ```````````````````````````````` ## escape mark ```````````````````````````````` example ==mark me\=== . <p><mark>mark me=</mark></p> ```````````````````````````````` ```````````````````````````````` example ==mark \=\= me== . <p><mark>mark == me</mark></p> ```````````````````````````````` ## mark link ```````````````````````````````` example ==mark [me==](/) . <p><mark>mark [me</mark>](/)</p> ```````````````````````````````` ```````````````````````````````` example ==[hello](/)== . <p><mark><a href="/">hello</a></mark></p> ```````````````````````````````` ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/fixtures/math.txt�����������������������������������������������������0000664�0000000�0000000�00000005171�15265371675�0021751�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Math ## Block Math ```````````````````````````````` example $$ . <p>$$</p> ```````````````````````````````` ```````````````````````````````` example $$ \operatorname{ker} f=\{g\in G:f(g)=e_{H}\}{\mbox{.}} $$ . <div class="math">$$ \operatorname{ker} f=\{g\in G:f(g)=e_{H}\}{\mbox{.}} $$</div> ```````````````````````````````` ```````````````````````````````` example $$ foo $$ bar . <div class="math">$$ foo $$</div> <p>bar</p> ```````````````````````````````` ```````````````````````````````` example $$ foo bar $$ . <div class="math">$$ foo bar $$</div> ```````````````````````````````` ## Inline Math ```````````````````````````````` example The homomorphism $f$ is injective if and only if its kernel is only the singleton set $e_G$, because otherwise $\exists a,b\in G$ with $a\neq b$ such that $f(a)=f(b)$. . <p>The homomorphism <span class="math">\(f\)</span> is injective if and only if its kernel is only the singleton set <span class="math">\(e_G\)</span>, because otherwise <span class="math">\(\exists a,b\in G\)</span> with <span class="math">\(a\neq b\)</span> such that <span class="math">\(f(a)=f(b)\)</span>.</p> ```````````````````````````````` ```````````````````````````````` example Escaped dollar sign in math: $x=\$$ . <p>Escaped dollar sign in math: <span class="math">\(x=\$\)</span></p> ```````````````````````````````` ```````````````````````````````` example The $n$th element is valid. . <p>The <span class="math">\(n\)</span>th element is valid.</p> ```````````````````````````````` ```````````````````````````````` example Result is $x^2$. . <p>Result is <span class="math">\(x^2\)</span>.</p> ```````````````````````````````` ```````````````````````````````` example $$x$$ . <div class="math">$$ x $$</div> ```````````````````````````````` ```````````````````````````````` example $$$$ . <div class="math">$$ $$</div> ```````````````````````````````` ```````````````````````````````` example No newline $$x$$ . <p>No newline <div class="math">$$ x $$</div> </p> ```````````````````````````````` ```````````````````````````````` example $`a+% b`$ . <p><span class="math">\(a+% b\)</span></p> ```````````````````````````````` ## Currency rejection ```````````````````````````````` example Price is $51,300 and cost is $51,300 total. . <p>Price is $51,300 and cost is $51,300 total.</p> ```````````````````````````````` ```````````````````````````````` example The $1.6T valuation narrative. . <p>The $1.6T valuation narrative.</p> ```````````````````````````````` ## Cross-line rejection ```````````````````````````````` example Line one $500 Line two $600 . <p>Line one $500 Line two $600</p> ```````````````````````````````` �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/fixtures/renderer_markdown.txt����������������������������������������0000664�0000000�0000000�00000006765�15265371675�0024542�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# MarkdownRenderer ## inline ```````````````````````````````` example this is _em_, **strong**, and `code` . this is *em*, **strong**, and `code` ```````````````````````````````` ## links ```````````````````````````````` example [link], [link][], [text][link], [link](/foo), [link](/foo "title") [link]: /url . [link][link], [link][link], [text][link], [link](/foo), [link](/foo "title") [link]: /url ```````````````````````````````` ```````````````````````````````` example [link], [link](https://foo(bar "title") [link]: /url "title" . [link][link], [link][link](https://foo(bar "title") [link]: /url "title" ```````````````````````````````` ```````````````````````````````` example [https://lepture.com](https://lepture.com) <https://lepture.com> <demo@example.com> [demo@example.com](mailto:demo@example.com) . <https://lepture.com> <https://lepture.com> <demo@example.com> <demo@example.com> ```````````````````````````````` ## images ```````````````````````````````` example [link]: /url ![link], ![link][], ![alt][link] . ![link][link], ![link][link], ![alt][link] [link]: /url ```````````````````````````````` ## linebreak ```````````````````````````````` example foo\ bar . foo bar ```````````````````````````````` ## html ```````````````````````````````` example inline html <a>text</a> and block html <div>hi</div> . inline html <a>text</a> and block html <div>hi</div> ```````````````````````````````` ## heading ```````````````````````````````` example # h1 ## h2 ### h3 #### h4 ##### h5 ###### h6 h1 == . # h1 ## h2 ### h3 #### h4 ##### h5 ###### h6 # h1 ```````````````````````````````` ## thematic break ```````````````````````````````` example hi *** . hi *** ```````````````````````````````` ## code ```````````````````````````````` example start def foo(): pass end . start ``` def foo(): pass ``` end ```````````````````````````````` ```````````````````````````````` example start ```py def foo(): pass ``` end . start ```py def foo(): pass ``` end ```````````````````````````````` ```````````````````````````````` example indent code markdown ``` fenced . indent code ~~~ markdown ``` fenced ~~~ ```````````````````````````````` ```````````````````````````````` example indent code markdown ~~~ fenced . indent code ``` markdown ~~~ fenced ``` ```````````````````````````````` ```````````````````````````````` example indent code markdown ``` fenced ~~~ . indent code ```` markdown ``` fenced ~~~ ```` ```````````````````````````````` ## quote ```````````````````````````````` example > quote . > quote ```````````````````````````````` ```````````````````````````````` example hello > quote . hello > quote ```````````````````````````````` > quote > quote > > continuation . > quote > quote > > continuation ## list ```````````````````````````````` example - list + list . - list + list ```````````````````````````````` ```````````````````````````````` example - item 1 item 2 . - item 1 item 2 ```````````````````````````````` ```````````````````````````````` example - item 1 item 2 - item 3 . - item 1 item 2 - item 3 ```````````````````````````````` ```````````````````````````````` example - item 1 1. item 2 . - item 1 1. item 2 ```````````````````````````````` ```````````````````````````````` example - item 1 2. item 2 . - item 1 2. item 2 ```````````````````````````````` ```````````````````````````````` example - list - . - list - ```````````````````````````````` �����������lepture-mistune-f19057f/tests/fixtures/renderer_rst.txt���������������������������������������������0000664�0000000�0000000�00000006144�15265371675�0023517�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# RSTRenderer ## inline ```````````````````````````````` example this is _em_, **strong**, and `code` . this is *em*, **strong**, and ``code`` ```````````````````````````````` ```````````````````````````````` example | escape | . \| escape \| ```````````````````````````````` ## links ```````````````````````````````` example this is [link][] and [link](/foo) [link]: /url . this is `link </url>`__ and `link </foo>`__ ```````````````````````````````` ## images ```````````````````````````````` example this is inline ![alt _text_](/foo) . this is inline |img-0| .. |img-0| image:: /foo :alt: alt *text* ```````````````````````````````` ```````````````````````````````` example this is figure ![alt _text_](/foo) . this is figure .. figure:: /foo alt *text* ```````````````````````````````` ```````````````````````````````` example this is figure ![alt _text_](/foo "title") . this is figure .. figure:: /foo :alt: title alt *text* ```````````````````````````````` ## html ```````````````````````````````` example ignore inline html <a>text</a> but show block html <div>hi</div> . ignore inline html text but show block html .. raw:: html <div>hi</div> ```````````````````````````````` ## line break ```````````````````````````````` example hello world . | hello | world ```````````````````````````````` ## heading ```````````````````````````````` example # h1 ## h2 ### h3 #### h4 ##### h5 ###### h6 . h1 == h2 -- h3 ~~ h4 ^^ h5 "" h6 '' ```````````````````````````````` ## thematic break ```````````````````````````````` example hi *** . hi -------------- ```````````````````````````````` ## code ```````````````````````````````` example start def foo(): pass end . start :: def foo(): pass end ```````````````````````````````` ```````````````````````````````` example start ```py def foo(): pass ``` end . start .. code:: py def foo(): pass end ```````````````````````````````` ## quote ```````````````````````````````` example > quote . quote ```````````````````````````````` ```````````````````````````````` example hello > quote . hello quote ```````````````````````````````` ```````````````````````````````` example > hello > quote . hello .. quote ```````````````````````````````` ## list ```````````````````````````````` example - list + list . - list + list ```````````````````````````````` ```````````````````````````````` example - item 1 item 2 . - item 1 item 2 ```````````````````````````````` ```````````````````````````````` example - item 1 item 2 - item 3 . - item 1 item 2 - item 3 ```````````````````````````````` ```````````````````````````````` example - item 1 1. item 2 . - item 1 1. item 2 ```````````````````````````````` ```````````````````````````````` example - item 1 1. item 2 . - item 1 1. item 2 ```````````````````````````````` ```````````````````````````````` example - item > quote . - item quote ```````````````````````````````` ```````````````````````````````` example - item > first > second . - item first .. second ```````````````````````````````` ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/fixtures/rst_admonition.txt�������������������������������������������0000664�0000000�0000000�00000001520�15265371675�0024043�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Admonition ```````````````````````````````` example .. hello:: Warning message . <div class="error"><pre>.. hello:: Warning message </pre></div> ```````````````````````````````` ```````````````````````````````` example .. note:: Warning message . <section class="admonition note"> <p class="admonition-title">Warning</p> <p>message</p> </section> ```````````````````````````````` Test with code block. ```````````````````````````````` example .. note:: print() . <section class="admonition note"> <p class="admonition-title">Note</p> <pre><code>print()</code></pre> </section> ```````````````````````````````` Test with no message. ```````````````````````````````` example .. note:: Warning . <section class="admonition note"> <p class="admonition-title">Warning</p> </section> ```````````````````````````````` ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/fixtures/rst_toc.txt��������������������������������������������������0000664�0000000�0000000�00000007316�15265371675�0022500�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Table of Contents ## No TOC ```````````````````````````````` example none . <p>none</p> ```````````````````````````````` ```````````````````````````````` example # H1 ## H2 . <h1>H1</h1> <h2>H2</h2> ```````````````````````````````` ## Simple TOC ```````````````````````````````` example .. toc:: # H1 ## H2 . <details class="toc" open> <summary>Table of Contents</summary> <ul> <li><a href="#toc_1">H1</a> <ul> <li><a href="#toc_2">H2</a></li> </ul> </li> </ul> </details> <h1 id="toc_1">H1</h1> <h2 id="toc_2">H2</h2> ```````````````````````````````` ## Invalid Option ```````````````````````````````` example # H1 ## H2 .. toc:: :max-level: s . <h1>H1</h1> <h2>H2</h2> <div class="error"><pre>"max-level" option MUST be integer</pre></div> ```````````````````````````````` ```````````````````````````````` example # H1 ## H2 .. toc:: :max-level: 9 . <h1>H1</h1> <h2>H2</h2> <div class="error"><pre>"max-level" option MUST be <= 3</pre></div> ```````````````````````````````` ```````````````````````````````` example # H1 ## H2 .. toc:: :min-level: 2 :max-level: 1 . <h1>H1</h1> <h2>H2</h2> <div class="error"><pre>"min-level" option MUST be less than "max-level" option</pre></div> ```````````````````````````````` ## Complex ```````````````````````````````` example # H1 ## H2 ### H3 #### H4 # H1 B # H1 `C` .. toc:: Contents :max-level: 3 . <h1 id="toc_1">H1</h1> <h2 id="toc_2">H2</h2> <h3 id="toc_3">H3</h3> <h4 id="toc_4">H4</h4> <h1 id="toc_5">H1 B</h1> <h1 id="toc_6">H1 <code>C</code></h1> <details class="toc" open> <summary>Contents</summary> <ul> <li><a href="#toc_1">H1</a> <ul> <li><a href="#toc_2">H2</a> <ul> <li><a href="#toc_3">H3</a></li> </ul> </li> </ul> </li> <li><a href="#toc_5">H1 B</a></li> <li><a href="#toc_6">H1 C</a></li> </ul> </details> ```````````````````````````````` ## Insane ```````````````````````````````` example # H1 ### H3 ## H2 #### H4 ### H3 B # H1 B .. toc:: . <h1 id="toc_1">H1</h1> <h3 id="toc_2">H3</h3> <h2 id="toc_3">H2</h2> <h4 id="toc_4">H4</h4> <h3 id="toc_5">H3 B</h3> <h1 id="toc_6">H1 B</h1> <details class="toc" open> <summary>Table of Contents</summary> <ul> <li><a href="#toc_1">H1</a> <ul> <li><a href="#toc_2">H3</a></li> <li><a href="#toc_3">H2</a> <ul> <li><a href="#toc_5">H3 B</a></li> </ul> </li> </ul> </li> <li><a href="#toc_6">H1 B</a></li> </ul> </details> ```````````````````````````````` ```````````````````````````````` example ### H3 ## H2 # H1 .. toc:: . <h3 id="toc_1">H3</h3> <h2 id="toc_2">H2</h2> <h1 id="toc_3">H1</h1> <details class="toc" open> <summary>Table of Contents</summary> <ul> <li><a href="#toc_1">H3</a></li> <li><a href="#toc_2">H2</a></li> <li><a href="#toc_3">H1</a></li> </ul> </details> ```````````````````````````````` ## Link in Heading ```````````````````````````````` example # [foo](/bar) # [baz][ref] [ref]: /quux .. toc:: . <h1 id="toc_1"><a href="/bar">foo</a></h1> <h1 id="toc_2"><a href="/quux">baz</a></h1> <details class="toc" open> <summary>Table of Contents</summary> <ul> <li><a href="#toc_1">foo</a></li> <li><a href="#toc_2">baz</a></li> </ul> </details> ```````````````````````````````` ## HTML in Heading ```````````````````````````````` example # <em>H1</em> .. toc:: . <h1 id="toc_1"><em>H1</em></h1> <details class="toc" open> <summary>Table of Contents</summary> <ul> <li><a href="#toc_1">H1</a></li> </ul> </details> ```````````````````````````````` ## Collapse TOC ```````````````````````````````` example .. toc:: :collapse: # H1 ## H2 . <details class="toc"> <summary>Table of Contents</summary> <ul> <li><a href="#toc_1">H1</a> <ul> <li><a href="#toc_2">H2</a></li> </ul> </li> </ul> </details> <h1 id="toc_1">H1</h1> <h2 id="toc_2">H2</h2> ```````````````````````````````` ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/fixtures/ruby.txt�����������������������������������������������������0000664�0000000�0000000�00000003415�15265371675�0022000�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Ruby ## ruby without link ```````````````````````````````` example [漢字(ㄏㄢˋㄗˋ)] . <p><ruby>漢字<rt>ㄏㄢˋㄗˋ</rt></ruby></p> ```````````````````````````````` ```````````````````````````````` example [漢(ㄏㄢˋ)字(ㄗˋ)] . <p><ruby>漢<rt>ㄏㄢˋ</rt></ruby><ruby>字<rt>ㄗˋ</rt></ruby></p> ```````````````````````````````` ```````````````````````````````` example [漢字(ㄏㄢˋㄗˋ)][] . <p><ruby>漢字<rt>ㄏㄢˋㄗˋ</rt></ruby>[]</p> ```````````````````````````````` ```````````````````````````````` example [漢字(ㄏㄢˋㄗˋ)][link] . <p><ruby>漢字<rt>ㄏㄢˋㄗˋ</rt></ruby>[link]</p> ```````````````````````````````` ## ruby with link ```````````````````````````````` example [link]: /url [漢字(ㄏㄢˋㄗˋ)][link] . <p><a href="/url"><ruby>漢字<rt>ㄏㄢˋㄗˋ</rt></ruby></a></p> ```````````````````````````````` ```````````````````````````````` example [漢字(ㄏㄢˋㄗˋ)]() . <p><a href=""><ruby>漢字<rt>ㄏㄢˋㄗˋ</rt></ruby></a></p> ```````````````````````````````` ```````````````````````````````` example [漢字(ㄏㄢˋㄗˋ)](/url) . <p><a href="/url"><ruby>漢字<rt>ㄏㄢˋㄗˋ</rt></ruby></a></p> ```````````````````````````````` ## ruby splits ```````````````````````````````` example [漢(かん)][字(じ)] . <p><ruby>漢<rt>かん</rt></ruby><ruby>字<rt>じ</rt></ruby></p> ```````````````````````````````` ```````````````````````````````` example [[漢(かん)][字(じ)]](https://jisho.org/search/漢字) . <p><a href="https://jisho.org/search/%E6%BC%A2%E5%AD%97"><ruby>漢<rt>かん</rt></ruby><ruby>字<rt>じ</rt></ruby></a></p> ```````````````````````````````` ```````````````````````````````` example [汉字(hàn zì)] . <p><ruby>汉字<rt>hàn zì</rt></ruby></p> ```````````````````````````````` ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/fixtures/spoiler.txt��������������������������������������������������0000664�0000000�0000000�00000002625�15265371675�0022476�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Spoiler ## Block spoiler ```````````````````````````````` example >! hi . <div class="spoiler"> <p>hi</p> </div> ```````````````````````````````` ```````````````````````````````` example >! not > spoiler . <blockquote> <p>! not spoiler</p> </blockquote> ```````````````````````````````` ```````````````````````````````` example >! multiple >! lines . <div class="spoiler"> <p>multiple lines</p> </div> ```````````````````````````````` ```````````````````````````````` example >! foo >! >! bar . <div class="spoiler"> <p>foo</p> <p>bar</p> </div> ```````````````````````````````` ```````````````````````````````` example >! foo > >! bar . <blockquote> <p>! foo</p> <p>! bar</p> </blockquote> ```````````````````````````````` ```````````````````````````````` example > > > > > >! secret . <blockquote> <blockquote> <blockquote> <blockquote> <blockquote> <blockquote> <p>! secret</p> </blockquote> </blockquote> </blockquote> </blockquote> </blockquote> </blockquote> ```````````````````````````````` ## Inline spoiler ```````````````````````````````` example hi >! hide !< . <p>hi <span class="spoiler">hide</span></p> ```````````````````````````````` ```````````````````````````````` example hi >!hide !< . <p>hi <span class="spoiler">hide</span></p> ```````````````````````````````` ```````````````````````````````` example hi >!hide!< . <p>hi <span class="spoiler">hide</span></p> ```````````````````````````````` �����������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/fixtures/strikethrough.txt��������������������������������������������0000664�0000000�0000000�00000001566�15265371675�0023726�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Strikethrough ## strikethrough ```````````````````````````````` example ~~delete me . <p>~~delete me</p> ```````````````````````````````` ```````````````````````````````` example ~~delete me~~ . <p><del>delete me</del></p> ```````````````````````````````` ```````````````````````````````` example ~~delete me~~~ . <p>~~delete me~~~</p> ```````````````````````````````` ```````````````````````````````` example ~~delete me\~~~ . <p><del>delete me~</del></p> ```````````````````````````````` ```````````````````````````````` example ~~delete \~\~ me~~ . <p><del>delete ~~ me</del></p> ```````````````````````````````` ```````````````````````````````` example ~~delete [me~~](/) . <p><del>delete [me</del>](/)</p> ```````````````````````````````` ```````````````````````````````` example ~~[hello](/)~~ . <p><del><a href="/">hello</a></del></p> ```````````````````````````````` ������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/fixtures/subscript.txt������������������������������������������������0000664�0000000�0000000�00000001011�15265371675�0023023�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Subscript ```````````````````````````````` example CH~3~CH~2~OH . <p>CH<sub>3</sub>CH<sub>2</sub>OH</p> ```````````````````````````````` ```````````````````````````````` example text~a\ subscript~ . <p>text<sub>a subscript</sub></p> ```````````````````````````````` ```````````````````````````````` example text~a subscript~ . <p>text~a subscript~</p> ```````````````````````````````` ```````````````````````````````` example text~a\~subscript~ . <p>text<sub>a~subscript</sub></p> ```````````````````````````````` �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/fixtures/superscript.txt����������������������������������������������0000664�0000000�0000000�00000001013�15265371675�0023372�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Superscript ```````````````````````````````` example CH^3^CH^2^OH . <p>CH<sup>3</sup>CH<sup>2</sup>OH</p> ```````````````````````````````` ```````````````````````````````` example text^a\ supscript^ . <p>text<sup>a supscript</sup></p> ```````````````````````````````` ```````````````````````````````` example text^a supscript^ . <p>text^a supscript^</p> ```````````````````````````````` ```````````````````````````````` example text^a\^supscript^ . <p>text<sup>a^supscript</sup></p> ```````````````````````````````` ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/fixtures/table.txt����������������������������������������������������0000664�0000000�0000000�00000013276�15265371675�0022114�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Table in Markdown https://michelf.ca/projects/php-markdown/extra/#table ## nptable ```````````````````````````````` example First Header | Second Header ------------- | ------------- Content Cell | Content Cell Content Cell | Content Cell . <table> <thead> <tr> <th>First Header</th> <th>Second Header</th> </tr> </thead> <tbody> <tr> <td>Content Cell</td> <td>Content Cell</td> </tr> <tr> <td>Content Cell</td> <td>Content Cell</td> </tr> </tbody> </table> ```````````````````````````````` ## Invalid Table ```````````````````````````````` example | A | B | --- | --- . <p>| A | B | --- | ---</p> ```````````````````````````````` ```````````````````````````````` example | A | B | | - | - | | a | b | c | paragraph . <p>| A | B | | - | - | | a | b | c | paragraph</p> ```````````````````````````````` ```````````````````````````````` example A | B --- | --- | --- . <p>A | B --- | --- | ---</p> ```````````````````````````````` ```````````````````````````````` example A | B - | - a | b | c paragraph . <p>A | B</p> <ul> <li>| - a | b | c paragraph</li> </ul> ```````````````````````````````` ## Not a delimiter row ```````````````````````````````` example Name | Age John | 30 Jane | 25 . <p>Name | Age John | 30 Jane | 25</p> ```````````````````````````````` ```````````````````````````````` example a | b foo | bar 1 | 2 . <p>a | b foo | bar 1 | 2</p> ```````````````````````````````` ## Table End ```````````````````````````````` example | A | B | | - | - | | a | b | paragraph . <table> <thead> <tr> <th>A</th> <th>B</th> </tr> </thead> <tbody> <tr> <td>a</td> <td>b</td> </tr> </tbody> </table> <p>paragraph</p> ```````````````````````````````` ```````````````````````````````` example A | B - | - a | b paragraph . <table> <thead> <tr> <th>A</th> <th>B</th> </tr> </thead> <tbody> <tr> <td>a</td> <td>b</td> </tr> </tbody> </table> <p>paragraph</p> ```````````````````````````````` ## Escaped Pipe ```````````````````````````````` example | A | B | | - | - | | a \| b | c | . <table> <thead> <tr> <th>A</th> <th>B</th> </tr> </thead> <tbody> <tr> <td>a | b</td> <td>c</td> </tr> </tbody> </table> ```````````````````````````````` ## table ```````````````````````````````` example | First Header | Second Header | | ------------- | ------------- | | Content Cell | | | Content Cell | Content Cell | . <table> <thead> <tr> <th>First Header</th> <th>Second Header</th> </tr> </thead> <tbody> <tr> <td>Content Cell</td> <td></td> </tr> <tr> <td>Content Cell</td> <td>Content Cell</td> </tr> </tbody> </table> ```````````````````````````````` ```````````````````````````````` example | Command | Description | | --- | --- | | git status | List all new or modified files | | git diff | Show file differences that haven't been staged | . <table> <thead> <tr> <th>Command</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td>git status</td> <td>List all new or modified files</td> </tr> <tr> <td>git diff</td> <td>Show file differences that haven't been staged</td> </tr> </tbody> </table> ```````````````````````````````` ## align table ```````````````````````````````` example Left | Center | Right :---- | :--------: | ------: a | b | c . <table> <thead> <tr> <th style="text-align:left">Left</th> <th style="text-align:center">Center</th> <th style="text-align:right">Right</th> </tr> </thead> <tbody> <tr> <td style="text-align:left">a</td> <td style="text-align:center">b</td> <td style="text-align:right">c</td> </tr> </tbody> </table> ```````````````````````````````` ```````````````````````````````` example | Left | Center | Right | | :--- | :----: | ----: | | a | b | c | . <table> <thead> <tr> <th style="text-align:left">Left</th> <th style="text-align:center">Center</th> <th style="text-align:right">Right</th> </tr> </thead> <tbody> <tr> <td style="text-align:left">a</td> <td style="text-align:center">b</td> <td style="text-align:right">c</td> </tr> </tbody> </table> ```````````````````````````````` ## Misc Table ```````````````````````````````` example | A | | | - | | | a | b | . <table> <thead> <tr> <th>A</th> <th></th> </tr> </thead> <tbody> <tr> <td>a</td> <td>b</td> </tr> </tbody> </table> ```````````````````````````````` ```````````````````````````````` example A | - | a | b . <table> <thead> <tr> <th>A</th> <th></th> </tr> </thead> <tbody> <tr> <td>a</td> <td>b</td> </tr> </tbody> </table> ```````````````````````````````` ```````````````````````````````` example | Foo | Bar | |-----|-----| | boo | baz | | faz | | . <table> <thead> <tr> <th>Foo</th> <th>Bar</th> </tr> </thead> <tbody> <tr> <td>boo</td> <td>baz</td> </tr> <tr> <td>faz</td> <td></td> </tr> </tbody> </table> ```````````````````````````````` ## Mismatch length ```````````````````````````````` example | First Header | | ------------- | ------------- | | Content Cell | | | Content Cell | Content Cell | . <p>| First Header | | ------------- | ------------- | | Content Cell | | | Content Cell | Content Cell |</p> ```````````````````````````````` ```````````````````````````````` example | First Header | Second Header | | ------------- | ------------- | | Content Cell | | Content Cell | Content Cell | . <p>| First Header | Second Header | | ------------- | ------------- | | Content Cell | | Content Cell | Content Cell |</p> ```````````````````````````````` ```````````````````````````````` example A | - | - | a | b | c . <p>A |</p> <ul> <li>| - | a | b | c</li> </ul> ```````````````````````````````` ```````````````````````````````` example A | B | C - | - | - a | b . <p>A | B | C</p> <ul> <li>| - | - a | b</li> </ul> ```````````````````````````````` ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/fixtures/task_lists.txt�����������������������������������������������0000664�0000000�0000000�00000010136�15265371675�0023175�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Task Lists ```````````````````````````````` example - [ ] foo - [x] bar - [X] baz . <ul> <li class="task-list-item"><input class="task-list-item-checkbox" type="checkbox" disabled/>foo</li> <li class="task-list-item"><input class="task-list-item-checkbox" type="checkbox" disabled checked/>bar</li> <li class="task-list-item"><input class="task-list-item-checkbox" type="checkbox" disabled checked/>baz</li> </ul> ```````````````````````````````` ```````````````````````````````` example - foo - [ ] bar . <ul> <li>foo</li> <li class="task-list-item"><input class="task-list-item-checkbox" type="checkbox" disabled/>bar</li> </ul> ```````````````````````````````` ```````````````````````````````` example - foo - [ ] bar - [x] baz text . <ul> <li><p>foo</p> </li> <li class="task-list-item"><p><input class="task-list-item-checkbox" type="checkbox" disabled/>bar</p> </li> <li class="task-list-item"><p><input class="task-list-item-checkbox" type="checkbox" disabled checked/>baz</p> <p>text</p> </li> </ul> ```````````````````````````````` ```````````````````````````````` example 1. [ ] foo 2. [x] bar 3. [X] baz . <ol> <li class="task-list-item"><input class="task-list-item-checkbox" type="checkbox" disabled/>foo</li> <li class="task-list-item"><input class="task-list-item-checkbox" type="checkbox" disabled checked/>bar</li> <li class="task-list-item"><input class="task-list-item-checkbox" type="checkbox" disabled checked/>baz</li> </ol> ```````````````````````````````` ```````````````````````````````` example - [ ] Task list item over two lines . <ul> <li class="task-list-item"><input class="task-list-item-checkbox" type="checkbox" disabled/>Task list item over two lines</li> </ul> ```````````````````````````````` ```````````````````````````````` example - [ ] foo - [x] bar - [ ] baz . <ul> <li class="task-list-item"><input class="task-list-item-checkbox" type="checkbox" disabled/>foo<ul> <li class="task-list-item"><input class="task-list-item-checkbox" type="checkbox" disabled checked/>bar</li> <li class="task-list-item"><input class="task-list-item-checkbox" type="checkbox" disabled/>baz</li> </ul> </li> </ul> ```````````````````````````````` ```````````````````````````````` example 1. [ ] foo 1. [ ] bar 2. [ ] baz . <ol> <li class="task-list-item"><input class="task-list-item-checkbox" type="checkbox" disabled/>foo<ol> <li class="task-list-item"><input class="task-list-item-checkbox" type="checkbox" disabled/>bar</li> <li class="task-list-item"><input class="task-list-item-checkbox" type="checkbox" disabled/>baz</li> </ol> </li> </ol> ```````````````````````````````` ```````````````````````````````` example > - [ ] foo > - [x] bar > - [ ] baz . <blockquote> <ul> <li class="task-list-item"><input class="task-list-item-checkbox" type="checkbox" disabled/>foo<ul> <li class="task-list-item"><input class="task-list-item-checkbox" type="checkbox" disabled checked/>bar</li> <li class="task-list-item"><input class="task-list-item-checkbox" type="checkbox" disabled/>baz</li> </ul> </li> </ul> </blockquote> ```````````````````````````````` # Leading headings are not task list paragraphs ```````````````````````````````` example - # [ ] unchecked heading - ## [x] checked heading - ### [X] uppercase checked heading . <ul> <li><h1>[ ] unchecked heading</h1> </li> <li><h2>[x] checked heading</h2> </li> <li><h3>[X] uppercase checked heading</h3> </li> </ul> ```````````````````````````````` ```````````````````````````````` example - [x] setext heading ================== - [ ] setext heading ------------------ . <ul> <li><h1>[x] setext heading</h1> </li> <li><h2>[ ] setext heading</h2> </li> </ul> ```````````````````````````````` ```````````````````````````````` example - # [x] heading [ ] paragraph after heading . <ul> <li><h1>[x] heading</h1> <p>[ ] paragraph after heading</p> </li> </ul> ```````````````````````````````` ```````````````````````````````` example - # [x] heading - [x] nested task . <ul> <li><h1>[x] heading</h1> <ul> <li class="task-list-item"><input class="task-list-item-checkbox" type="checkbox" disabled checked/>nested task</li> </ul> </li> </ul> ```````````````````````````````` ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/fixtures/url.txt������������������������������������������������������0000664�0000000�0000000�00000001022�15265371675�0021611�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# url plugin ```````````````````````````````` example visit https://lepture.com/ . <p>visit <a href="https://lepture.com/">https://lepture.com/</a></p> ```````````````````````````````` ```````````````````````````````` example visit [https://lepture.com/](/foo) . <p>visit <a href="/foo">https://lepture.com/</a></p> ```````````````````````````````` ```````````````````````````````` example visit <a href="/foo">https://lepture.com/</a> . <p>visit <a href="/foo">https://lepture.com/</a></p> ```````````````````````````````` ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/perf_utils.py���������������������������������������������������������0000664�0000000�0000000�00000002376�15265371675�0021140�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import statistics import time from typing import Callable, Tuple, TypeVar from unittest import TestCase T = TypeVar("T") def assert_near_linear( test_case: TestCase, operation: Callable[[int], T], small_size: int, large_size: int, *, max_growth: float = 3.5, noise_seconds: float = 0.02, warmup_size: int = 200, ) -> Tuple[T, T]: """Assert that doubling adversarial input has bounded time growth.""" if small_size < 1 or large_size <= small_size: raise ValueError("sizes must be positive and increasing") operation(warmup_size) small_result, small_elapsed = _measure(operation, small_size) large_result, large_elapsed = _measure(operation, large_size) test_case.assertLess( large_elapsed, small_elapsed * max_growth + noise_seconds, f"time growth {large_elapsed / max(small_elapsed, 1e-12):.2f}x exceeded {max_growth:.2f}x", ) return small_result, large_result def _measure(operation: Callable[[int], T], size: int) -> Tuple[T, float]: timings = [] result = operation(size) for _ in range(3): started = time.perf_counter() result = operation(size) timings.append(time.perf_counter() - started) return result, statistics.median(timings) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/test_cli.py�����������������������������������������������������������0000664�0000000�0000000�00000001065�15265371675�0020564�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import io import sys from contextlib import redirect_stdout from unittest.mock import patch from mistune.__main__ import cli from tests import BaseTestCase class TestCliMessage(BaseTestCase): def parse(self, text: str) -> str: with patch.object(sys, "argv", ["python -m mistune", "-m", text]): buf = io.StringIO() with redirect_stdout(buf): cli() output = buf.getvalue() if output.endswith("\n"): output = output[:-1] return output TestCliMessage.load_fixtures("cli.txt") ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/test_commonmark.py����������������������������������������������������0000664�0000000�0000000�00000002447�15265371675�0022165�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import mistune from tests import BaseTestCase, normalize_html class TestCommonMark(BaseTestCase): markdown = mistune.create_markdown( renderer=mistune.HTMLRenderer(escape=False, allow_harmful_protocols=True), ) def assert_case(self, n, text, html): result = self.markdown(text) self.assertEqual(normalize_html(result), normalize_html(html)) def test_commonmark_0312_inline_html_comments(self): cases = [ ( "foo <!-- this is a --\ncomment - with hyphens -->\n", "<p>foo <!-- this is a --\ncomment - with hyphens --></p>\n", "<p>foo <!-- this is a --\ncomment - with hyphens --></p>\n", ), ( "foo <!--> foo -->\n\nfoo <!---> foo -->\n", "<p>foo <!--> foo --></p>\n<p>foo <!---> foo --></p>\n", "<p>foo <!--> foo --></p>\n<p>foo <!---> foo --></p>\n", ), ] escaped_markdown = mistune.create_markdown() for text, raw_html, escaped_html in cases: with self.subTest(text=text): self.assertEqual(self.markdown(text), raw_html) self.assertEqual(escaped_markdown(text), escaped_html) TestCommonMark.load_fixtures("commonmark.json") �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/test_def_list.py������������������������������������������������������0000664�0000000�0000000�00000004325�15265371675�0021610�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import pytest from mistune import create_markdown @pytest.fixture(params=[False, True], ids=["plain", "speedup"]) def md(request): plugins = ["def_list", "speedup"] if request.param else ["def_list"] return create_markdown(plugins=plugins) @pytest.mark.parametrize("indent", range(4)) @pytest.mark.parametrize("separator", [" ", "\t"], ids=["space", "tab"]) @pytest.mark.parametrize("loose", [False, True], ids=["tight", "loose"]) def test_definition_marker_indentation(md, indent, separator, loose): source = "Term\n" + ("\n" if loose else "") + " " * indent + ":" + separator + "definition\n" definition = "<p>definition</p>\n" if loose else "definition" assert md(source) == "<dl>\n<dt>Term</dt>\n<dd>" + definition + "</dd>\n</dl>\n" def test_successive_definition_markers_with_different_indentation(md): source = "Term\n: first\n : second\n : third\n : fourth\n" assert md(source) == ( "<dl>\n<dt>Term</dt>\n<dd>first</dd>\n<dd>second</dd>\n<dd>third</dd>\n<dd>fourth</dd>\n</dl>\n" ) def test_indented_definition_preserves_continuation_blocks(md): source = "Term\n : definition\n continuation\n\n code\n\nparagraph\n" assert md(source) == ( "<dl>\n<dt>Term</dt>\n<dd><p>definition\ncontinuation</p>\n" "<pre><code>code</code></pre>\n</dd>\n</dl>\n<p>paragraph</p>\n" ) def test_four_space_indented_colon_is_not_a_definition_marker(md): assert md("Term\n : definition\n") == "<p>Term\n: definition</p>\n" def test_indented_marker_requires_a_term(md): assert md(" : orphan\n") == "<p>: orphan</p>\n" @pytest.mark.parametrize("speedup", [False, True]) def test_indented_definition_ast(speedup): plugins = ["def_list", "speedup"] if speedup else ["def_list"] md = create_markdown(renderer=None, plugins=plugins) assert md("Term\n : definition\n") == [ { "type": "def_list", "children": [ {"type": "def_list_head", "children": [{"type": "text", "raw": "Term"}]}, { "type": "def_list_item", "children": [{"type": "block_text", "children": [{"type": "text", "raw": "definition"}]}], }, ], } ] �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/test_directives.py����������������������������������������������������0000664�0000000�0000000�00000010705�15265371675�0022157�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import os from mistune import create_markdown from mistune.directives import Admonition, FencedDirective, Figure, Image, Include, RSTDirective, TableOfContents from tests import BaseTestCase from tests.fixtures import ROOT def load_directive_test(filename, directive, cls): class TestDirective(BaseTestCase): @staticmethod def parse(text): md = create_markdown( escape=False, plugins=[cls([directive])], ) html = md(text) return html TestDirective.load_fixtures(filename + ".txt") globals()["TestDirective_" + filename] = TestDirective load_directive_test("rst_admonition", Admonition(), RSTDirective) load_directive_test("rst_toc", TableOfContents(), RSTDirective) load_directive_test("fenced_admonition", Admonition(), FencedDirective) load_directive_test("fenced_toc", TableOfContents(), FencedDirective) load_directive_test("fenced_image", Image(), FencedDirective) load_directive_test("fenced_figure", Figure(), FencedDirective) class CustomizeTableOfContents(TableOfContents): def generate_heading_id(self, token, i): return "t-" + str(i + 1) class TestCustomizeToc(BaseTestCase): def test_rst_toc(self): md = create_markdown( escape=False, plugins=[ RSTDirective([CustomizeTableOfContents()]), ], ) html = md("# h1\n\n.. toc::\n") self.assertIn('<h1 id="t-1">h1</h1>', html) self.assertIn('<a href="#t-1">h1</a>', html) def test_fenced_toc(self): md = create_markdown( escape=False, plugins=[ FencedDirective([CustomizeTableOfContents()]), ], ) html = md("# h1\n\n```{toc}\n```\n") self.assertIn('<h1 id="t-1">h1</h1>', html) self.assertIn('<a href="#t-1">h1</a>', html) def test_colon_fenced_toc(self): md = create_markdown( escape=False, plugins=[ FencedDirective([CustomizeTableOfContents()], ":"), ], ) html = md("# h1\n\n:::{toc}\n:::\n") self.assertIn('<h1 id="t-1">h1</h1>', html) self.assertIn('<a href="#t-1">h1</a>', html) class TestFencedDirectiveInList(BaseTestCase): md = create_markdown( # type: ignore[list-item] escape=False, plugins=[FencedDirective([Admonition()], markers=":")], ) def test_marker_run_below_fence_length_is_not_a_directive(self): # A directive needs three or more markers, inside a list item as well # as outside one. The list break rules are recompiled per item, and a # marker run shorter than the fence must stay literal text. for text in (":{note}\nlazy\n", "100. item\n:{note}\nlazy\n"): self.assertNotIn("admonition", self.md(text)) html = self.md("- item\n:{note}\nlazy\n") self.assertNotIn("admonition", html) self.assertIn(":{note}", html) def test_directive_still_breaks_a_list(self): html = self.md("- item\n:::{note}\nbody\n:::\n") self.assertIn('<section class="admonition note">', html) self.assertIn("<p>body</p>", html) class TestDirectiveInclude(BaseTestCase): md = create_markdown(escape=False, plugins=[RSTDirective([Include()])]) # type: ignore[list-item] def test_html_include(self): html = self.md.read(os.path.join(ROOT, "include/text.md"))[0] self.assertIn("Could not include self", html) self.assertIn("Could not find file", html) self.assertIn("<div>include html</div>", html) self.assertIn("<blockquote>", html) self.assertIn("Could not include outside source dir", html) def test_include_missing_source(self): s = ".. include:: foo.txt" html = self.md(s) self.assertIn("Missing source file", html) class TestImageDirectiveSrc(BaseTestCase): md = create_markdown(escape=False, plugins=[RSTDirective([Image()])]) # type: ignore[list-item] def test_harmful_src_blocked(self): html = self.md(".. image:: javascript:alert") self.assertIn('src="#harmful-link"', html) self.assertNotIn("javascript:alert", html) def test_safe_src_preserved(self): html = self.md(".. image:: cat.png") self.assertIn('src="cat.png"', html) def test_target_still_filtered(self): html = self.md(".. image:: cat.png\n :target: javascript:alert") self.assertNotIn("javascript:alert", html) �����������������������������������������������������������lepture-mistune-f19057f/tests/test_hooks.py���������������������������������������������������������0000664�0000000�0000000�00000001556�15265371675�0021145�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from mistune import create_markdown from mistune.toc import add_toc_hook, render_toc_ul from tests import BaseTestCase class TestTocHook(BaseTestCase): @staticmethod def parse(text): md = create_markdown(escape=False) add_toc_hook(md) html, state = md.parse(text) result = html + render_toc_ul(state.env["toc_items"]) return result def test_customize_heading_id_func(self): def heading_id(token, i): return "t-" + str(i + 1) md = create_markdown(escape=False) add_toc_hook(md, heading_id=heading_id) html = md("# h1") self.assertEqual(html, '<h1 id="t-1">h1</h1>\n') def test_render_empty_toc(self): self.assertEqual(render_toc_ul([]), "") self.assertEqual(render_toc_ul(filter(lambda _: False, [])), "") TestTocHook.load_fixtures("hook_toc.txt") ��������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/test_inline_limits.py�������������������������������������������������0000664�0000000�0000000�00000017710�15265371675�0022660�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from unittest import TestCase import pytest from mistune import BlockParser, InlineParser, Markdown, create_markdown from mistune.plugins import import_plugin from tests.perf_utils import assert_near_linear @pytest.mark.parametrize("length", [500, 501, 998, 999, 1000]) def test_reference_label_length_is_measured_in_source_characters(length): label = "a" * length source = f"[text][{label}]\n\n[{label}]: /url\n" result = create_markdown()(source) if length <= 999: assert result == '<p><a href="/url">text</a></p>\n' else: assert '<a href="/url">' not in result assert label in result @pytest.mark.parametrize("pairs,valid", [(499, True), (500, False)]) def test_escaped_reference_label_characters_count_toward_limit(pairs, valid): label = r"\*" * pairs result = create_markdown()(f"[text][{label}]\n\n[{label}]: /url\n") assert ('<a href="/url">text</a>' in result) is valid def test_reference_label_limit_does_not_limit_inline_link_text(): text = "a" * 2000 assert create_markdown()(f"[{text}](/url)") == f'<p><a href="/url">{text}</a></p>\n' @pytest.mark.parametrize("level,valid", [(19, True), (20, True), (21, False)]) def test_destination_parenthesis_limit(level, valid): destination = "(" * level + "url" + ")" * level result = create_markdown()(f"[text]({destination}) [ok](/ok) *em* `code`") assert ('<a href="' + destination + '">text</a>' in result) is valid assert result.endswith('<a href="/ok">ok</a> <em>em</em> <code>code</code></p>\n') if not valid: assert f"[text]({destination})" in result @pytest.mark.parametrize("character", ["\x01", "\x08", "\x1f", "\x7f"]) def test_bare_destination_rejects_ascii_control_characters(character): result = create_markdown()(f"[bad](a{character}b) [ok](/ok)") assert result.count("<a ") == 1 assert result.endswith('<a href="/ok">ok</a></p>\n') def test_parenthesized_title_rejects_unescaped_nested_parentheses(): result = create_markdown()('[bad](/url (a (b))) [ok](/ok "a (b)")') assert result == '<p>[bad](/url (a (b))) <a href="/ok" title="a (b)">ok</a></p>\n' @pytest.mark.parametrize("destination", ["<a<b>", "<a\\\nb>", "a(b", "a)b"]) def test_invalid_reference_destination_remains_text(destination): result = create_markdown()(f"[bad]: {destination}\n\n[bad] [ok](/ok)") assert '<a href="/ok">ok</a>' in result assert "[bad]" in result assert result.count("<a ") == 1 def test_invalid_image_reference_keeps_inner_link(): result = create_markdown()("[![x][y](/inner)](/outer)") assert result == '<p>[![x]<a href="/inner">y</a>](/outer)</p>\n' @pytest.mark.parametrize( "source", [ "[[missing]][ref] [ok](/ok)", "[](foo( [outer ![inner](url)](/outer) [ok](/ok)", "[]( <foo [bar](/url) [ok](/ok)", "[" * 2000 + "missing" + "]" * 2000 + " [ok](/ok)", "![" * 1000 + "text" + "](/image)" * 1000 + " [ok](/ok)", ], ) def test_failed_candidates_preserve_following_legal_syntax(source): result = create_markdown()(source + " *em* `code`") assert result.endswith('<a href="/ok">ok</a> <em>em</em> <code>code</code></p>\n') def inline_depth(tokens): maximum = 0 stack = [(token, 0) for token in tokens] while stack: token, depth = stack.pop() if "children" in token: depth += 1 maximum = max(maximum, depth) stack.extend((child, depth) for child in token["children"]) return maximum @pytest.mark.parametrize("limit", [1, 3, 7]) @pytest.mark.parametrize("plugin", ["strikethrough", "mark", "insert", "spoiler"]) def test_mixed_inline_syntax_shares_one_depth_budget(limit, plugin): markers = {"strikethrough": ("~~", "~~"), "mark": ("==", "=="), "insert": ("^^", "^^"), "spoiler": (">!", "!<")} start, end = markers[plugin] text = "text" for _ in range(30): text = f"{start} before *![alt {text}](/image)* after {end}" md = Markdown(inline=InlineParser(max_nested_level=limit)) md.use(import_plugin(plugin)) ast = md("prefix " + text + " [ok](/ok) *em*") assert inline_depth(ast[0]["children"]) <= limit tail = ast[0]["children"] assert any(token["type"] == "link" and token["attrs"]["url"] == "/ok" for token in tail) assert tail[-1]["type"] == "emphasis" @pytest.mark.parametrize( "content,plugins,definitions", [ ("<https://example.com>", [], ""), ("<user@example.com>", [], ""), ("https://example.com", ["url"], ""), ("HTML", ["abbr"], "\n\n*[HTML]: expansion\n"), ("[字(read)](/inner)", ["ruby"], ""), ], ) def test_automatic_and_plugin_links_respect_the_remaining_budget(content, plugins, definitions): md = Markdown(inline=InlineParser(max_nested_level=1)) for plugin in ["strikethrough", *plugins]: md.use(import_plugin(plugin)) ast = md(f"~~{content}~~ [ok](/ok)" + definitions) inline = ast[0]["children"] assert inline[0]["type"] == "strikethrough" assert inline_depth(inline) == 1 assert any(token["type"] == "link" and token["attrs"]["url"] == "/ok" for token in inline) @pytest.mark.parametrize("limit", [0, -1]) def test_nesting_limits_must_be_positive(limit): with pytest.raises(ValueError, match="max_nested_level"): InlineParser(max_nested_level=limit) with pytest.raises(ValueError, match="max_nested_level"): BlockParser(max_nested_level=limit) def test_inline_depth_aliases_configure_the_same_limit(): parser = InlineParser(max_image_depth=3) assert parser.max_nested_level == parser.max_emphasis_depth == 3 parser.max_emphasis_depth = 7 assert parser.max_image_depth == parser.max_nested_level == 7 def test_code_delimiters_are_matched_by_complete_run_length(): source = " ".join("`" * length + "text" for length in range(1, 120)) result = create_markdown()(source + " [ok](/ok) *em*") assert result.endswith('<a href="/ok">ok</a> <em>em</em></p>\n') assert "<code>" not in result @pytest.mark.parametrize("parser", [BlockParser(max_nested_level=3), InlineParser(max_nested_level=3)]) def test_markdown_uses_the_same_default_limit_for_both_parsers(parser): md = Markdown(block=parser) if isinstance(parser, BlockParser) else Markdown(inline=parser) assert md.block.max_nested_level == md.inline.max_nested_level == 3 @pytest.mark.parametrize("marker", ["<!--", "<?", "<![CDATA[", "<!DOCTYPE text"]) def test_unclosed_inline_html_recovers_without_rescanning_the_document(marker): md = create_markdown() def render(size): return md("prefix " + (marker + " text ") * size + "[ok](/ok) *em* `code`") _, result = assert_near_linear(TestCase(), render, 1000, 2000) assert result.endswith('<a href="/ok">ok</a> <em>em</em> <code>code</code></p>\n') @pytest.mark.parametrize("html", ["<??>", "<![CDATA[]]>", "<!DOCTYPE html>", "<!-->", "<!--->", "<!-- a -- b -->"]) def test_inline_html_delimiter_boundaries(html): result = create_markdown(escape=False)("prefix " + html + " [ok](/ok)") assert result == f'<p>prefix {html} <a href="/ok">ok</a></p>\n' @pytest.mark.parametrize("source", ["<!A>", "<!ABC>", "<!A!>", "<!a b>"]) def test_invalid_declarations_do_not_consume_later_closing_delimiters(source): result = create_markdown(escape=False)("prefix " + source + " later > [ok](/ok)") assert "<!" in result assert result.endswith('later > <a href="/ok">ok</a></p>\n') def test_links_inside_many_pending_images_do_not_rescan_image_openers(): md = create_markdown() def render(size): return md("![" * size + "[text](/inner) " * size + "](/image)" * size + " [ok](/ok)") _, result = assert_near_linear(TestCase(), render, 500, 1000) assert result.endswith('<a href="/ok">ok</a></p>\n') def test_unclosed_destinations_recover_in_linear_time(): md = create_markdown() def render(size): return md("[](" * size + " [ok](/ok) *em*") _, result = assert_near_linear(TestCase(), render, 2000, 4000) assert result.endswith('<a href="/ok">ok</a> <em>em</em></p>\n') ��������������������������������������������������������lepture-mistune-f19057f/tests/test_misc.py����������������������������������������������������������0000664�0000000�0000000�00000050411�15265371675�0020747�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from time import perf_counter from unittest import TestCase import mistune class TestMiscCases(TestCase): def test_none(self): self.assertEqual(mistune.html(None), "") def test_before_parse_hooks(self): def _add_name(md, state): state.env["name"] = "test" md = mistune.create_markdown() md.before_parse_hooks.append(_add_name) state = md.block.state_cls() md.parse("", state) self.assertEqual(state.env["name"], "test") def test_escape_applies_to_custom_renderer(self): class CustomRenderer(mistune.HTMLRenderer): pass md = mistune.create_markdown(renderer=CustomRenderer(), escape=False) self.assertEqual(md("<b>hi</b>").strip(), "<p><b>hi</b></p>") md = mistune.create_markdown(renderer=CustomRenderer(escape=False), escape=True) self.assertEqual(md("<b>hi</b>").strip(), "<p><b>hi</b></p>") # without an explicit escape flag the renderer keeps its own setting md = mistune.create_markdown(renderer=CustomRenderer(escape=False)) self.assertEqual(md("<b>hi</b>").strip(), "<p><b>hi</b></p>") def test_hard_wrap(self): md = mistune.create_markdown(escape=False, hard_wrap=True) result = md("foo\nbar") expected = "<p>foo<br />\nbar</p>" self.assertEqual(result.strip(), expected) md = mistune.create_markdown(escape=False, hard_wrap=True, plugins=["speedup"]) result = md("foo\nbar") self.assertEqual(result.strip(), expected) def test_ordered_marker_needs_a_digit(self): self.assertEqual( mistune.html("1. a\n. b\n"), "<ol>\n<li>a\n. b</li>\n</ol>\n", ) self.assertEqual( mistune.html("1) a\n) b\n"), "<ol>\n<li>a\n) b</li>\n</ol>\n", ) self.assertEqual( mistune.html("1. a\n2. b\n"), "<ol>\n<li>a</li>\n<li>b</li>\n</ol>\n", ) self.assertEqual( mistune.html("1. a\n123456789. b\n"), "<ol>\n<li>a</li>\n<li>b</li>\n</ol>\n", ) def test_speedup_plugin_is_compat_noop(self): base = mistune.create_markdown(escape=False) compat = mistune.create_markdown(escape=False, plugins=["speedup"]) text = "foo **bar**\n\n[link](https://example.com)\n" self.assertEqual(compat(text), base(text)) self.assertNotIn("paragraph", compat.block.rules) self.assertNotIn("text", compat.inline.rules) def test_block_plain_paragraph_fast_path_interrupts(self): cases = [ ( mistune.create_markdown(escape=False), "Title\n---\n", "<h2>Title</h2>", ), ( mistune.create_markdown(escape=False), "foo\n- bar\n", "<p>foo</p>\n<ul>\n<li>bar</li>\n</ul>", ), ( mistune.create_markdown(escape=False, plugins=["table"]), "A | B\n--|--\n1 | 2\n", "<table>\n<thead>\n<tr>\n <th>A</th>\n <th>B</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n <td>1</td>\n <td>2</td>\n</tr>\n</tbody>\n</table>", ), ( mistune.create_markdown(escape=False, plugins=["def_list"]), "Term\n: def\n", "<dl>\n<dt>Term</dt>\n<dd>def</dd>\n</dl>", ), ] for md, text, html in cases: self.assertEqual(md(text).strip(), html) def test_block_quote_line_based_boundaries(self): cases = { "> foo\nbar\n": "<blockquote>\n<p>foo\nbar</p>\n</blockquote>", "> foo\n>\nbar\n": "<blockquote>\n<p>foo</p>\n</blockquote>\n<p>bar</p>", "> foo\n>\n> bar\n": "<blockquote>\n<p>foo</p>\n<p>bar</p>\n</blockquote>", "> foo\n---\n": "<blockquote>\n<p>foo</p>\n</blockquote>\n<hr />", } for text, html in cases.items(): self.assertEqual(mistune.html(text).strip(), html) def test_list_tab_continuation_columns(self): result = mistune.html("-\t\tfoo\n") expected = "<ul>\n<li><pre><code> foo</code></pre>\n</li>\n</ul>" self.assertEqual(result.strip(), expected) def test_deeply_indented_list_does_not_scale_quadratically(self): payload = "\n".join(" " * i + "- item" for i in range(1000)) start = perf_counter() result = mistune.create_markdown()(payload) self.assertTrue(result.startswith("<ul>")) self.assertLess(perf_counter() - start, 2.0) def test_escape_html(self): md = mistune.create_markdown(escape=True) result = md("<div>1</div>") expected = "<p><div>1</div></p>" self.assertEqual(result.strip(), expected) result = md("<em>1</em>") expected = "<p><em>1</em></p>" self.assertEqual(result.strip(), expected) def test_harmful_links(self): result = mistune.html("[h](javAscript:alert)") expected = '<p><a href="#harmful-link">h</a></p>' self.assertEqual(result.strip(), expected) def test_backslash_space_in_link_destination_is_not_an_escape(self): # A space is not ASCII punctuation, so "\ " is a literal backslash and a # space that ends the bare destination: the link fails to parse and is # rendered as text (as CommonMark and other parsers do). Previously the # scanner treated "\ " as an escape and swallowed the space into the URL, # producing an illegal href containing %5C%20. result = mistune.html(r"[a](foo\ bar)") self.assertEqual(result.strip(), r"<p>[a](foo\ bar)</p>") # An escaped punctuation character is still consumed as an escape. result = mistune.html(r"[a](foo\*bar)") self.assertEqual(result.strip(), '<p><a href="foo*bar">a</a></p>') def test_harmful_links_variants(self): # entity-decoded, alternate-scheme, and reference-link forms are all # routed to the #harmful-link sentinel. for text in [ "[h](javascript:alert)", "[h](javascript:alert)", "[h](javascript:alert)", "[h](vbscript:msgbox)", "[h](file:///etc/passwd)", "[h](data:text/html,xss)", "[h](data:image/svg+xml,xss)", "[h][r]\n\n[r]: javascript:alert", ]: result = mistune.html(text) self.assertIn('href="#harmful-link"', result, text) self.assertNotIn("javascript:alert", result, text) def test_control_char_scheme_not_executable(self): # A control char or encoded colon inside the scheme is percent-encoded # by escape_url, so the rendered href is never an executable # javascript: scheme (regardless of the sentinel path). for text in [ "[h](<java\tscript:alert>)", "[h](<java script:alert>)", "[h](javascript%3Aalert)", ]: self.assertNotIn("javascript:alert", mistune.html(text), text) def test_ref_link(self): result = mistune.html("[link][h]\n\n[h]: /foo") expected = '<p><a href="/foo">link</a></p>' self.assertEqual(result.strip(), expected) def test_link_bracket_cache_cases(self): cases = { "[[a]](/url)": '<p><a href="/url">[a]</a></p>', "[a [b] c](/url)": '<p><a href="/url">a [b] c</a></p>', r"[a\]b](/url)": '<p><a href="/url">a]b</a></p>', "[a [b [c": "<p>[a [b [c</p>", } for text, html in cases.items(): self.assertEqual(mistune.html(text).strip(), html) def test_angle_link_escaped_backslash(self): cases = { r"[link](<foo\*bar>)": '<p><a href="foo*bar">link</a></p>', "[x]: <a\\*b>\n\n[x]": '<p><a href="a*b">x</a></p>', } for text, html in cases.items(): self.assertEqual(mistune.html(text).strip(), html, text) def test_allow_harmful_protocols(self): renderer = mistune.HTMLRenderer(allow_harmful_protocols=True) md = mistune.Markdown(renderer) result = md("[h](javascript:alert)") expected = '<p><a href="javascript:alert">h</a></p>' self.assertEqual(result.strip(), expected) def test_allow_data_protocols(self): renderer = mistune.HTMLRenderer(allow_harmful_protocols=["data:"]) md = mistune.Markdown(renderer) result = md("[h](data:alert)") expected = '<p><a href="data:alert">h</a></p>' self.assertEqual(result.strip(), expected) def test_use_plugin(self): from mistune.plugins.url import url md = mistune.Markdown(mistune.HTMLRenderer()) md.use(url) def test_inline_plugin_refreshes_fast_trigger_cache(self): def parse_at(inline, m, state): state.append_token({"type": "at", "raw": m.group(0)}) return m.end() def render_at(renderer, text): return "<at>" + text + "</at>" def plugin(md): md.inline.register("at", r"@+", parse_at, start_chars="@") md.renderer.register("at", render_at) md = mistune.create_markdown(escape=False) md("plain text") md.use(plugin) self.assertEqual(md("@@").strip(), "<p><at>@@</at></p>") def test_inline_plugin_with_untracked_trigger_uses_regex_scanner(self): def parse_x(inline, m, state): state.append_token({"type": "xword", "raw": m.group(0)}) return m.end() def render_x(renderer, text): return "<x>" + text + "</x>" def plugin(md): md.inline.register("xword", r"(?=x)x+", parse_x) md.renderer.register("xword", render_x) md = mistune.create_markdown(escape=False) md.use(plugin) self.assertEqual(md("xx").strip(), "<p><x>xx</x></p>") def test_inline_plugin_alternation_without_start_hints(self): def parse_word(inline, m, state): state.append_token({"type": "word", "raw": m.group(0)}) return m.end() def render_word(renderer, text): return "<word>" + text + "</word>" def plugin(md): md.inline.register("word", r"foo|bar", parse_word) md.renderer.register("word", render_word) md = mistune.create_markdown(escape=False, plugins=[plugin]) self.assertEqual(md("foo bar").strip(), "<p><word>foo</word> <word>bar</word></p>") def test_inline_plugin_alternation_with_start_hints(self): def parse_word(inline, m, state): state.append_token({"type": "word", "raw": m.group(0)}) return m.end() def render_word(renderer, text): return "<word>" + text + "</word>" def plugin(md): md.inline.register("word", r"foo|bar", parse_word, start_chars={"f", "b"}) md.renderer.register("word", render_word) md = mistune.create_markdown(escape=False, plugins=[plugin]) self.assertEqual(md("foo bar").strip(), "<p><word>foo</word> <word>bar</word></p>") def test_inline_plugin_rejects_invalid_start_hints(self): def parse_word(inline, m, state): return m.end() inline = mistune.InlineParser() for start_chars in ("", "ab", [], ["a", "bc"]): with self.subTest(start_chars=start_chars): with self.assertRaises(ValueError): inline.register("word", r"foo|bar", parse_word, start_chars=start_chars) def test_inline_rules_with_shared_hint_preserve_registration_order(self): def parse_first(inline, m, state): state.append_token({"type": "first", "raw": m.group(0)}) return m.end() def parse_second(inline, m, state): state.append_token({"type": "second", "raw": m.group(0)}) return m.end() def render_first(renderer, text): return "<first>" + text + "</first>" def render_second(renderer, text): return "<second>" + text + "</second>" def plugin(md): md.inline.register("first", r"@+", parse_first, before="linebreak", start_chars="@") md.inline.register("second", r"@+", parse_second, before="linebreak", start_chars="@") md.renderer.register("first", render_first) md.renderer.register("second", render_second) md = mistune.create_markdown(escape=False, plugins=[plugin]) self.assertEqual(md("@@").strip(), "<p><first>@@</first></p>") def test_markdown_func(self): result = mistune.markdown("**b**") expected = "<p><strong>b</strong></p>\n" self.assertEqual(result, expected) # trigger to use cached parser result = mistune.markdown("**b**") self.assertEqual(result, expected) def test_markdown_func_accepts_plugin_iterables(self): expected = ( "<table>\n<thead>\n<tr>\n <th>A</th>\n <th>B</th>\n</tr>\n</thead>\n" "<tbody>\n<tr>\n <td>1</td>\n <td>2</td>\n</tr>\n</tbody>\n</table>\n" ) text = "A | B\n--|--\n1 | 2\n" self.assertEqual(mistune.markdown(text, plugins=["table"]), expected) self.assertEqual(mistune.markdown(text, plugins=("table",)), expected) consumed = 0 def plugin_names(): nonlocal consumed consumed += 1 yield "table" self.assertEqual(mistune.markdown(text, plugins=plugin_names()), expected) self.assertEqual(consumed, 1) def test_markdown_func_does_not_cache_custom_renderer(self): renderer = mistune.HTMLRenderer() text = "<b>hi</b>" self.assertEqual(mistune.markdown(text, escape=True, renderer=renderer).strip(), "<p><b>hi</b></p>") self.assertEqual(mistune.markdown(text, escape=False, renderer=renderer).strip(), "<p><b>hi</b></p>") self.assertEqual(mistune.markdown(text, escape=True, renderer=renderer).strip(), "<p><b>hi</b></p>") def test_markdown_func_does_not_treat_equal_renderer_as_builtin(self): class EqualRenderer(mistune.HTMLRenderer): __hash__ = None def __eq__(self, other): return other == "html" renderer = EqualRenderer() self.assertEqual(mistune.markdown("<b>x</b>", renderer=renderer).strip(), "<p><b>x</b></p>") def test_markdown_func_cache_eviction_preserves_output(self): expected = "<p><strong>b</strong></p>\n" self.assertEqual(mistune.markdown("**b**"), expected) for size in range(129): plugins = ("speedup",) * size self.assertEqual(mistune.markdown("plain", plugins=plugins), "<p>plain</p>\n") self.assertEqual(mistune.markdown("**b**"), expected) def test_ast_output(self): md = mistune.create_markdown(escape=False, renderer=None) text = '# h1\n\nfoo **bar**\n\n`&<>"`' result = md(text) expected = [ { "type": "heading", "children": [{"type": "text", "raw": "h1"}], "attrs": {"level": 1}, "style": "atx", }, {"type": "blank_line"}, { "type": "paragraph", "children": [ {"type": "text", "raw": "foo "}, {"type": "strong", "children": [{"type": "text", "raw": "bar"}]}, ], }, {"type": "blank_line"}, { "type": "paragraph", "children": [ {"type": "codespan", "raw": '&<>"'}, ], }, ] self.assertEqual(result, expected) def test_emphasis_default(self): result = mistune.html("*_em_* __**strong**__") expected = "<p><em><em>em</em></em> <strong><strong>strong</strong></strong></p>" self.assertEqual(result.strip(), expected) def test_ast_url(self): md = mistune.create_markdown(escape=False, renderer=None) label = 'hi &<>"' url = "https://example.com/foo?a=1&b=2" text = "[{}]({})".format(label, url) result = md(text) expected = [ { "type": "paragraph", "children": [ { "type": "link", "children": [{"type": "text", "raw": label}], "attrs": {"url": url}, }, ], }, ] self.assertEqual(result, expected) def test_emsp(self): md = mistune.create_markdown(escape=False, hard_wrap=True) result = md("\u2003\u2003foo\nbar\n\n\u2003\u2003foobar") expected = "<p>\u2003\u2003foo<br />\nbar</p>\n<p>\u2003\u2003foobar</p>" self.assertEqual(result.strip(), expected) def test_unicode_whitespace(self): text = "# \u3000\u3000abc" result = mistune.html(text) expected = "<h1>\u3000\u3000abc</h1>\n" self.assertEqual(result, expected) def test_image_alt_no_double_encoding(self): result = mistune.html("![dogs & cats](dogs.png)") expected = '<p><img src="dogs.png" alt="dogs & cats" /></p>' self.assertEqual(result.strip(), expected) result = mistune.html("![dogs > cats](dogs.png)") expected = '<p><img src="dogs.png" alt="dogs > cats" /></p>' self.assertEqual(result.strip(), expected) result = mistune.html('!["quoted"](dogs.png)') expected = '<p><img src="dogs.png" alt=""quoted"" /></p>' self.assertEqual(result.strip(), expected) def test_html_tag_text_following_list(self): md = mistune.create_markdown(escape=False, hard_wrap=True) result = md("foo\n- bar\n\ntable") expected = "<p>foo</p>\n<ul>\n<li>bar</li>\n</ul>\n<p>table</p>" self.assertEqual(result.strip(), expected) def test_max_nested_level_setting(self): self.assertEqual(mistune.BlockParser().max_nested_level, 20) self.assertEqual(mistune.create_markdown().block.max_nested_level, 20) md = mistune.Markdown(block=mistune.BlockParser(max_nested_level=7)) self.assertEqual(md.block.max_nested_level, 7) def test_max_emphasis_depth_setting(self): self.assertEqual(mistune.InlineParser().max_emphasis_depth, 20) self.assertEqual(mistune.create_markdown().inline.max_emphasis_depth, 20) md = mistune.Markdown(inline=mistune.InlineParser(max_emphasis_depth=7)) self.assertEqual(md.inline.max_emphasis_depth, 7) def test_max_image_depth_setting(self): self.assertEqual(mistune.InlineParser().max_image_depth, 20) self.assertEqual(mistune.create_markdown().inline.max_image_depth, 20) md = mistune.Markdown(inline=mistune.InlineParser(max_image_depth=7)) self.assertEqual(md.inline.max_image_depth, 7) def test_deeply_nested_block_quote_and_list(self): # Block quotes and lists each capped their own nesting at the limit but # not each other's, so alternating them recursed without bound. This # must terminate instead of raising RecursionError. max_level = mistune.create_markdown().block.max_nested_level text = "".join(">" * i + " " + "- " * i + "item\n" for i in range(1, max_level + 80)) md = mistune.create_markdown() md(text) ast = mistune.create_markdown(renderer="ast") ast(text) def test_table_plugin_redos_candidates(self): md = mistune.create_markdown(escape=False, plugins=["table"]) md("|x" + " " * 16000 + "|\n|---|\n") md("|x|\n" + "|" * 32000 + "\n") def test_def_list_plugin_redos_candidate(self): md = mistune.create_markdown(escape=False, plugins=["def_list"]) result = md("x\n" * 8000) self.assertTrue(result.startswith("<p>x\nx\n")) def test_cli_output_file_uses_utf8(self): from argparse import Namespace from pathlib import Path from tempfile import TemporaryDirectory from mistune.__main__ import _output with TemporaryDirectory() as tmpdir: path = Path(tmpdir) / "out.html" _output("★", Namespace(output=str(path))) self.assertEqual(path.read_text(encoding="utf-8"), "★") def test_project_script_entrypoint(self): from pathlib import Path pyproject = Path("pyproject.toml").read_text(encoding="utf-8") self.assertIn('mistune = "mistune.__main__:cli"', pyproject) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/test_plugins.py�������������������������������������������������������0000664�0000000�0000000�00000007127�15265371675�0021503�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from mistune import create_markdown from mistune.plugins.math import math_in_list, math_in_quote from mistune.plugins.table import table_in_list, table_in_quote from tests import BaseTestCase def load_plugin(plugin_name): md1 = create_markdown(escape=False, plugins=[plugin_name]) md2 = create_markdown(escape=False, plugins=[plugin_name, "speedup"]) class TestPlugin1(BaseTestCase): parse = md1 class TestPlugin2(BaseTestCase): parse = md2 TestPlugin1.load_fixtures(plugin_name + ".txt") TestPlugin2.load_fixtures(plugin_name + ".txt") globals()["TestPlugin1_" + plugin_name] = TestPlugin1 globals()["TestPlugin2_" + plugin_name] = TestPlugin2 load_plugin("url") load_plugin("strikethrough") load_plugin("mark") load_plugin("insert") load_plugin("superscript") load_plugin("subscript") load_plugin("task_lists") load_plugin("table") load_plugin("def_list") load_plugin("footnotes") load_plugin("abbr") load_plugin("math") load_plugin("ruby") load_plugin("spoiler") class TestExtraPlugins(BaseTestCase): def test_table_in_list(self): text = """- Cell | Cell\n ---- | ----\n 1 | 2\n""" md1 = create_markdown(escape=False) md2 = create_markdown(escape=False, plugins=["table", table_in_list]) self.assertNotIn("<table>", md1(text)) self.assertIn("<table>", md2(text)) def test_table_in_quote(self): text = """> Cell | Cell\n> ---- | ----\n> 1 | 2\n""" md1 = create_markdown(escape=False) md2 = create_markdown(escape=False, plugins=["table", table_in_quote]) self.assertNotIn("<table>", md1(text)) self.assertIn("<table>", md2(text)) def test_math_in_list(self): text = """- $$\n foo\n $$\n""" md1 = create_markdown(escape=False) md2 = create_markdown(escape=False, plugins=["math", math_in_list]) self.assertNotIn('class="math"', md1(text)) self.assertIn('class="math"', md2(text)) def test_math_in_quote(self): text = """> $$\n> foo\n> $$\n""" md1 = create_markdown(escape=False) md2 = create_markdown(escape=False, plugins=["math", math_in_quote]) self.assertNotIn('class="math"', md1(text)) self.assertIn('class="math"', md2(text)) class TestFootnoteReferenceDefinitions(BaseTestCase): def test_definition_before_another_paragraph(self): text = ( "Text[^one].\n\n[^one]: See [link][ref].\n\n" " [ref]: /url\n\n Final paragraph.\n" ) result = create_markdown(plugins=["footnotes"])(text) self.assertIn('<a href="/url">link</a>', result) self.assertIn("Final paragraph.", result) self.assertNotIn("[ref]", result) def test_definition_at_end_of_footnote(self): text = "Text[^one].\n\n[^one]: See [link][ref].\n\n [ref]: /url\n" result = create_markdown(plugins=["footnotes"])(text) self.assertIn('<a href="/url">link</a>', result) self.assertNotIn("[ref]", result) def test_existing_document_definition_takes_precedence(self): text = ( "Text[^one].\n\n[ref]: /original\n\n" "[^one]: See [link][ref].\n\n [ref]: /replacement\n" ) result = create_markdown(plugins=["footnotes"])(text) self.assertIn('<a href="/original">link</a>', result) self.assertNotIn("replacement", result) def test_missing_reference_stays_literal(self): text = "Text[^one].\n\n[^one]: See [link][missing].\n\n Another paragraph.\n" result = create_markdown(plugins=["footnotes"])(text) self.assertIn("[link][missing]", result) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/test_renderers.py�����������������������������������������������������0000664�0000000�0000000�00000040063�15265371675�0022007�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from unittest import TestCase from mistune import BlockState, HTMLRenderer, create_markdown from mistune.renderers.markdown import MarkdownRenderer from mistune.renderers.rst import RSTRenderer from tests import BaseTestCase def load_renderer(renderer): class TestRenderer(BaseTestCase): parse = create_markdown(renderer=renderer) name = renderer.NAME TestRenderer.load_fixtures("renderer_" + name + ".txt") globals()["TestRenderer" + name.title()] = TestRenderer load_renderer(RSTRenderer()) load_renderer(MarkdownRenderer()) class TestRSTRendererLineBreaks(TestCase): def test_tight_list_hard_breaks(self): render = create_markdown(renderer=RSTRenderer()) for text, expected in ( ("- first \n second\n", "- | first\n | second\n"), ("1. first\\\n second\n", "1. | first\n | second\n"), ): with self.subTest(text=text): self.assertEqual(render(text), expected) class TestMarkdownRendererRoundTrip(TestCase): """Reformatting valid Markdown must not change its meaning: rendering the reformatted source to HTML must match rendering the original source.""" to_html = create_markdown(escape=False) reformat = create_markdown(renderer=MarkdownRenderer()) def assert_round_trip(self, text): self.assertEqual( self.to_html(self.reformat(text)), self.to_html(text), ) def test_escaped_block_markers(self): # an escaped leading marker is literal text, not a new block for marker in (r"\*", r"\-", r"\+", r"\#", r"\##", r"\>", r"1\.", r"3\)"): self.assert_round_trip(marker + " literal\n") def test_escaped_marker_on_continuation_line(self): self.assert_round_trip("paragraph\n\\* not a list\n") def test_escaped_marker_inside_list_item(self): self.assert_round_trip("- item\n\n \\# not a heading\n") def test_escaped_backtick(self): self.assert_round_trip(r"\`not code\`" + "\n") def test_literal_inline_markers(self): for text in ( r"\![label](https://example.com)" + "\n", r"\\*emphasis*" + "\n", r"\<b>text\</b>" + "\n", r"\<https://example.com>" + "\n", r"\©" + "\n", r"\A" + "\n", r"\A" + "\n", ): with self.subTest(text=text): self.assert_round_trip(text) def test_inline_punctuation_and_real_markup_controls(self): for text in ( "Tom & Jerry!\n", "Entities: © A A ¬anentity;\n", "C# and a.b.c, (parentheses), [unmatched brackets]\n", "*emphasis* and `code ©`\n", "![image](https://example.com/image.png)\n", "<b>real HTML</b>\n", "<https://example.com/?a=1&b=2>\n", ): with self.subTest(text=text): self.assert_round_trip(text) def test_escaped_emphasis_markers(self): # an escaped "*"/"_" is a literal delimiter, not emphasis; re-emitting # it unescaped would turn plain text back into <em>/<strong> for text in ( r"\*not emphasis\*" + "\n", r"\_not emphasis\_" + "\n", r"\*\*not strong\*\*" + "\n", r"\_\_not strong\_\_" + "\n", r"a word\_with\_underscores" + "\n", r"2 \* 3 \* 4" + "\n", r"trailing star\*" + "\n", r"\*leading star" + "\n", ): self.assert_round_trip(text) def test_real_emphasis_not_over_escaped(self): # genuine emphasis must survive untouched, and prose punctuation with # spaces around a "*"/"_" must not gain stray backslashes for text in ( "*emphasis*\n", "**strong**\n", "***both***\n", "_under_ and __strong__\n", "a *b* and _c_ mixed\n", "2 * 3 = 6 and 4 * 5\n", "snake_case_variable\n", ): self.assert_round_trip(text) def test_codespan_containing_backticks(self): # the delimiter must grow past any backtick run inside the code span, # and pad away a leading/trailing backtick, or the re-parse breaks for text in ( "``a single ` backtick``\n", "``` two `` backticks ```\n", "`` `leading backtick``\n", "``trailing backtick` ``\n", "`` `surrounded` ``\n", ): self.assert_round_trip(text) def test_codespan_edge_spaces(self): for text in ( "` x `", "` x `", "` x `", "` x `", "` `", "` `", "`` a ` b ``", ): with self.subTest(text=text): self.assert_round_trip(text) def test_image_alt_matching_url_stays_an_image(self): for text in ( "![https://example.com](https://example.com)", "![user@example.com](mailto:user@example.com)", "[![https://example.com](https://example.com)](/target)", ): with self.subTest(text=text): self.assert_round_trip(text) def test_link_autolinks_still_render(self): self.assertEqual( self.reformat("[https://example.com](https://example.com)"), "<https://example.com>\n", ) self.assertEqual( self.reformat("[user@example.com](mailto:user@example.com)"), "<user@example.com>\n", ) def test_indented_code_containing_fences(self): parse = create_markdown(renderer="ast") for indentation in range(4): for markers in (("```",), ("~~~",), ("```", "~~~"), ("````", "~~~")): with self.subTest(indentation=indentation, markers=markers): lines = ["before"] + [" " * indentation + marker for marker in markers] + ["after"] source = "".join(" " + line + "\n" for line in lines) tokens = parse(self.reformat(source)) self.assertEqual([token["type"] for token in tokens], ["block_code"]) self.assertEqual(tokens[0]["raw"], "\n".join(lines) + "\n") def test_link_title_containing_quote(self): # a double quote inside a link/image title must be escaped, or the # re-parse closes the title early and drops it for text in ( "[t](/u 'say \"hi\"')\n", '[t](/u "say \\"hi\\"")\n', "![a](/u 'say \"hi\"')\n", "[t][r]\n\n[r]: /u 'say \"hi\"'\n", '[t](/u "back\\\\slash \\" quote")\n', ): self.assert_round_trip(text) def test_empty_reference_link_destination(self): for reference in ("[text][r]", "[r][]", "[r]"): for title in ("", ' "title"', " 'say \"hi\"'"): with self.subTest(reference=reference, title=title): text = reference + "\n\n[r]: <>" + title + "\n" self.assertIn('href=""', self.to_html(text)) self.assert_round_trip(text) def test_empty_reference_image_destination(self): for title in ("", ' "title"', " 'say \"hi\"'"): with self.subTest(title=title): text = "![alt][r]\n\n[r]: <>" + title + "\n" self.assertIn('src=""', self.to_html(text)) self.assert_round_trip(text) def test_unused_empty_reference_destination(self): self.assertEqual(self.reformat("[r]: <>\n"), "[r]: <>\n") self.assertEqual(self.reformat('[r]: <> "title"\n'), '[r]: <> "title"\n') def test_nonempty_reference_destination_format(self): for destination in ("/url", "https://example.com", "/path(a)"): with self.subTest(destination=destination): text = '[text][r]\n\n[r]: ' + destination + ' "title"\n' self.assertEqual(self.reformat(text), text) def test_block_quote_content_ending_in_gt(self): # a block quote whose content ends with ">" (an autolink, an inline # HTML tag, or a literal ">") must keep that character; it was being # stripped along with the trailing quote marker for text in ( "> <https://example.com>\n", "> <b>raw</b>\n", "> ends with a literal > >\n", "> > nested <https://example.com>\n", "> first\n>\n> <https://example.com>\n", ): self.assert_round_trip(text) def test_multiline_setext_heading(self): # a setext heading may span several lines; re-emitting it as an ATX # heading ("# ...") drops every line after the first out of the # heading, because an ATX heading is a single line for text in ( "Foo\nBar\n===\n", "Foo\nBar\n---\n", "one\ntwo\nthree\n===\n", "Foo *bar\nbaz*\n====\n", ): self.assert_round_trip(text) def test_real_markers_preserved(self): for text in ( "* bullet\n", "# heading\n", "1. ordered\n", "> quote\n", "`code`\n", "*emphasis*\n", ): self.assert_round_trip(text) def test_heading_literal_trailing_hashes(self): for text in ( "foo #\n---\n", "foo ###\n===\n", "# foo \\#\n", "###### \\###\n", "foo\t###\n---\n", "foo#\n---\n", "# C#\n", "# `foo #`\n", ): with self.subTest(text=text): self.assert_round_trip(text) def test_prose_not_over_escaped(self): for text in ( "snake_case_var\n", "use - dashes - here\n", "C# and a.b.c and 1.5\n", "ratio a/b is fine\n", ): self.assert_round_trip(text) def test_leading_blank_lines_preserved(self): # blank_line tokens at the start of the document were rendered as # empty strings, so leading newlines disappeared on reformat self.assertEqual(self.reformat("\nabc"), "\nabc\n") self.assertEqual(self.reformat("\n\n\n\nabc"), "\n\n\n\nabc\n") class TestRendererListLineEndings(TestCase): non_line_breaks = ("\v", "\f", "\x1c", "\x1d", "\x1e", "\x85", "\u2028", "\u2029") def test_markdown_list_content(self): reformat = create_markdown(renderer=MarkdownRenderer()) to_html = create_markdown(escape=False) for separator in self.non_line_breaks: content = "before" + separator + "after" for template in ( "- {}\n", "1. {}\n", "- parent\n - {}\n", "- first\n\n- {}\n", "- `{}`\n", "- item\n\n ```\n {}\n ```\n", ): with self.subTest(separator=repr(separator), template=template): source = template.format(content) result = reformat(source) self.assertIn(content, result) self.assertEqual(to_html(result), to_html(source)) def test_rst_list_content(self): render = create_markdown(renderer=RSTRenderer()) for separator in self.non_line_breaks: content = "before" + separator + "after" for source, expected in ( ("- " + content + "\n", "- " + content + "\n"), ("1. " + content + "\n", "1. " + content + "\n"), ("- `" + content + "`\n", "- ``" + content + "``\n"), ): with self.subTest(separator=repr(separator), source=source): self.assertEqual(render(source), expected) def test_markdown_list_line_endings(self): reformat = create_markdown(renderer=MarkdownRenderer()) expected = "- first\n continued\n- second\n" for ending in ("\n", "\r", "\r\n"): with self.subTest(ending=repr(ending)): self.assertEqual(reformat(expected.replace("\n", ending)), expected) class TestRendererMethodRegistration(TestCase): def test_registered_renderer_method(self): renderer = HTMLRenderer(escape=False) def render_wiki(renderer, key, title): return f'<a href="/wiki/{key}">{title}</a>' renderer.register("wiki", render_wiki) token = {"type": "wiki", "raw": "python", "attrs": {"title": "Python"}} self.assertEqual( renderer.render_token(token, BlockState()), '<a href="/wiki/python">Python</a>', ) def test_html_safety_helpers(self): renderer = HTMLRenderer(escape=False) self.assertFalse(renderer.escape_enabled) self.assertEqual(renderer.escape_raw("<b>raw</b>"), "<b>raw</b>") self.assertEqual(renderer.escape_attribute('a"<b>'), "a"<b>") self.assertEqual( renderer.render_attrs({"class": 'a"b', "hidden": True, "empty": False, "missing": None}), ' class="a"b" hidden', ) self.assertEqual(renderer.sanitize_url("javascript:marker"), "#harmful-link") self.assertEqual(renderer.safe_url('https://example.com/?q="x"'), "https://example.com/?q="x"") renderer.escape_enabled = True self.assertEqual(renderer.escape_raw("<b>raw</b>"), "<b>raw</b>") with self.assertRaises(ValueError): renderer.render_attrs({'class" onclick': "marker"}) def test_escape_false_only_allows_raw_html(self): md = create_markdown(escape=False) html = md('<b>raw</b> [link](javascript:marker "a\\\"b")') self.assertIn("<b>raw</b>", html) self.assertIn('href="#harmful-link"', html) self.assertIn('title="a"b"', html) class TestMarkdownRendererPlugins(TestCase): def test_task_list_item_can_be_overridden(self): class MyRenderer(MarkdownRenderer): def task_list_item(self, token, state): return "TASK\n" md = create_markdown(renderer=MyRenderer(), plugins=["task_lists"]) self.assertEqual(md("- [x] a task"), "TASK\n") def test_task_list_item_default_markdown(self): md = create_markdown(renderer=MarkdownRenderer(), plugins=["task_lists"]) self.assertEqual(md("- [x] a task"), "- [x] a task\n") def test_table_markdown(self): md = create_markdown(renderer=MarkdownRenderer(), plugins=["table"]) result = md("| A | B |\n|---|---|\n| 1 | 2 |\n") self.assertEqual(result, "| A | B |\n| --- | --- |\n| 1 | 2 |\n") def test_table_codespan_escaped_pipes_round_trip(self): md = create_markdown(renderer=MarkdownRenderer(), plugins=["table"]) to_html = create_markdown(plugins=["table"]) for cell in (r"`a\|b`", r"`a\\\|b`", r"`a\|b\|c`"): for source in ( "| Header |\n| --- |\n| " + cell + " |\n", "| " + cell + " |\n| --- |\n| Body |\n", ): with self.subTest(source=source): result = md(source) self.assertEqual(result, source) self.assertEqual(to_html(result), to_html(source)) def test_table_plain_escaped_pipe_round_trip(self): md = create_markdown(renderer=MarkdownRenderer(), plugins=["table"]) to_html = create_markdown(plugins=["table"]) source = "| Header |\n| --- |\n| a \\| b |\n" self.assertEqual(md(source), source) self.assertEqual(to_html(md(source)), to_html(source)) def test_formatting_plugins_markdown(self): md = create_markdown(renderer=MarkdownRenderer(), plugins=["strikethrough", "mark", "insert"]) self.assertEqual(md("~~gone~~, ==marked== and ^^inserted^^\n"), "~~gone~~, ==marked== and ^^inserted^^\n") self.assertEqual(md("~~a **b** c~~\n"), "~~a **b** c~~\n") def test_standalone_list_item(self): renderer = MarkdownRenderer() token = { "type": "list_item", "children": [ { "type": "paragraph", "children": [{"type": "text", "raw": "x"}], } ], } self.assertEqual(renderer.render_token(token, BlockState()), "- x\n\n") �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/test_security_edge_cases.py�������������������������������������������0000664�0000000�0000000�00000004401�15265371675�0024023�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from unittest import TestCase from mistune import create_markdown from tests.perf_utils import assert_near_linear class TestEdgeCaseSecurity(TestCase): def test_blank_list_continuations_are_near_linear(self): md = create_markdown() def render(size): return md("- first\n" + "\n" * size + " last\n") _small, html = assert_near_linear(self, render, 2000, 4000) self.assertIn("last", html) def test_dense_emphasis_is_near_linear(self): md = create_markdown() def render(size): return md("*a" * size + "\n") _small, html = assert_near_linear(self, render, 4000, 8000, warmup_size=1000) self.assertIn("<em>", html) def test_dense_emphasis_preserves_adjacent_tokens(self): md = create_markdown() self.assertEqual( md("*a" * 6 + "\n"), "<p><em>a</em>a<em>a</em>a<em>a</em>a</p>\n", ) def test_mixed_emphasis_delimiters_are_near_linear(self): md = create_markdown() def render(size): return md("*a_b" * size) _small, html = assert_near_linear(self, render, 2000, 4000, warmup_size=500) self.assertIn("a_b", html) def test_malformed_images_are_near_linear(self): md = create_markdown() def render(size): return md("![" * size + "x" + "]" * size) _small, html = assert_near_linear(self, render, 2000, 4000, warmup_size=500) self.assertIn("![", html) def test_unclosed_link_destinations_are_near_linear(self): md = create_markdown() def render(size): return md("[](" * size) _small, html = assert_near_linear(self, render, 2000, 4000, warmup_size=500) self.assertIn("[](", html) def test_failed_parent_destination_does_not_hide_nested_images(self): md = create_markdown() self.assertEqual( md("[](foo( [outer ![inner](url)](/outer)"), '<p>[](foo( <a href="/outer">outer <img src="url" alt="inner" /></a></p>\n', ) def test_failed_angle_destination_does_not_hide_later_links(self): md = create_markdown() self.assertEqual( md("[]( <foo [bar](/url)"), '<p>[]( <foo <a href="/url">bar</a></p>\n', ) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/test_security_footnotes.py��������������������������������������������0000664�0000000�0000000�00000002307�15265371675�0023764�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import re from unittest import TestCase from mistune.core import InlineState from mistune.inline_parser import InlineParser from mistune.plugins.footnotes import INLINE_FOOTNOTE, parse_inline_footnote class _NoMembershipList(list[str]): def __contains__(self, item: object) -> bool: raise AssertionError("footnote membership must use footnote_indexes") class TestFootnoteSecurity(TestCase): def test_inline_footnote_membership_uses_index_mapping(self): notes = _NoMembershipList(["FIRST"]) indexes = {"FIRST": 0} state = InlineState( { "ref_footnotes": {"FIRST": "First note", "SECOND": "Second note"}, "footnotes": notes, "footnote_indexes": indexes, } ) match = re.match(INLINE_FOOTNOTE, "[^second]") self.assertIsNotNone(match) assert match is not None parse_inline_footnote(InlineParser(), match, state) self.assertEqual(notes, ["FIRST", "SECOND"]) self.assertEqual(indexes, {"FIRST": 0, "SECOND": 1}) self.assertEqual( state.tokens, [{"type": "footnote_ref", "raw": "SECOND", "attrs": {"index": 2}}], ) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/test_security_formatting.py�������������������������������������������0000664�0000000�0000000�00000002731�15265371675�0024117�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from unittest import TestCase from mistune import create_markdown from tests.perf_utils import assert_near_linear class TestFormattingSecurity(TestCase): def test_repeated_formatting_pairs_render_as_adjacent_spans(self): md = create_markdown(plugins=["strikethrough"]) result = md("~~x~~" * 3) self.assertEqual(result.strip(), "<p><del>x</del><del>x</del><del>x</del></p>") def test_repeated_formatting_pairs_return_quickly(self): cases = [ ("strikethrough", "~~x~~"), ("mark", "==x=="), ("insert", "^^x^^"), ] for plugin, unit in cases: with self.subTest(plugin=plugin): md = create_markdown(plugins=[plugin]) def render(size): return md(unit * size) _small, html = assert_near_linear(self, render, 1500, 3000) self.assertEqual(html.count("</"), 3001) def test_repeated_unclosed_formatting_markers_are_near_linear(self): cases = [ ("strikethrough", "~~a "), ("mark", "==a "), ("insert", "^^a "), ] for plugin, unit in cases: with self.subTest(plugin=plugin): md = create_markdown(plugins=[plugin]) def render(size): return md(unit * size + "\n") _small, html = assert_near_linear(self, render, 1000, 2000) self.assertIn(unit.strip(), html) ���������������������������������������lepture-mistune-f19057f/tests/test_security_image.py������������������������������������������������0000664�0000000�0000000�00000004223�15265371675�0023025�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from unittest import TestCase from mistune import HTMLRenderer, create_markdown from mistune.directives import FencedDirective, Figure, Image from mistune.directives.image import render_block_image, render_figure class TestImageDirectiveSecurity(TestCase): def test_image_directive_rejects_css_dimension_injection(self): md = create_markdown(escape=True, plugins=[FencedDirective([Image()])]) html = md("```{image} x.jpg\n:width: 100vw;height:100vh;position:fixed;top:0\n:height: 50%\n:alt: <alt>\n```\n") self.assertIn('alt="<alt>"', html) self.assertIn('style="height:50%;"', html) self.assertNotIn("position:fixed", html) def test_figure_directive_escapes_class_and_rejects_figwidth_css_injection(self): md = create_markdown(escape=True, plugins=[FencedDirective([Figure()])]) html = md( '```{figure} x.jpg\n:figclass: evil" onclick="alert(1)\n:figwidth: 10px;position:fixed\n\ncaption\n```\n' ) self.assertIn('class="figure evil" onclick="alert(1)"', html) self.assertNotIn('onclick="alert(1)"', html) self.assertNotIn("position:fixed", html) self.assertNotIn('style="width:', html) def test_directive_renderers_escape_all_attribute_contexts(self): renderer = HTMLRenderer(escape=False) image = render_block_image( renderer, 'https://example.com/a"b.png', alt='a"<b>', width="10px;position:fixed", height="50%", align="left", target="javascript:marker", ) figure = render_figure(renderer, "caption", figclass='wide" onclick="marker', figwidth="10px;position:fixed") self.assertIn('src="https://example.com/a"b.png"', image) self.assertIn('alt="a"<b>"', image) self.assertIn('href="#harmful-link"', image) self.assertIn('style="height:50%;"', image) self.assertNotIn("position:fixed", image) self.assertIn('class="figure wide" onclick="marker"', figure) self.assertNotIn('onclick="marker"', figure) self.assertNotIn("position:fixed", figure) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/test_security_include.py����������������������������������������������0000664�0000000�0000000�00000005266�15265371675�0023376�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import os import tempfile from unittest import TestCase from mistune import create_markdown from mistune.directives import Include, RSTDirective class TestIncludeSecurity(TestCase): def test_include_rejects_traversal_and_absolute_paths(self): with tempfile.TemporaryDirectory() as tmpdir: root = os.path.join(tmpdir, "root") os.mkdir(root) secret = os.path.join(tmpdir, "secret.txt") source = os.path.join(root, "source.md") with open(secret, "w") as f: f.write("topsecret") with open(source, "w") as f: f.write(".. include:: ../secret.txt\n\n.. include:: " + secret + "\n") md = create_markdown(plugins=[RSTDirective([Include()])]) html = md.read(source)[0] self.assertIn("Could not include outside source dir", html) self.assertNotIn("topsecret", html) def test_include_text_escapes_with_html_escape_enabled(self): with tempfile.TemporaryDirectory() as tmpdir: source = os.path.join(tmpdir, "source.md") child = os.path.join(tmpdir, "child.txt") with open(source, "w") as f: f.write(".. include:: child.txt\n") with open(child, "w") as f: f.write("<script>alert(1)</script>") md = create_markdown(plugins=[RSTDirective([Include()])]) html = md.read(source)[0] self.assertIn("<script>alert(1)</script>", html) self.assertNotIn("<script>", html) def test_include_html_escapes_with_html_escape_enabled(self): with tempfile.TemporaryDirectory() as tmpdir: source = os.path.join(tmpdir, "source.md") child = os.path.join(tmpdir, "child.html") with open(source, "w") as f: f.write(".. include:: child.html\n") with open(child, "w") as f: f.write("<script>alert(1)</script>") md = create_markdown(plugins=[RSTDirective([Include()])]) html = md.read(source)[0] self.assertIn("<script>alert(1)</script>", html) self.assertNotIn("<script>", html) def test_include_rejects_circular_references(self): with tempfile.TemporaryDirectory() as tmpdir: a = os.path.join(tmpdir, "a.md") b = os.path.join(tmpdir, "b.md") with open(a, "wb") as f: f.write(b".. include:: b.md\r\n") with open(b, "wb") as f: f.write(b".. include:: a.md\r\n") md = create_markdown(plugins=[RSTDirective([Include()])]) html = md.read(a)[0] self.assertIn("Could not include circular reference", html) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/test_security_inline.py�����������������������������������������������0000664�0000000�0000000�00000010075�15265371675�0023223�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from unittest import TestCase from mistune import create_markdown from tests.perf_utils import assert_near_linear class TestInlineParserSecurity(TestCase): def assert_max_token_depth(self, tokens, token_type, max_depth): stack = [(token, 0) for token in tokens] while stack: token, depth = stack.pop() if token["type"] == token_type: depth += 1 self.assertLessEqual(depth, max_depth) for child in token.get("children", ()): stack.append((child, depth)) def test_link_title_redos_payload_returns_quickly(self): md = create_markdown() def render(size): return md('[x](y "' + "\\!" * size + ")") _small, html = assert_near_linear(self, render, 1000, 2000) self.assertIn("[x](y", html) def test_nested_bracket_link_input_does_not_recurse_forever(self): md = create_markdown() def render(size): return md("[" * size + "x" + "]" * size) _small, html = assert_near_linear(self, render, 4000, 8000) self.assertIn("[", html) def test_failed_outer_bracket_preserves_nested_link(self): html = create_markdown()("[[x](https://example.com)]") self.assertEqual('<p>[<a href="https://example.com">x</a>]</p>\n', html) def test_failed_reference_after_nested_brackets_returns_quickly(self): md = create_markdown() def render(size): return md("[" * size + "x" + "]" * size + "[missing]") _small, html = assert_near_linear(self, render, 2000, 4000) self.assertIn("[missing]", html) def test_failed_reference_does_not_hide_following_inline_link(self): html = create_markdown()("[foo][bar](https://example.com)") self.assertEqual('<p>[foo]<a href="https://example.com">bar</a></p>\n', html) def test_unmatched_bracket_input_returns_quickly(self): md = create_markdown() def render(size): return md("[" * size) _small, html = assert_near_linear(self, render, 2000, 4000) self.assertIn("[", html) def test_deep_emphasis_input_does_not_recurse_forever(self): marks = "*" * 1000 text = marks + "a" + marks html = create_markdown()(text) ast = create_markdown(renderer="ast")(text) self.assertLessEqual(html.count("<strong>") + html.count("<em>"), 20) self.assertTrue(ast) def test_deep_image_input_does_not_recurse_forever(self): text = "![" * 1000 + "a" + "](u)" * 1000 create_markdown()(text) ast = create_markdown(renderer="ast")(text) self.assert_max_token_depth(ast, "image", 20) def test_link_with_deep_image_input_does_not_recurse_forever(self): text = "[" + "![" * 1000 + "a" + "](u)" * 1000 + "](u)" create_markdown()(text) ast = create_markdown(renderer="ast")(text) self.assert_max_token_depth(ast, "image", 20) def test_deep_link_input_does_not_recurse_forever(self): md = create_markdown(renderer="ast") def render(size): return md("[" * size + "a" + "](u)" * size) _small, ast = assert_near_linear(self, render, 500, 1000) self.assertTrue(ast) def test_repeated_link_suffixes_are_near_linear(self): md = create_markdown() def render(size): return md("[" * size + "a" + "](/u)" * size + "\n") _small, html = assert_near_linear(self, render, 1000, 2000) self.assertIn('href="/u"', html) def test_repeated_unclosed_inline_spoilers_are_near_linear(self): md = create_markdown(plugins=["spoiler"]) def render(size): return md(">! a " * size + "\n") _small, html = assert_near_linear(self, render, 1000, 2000) self.assertIn(">! a", html) def test_adjacent_ruby_tokens_do_not_recurse_forever(self): md = create_markdown(plugins=["ruby"]) def render(size): return md("[a(b)]" * size + "\n") _small, html = assert_near_linear(self, render, 1500, 3000) self.assertIn("<ruby>", html) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/test_security_math.py�������������������������������������������������0000664�0000000�0000000�00000002160�15265371675�0022672�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from unittest import TestCase from mistune import create_markdown from tests.perf_utils import assert_near_linear class TestMathSecurity(TestCase): def test_math_plugin_escapes_math_content(self): md = create_markdown(escape=True, plugins=["math"]) inline_html = md("$<script>alert(1)</script>$\n") block_html = md("$$\n<script>alert(1)</script>\n$$\n") self.assertIn("<script>alert(1)</script>", inline_html) self.assertIn("<script>alert(1)</script>", block_html) self.assertNotIn("<script>", inline_html) self.assertNotIn("<script>", block_html) def test_math_plugin_escapes_content_when_raw_html_is_enabled(self): md = create_markdown(escape=False, plugins=["math"]) self.assertIn("<marker>", md("$<marker>$\n")) def test_repeated_inline_math_openers_are_near_linear(self): md = create_markdown(plugins=["math"]) def render(size): return md("$a " * size + "\n") _small, html = assert_near_linear(self, render, 1000, 2000) self.assertIn('<span class="math">', html) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/test_security_ref_links.py��������������������������������������������0000664�0000000�0000000�00000000700�15265371675�0023713�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from unittest import TestCase from mistune import create_markdown from tests.perf_utils import assert_near_linear class TestRefLinkSecurity(TestCase): def test_many_reference_links_return_quickly(self): md = create_markdown() def render(size): return md("".join("[a{}]: u\n".format(i) for i in range(size))) _small, html = assert_near_linear(self, render, 1500, 3000) self.assertEqual(html, "") ����������������������������������������������������������������lepture-mistune-f19057f/tests/test_security_toc.py��������������������������������������������������0000664�0000000�0000000�00000006330�15265371675�0022531�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from unittest import TestCase from mistune import create_markdown from mistune.directives import FencedDirective, TableOfContents from mistune.toc import add_toc_hook, render_toc_ul class TestTocSecurity(TestCase): def test_custom_heading_id_is_escaped(self): md = create_markdown(escape=True) add_toc_hook(md, heading_id=lambda token, index: token.get("text", "")) html, _state = md.parse('## foo" onmouseover="alert(1)" x="\n') self.assertIn('id="foo" onmouseover="alert(1)" x=""', html) self.assertNotIn('onmouseover="alert(1)"', html) def test_toc_href_is_escaped(self): md = create_markdown(escape=True) add_toc_hook(md, heading_id=lambda token, index: token.get("text", "")) _html, state = md.parse('## x"><script>alert(1)</script><a href="\n') toc = render_toc_ul(state.env["toc_items"]) self.assertIn('href="#x"><script>alert(1)</script><a href=""', toc) self.assertNotIn("<script>", toc) def test_default_toc_id_avoids_existing_html_id_collision(self): md = create_markdown(escape=False) add_toc_hook(md) html, state = md.parse('<div id="toc_1"></div>\n\n# title\n') toc = render_toc_ul(state.env["toc_items"]) self.assertIn('<h1 id="toc_1_1">title</h1>', html) self.assertIn('href="#toc_1_1"', toc) def test_directive_toc_avoids_sequential_html_id_collisions(self): md = create_markdown(escape=False, plugins=[FencedDirective([TableOfContents()])]) source = '<div id="toc_1"></div>\n<div id="toc_1_1"></div>\n\n```{toc}\n```\n\n# title\n' html = md(source) self.assertIn('<h1 id="toc_1_2">title</h1>', html) self.assertIn('href="#toc_1_2"', html) def test_toc_hooks_preserve_existing_heading_id(self): md = create_markdown(escape=False, plugins=[FencedDirective([TableOfContents()])]) def set_heading_id(_md, state): for token in state.tokens: if token["type"] == "heading": token["attrs"]["id"] = "existing" md.before_render_hooks.insert(0, set_heading_id) html = md("```{toc}\n```\n\n# title\n") self.assertIn('<h1 id="existing">title</h1>', html) self.assertIn('href="#existing"', html) self.assertNotIn('id="toc_1"', html) def test_two_toc_sections_share_heading_ids(self): md = create_markdown(escape=False, plugins=[FencedDirective([TableOfContents()])]) html = md("```{toc}\n```\n\n```{toc}\n```\n\n# title\n") self.assertEqual(html.count('<h1 id="toc_1">title</h1>'), 1) self.assertEqual(html.count('href="#toc_1"'), 2) def test_hook_preserves_existing_heading_id(self): md = create_markdown(escape=False) def set_heading_id(_md, state): for token in state.tokens: if token["type"] == "heading": token["attrs"]["id"] = "existing" md.before_render_hooks.append(set_heading_id) add_toc_hook(md) html, state = md.parse("# title\n") self.assertIn('<h1 id="existing">title</h1>', html) self.assertIn('href="#existing"', render_toc_ul(state.env["toc_items"])) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/tests/test_security_urls.py�������������������������������������������������0000664�0000000�0000000�00000005760�15265371675�0022737�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from unittest import TestCase from mistune import create_markdown, html class TestSafeUrlSecurity(TestCase): def test_known_harmful_url_schemes_are_blocked(self): for url in [ "javascript:alert(1)", "vbscript:msgbox(1)", "file:///etc/passwd", "data:text/html;base64,PHNjcmlwdD4=", "feed:javascript:alert(1)", "livescript:alert(1)", "mocha:alert(1)", "view-source:javascript:alert(1)", "jar:javascript:alert(1)", "ms-its:javascript:alert(1)", "mk:@MSITStore:javascript:alert(1)", "res:javascript:", ]: rendered = html(f"[h]({url})") self.assertIn('href="#harmful-link"', rendered, url) def test_unknown_url_scheme_is_blocked(self): rendered = html("[h](x-javascript:alert(1))") self.assertIn('href="#harmful-link"', rendered) def test_reference_and_autolink_harmful_url_schemes_are_blocked(self): cases = [ "[h][r]\n\n[r]: feed:javascript:alert(1)", "<feed:javascript:alert(1)>", "[h][r]\n\n[r]: x-javascript:alert(1)", "<x-javascript:alert(1)>", ] for text in cases: rendered = create_markdown()(text) self.assertIn('href="#harmful-link"', rendered, text) def test_percent_encoded_harmful_url_scheme_is_blocked(self): for text in [ "[h](javascript%3Aalert(1))", "[h](javascript%253Aalert(1))", "[h][r]\n\n[r]: javascript%3Aalert(1)", "![h](data%3Atext/html;base64,PHNjcmlwdD4=)", "[h](view-source:javascript:alert(1))", "[h](%20javascript%3Aalert(1))", ]: rendered = create_markdown()(text) self.assertIn("#harmful-link", rendered, text) def test_safe_percent_encoded_data_image_is_allowed(self): rendered = create_markdown()("![h](data%3Aimage/png;base64,AAAA)") self.assertIn('src="data%3Aimage/png;base64,AAAA"', rendered) def test_safe_url_schemes_are_allowed(self): for url in [ "http://example.com", "https://example.com", "mailto:user@example.com", "tel:+123456789", "ftp://example.com/file", "ftps://example.com/file", "irc://example.com/channel", "ircs://example.com/channel", "//example.com/path", "/path", "./path:with-colon", "../path:with-colon", "path/with:colon", "#fragment", "?query", ]: rendered = html(f"[h]({url})") self.assertIn(f'href="{url}"', rendered, url) def test_attribute_escaping_is_independent_of_raw_html_mode(self): md = create_markdown(escape=False) rendered = md('![a"<b>](https://example.com/image.png "t\\\"itle")') self.assertIn('alt="a""', rendered) self.assertIn('title="t"itle"', rendered) ����������������lepture-mistune-f19057f/tests/test_syntax.py��������������������������������������������������������0000664�0000000�0000000�00000000446�15265371675�0021345�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import mistune from tests import BaseTestCase, normalize_html class TestSyntax(BaseTestCase): def assert_case(self, n, text, html): result = mistune.html(text) self.assertEqual(normalize_html(result), normalize_html(html)) TestSyntax.load_fixtures("fix-commonmark.txt") ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lepture-mistune-f19057f/uv.lock���������������������������������������������������������������������0000664�0000000�0000000�00001023100�15265371675�0016541�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������version = 1 revision = 3 requires-python = ">=3.10" resolution-markers = [ "python_full_version >= '3.15'", "python_full_version >= '3.12' and python_full_version < '3.15'", "python_full_version == '3.11.*'", "python_full_version < '3.11'", ] [[package]] name = "alabaster" version = "1.0.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/a6/f8/d9c74d0daf3f742840fd818d69cfae176fa332022fd44e3469487d5a9420/alabaster-1.0.0.tar.gz", hash = "sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e", size = 24210, upload-time = "2024-07-26T18:15:03.762Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b", size = 13929, upload-time = "2024-07-26T18:15:02.05Z" }, ] [[package]] name = "ast-serialize" version = "0.13.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/d2/7c/dcde7ac261e0bfbb0360c207a1e3f9fd467f9bfaeaff7b62d01625bc86d2/ast_serialize-0.13.0.tar.gz", hash = "sha256:a0bdcef01e643e0810d2dedfb64d924bcfe079a15dc20d1c067870cc01d5c5e6", size = 954999, upload-time = "2026-10-12T17:06:22.222Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/25/86/6d1e047a41fc360ca4c7f8d1d3d0727302d7e0b0af4933a462c18390a00a/ast_serialize-0.13.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:4d1e15da4b6afc6fe80b87704be452aa0639df93d019a516e9ac9540357fc9b2", size = 897213, upload-time = "2026-10-12T17:04:48.544Z" }, { url = "https://files.pythonhosted.org/packages/e2/1e/4a55b8d219616dcb9523c062dd4110ca7dd9d3c99a0ea169ce1de049e8dc/ast_serialize-0.13.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:619050b18705310e19e254cdb7554289fe14da374cbfbb1362cd84635896fb7f", size = 1236396, upload-time = "2026-10-12T17:04:50.401Z" }, { url = "https://files.pythonhosted.org/packages/be/ad/93ec0502d21691152a26103f76064c4a5bef6945866cadd8288485907306/ast_serialize-0.13.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7ce1b50c5a68233e890926405afc308a5f10f6f49ec3a094d3dfa8b6733e4496", size = 1217965, upload-time = "2026-10-12T17:04:52.692Z" }, { url = "https://files.pythonhosted.org/packages/86/37/12412da699bdfde52233836c98a30abc6086dbe17bdf0ad3497788e719c3/ast_serialize-0.13.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bab08a6f287cd620578084f9974cfaf3bef71959105f62af85fa70298b24851", size = 1282094, upload-time = "2026-10-12T17:04:54.128Z" }, { url = "https://files.pythonhosted.org/packages/74/a4/42ba2ca24865442c6aea14bc648a0800181f76dde7e6e3f4036887cf7ce6/ast_serialize-0.13.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4e0bc018a457052d4638b469f90674e6ec0e32d86ac4a7bfa1f7d1c71a961426", size = 1287429, upload-time = "2026-10-12T17:04:55.546Z" }, { url = "https://files.pythonhosted.org/packages/1f/ec/3a5923554ea5f7148ea5742ffbef2f65deed68a8a5cbad6ca5f744adfcf2/ast_serialize-0.13.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:452fdaf5ff0b791870bb332254e083107d7abe29ef43251411c265c5b138f9a2", size = 1531892, upload-time = "2026-10-12T17:04:57.147Z" }, { url = "https://files.pythonhosted.org/packages/ae/b4/e61038bf0dfb42c208e96e3ef953855e3bdb435f015f9dbf14e721c98066/ast_serialize-0.13.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:12441bc7e41e495db5634c98adc8f8886b619ce2f1e68effe3f792a2adca9f47", size = 1309544, upload-time = "2026-10-12T17:04:59.026Z" }, { url = "https://files.pythonhosted.org/packages/46/a2/5fc3e341f00711931bae32af6937122e205173d8521d1f7282b6cc2cc0f1/ast_serialize-0.13.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84cd9efdd3cd780b1f5361049becd91e0bcb0f16c2c216f41ee82e728a98390b", size = 1301823, upload-time = "2026-10-12T17:05:00.671Z" }, { url = "https://files.pythonhosted.org/packages/42/51/592a4640cb7a88cd27c457a0448c5a635cf5c01c78b693dd6ef4dfe4d3bf/ast_serialize-0.13.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:4dc7a24c734aded0557ef90bfabd2278b37502aacde84f49b53b4cb6a0711ea9", size = 1298520, upload-time = "2026-10-12T17:05:02.229Z" }, { url = "https://files.pythonhosted.org/packages/66/f6/7d938404c3b94e3a18b2b53a4250abf3f28f38caf46b6e381020e83977ab/ast_serialize-0.13.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6c95c04f1781cbefe89d512ce30e051d10823827ae542d9f18d5c2e7ba0fad08", size = 1355363, upload-time = "2026-10-12T17:05:03.631Z" }, { url = "https://files.pythonhosted.org/packages/ce/2e/88d437318054d5ce5c6c2be477258ae8d756620463221276fb0ae267fe93/ast_serialize-0.13.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:fadba24386498ed745c848b0d45e4939a506694bd2b474c57576e9640f3defe2", size = 1459864, upload-time = "2026-10-12T17:05:05.255Z" }, { url = "https://files.pythonhosted.org/packages/e3/6c/6e502e9d9e8296d621bcb9173ec4eda6498b80757c91974be3d6e89058d2/ast_serialize-0.13.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:771cf5ee8329ee8472dd7a3d8bea7dbc480032ed8ddb4d37d40b57b95ee19ef2", size = 1563855, upload-time = "2026-10-12T17:05:07.017Z" }, { url = "https://files.pythonhosted.org/packages/70/0b/f162a027c5f0c7f3f782803ee58f10ba355e49ba3e7931649635bacf2c07/ast_serialize-0.13.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:a1714ee591a8e19833c0530a89e5a9faa7f62a11fc88f62fc5b722c7425dcc1f", size = 1557563, upload-time = "2026-10-12T17:05:08.709Z" }, { url = "https://files.pythonhosted.org/packages/13/0e/71b81259135a68122486ce1522ddb1d8acdd3c11df260a3e7a337d428d90/ast_serialize-0.13.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:220a993dfc8b173e7062f690f9e00f4ebefe56718171bf35dccd73a9f8cea100", size = 1664708, upload-time = "2026-10-12T17:05:10.505Z" }, { url = "https://files.pythonhosted.org/packages/a7/dc/9851e6b6c4771fa0d4b10fce536d427f184f85a0fb83ae19633f4c9337b9/ast_serialize-0.13.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:446de6067d853f61b4bde8741762c83d06b57ea81f96dd47977714d9f31837fa", size = 1472153, upload-time = "2026-10-12T17:05:12.575Z" }, { url = "https://files.pythonhosted.org/packages/b5/5c/73bcf627607855408c500106baf849cd1cb24d2a95e480eda3c5245c908e/ast_serialize-0.13.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f0cc1f94fcd3b67005a32ee3e4c6b27cdc41659f697840d00fbb1e815ec27044", size = 1500997, upload-time = "2026-10-12T17:05:14.15Z" }, { url = "https://files.pythonhosted.org/packages/7e/b4/ee6942656e725a1e5e15d8680425356a3c96c2fbfb519f476cd82261e93d/ast_serialize-0.13.0-cp314-cp314t-win32.whl", hash = "sha256:77efef815ecae1195ac9889f616bd518d53b2173e87157043253b864af1c81c5", size = 1122428, upload-time = "2026-10-12T17:05:15.569Z" }, { url = "https://files.pythonhosted.org/packages/23/9b/dacfec064d40c3be7051a95140bb4f343491aba0de06b612aec64a84a8bf/ast_serialize-0.13.0-cp314-cp314t-win_amd64.whl", hash = "sha256:c77e5b62dfbfdfc1b025105f5038114ae988a0e616d48a845e0e57173f3f37c8", size = 1158940, upload-time = "2026-10-12T17:05:17.497Z" }, { url = "https://files.pythonhosted.org/packages/70/75/f65e883e7cd0e804fdda0ee690aeebbf3a28b96eebc1588f99e9a24a9b3e/ast_serialize-0.13.0-cp314-cp314t-win_arm64.whl", hash = "sha256:8e7c6fec7fe03cb8f40c4af81d742aa0cf690cf0b7bded47508a8a392093f414", size = 1133534, upload-time = "2026-10-12T17:05:19.13Z" }, { url = "https://files.pythonhosted.org/packages/bf/b4/a791bafbc7b9ecc3e727ab54651667372f3b33a6d1449c28783aeb1e3835/ast_serialize-0.13.0-cp315-abi3.abi3t-macosx_10_12_x86_64.whl", hash = "sha256:9eaa20714acf43ef0a0c82850a2ec8097f834648f527c38f1483e2fd9a52cd3e", size = 1236335, upload-time = "2026-10-12T17:05:20.89Z" }, { url = "https://files.pythonhosted.org/packages/30/c9/4a8d26f08d8053d4623fde6c83989b240120718cbea0b59727284fedd311/ast_serialize-0.13.0-cp315-abi3.abi3t-macosx_11_0_arm64.whl", hash = "sha256:3f5d4a7fcc916026010bae2a154e5be2c05040e67ef5c494c66a5cf315c41e30", size = 1217138, upload-time = "2026-10-12T17:05:22.586Z" }, { url = "https://files.pythonhosted.org/packages/82/53/68ef7ef55880e2087dc585f319847bc6670192987aad2e3a79ba4fb700f9/ast_serialize-0.13.0-cp315-abi3.abi3t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:807875ed8c5de739c8c55a45944336fcb9b8601d77fcee384a743cd0497211d6", size = 1282493, upload-time = "2026-10-12T17:05:23.929Z" }, { url = "https://files.pythonhosted.org/packages/e4/e7/ef9e47cd8b11cc3cfed2b37d64d3166197db2aa03e9707d04af440b58c82/ast_serialize-0.13.0-cp315-abi3.abi3t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e611937e6e77448496489627ae2558b6f6143449b1fb33f8a495665212eee58a", size = 1287893, upload-time = "2026-10-12T17:05:25.5Z" }, { url = "https://files.pythonhosted.org/packages/d6/58/3426be929c1888ef63e4defcb053e900ecee819c646db55c5a7f60de32ca/ast_serialize-0.13.0-cp315-abi3.abi3t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bb8dd779c0a25478fe1db1a8b06dd4dd5e66077d6d0afe354acadb6d9aee7d0", size = 1533846, upload-time = "2026-10-12T17:05:26.924Z" }, { url = "https://files.pythonhosted.org/packages/0a/3d/1eab7d9974578c2d1c514934ed88d174bdd680780857958a72aad5b8c9d3/ast_serialize-0.13.0-cp315-abi3.abi3t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6a49f2a01a6df3150e022087cec0bf0ad580fec8f38a17f124d07dbb115106d1", size = 1308580, upload-time = "2026-10-12T17:05:28.466Z" }, { url = "https://files.pythonhosted.org/packages/50/a2/6164467e272527c107dd2209c6c4963c48a1b40c914a560c0ce77027566d/ast_serialize-0.13.0-cp315-abi3.abi3t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f30f0e59be30c0c9540e8908b14874bc8d3c1d52a4562a4cfb426b003bd6c28b", size = 1302242, upload-time = "2026-10-12T17:05:29.999Z" }, { url = "https://files.pythonhosted.org/packages/47/bd/9024bdeead34b560f8278fb5ac96098be9a3d65ba74c6d7accd9cab21e0e/ast_serialize-0.13.0-cp315-abi3.abi3t-manylinux_2_31_riscv64.whl", hash = "sha256:be6b1a4ee49866c77eb8a50e9cbc845370e6c15230a126d0a71aeab35f31c78c", size = 1299515, upload-time = "2026-10-12T17:05:31.981Z" }, { url = "https://files.pythonhosted.org/packages/ef/d5/d1f5b9c0990fd0455d054c52bf461baa2b3ec4a93f6d8c633dbf895dd7fe/ast_serialize-0.13.0-cp315-abi3.abi3t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f8da1a31e941adbea886a85fb25efc6f09353d58c665fdbc523a914e3d2e49fe", size = 1355301, upload-time = "2026-10-12T17:05:33.384Z" }, { url = "https://files.pythonhosted.org/packages/c7/0d/7c05f233ca26f1837a44880c2167de440191bc5d44c0f3c880162952d702/ast_serialize-0.13.0-cp315-abi3.abi3t-musllinux_1_2_aarch64.whl", hash = "sha256:3a9469e4b93d87e4ee8f5c7e9462f973032793a24b9ae37ffee860220f17586a", size = 1459499, upload-time = "2026-10-12T17:05:34.977Z" }, { url = "https://files.pythonhosted.org/packages/06/72/04bf634442d7dc3246d77ac1738be7ee9524869e78097332c497178640a4/ast_serialize-0.13.0-cp315-abi3.abi3t-musllinux_1_2_armv7l.whl", hash = "sha256:192aed400b2b92ebe41da17e856b9b6e17dbcebe0011ce4c6370d4a8a0486233", size = 1564419, upload-time = "2026-10-12T17:05:37.641Z" }, { url = "https://files.pythonhosted.org/packages/01/4d/0c693c6b60c2abd9e03450e37c88ec86e2ac57d7734f06c296f336a2f0cb/ast_serialize-0.13.0-cp315-abi3.abi3t-musllinux_1_2_i686.whl", hash = "sha256:ee58f0db40f121ff0820242b286702700bc0ec58a53b6ac43ce4f43714d42e0d", size = 1557221, upload-time = "2026-10-12T17:05:39.108Z" }, { url = "https://files.pythonhosted.org/packages/44/35/f35b73694cf0daf539bfd74ab51502428b403d1ccc42358730b7e93ccd3f/ast_serialize-0.13.0-cp315-abi3.abi3t-musllinux_1_2_ppc64le.whl", hash = "sha256:e241f68cf5060bff9b161b202b60d6d52161ff3777fe56eb6a9a6764fdb7fdd9", size = 1665471, upload-time = "2026-10-12T17:05:40.654Z" }, { url = "https://files.pythonhosted.org/packages/f3/fa/fd6ec20c4cc6063ca67671df8ce59ea9e1512deb149289e50f36b7d413a2/ast_serialize-0.13.0-cp315-abi3.abi3t-musllinux_1_2_riscv64.whl", hash = "sha256:bd89da715b857a27c33fad713ea0561912c56f773ebd0fed2760cedd99724dc6", size = 1473045, upload-time = "2026-10-12T17:05:42.243Z" }, { url = "https://files.pythonhosted.org/packages/da/53/8fc26dac873859e5b9fc3117cae2ed6b4afb6dc6f9e2d6fb62ee9fcade72/ast_serialize-0.13.0-cp315-abi3.abi3t-musllinux_1_2_x86_64.whl", hash = "sha256:6cbfa6dae34d5686056ef7c40ce1d3e7e1de48555e3a2fed985aef2d1f869d9a", size = 1501600, upload-time = "2026-10-12T17:05:44.089Z" }, { url = "https://files.pythonhosted.org/packages/4f/35/363f4c3428b382d981d64fa871e468ddd9d48c9f0b969babbd462150ec98/ast_serialize-0.13.0-cp315-abi3.abi3t-win32.whl", hash = "sha256:6a406251363eeb5c7b85a405eddd123e627a531bd150dc673a7f5dd087743b5c", size = 1120541, upload-time = "2026-10-12T17:05:45.595Z" }, { url = "https://files.pythonhosted.org/packages/8b/07/df7ecee097d62214d042216fd2945207a10b681bb933daa64f238765cdb5/ast_serialize-0.13.0-cp315-abi3.abi3t-win_amd64.whl", hash = "sha256:cdd8fd066858b57ea2761b3d3989c90ea23913825bbb5453cc684c28bba3fb19", size = 1157906, upload-time = "2026-10-12T17:05:47.326Z" }, { url = "https://files.pythonhosted.org/packages/be/4f/7781e45103d530f9fc963416e0a0beef6a2608a04d18290902ae6b074073/ast_serialize-0.13.0-cp315-abi3.abi3t-win_arm64.whl", hash = "sha256:841262622499585f0610a927434db526578553d8dae270b90d4c419a385e46b7", size = 1133990, upload-time = "2026-10-12T17:05:49.17Z" }, { url = "https://files.pythonhosted.org/packages/6d/15/7284905fbd1600016f014ac3edc82199cc0f108f31d42221faa6067fe847/ast_serialize-0.13.0-cp315-cp315-pyemscripten_2026_5_wasm32.whl", hash = "sha256:efaab6400de8ee2d0e38695feccb0758acf11c1d0f8bc58a7090c566dd3ae88e", size = 897415, upload-time = "2026-10-12T17:05:50.722Z" }, { url = "https://files.pythonhosted.org/packages/a9/d1/2bbd7fe3ea2381410d0efb529e8af64027ea78bb58afad3c7ff641b33934/ast_serialize-0.13.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:c51c855d8b7d5403925599acd3c6fc91b321eba3bf46dcc9fe88fd2d6619dac7", size = 1243056, upload-time = "2026-10-12T17:05:52.154Z" }, { url = "https://files.pythonhosted.org/packages/09/b8/a7c8d5ccc0a31589750e476f629bd8681f9bd08421112c71a9c388bf8d7e/ast_serialize-0.13.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:d47c8f0eedf0a41681c10a7c497fef3691c4a6b4af4de6c93a4916bb29712554", size = 1227662, upload-time = "2026-10-12T17:05:53.996Z" }, { url = "https://files.pythonhosted.org/packages/64/54/4d64557c43abbd425b49c8e0c5b27093ee915c27e22bd46ea84c07d94908/ast_serialize-0.13.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7d7376c611055f5ee44e5e13a2620dbc6846f47c583952c1704c8805154c2d2f", size = 1292779, upload-time = "2026-10-12T17:05:55.629Z" }, { url = "https://files.pythonhosted.org/packages/7c/6f/93ab5d55402ede8444d01848cf35546c5e7ae24e9bedced6b17f530e2ef5/ast_serialize-0.13.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fe2a3c8480e8e5eb41eaa958279b8c530b77b45065423f4ebd5223e118293055", size = 1295902, upload-time = "2026-10-12T17:05:57.191Z" }, { url = "https://files.pythonhosted.org/packages/f6/5f/7292ef873948a99d26c6648fe92f4911b10c0396216388adfdbfc79a70dc/ast_serialize-0.13.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:98edcd24240fa217d903c8f221bc05575baf38a87a207264ee7c800d21eef5a4", size = 1542236, upload-time = "2026-10-12T17:05:59.002Z" }, { url = "https://files.pythonhosted.org/packages/ad/bf/4028224723d2038392ca176cfa1f982b15f12f4606d62a7f681550600c80/ast_serialize-0.13.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19b1e8f4c088ce91053df310b444fceeddb39f728ca7d04272c983646e36314b", size = 1319397, upload-time = "2026-10-12T17:06:00.527Z" }, { url = "https://files.pythonhosted.org/packages/00/ef/8d710fb1a5cc0e1985d023bfdee62c77cccaec6be1dee2ed841074a1ee0b/ast_serialize-0.13.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f55668338bcb871e83ee21ba865fb08b7b4b13af9312742f9878c39f9d84ee3", size = 1312759, upload-time = "2026-10-12T17:06:02.096Z" }, { url = "https://files.pythonhosted.org/packages/b0/a3/d0cff408a37f253c1ce5fd061389217d4e2b19645fb3a4bd8f9582f5ed56/ast_serialize-0.13.0-cp39-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:a918572608ceb20fba8c2b83560f3d20be90effa4614589477b46d81672f0c3d", size = 1308696, upload-time = "2026-10-12T17:06:03.985Z" }, { url = "https://files.pythonhosted.org/packages/41/c5/0a84554655da9c235e4f80a4799c6a3d7ee5d8c1ea16009077a5d0e6f289/ast_serialize-0.13.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b004c3bdab0beb45194cd66c0b8feea40d676e461d26296f9c791c8e3e1b7061", size = 1362306, upload-time = "2026-10-12T17:06:05.939Z" }, { url = "https://files.pythonhosted.org/packages/b1/12/d85d300fb0a628b8183bd9301df624a819160b9fb7a3db3745c097ea2672/ast_serialize-0.13.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:5e88733df5ffff9062b5ff2779cf402e0aa1a61ca3f7f84b577a1af2b7e09676", size = 1470459, upload-time = "2026-10-12T17:06:07.699Z" }, { url = "https://files.pythonhosted.org/packages/c6/96/5201ebd0eaa758de11e9b4802e094d995c8d7306ce07bf62cc54ba396122/ast_serialize-0.13.0-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:017ddd4f22e727ef93e66df2d53340a6ff809b7e34cc2218f67918ae6239aad0", size = 1572881, upload-time = "2026-10-12T17:06:09.132Z" }, { url = "https://files.pythonhosted.org/packages/08/62/05e0447e112ebaabcfc5cbf86b6f2ea455e3e08b2aebbf1f957546fd6991/ast_serialize-0.13.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:4b2ee61692de03009e6a8f372f24fbc2d4b768a2f51ecd426bb84acdfd6da3d1", size = 1568287, upload-time = "2026-10-12T17:06:10.744Z" }, { url = "https://files.pythonhosted.org/packages/69/04/eaa3aa0543a747375d2a6e0b58efbf20cf149d9c3014898c63b13aef70da/ast_serialize-0.13.0-cp39-abi3-musllinux_1_2_ppc64le.whl", hash = "sha256:dffcffa543c8fcfb1ca941038eeae23e7f97ad8994e4d6f81fbd658cfa8cb440", size = 1674375, upload-time = "2026-10-12T17:06:12.407Z" }, { url = "https://files.pythonhosted.org/packages/6a/25/cf850c03635876e6c6e53cf853d18aaed1fecc8b4e9b8f8a9300c269dc90/ast_serialize-0.13.0-cp39-abi3-musllinux_1_2_riscv64.whl", hash = "sha256:3e20e9ca3952196b91798f77ef267c36c7b3470021f950aa361d9be003fb655f", size = 1482386, upload-time = "2026-10-12T17:06:13.944Z" }, { url = "https://files.pythonhosted.org/packages/28/b3/305c5144eade6c39a871f6ab33d6cbb6fbf7367c89bd4860cdbfd3453c71/ast_serialize-0.13.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:359fcebc49f855bd189cf568235dc84eabf521e00d03fce43135cad6484906bc", size = 1512130, upload-time = "2026-10-12T17:06:15.849Z" }, { url = "https://files.pythonhosted.org/packages/2d/a8/0b26e4e4b16e3ddc9b77b6b42a29b0d6cf11a9342523ed7f0eaf4f1e1c45/ast_serialize-0.13.0-cp39-abi3-win32.whl", hash = "sha256:684e191dd41b08b0b92692a181380a70cd76e3b6469606a40aae1ca6dab39e7d", size = 1130669, upload-time = "2026-10-12T17:06:17.293Z" }, { url = "https://files.pythonhosted.org/packages/5d/09/862169d471439eb11961692f867b09f34f0560977cafa042305705d2d0a4/ast_serialize-0.13.0-cp39-abi3-win_amd64.whl", hash = "sha256:8f672c8e6d3b9ef6e365a5543aee2012247d1d58d948ceddb75b33a6679609ca", size = 1167803, upload-time = "2026-10-12T17:06:18.918Z" }, { url = "https://files.pythonhosted.org/packages/d6/85/c1c583ec96be412c4119a0ba4354c1e3519464036dd8d2909536661bed6a/ast_serialize-0.13.0-cp39-abi3-win_arm64.whl", hash = "sha256:8aff1682f9fa3e119a1cf8ef47504d38f7019b22b79e0f2b5c2135b9532d14db", size = 1138203, upload-time = "2026-10-12T17:06:20.466Z" }, ] [[package]] name = "babel" version = "2.18.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/7d/b2/51899539b6ceeeb420d40ed3cd4b7a40519404f9baf3d4ac99dc413a834b/babel-2.18.0.tar.gz", hash = "sha256:b80b99a14bd085fcacfa15c9165f651fbb3406e66cc603abf11c5750937c992d", size = 9959554, upload-time = "2026-02-01T12:30:56.078Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl", hash = "sha256:e2b422b277c2b9a9630c1d7903c2a00d0830c409c59ac8cae9081c92f1aeba35", size = 10196845, upload-time = "2026-02-01T12:30:53.445Z" }, ] [[package]] name = "certifi" version = "2026.7.22" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/a3/c2/24167ea9858356b47a87a50d39908bfdb72ceeefe0041586e704e5376b3a/certifi-2026.7.22.tar.gz", hash = "sha256:741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55", size = 138112, upload-time = "2026-07-22T03:35:12.644Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/0b/a7/71ac2cff56fec219ed242bb11b8efb69fcc4bec75db06fb7bfe35de520e6/certifi-2026.7.22-py3-none-any.whl", hash = "sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775", size = 136983, upload-time = "2026-07-22T03:35:11.276Z" }, ] [[package]] name = "charset-normalizer" version = "3.5.2" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/33/1c/f41d4e74c28ab327ff3acd36053f7ea506c55872d7a90b0fa71aa3ab0c89/charset_normalizer-3.5.2.tar.gz", hash = "sha256:39de2a259fc954455c57274dc94c79d5842774e1247a016aff30bc0efed0f4ef", size = 172659, upload-time = "2026-09-30T04:39:23.398Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/98/77/46e87bcfc45d25ab4db7cfc9bb544bfa3ffd302289ed31ae93f5433eb899/charset_normalizer-3.5.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:195c26fb65950f8fce54e26349852b7bdd7c5f120aeefbcc440b8a20faaed4a3", size = 373348, upload-time = "2026-09-30T04:34:42.843Z" }, { url = "https://files.pythonhosted.org/packages/52/fc/e518013affcc43c9f919c3ba41bffe9b4ee4aceb0a6462a6243efcca5f2d/charset_normalizer-3.5.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9373ad13ef0d2c0fb761e04e55bfdee5a08b52cef2c882c8fbe9935b1517152e", size = 260860, upload-time = "2026-09-30T04:34:44.817Z" }, { url = "https://files.pythonhosted.org/packages/d5/ad/2a895c945ee61988dfd9ccee64f0b78dc09f29c9b34d1dd545246d78e0ad/charset_normalizer-3.5.2-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:ddf19c062bea7a0cc80f519243d2c01dd091be0cf952a0750d4ad576709559f5", size = 246491, upload-time = "2026-09-30T04:34:46.227Z" }, { url = "https://files.pythonhosted.org/packages/c9/05/5d958bc8ea503e26be25ada5430fd409cfb45dc22ff33f9f96e649613c99/charset_normalizer-3.5.2-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3d14b50de6bf4d0edf857a9386836846f982b8f524e188e2e68b96d702bcf4aa", size = 290875, upload-time = "2026-09-30T04:34:47.691Z" }, { url = "https://files.pythonhosted.org/packages/55/e2/06bad57dfdb49cad92c0ba85b6b4fa5827a67df37897287cfef0553843c2/charset_normalizer-3.5.2-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:28a15fdad492a99b6eccfaaed66ef3f74050680545ea61ec8b2f4c538f1f1320", size = 286987, upload-time = "2026-09-30T04:34:49.356Z" }, { url = "https://files.pythonhosted.org/packages/c4/9f/9f52d2886d52645987d603425482c63c5045a3005db1354a7097e5ed1ae9/charset_normalizer-3.5.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8a893cc101149f80a653f82062ebc95b34525a2614382e1da5458fe7c6997249", size = 271105, upload-time = "2026-09-30T04:34:50.957Z" }, { url = "https://files.pythonhosted.org/packages/4a/41/e05e19578b7b87e7db2c3ecb884bd09d065274ab41e1f535542e8bae9b06/charset_normalizer-3.5.2-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:619799369eeef6366ed3e8755a5670f4f2f0fb6b30a0fd7264dc0fdc2357058e", size = 269833, upload-time = "2026-09-30T04:34:52.623Z" }, { url = "https://files.pythonhosted.org/packages/c2/cd/fc7152414561ff78f9c61a4a627025f65fd244abaefc99ac4e75c6169b33/charset_normalizer-3.5.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:447441e76ec720b15e64418d32e092297340387053047c7c694f579efb0ee1d9", size = 263048, upload-time = "2026-09-30T04:34:54.013Z" }, { url = "https://files.pythonhosted.org/packages/71/71/fb379e399b1013962716a059d551e03bd80b3e02f05d81246886af6c0958/charset_normalizer-3.5.2-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:62588a277bfb59def052abd940703fa35107152bf479781a878617d60faf8fb5", size = 249237, upload-time = "2026-09-30T04:34:55.373Z" }, { url = "https://files.pythonhosted.org/packages/33/4f/aeadccd6d20882909eb2597ec40eccc05d505e2262f14dc76d7620700657/charset_normalizer-3.5.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:44bd4fbb29dfbeba60e7d2bd000c59e4b21ddb3cc53912b14048d37092706d7c", size = 290756, upload-time = "2026-09-30T04:34:56.867Z" }, { url = "https://files.pythonhosted.org/packages/b9/7b/e8a92613236b257d3b75d532496eb21f68ad8231d7d56df94497e460112e/charset_normalizer-3.5.2-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:30fcd120b732aa79317f08dee04d7de0847822e4cf7ee0e9f445bb958832252c", size = 269026, upload-time = "2026-09-30T04:34:58.278Z" }, { url = "https://files.pythonhosted.org/packages/ff/ac/21d5c6b972285c5f095ff78afdc99f3539e3985dfcf7ff1cfbe9e772f529/charset_normalizer-3.5.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:50e3adfb96fc189eb27b1cf62d3b598b89b4bb0420d93a3d3e42e137409011be", size = 287601, upload-time = "2026-09-30T04:34:59.703Z" }, { url = "https://files.pythonhosted.org/packages/59/72/263491ec1494a194b16fcbff88a0220f2af633738c79e92b4d7189226322/charset_normalizer-3.5.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b736353c0a625bbd5fcec108576e2385db3496f4f771f785ff32e108d3c3bc45", size = 272660, upload-time = "2026-09-30T04:35:01.26Z" }, { url = "https://files.pythonhosted.org/packages/38/7a/81f1186c57e406233969ae96b5fd0c907254ab8b6e47da8ae24cd20fb9d7/charset_normalizer-3.5.2-cp310-cp310-win32.whl", hash = "sha256:f5833ad231be5eb6553de524a70f48d71b2c8563101750531e0b80184e175cd4", size = 187301, upload-time = "2026-09-30T04:35:02.659Z" }, { url = "https://files.pythonhosted.org/packages/ae/ab/fb8b5178fdf7bf68efa61cbe892286bc9f73846f26147d4725fb89388475/charset_normalizer-3.5.2-cp310-cp310-win_amd64.whl", hash = "sha256:1461ac396c4fdb983a675f20aa555624f0ee18ac83d832b9244ffff3d8055275", size = 215446, upload-time = "2026-09-30T04:35:04.011Z" }, { url = "https://files.pythonhosted.org/packages/36/40/e270b74e0d3f583d78d902960845a149e80eb7c737ee5613ccc6efc7264b/charset_normalizer-3.5.2-cp310-cp310-win_arm64.whl", hash = "sha256:c6708715abcf3c73b99508253e961a9967f02fe536532834149574eda6de0d1c", size = 203389, upload-time = "2026-09-30T04:35:05.577Z" }, { url = "https://files.pythonhosted.org/packages/22/67/6a0b94a7960d5e1b5eacd2fb529f3fccc47db4644f7f0a7cfdcfc3be578a/charset_normalizer-3.5.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3d21b8b13c7592db2ac5e544a6d83187b995257472b0c9e8351b6d507ae37ed6", size = 370642, upload-time = "2026-09-30T04:35:06.91Z" }, { url = "https://files.pythonhosted.org/packages/fb/94/01009e13b94041599004edf32e56e382c24e570f60f79bab8efe45cfe1eb/charset_normalizer-3.5.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d760fe2a4d7c3b226cb9026d6a842868d52a7901bd98420e1baf14e80da85cf5", size = 259280, upload-time = "2026-09-30T04:35:08.448Z" }, { url = "https://files.pythonhosted.org/packages/66/85/3b5358f60a13210f0b67d3755c168ef758701b021e655d88d4da28554467/charset_normalizer-3.5.2-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c9790464842f85f437dbbb54417eda1e0e6bfc52dd8d22d6fd1c994b73b2dc74", size = 245335, upload-time = "2026-09-30T04:35:10.104Z" }, { url = "https://files.pythonhosted.org/packages/74/75/77c1c479b09ecd751d1e767b251ea5c14d4d50ff757bf404afab2692f600/charset_normalizer-3.5.2-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4685902cf26edf013ed7a3da0f426ebba7a00ebb9541386d835afbf002c11cab", size = 291707, upload-time = "2026-09-30T04:35:11.575Z" }, { url = "https://files.pythonhosted.org/packages/0b/0d/363f78cacb70f58f15f4b083961bbd9d292f335d3f5c66fc4f1cfe69cb90/charset_normalizer-3.5.2-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4495c5002a7b28557e7e222e77e0b661183e432b7d6d2e788101e3f240e05b8c", size = 286747, upload-time = "2026-09-30T04:35:13.022Z" }, { url = "https://files.pythonhosted.org/packages/e4/ed/cf505d3011ffceb12c2067a7a5d3cfe92b875d4d44bb0ff0d69375e2c184/charset_normalizer-3.5.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:211d5a3eb6af8f513b8d4ca19a8c1b7accab1b5f0d3175f9826b03c1a920dc1f", size = 269972, upload-time = "2026-09-30T04:35:14.606Z" }, { url = "https://files.pythonhosted.org/packages/15/d8/f0a93a431d170e7ca681d4f6650fee3de934d18560e474e7267eb4b0f987/charset_normalizer-3.5.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ef4fcbf3327382cd4c9f540babd61248208af7b93eec4de397b4d5f58a09e288", size = 269339, upload-time = "2026-09-30T04:35:16.087Z" }, { url = "https://files.pythonhosted.org/packages/86/bd/9b2bd1c5b7af02462c9752d33994834ff972a96b4c483eefde9e594488e2/charset_normalizer-3.5.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:bd16aabe4a02a297c23417aa17ac6299dbd8c49f673bcd645b4929b11f5a4400", size = 261683, upload-time = "2026-09-30T04:35:17.488Z" }, { url = "https://files.pythonhosted.org/packages/76/a5/cac540ab0fd61f3fec88ad3dbb64509e71424593d73cfdfff5ab3e4db279/charset_normalizer-3.5.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:fb9e68df06293761f9fe66ade60a9bc6d0f5e42b8acf2939a9158af86ab0e5bd", size = 248143, upload-time = "2026-09-30T04:35:18.849Z" }, { url = "https://files.pythonhosted.org/packages/71/7a/ff467301deef2089fad87f72df9e000a26a78fec7acbb18e1999371b8369/charset_normalizer-3.5.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:59f63901b0031c3136cf64704dcb21de0bbae62ce2c9529bc39d27665463de37", size = 292358, upload-time = "2026-09-30T04:35:20.326Z" }, { url = "https://files.pythonhosted.org/packages/ad/77/22d7e785d1e210afc2e2f58600dd1799d17a35665faf84383f002826c5f8/charset_normalizer-3.5.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:304d5463e65a35d7bb0850550e0780395395f6fcf452f04db7d5ca7cecc425ac", size = 268766, upload-time = "2026-09-30T04:35:21.72Z" }, { url = "https://files.pythonhosted.org/packages/ae/91/e8e946267f1c2d9e2bd651726e2fbd2addf02c4d36cea5069e32ca9d7bb5/charset_normalizer-3.5.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:9cf9b1a857e25c4baceeb3624e92a56df3668f398c4acba74e174d81fb4d1d3a", size = 287432, upload-time = "2026-09-30T04:35:23.273Z" }, { url = "https://files.pythonhosted.org/packages/4e/88/7561d8a88d555e7df6623abe7c0070b4baf47549b9408783a2ae0a1a6cf7/charset_normalizer-3.5.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:114e4d0c92d618409ed82a99e22b5c5e768fe995f2973f78265f4524f49d4640", size = 272470, upload-time = "2026-09-30T04:35:24.655Z" }, { url = "https://files.pythonhosted.org/packages/35/7e/578c702301ec036f01455f30744a08d2b42f6ab35b9b2d4bf8cae0ef2a80/charset_normalizer-3.5.2-cp311-cp311-win32.whl", hash = "sha256:2625388c6c754520c37abaf3b41eb34d1cc4a373f457898f08606c8e362b891d", size = 186688, upload-time = "2026-09-30T04:35:26.225Z" }, { url = "https://files.pythonhosted.org/packages/e8/fc/fdf8cf52ff21cd5bf158f20978991cf985325842f74283eb6df26c8a39d8/charset_normalizer-3.5.2-cp311-cp311-win_amd64.whl", hash = "sha256:87e50a3e7cb90af586b6c5faf23e302a970415ac73bd7bd90a515a04b427ef96", size = 214932, upload-time = "2026-09-30T04:35:27.796Z" }, { url = "https://files.pythonhosted.org/packages/97/66/3e45a506d8110b632541faf9a9470185aa9878f1ed44020f31346c1c5e5b/charset_normalizer-3.5.2-cp311-cp311-win_arm64.whl", hash = "sha256:254eb48b9fa5ee9898a3c445825a1f340fe53712a098904b39b0bddba8ea3cb1", size = 202828, upload-time = "2026-09-30T04:35:29.259Z" }, { url = "https://files.pythonhosted.org/packages/e7/c8/693809898870237d82785a03f3b2b58fe4c9f14669f84a7d4e623c92a59e/charset_normalizer-3.5.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ed2a239c0ea213acc1908150a3037257083c7c083128f1a4cec2ec4b97dca491", size = 367780, upload-time = "2026-09-30T04:35:30.888Z" }, { url = "https://files.pythonhosted.org/packages/c9/87/2fea8c13dc24b3ca9c6f803a5b2dfdeae73eb4f9e12c7885ed908ff0433c/charset_normalizer-3.5.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b91363207bd9dc966a691e959bb47f64b30f7ac4b072be9968b366982f7db77c", size = 246730, upload-time = "2026-09-30T04:35:32.286Z" }, { url = "https://files.pythonhosted.org/packages/a8/9e/09efac30b937722f46d3110ba30b875b24b2e3a266ed746cc4e376a94d80/charset_normalizer-3.5.2-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:38a873987f3be698494da8b2e3085e29da02da7b633dce73e79c699a113d7bf0", size = 237707, upload-time = "2026-09-30T04:35:33.709Z" }, { url = "https://files.pythonhosted.org/packages/9e/18/70d76670b13686237863a379928d60bd10e021f17d243ab3d7014c4a5f4e/charset_normalizer-3.5.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:355ad8011081dec5412240c087a9a0c9d4d5039f3ed11a3f13e18c2b29b56c51", size = 273050, upload-time = "2026-09-30T04:35:35.138Z" }, { url = "https://files.pythonhosted.org/packages/54/e2/77a8b09d5adc013ed07b95b01b8b8fa5441c4e810e83ee7e4aae2fa4d91a/charset_normalizer-3.5.2-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ee21e28f0430bd6dc9086c6e525d5e818a44a5ad19720c8a0ef766792f3eb5e5", size = 270345, upload-time = "2026-09-30T04:35:36.502Z" }, { url = "https://files.pythonhosted.org/packages/7f/c5/38806a25ab5e65fc178f39affeda20858efafede2fce1ffc2556cfc9fe73/charset_normalizer-3.5.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3d31298449090ab8d47b7b1b2a555ff73cac7ed438a08b7ac160980c7ebed649", size = 257601, upload-time = "2026-09-30T04:35:37.919Z" }, { url = "https://files.pythonhosted.org/packages/ae/8d/213565184708fdb263ae55e2c04ee1ff748129dd65d48ed0e3502da9c85a/charset_normalizer-3.5.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5cde776b7cc66e4f6c99612cea4aa7269aa65863f7a15841b2c264f103822f4e", size = 252222, upload-time = "2026-09-30T04:35:39.544Z" }, { url = "https://files.pythonhosted.org/packages/7e/24/76d2cefc25472531e4c5c7dfff68865eb1c39b78482f0fdc15b46f047830/charset_normalizer-3.5.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ae4f5fea5b8b8ccff88238cc8569303e5ee95efae67fa62922a311397a71f346", size = 248482, upload-time = "2026-09-30T04:35:41.088Z" }, { url = "https://files.pythonhosted.org/packages/7d/dc/65a801b66ab4c197e22c433ab25e7ac24324ac6f45a2269aca42cce309bf/charset_normalizer-3.5.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:f7d486c83842422badd511868fd8a9a20e9407ace71564b6af47ce7e60a336c1", size = 241206, upload-time = "2026-09-30T04:35:42.59Z" }, { url = "https://files.pythonhosted.org/packages/a7/95/ca9b5eabde673002c6f1e7ada1b223916fe18f6d661da7aabd4d643718f1/charset_normalizer-3.5.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:11a4d68a6ecda3292cb1e50239e111543ba5d709bb62a6b4ea1afcfa729d8875", size = 273190, upload-time = "2026-09-30T04:35:44.347Z" }, { url = "https://files.pythonhosted.org/packages/2d/8b/803b4d2a3f6e1740f63f1e87b04d14b42f3d4fdfe6ed7d4db2d34102b14f/charset_normalizer-3.5.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d6734d2ef8a50fbf8445c139477da401f50d62a0606bf00e20ec6d87773fefb1", size = 253527, upload-time = "2026-09-30T04:35:45.915Z" }, { url = "https://files.pythonhosted.org/packages/a9/55/93c0e5dbd085ae0471346026abbe7e0db9ea2d6fea74e51f0b5a46f233a7/charset_normalizer-3.5.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:a815775b6c38d4e0ff7bcffbeba67feded90202bb6a226b8dd35f1c855217413", size = 271285, upload-time = "2026-09-30T04:35:47.49Z" }, { url = "https://files.pythonhosted.org/packages/95/69/0dbd0e0b9b16cfa816cdfcb3e2e3854a1f680dc07fb1245ea125e7448060/charset_normalizer-3.5.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:23851fb4e1b85ed3f6c2a27b777cdfe2e19fb5b38429a8faf38c7542b7665869", size = 260010, upload-time = "2026-09-30T04:35:48.996Z" }, { url = "https://files.pythonhosted.org/packages/58/9d/e7b88e7b1bf403590c3b573277b5e1e488c68c7a6fbacca310a2c324e90c/charset_normalizer-3.5.2-cp312-cp312-win32.whl", hash = "sha256:db19d07e2e0129e974a0e65d0064fc222a446cd5122c2fd4184d2af9fc734a9e", size = 184125, upload-time = "2026-09-30T04:35:50.777Z" }, { url = "https://files.pythonhosted.org/packages/eb/e6/e6e083884cbcfd49c64865af05027fe7011be7b2d9179524f099a1b611f3/charset_normalizer-3.5.2-cp312-cp312-win_amd64.whl", hash = "sha256:780fbe7cab297b81dad9fb8dc5eb003c0468ffb0d9e5f65068c53a34661a96bc", size = 207486, upload-time = "2026-09-30T04:35:52.194Z" }, { url = "https://files.pythonhosted.org/packages/c4/e3/017aea0911ada7405a825c7d937eb3a13009664e2f5b38e8c4bbf2abf894/charset_normalizer-3.5.2-cp312-cp312-win_arm64.whl", hash = "sha256:e2af3aad578aa6bd1384bcf4750fc285e5a9de53f40b7d41e5a0bf748edeb2b3", size = 196734, upload-time = "2026-09-30T04:35:53.636Z" }, { url = "https://files.pythonhosted.org/packages/c5/34/68292d68512768591aaff07c59bb53ee31341c87759433a859c4641a50c2/charset_normalizer-3.5.2-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:ed905975ab14056a2e5eb1c376cb2e1ebc5396baf84163939c518556fccde9f5", size = 225946, upload-time = "2026-09-30T04:35:55.313Z" }, { url = "https://files.pythonhosted.org/packages/e3/80/bee0b01b90ccd5322ae1d0abb33fab1bd95b7c2eadaf02aeccf22e04ee83/charset_normalizer-3.5.2-cp313-cp313-android_24_x86_64.whl", hash = "sha256:a66c3bc5ab1f0ff2164fc9965ddd611ff0802173f4b9d24554c563f6ab7e1d6e", size = 238619, upload-time = "2026-09-30T04:35:56.863Z" }, { url = "https://files.pythonhosted.org/packages/78/6e/60ce52a85a7fd631ae8482ae6d74521014ca2f255892679484dc04d7ef56/charset_normalizer-3.5.2-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:d2374b62878abb00cd8309b32af6c0b715cd02dec0ca74ef12e5069bdc64144a", size = 206701, upload-time = "2026-09-30T04:35:58.639Z" }, { url = "https://files.pythonhosted.org/packages/36/8c/71aafad23f971afc84c2b295bc0c560739ce1dac558aad9fec22e39f3639/charset_normalizer-3.5.2-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:d376bbd28b3a8999db1a103b3b388aee6f1ddeb3e51bc2172993efdcd86e064d", size = 210506, upload-time = "2026-09-30T04:36:00.147Z" }, { url = "https://files.pythonhosted.org/packages/91/da/3c5a7798c046df7d2d68ad653cf5b6c5a8bfee225055a843c6f2f42aac1a/charset_normalizer-3.5.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6045373d5a89a5ec71afde535db987ca28e76dfa276c2d4c818265b375d4b055", size = 366626, upload-time = "2026-09-30T04:36:01.77Z" }, { url = "https://files.pythonhosted.org/packages/e1/16/710ac3de2ee354e2bd1a9c94efe45a2d27b5c6ad39b2d6a905be2c094b6c/charset_normalizer-3.5.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:849df64e889b2e17230d58410a03dba311a65b163508fd33679b2b737d4b7858", size = 244624, upload-time = "2026-09-30T04:36:03.389Z" }, { url = "https://files.pythonhosted.org/packages/d6/39/45c7439f5b63d24f7d5b2a1d760f34af7628782d7144b4cc8ded45c2d4bc/charset_normalizer-3.5.2-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:15c44f7edfd477b06f517a5cc317fc1707edb9de2c865f43d4b6513907473234", size = 235731, upload-time = "2026-09-30T04:36:04.987Z" }, { url = "https://files.pythonhosted.org/packages/4d/34/38f3154785ce92e9f56eb226f4d35bdfae6b008480dd055f58837a89c810/charset_normalizer-3.5.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a89012d6d5476ee112d20d998570ed58df2260a852afb1758809cd6900411d21", size = 270352, upload-time = "2026-09-30T04:36:06.412Z" }, { url = "https://files.pythonhosted.org/packages/04/f3/859f74e7babc977705026b30593b3be04049632a522fb7000f83c033d747/charset_normalizer-3.5.2-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0c951d5e6dd9c2ff60609476752bee49da4206adde960ebc247766937f72e718", size = 267393, upload-time = "2026-09-30T04:36:07.865Z" }, { url = "https://files.pythonhosted.org/packages/4b/85/41d27f234b82e47c167a5f6c0f62501dc0c640585ff4aba79e08a390336a/charset_normalizer-3.5.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7218e8f32b0956cfcd048fd42d9d5779809745ca1d86113ca56f66e7ae1549c4", size = 254660, upload-time = "2026-09-30T04:36:09.248Z" }, { url = "https://files.pythonhosted.org/packages/58/ca/5d1a997587febe5b26d8daffe363b5c1a091cece19828eec6502fd09c5ef/charset_normalizer-3.5.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a19a731138fc27d5682277d3b9df22855cea1239bce7fcec5f78f42ef2d1f3c3", size = 249996, upload-time = "2026-09-30T04:36:10.73Z" }, { url = "https://files.pythonhosted.org/packages/b3/1f/d1e78246f7ed60c8c8d606b4ac27f66ce49cc3e95f24893ccbeba9f77302/charset_normalizer-3.5.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:62603db9a7caa0802eaa28c1c46fecd7b3a263a774069c24c3c28c302448721c", size = 247028, upload-time = "2026-09-30T04:36:12.294Z" }, { url = "https://files.pythonhosted.org/packages/8e/37/eba316edd4f0c4d3a5d945924c4eeeae59abac4056aa815d8a4268f863a2/charset_normalizer-3.5.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:b6856554c4f44d79fc2307d5768854310a8f0096e501c75637542c82292b0429", size = 240562, upload-time = "2026-09-30T04:36:13.887Z" }, { url = "https://files.pythonhosted.org/packages/c8/8e/aaa037d40ca9ef045977f1a661048b1aa33f223adfce3452fe9be9f79d14/charset_normalizer-3.5.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:1bc0baf5ef96b6ede57d47f4b8fe4d9d84019c3bfcbeb20a41edc6a6ee341f1f", size = 271699, upload-time = "2026-09-30T04:36:15.41Z" }, { url = "https://files.pythonhosted.org/packages/26/19/1c1c9f75974adf523b87f34b8a2adc5a435cd65916812bcbd0dfa45f9a29/charset_normalizer-3.5.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:56bc200a365efb37383b7852e4cc5898d3b2da5987289b543956cf8cad71018a", size = 252030, upload-time = "2026-09-30T04:36:16.839Z" }, { url = "https://files.pythonhosted.org/packages/bc/90/0660ef18e18df0a4d2a1a0edff7dfbba42d4e50ef2425557a5bb7051f77b/charset_normalizer-3.5.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:2c9ad19a6cfcd5ea5c0d41161d22f9df1dcc277e9bef2751391334546a314c00", size = 268565, upload-time = "2026-09-30T04:36:18.468Z" }, { url = "https://files.pythonhosted.org/packages/79/ba/57adc269824e8658f1a0f97a9e514c247445a9632b3419b97e0ba37f16dc/charset_normalizer-3.5.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e243bd13217235fc7290c621941c3f5cc8b66e4872495be821d7436ba2fb838d", size = 257627, upload-time = "2026-09-30T04:36:19.938Z" }, { url = "https://files.pythonhosted.org/packages/9a/85/33abd4315c052d3d4f54c92b1ee49bfbc0dc7115a981e462a793b6d2ab87/charset_normalizer-3.5.2-cp313-cp313-pyemscripten_2025_0_wasm32.whl", hash = "sha256:a090bb2c68df85450502e3e20d665e3a5af9c65a84d6508ed477badd49166fd3", size = 143407, upload-time = "2026-09-30T04:36:21.376Z" }, { url = "https://files.pythonhosted.org/packages/4f/de/6435e18d1aaa5d910b896d551411c96af1f42a0c56c29afc2016c61ccc2e/charset_normalizer-3.5.2-cp313-cp313-win32.whl", hash = "sha256:2b7b3bbfb4fe8ef40600792d762fbaa9057559f9d3fad209525b7a22b99e91fd", size = 183207, upload-time = "2026-09-30T04:36:22.776Z" }, { url = "https://files.pythonhosted.org/packages/9c/76/b8ec57f4e9ee3253541abf95e4a462c0175fe8032dcd070f1f2421240942/charset_normalizer-3.5.2-cp313-cp313-win_amd64.whl", hash = "sha256:78456a747de8dc58360ffa581f30a002baf5aa28cb262536545e91f113ed7639", size = 206489, upload-time = "2026-09-30T04:36:24.306Z" }, { url = "https://files.pythonhosted.org/packages/3e/60/c647c6ae47480221e875ea5d743ff94946f7416e3c69415ab772928e8d32/charset_normalizer-3.5.2-cp313-cp313-win_arm64.whl", hash = "sha256:11912e4bb14baae7c5d8791aa55ba0a3a03ec6729073307b0f57270abaa713d3", size = 195501, upload-time = "2026-09-30T04:36:25.846Z" }, { url = "https://files.pythonhosted.org/packages/58/ca/7aa91362a2f77ac8e9e28a9b902a74f7d0e11a851ef0d27a74308da8cd90/charset_normalizer-3.5.2-cp314-cp314-android_24_arm64_v8a.whl", hash = "sha256:1afb975bd5d68d5ce9f6b6d44fdf2f7e34b895a35e95708a7a91b20a3b51d187", size = 226010, upload-time = "2026-09-30T04:36:27.669Z" }, { url = "https://files.pythonhosted.org/packages/a8/cf/ac8878d0322cf88a1aad4c7b147db32ca0bd806eb0060957b2e31486dbe6/charset_normalizer-3.5.2-cp314-cp314-android_24_x86_64.whl", hash = "sha256:bbbfc8e28816f19d7c0f1816664980c0a9875d01b27cdf8eedddb639d9e108ad", size = 239266, upload-time = "2026-09-30T04:36:29.434Z" }, { url = "https://files.pythonhosted.org/packages/c9/6d/9a08d7e0b29b7208e2c6c01dc56c8e0520e7c7beadbbfb024b58fd69c8a5/charset_normalizer-3.5.2-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:7967d08cf06dee78443b874f98c98036f624f3a4e73e11f9f64f5be4d25393cf", size = 206783, upload-time = "2026-09-30T04:36:30.872Z" }, { url = "https://files.pythonhosted.org/packages/82/44/b0aa350280e6ff5a5492d17cf10460dd39d5ee848f872f7ba2df10607f60/charset_normalizer-3.5.2-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:4c2b5031f63e331e3839b40aed2dd6f191e9c07edbde303e7876846ea1946995", size = 210449, upload-time = "2026-09-30T04:36:32.625Z" }, { url = "https://files.pythonhosted.org/packages/7c/8a/40db9aa9f5907bb0e6f8b6d64064bf8852fb33d4b813ff9414911df7647c/charset_normalizer-3.5.2-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:fcff63213e8e6e47770541a4607175404f47cbb3ebea7b6058cc82d524a0e424", size = 367815, upload-time = "2026-09-30T04:36:34.197Z" }, { url = "https://files.pythonhosted.org/packages/7f/72/9c5e7707b57c8ddfa9ddf7b0b1d009d7fbab9e9e887d5b721060f37e307d/charset_normalizer-3.5.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8d86d6fc60743dc916eb79e2eb1ec4818e21e427731543af40a3021851174a13", size = 247095, upload-time = "2026-09-30T04:36:35.803Z" }, { url = "https://files.pythonhosted.org/packages/83/09/71e453691e927de4ddf792770cfaab3f49d494e222f66ea5e404bbd5e39c/charset_normalizer-3.5.2-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7a881931aa470808df94a8c380eed2bbbc76cd9dc622310f99665658c821eb6d", size = 233942, upload-time = "2026-09-30T04:36:37.407Z" }, { url = "https://files.pythonhosted.org/packages/9f/86/85c84e4da8b27dd409577d9437926ff581c5f9d3c66038dc68c1a526de51/charset_normalizer-3.5.2-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8024d00c3faf3fc0c16e07a69f4405e8eac7cc0ab15f65fe6cf43827c4cf72b4", size = 273762, upload-time = "2026-09-30T04:36:38.904Z" }, { url = "https://files.pythonhosted.org/packages/92/08/564955a4b5f2ccb410ab480bbe8c6a18063ff27f2d35458731c4a5335df9/charset_normalizer-3.5.2-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4d48f2d08b9de5864e2c8744d4461b862fb149a18274abc8b698c45975573438", size = 269514, upload-time = "2026-09-30T04:36:40.469Z" }, { url = "https://files.pythonhosted.org/packages/18/24/bad3ac4271589df29cf5ce2f5ae490518a5739358052bd0d61209e6fea54/charset_normalizer-3.5.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34276fd796040bf0993ab33a369aa572e6979c7aab225a88893667ad8eac8f7a", size = 255056, upload-time = "2026-09-30T04:36:42.02Z" }, { url = "https://files.pythonhosted.org/packages/d6/3e/350d89ad49916b86554d6f5f2d03ec1152148f87e5ff735106c6a03b1a36/charset_normalizer-3.5.2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0521c5665880b33d603717defa76c094048900010897909952397feb3039da56", size = 251311, upload-time = "2026-09-30T04:36:43.577Z" }, { url = "https://files.pythonhosted.org/packages/56/5b/4970a2d154df502e133402906dd04e3ae7cada7b3011283c88d0479a2585/charset_normalizer-3.5.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:eff0ac9dbe711a4aee69bf04a83896aa9b85f19641264053a9f6d48573abb7dd", size = 250190, upload-time = "2026-09-30T04:36:45.185Z" }, { url = "https://files.pythonhosted.org/packages/88/8c/f1a91bddc8fb47c2889e29ea7ea49a194eb0d9868675d786806519c00d76/charset_normalizer-3.5.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:1503bccbeb36d5527790c3930327704c39af22de3112f1b1666a9f3ce15ee204", size = 237098, upload-time = "2026-09-30T04:36:46.689Z" }, { url = "https://files.pythonhosted.org/packages/24/0e/bb5dace3cc7e79068425386a6589c19b5a2ab5fefc2a46abea6919683332/charset_normalizer-3.5.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:52aa6992700996af31f375de0c6bacd402b0097fe40b53c426b9f51a90ebabc7", size = 274228, upload-time = "2026-09-30T04:36:48.31Z" }, { url = "https://files.pythonhosted.org/packages/9d/79/b849ad523017ea9f5a45581bbebed91439e0cf42fd2860a6f64e358eb5a6/charset_normalizer-3.5.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e09a3942ecbdee5cce73ea9d42da82b81b72ac1bf031ce069b93b5adf4eac8cd", size = 252401, upload-time = "2026-09-30T04:36:50.091Z" }, { url = "https://files.pythonhosted.org/packages/89/8c/75469d690cf47200bce8f6cad7655724fc23148e147abfc5ce78b5f65863/charset_normalizer-3.5.2-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:c7c9ab723cde841fefb34efbad91e87f00a674b1fe1cd0784fde742bf2c154dc", size = 271846, upload-time = "2026-09-30T04:36:51.719Z" }, { url = "https://files.pythonhosted.org/packages/26/cd/6d52d3c7437cdcf2e310ce9f28f282e733d4ef60ed19105d1819c356255f/charset_normalizer-3.5.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ddc7dacc8ece3a182e7f15cb862d1fd616b46d076cb1ae9dd232b2c38b655874", size = 258151, upload-time = "2026-09-30T04:36:53.234Z" }, { url = "https://files.pythonhosted.org/packages/f7/4c/070b38bdb5f49a70199fce923ec0726a49536a63ab262abbfcaaf351110b/charset_normalizer-3.5.2-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:ee43c17b173d46a3212baa6ead3ae258eeabdae48c263a01ccf0218c366dd655", size = 143570, upload-time = "2026-09-30T04:36:54.816Z" }, { url = "https://files.pythonhosted.org/packages/81/84/9ebfc8ed6c8c4fcd8e726ff6bf220cc8deb3966e31dce9be8dd8aa017e64/charset_normalizer-3.5.2-cp314-cp314-win32.whl", hash = "sha256:4f87960d57feabfb618e4e0af6e7371645fa26a277860739d6e5d6e0012c92f0", size = 186412, upload-time = "2026-09-30T04:36:56.643Z" }, { url = "https://files.pythonhosted.org/packages/d1/78/5ed86f743d4bc350db307e7636419a0a5ee1d91806d30c7f667bd5c80dae/charset_normalizer-3.5.2-cp314-cp314-win_amd64.whl", hash = "sha256:e4e81e09c1578b8df602e3db08b0b3ea0a6947ad612f52bf8dc5ea8d47691f0c", size = 210965, upload-time = "2026-09-30T04:36:58.205Z" }, { url = "https://files.pythonhosted.org/packages/53/94/a3a7698e9b1a395e1eb99ccd9a324be9347973bff4e72db2a06496d7cd27/charset_normalizer-3.5.2-cp314-cp314-win_arm64.whl", hash = "sha256:80d02b6f04e92601a081dd97b23d3128033098bff5d35d392ddcc0476ea11253", size = 200406, upload-time = "2026-09-30T04:36:59.764Z" }, { url = "https://files.pythonhosted.org/packages/c1/48/c5dd00d5ef7791f02666de250a5bb6071e29b7e133cf4b835800b6d3bc27/charset_normalizer-3.5.2-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:dca9ab98072a5a54ebacebdc45f53e645336b320c667410b061be1ca588ae709", size = 396871, upload-time = "2026-09-30T04:37:01.543Z" }, { url = "https://files.pythonhosted.org/packages/12/c8/8379554b42e8368161d898476686947a0fdbd3e8865170d7909dcabfdee8/charset_normalizer-3.5.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f0aa869112ef88429ae17820d99c3dd9504c9e9c671d3c246f3d7442cb051084", size = 249711, upload-time = "2026-09-30T04:37:03.111Z" }, { url = "https://files.pythonhosted.org/packages/4a/eb/2ddb1035d17320caa9f41682935123a9a250277b261c3efc86b2d2a21343/charset_normalizer-3.5.2-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c0afc6800ba57ccc350374c5bd6150419915d95ce93cdbab2d783d75eaf30ecb", size = 231146, upload-time = "2026-09-30T04:37:04.721Z" }, { url = "https://files.pythonhosted.org/packages/4a/24/2ecb4bde104322cd7859d6594fcfa74649f8d90b3221c9feecbef149875b/charset_normalizer-3.5.2-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7dcd882da75ef9adf94903b1e3b9419e8aa8fb4c7396822b834b9ef7fb96954f", size = 271552, upload-time = "2026-09-30T04:37:06.295Z" }, { url = "https://files.pythonhosted.org/packages/3f/98/9d5f6ebc3aee9fef5d30b4aff11fb2ab7a1222b4064f8ef2c7c87cde217a/charset_normalizer-3.5.2-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2e06a3a98f916dd41d27f3105e02e7a40181c98c94b9158733d03a6f80506c09", size = 269810, upload-time = "2026-09-30T04:37:07.905Z" }, { url = "https://files.pythonhosted.org/packages/09/e1/a3b06a10461b1b7628853c934c644e03bc28e42767116afb52f19a56519b/charset_normalizer-3.5.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6bd128f206a7752ae1f2ab6c61bf8a24ba28913a10df8b14c2637b973ff97a80", size = 259845, upload-time = "2026-09-30T04:37:09.554Z" }, { url = "https://files.pythonhosted.org/packages/fd/d3/6f561f74a296cf27d61775a1dc665ad13f3bff6a798810ca05907f37a7c4/charset_normalizer-3.5.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c8f3d67aeaf55f017982b73683f0e7342ba2f6635a78f69ce89ebb26aa411e5c", size = 252825, upload-time = "2026-09-30T04:37:11.274Z" }, { url = "https://files.pythonhosted.org/packages/26/9f/69e13ca3b18f43e0eafcd34c04a45b732ae22a43b54a5fc9e119103356eb/charset_normalizer-3.5.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:fe9753dfee015c570d73df76f899f18444d41388bffcde097deba51c4fadbb9f", size = 252659, upload-time = "2026-09-30T04:37:12.941Z" }, { url = "https://files.pythonhosted.org/packages/73/a9/ace29806a0dae18939919c76ba526472d83214afa101105fabff2cf30625/charset_normalizer-3.5.2-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:92888bb3187c5ba50500b00b3b310c9f2c651709d28036077680cb5255450a03", size = 238819, upload-time = "2026-09-30T04:37:14.659Z" }, { url = "https://files.pythonhosted.org/packages/f8/c1/6116d52a2e3311ec80f21f5fb5e17b27405f10b9608af8f6e69516841a1b/charset_normalizer-3.5.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:d008d90a7f2471519aef0c90dfbe73b3e6e4d5e66ac48e19154c17e89e98b604", size = 272973, upload-time = "2026-09-30T04:37:16.346Z" }, { url = "https://files.pythonhosted.org/packages/19/aa/9955c7e93bba10a9c7e8f7a5031b7ced66f3a1883a55c00712b8d5850ff3/charset_normalizer-3.5.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:31f3930700408d211f13378ccbe1c40845d8da54bd0681fac3a9b5aae81c7aa8", size = 253692, upload-time = "2026-09-30T04:37:18.212Z" }, { url = "https://files.pythonhosted.org/packages/bb/33/2a6ae7fdc1b10cb581cef91addd8cdfc5f40d50abb5702309369d5834579/charset_normalizer-3.5.2-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:2a925889534b3748302dae5dead07cc13480de1dac3aea80a941b729b471ef93", size = 268757, upload-time = "2026-09-30T04:37:19.877Z" }, { url = "https://files.pythonhosted.org/packages/a2/22/80992720a0282cd39bba1db35868e6b9c22f41281160143a836544bc1d8a/charset_normalizer-3.5.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f5ec61164adcec446f8969a3358ec3f9b26bbda3b9213e5586d219afa8df2915", size = 262220, upload-time = "2026-09-30T04:37:21.583Z" }, { url = "https://files.pythonhosted.org/packages/92/9f/181fd07e1bffea1d95cd80c84ac537354f50699c22cfc4d3c02b6fc16208/charset_normalizer-3.5.2-cp314-cp314t-win32.whl", hash = "sha256:598a11a2c7ebaa5334bf698bf29568c9c390abac6a154d8170fedecd1cea38c5", size = 197797, upload-time = "2026-09-30T04:37:23.235Z" }, { url = "https://files.pythonhosted.org/packages/49/1c/25d8415ec1c4f2f41f1680435e4c87cfb378ff2f677d950946f2a45d0632/charset_normalizer-3.5.2-cp314-cp314t-win_amd64.whl", hash = "sha256:7fdde2c9fd9e3eca40631e024664cf2584272cc8f96308cbe5fdfc930f51d8bc", size = 222765, upload-time = "2026-09-30T04:37:24.891Z" }, { url = "https://files.pythonhosted.org/packages/3e/b4/46b48f013dadfc0d0d33b375438e31bdf5a989dc68389c6bf627054d4df9/charset_normalizer-3.5.2-cp314-cp314t-win_arm64.whl", hash = "sha256:d1befeed746d247c81127bb14de9dc3d30edb6e5976d34f83f86ed262b1d9105", size = 210985, upload-time = "2026-09-30T04:37:26.634Z" }, { url = "https://files.pythonhosted.org/packages/ca/e9/34e597dee616d0b8ee4b34d29399e85c2204ade174157a48505d42baa4ff/charset_normalizer-3.5.2-cp315-cp315-macosx_10_15_universal2.whl", hash = "sha256:87475fabc8d9996fd9c27debb395e642e8c838d78a00b6e932227a0e06b81e26", size = 367676, upload-time = "2026-09-30T04:37:28.329Z" }, { url = "https://files.pythonhosted.org/packages/60/9f/a5d1c91c0263745e2cd344c5a4415d787c575501ab1d449f1148ac6b495d/charset_normalizer-3.5.2-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9409a8bf35cf78353942504b24a57de3d75b708997a1e4bd8db71ac8633ce364", size = 248414, upload-time = "2026-09-30T04:37:30.167Z" }, { url = "https://files.pythonhosted.org/packages/26/79/e697f77464748a3ee3cf490c83d592459400d4898380d66c38366b03080c/charset_normalizer-3.5.2-cp315-cp315-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:498dc3188ca05a68231ac3fdbfc7f57eb67e1343c30e0fea17f8218c1599b253", size = 244775, upload-time = "2026-09-30T04:37:31.964Z" }, { url = "https://files.pythonhosted.org/packages/ca/87/3d42a42e18ea066e2513936fd678a00696e77878b5ae04528976abdbcb83/charset_normalizer-3.5.2-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e242bb1c5e76e97dfa9e7f209a71e93a01d7f19ffdd5cfbb2e2d55b4f08f8ab0", size = 273877, upload-time = "2026-09-30T04:37:33.661Z" }, { url = "https://files.pythonhosted.org/packages/c3/76/8a28136f3938ba9836f84280ce0c4d61ed1cf15a036b2034900c62634162/charset_normalizer-3.5.2-cp315-cp315-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:def79fa35ef0cef8d2accec024f4fdc7ead3012ff02f5215c783f39f03ef8cfc", size = 269455, upload-time = "2026-09-30T04:37:35.573Z" }, { url = "https://files.pythonhosted.org/packages/a0/a1/4fbf5d0f0f1b2a080474c1cf9a2f12c4c6531bb0e8ba591055e846d2b4e9/charset_normalizer-3.5.2-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3df041de8887954562c9b261cba85ca0e9ded74048daf125f45edcfaa4832229", size = 257336, upload-time = "2026-09-30T04:37:37.397Z" }, { url = "https://files.pythonhosted.org/packages/ba/a2/8b50aa320adb880ad579518e6f718f24944804b42a88b83d267d5d444125/charset_normalizer-3.5.2-cp315-cp315-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:04851f73ae72b8413dddadb16a49dfee95263553741fd42d546f7d66907e6be5", size = 257584, upload-time = "2026-09-30T04:37:39.522Z" }, { url = "https://files.pythonhosted.org/packages/a5/57/50e3fed84e175f40349bd0da7a4fce94c87f0378f52d74f511d89e0bdc20/charset_normalizer-3.5.2-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:183b88127acdb4fabe59d951ab424faf1af7b63cdbb5f776186c1ea2ffcaed98", size = 251854, upload-time = "2026-09-30T04:37:41.23Z" }, { url = "https://files.pythonhosted.org/packages/d6/54/f7fbb3493c9f49091213b9c2d6dd65800696f1ce1a3f196a4205f50417b1/charset_normalizer-3.5.2-cp315-cp315-musllinux_1_2_armv7l.whl", hash = "sha256:16fa0eccf81304b79c5cd87f9271c3b85dd9dd99245e4422ae9c0dd45e0f99d3", size = 248767, upload-time = "2026-09-30T04:37:42.883Z" }, { url = "https://files.pythonhosted.org/packages/d9/37/b3a6385acc5a1e45b39ae9c90bfb9cf838a09b9dd37ef2740ab4c6b4a2eb/charset_normalizer-3.5.2-cp315-cp315-musllinux_1_2_ppc64le.whl", hash = "sha256:7441d755b7ab94f8d4eb3e43ec05482d760842fd263d003a99102d742cd835e2", size = 274479, upload-time = "2026-09-30T04:37:44.658Z" }, { url = "https://files.pythonhosted.org/packages/89/44/809913e2cfd279e635a9294fdbbfb1b1dc62a8189d473d561f649fce98d8/charset_normalizer-3.5.2-cp315-cp315-musllinux_1_2_riscv64.whl", hash = "sha256:ca403d7e4798f525fdfc78e258820419cbbd0f0ecbab9de7840e3c017cf6b8cf", size = 258310, upload-time = "2026-09-30T04:37:46.529Z" }, { url = "https://files.pythonhosted.org/packages/af/a2/f28400ab13359d91bd39179df8e149376b9bf36588e739a3a4f9de2b84b2/charset_normalizer-3.5.2-cp315-cp315-musllinux_1_2_s390x.whl", hash = "sha256:df29a0a7107f7011e77f4eebdddec4c7331e24d787a0b21a46d63bdf7445da95", size = 271100, upload-time = "2026-09-30T04:37:48.399Z" }, { url = "https://files.pythonhosted.org/packages/e9/89/9bab37955edf0adb3b66f8a3a6617d9f2f487e0d56f295a6a286cb640aa6/charset_normalizer-3.5.2-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:f3c96f633825733f735c5a9cf21d21a257d8e1edf0b1cee0a064b9c424ca0f7d", size = 259936, upload-time = "2026-09-30T04:37:50.023Z" }, { url = "https://files.pythonhosted.org/packages/23/b5/4459e08d45a679f903d50fea08bc52cfa728cca4d7bd02c757b5e5abda2e/charset_normalizer-3.5.2-cp315-cp315-win32.whl", hash = "sha256:281cb91036248400f4cc957495cccd44c275c2e0c5854f7e45ac5cf7dc193847", size = 186301, upload-time = "2026-09-30T04:37:51.722Z" }, { url = "https://files.pythonhosted.org/packages/98/e8/55d5fd3935b4bce6da4fe0df61898e8c82653e317e677bd58aceb9c60f13/charset_normalizer-3.5.2-cp315-cp315-win_amd64.whl", hash = "sha256:89b53f3cda69831909888e0494f4fa0bcd3537e3e138dabeb620bd6ad946bae8", size = 210858, upload-time = "2026-09-30T04:37:53.427Z" }, { url = "https://files.pythonhosted.org/packages/a9/5b/974423c2fd8e524c7a7f64318c1e02240ef954912fa2b4d70344107b9c68/charset_normalizer-3.5.2-cp315-cp315-win_arm64.whl", hash = "sha256:6be488a102b8cf28d0391d8c4ba7748938ae28b78ad901f8585520fca33ead1a", size = 200309, upload-time = "2026-09-30T04:37:55.015Z" }, { url = "https://files.pythonhosted.org/packages/ee/f9/00ee0195db1013d8f7c416fd770fbeb560bb46eb2e36b054d05cb56f6cfa/charset_normalizer-3.5.2-cp315-cp315t-macosx_10_15_universal2.whl", hash = "sha256:915563965d418f986e7e145accc592eae9e1a1be3566ff98a05d7a9ec42a76e1", size = 395343, upload-time = "2026-09-30T04:37:56.743Z" }, { url = "https://files.pythonhosted.org/packages/04/3a/c00b50e94c964cf934c7899cd47c97952fc11dad71cc5884b3c61795b09b/charset_normalizer-3.5.2-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:65cd72beeeca9d3aaea1201e5923859f308f952f9c71de93f06063c79f0f7a3b", size = 250114, upload-time = "2026-09-30T04:37:58.607Z" }, { url = "https://files.pythonhosted.org/packages/50/27/d102dc880bbcffd0479ab64dfc1fb96777a854355a55e2bda72a71efadcb/charset_normalizer-3.5.2-cp315-cp315t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b7fd005a73d9e657273b7a10dc71a9e03c8fb9ee6999798d6918ce095b81ac7f", size = 239997, upload-time = "2026-09-30T04:38:00.511Z" }, { url = "https://files.pythonhosted.org/packages/a5/4a/bf7ef45794dd293fab5f98a9309817977fbb845b9998f171b8cc5d8437a3/charset_normalizer-3.5.2-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e54da4baf05720032d527874d40b65fa4d7e5c6c6a43d0c3adbeffcaf275a2b3", size = 272313, upload-time = "2026-09-30T04:38:02.509Z" }, { url = "https://files.pythonhosted.org/packages/e8/ee/008a2837737991474c5754bb3191010007663860979701990982a502cbaf/charset_normalizer-3.5.2-cp315-cp315t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:124fbf1a8ff966d87ae05bb8bd45a71f966055ed8bba320d0c7cf450bc5f4d0e", size = 269986, upload-time = "2026-09-30T04:38:04.435Z" }, { url = "https://files.pythonhosted.org/packages/93/ad/bd74a283940dc910c5b14f8e4f80a248082bc9c0fcbe1f54530cb6d9cc5e/charset_normalizer-3.5.2-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:28b4f0d66fb834ff90f28209ac7bce77868c45d8c93e26f906709d9b7c2e1af9", size = 260202, upload-time = "2026-09-30T04:38:06.549Z" }, { url = "https://files.pythonhosted.org/packages/8a/7b/ed341c66f69f688723501fac752be3d63c7159ca0d0d4174fc611e5710bb/charset_normalizer-3.5.2-cp315-cp315t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:58ca3755ee7ff7f59b57789ec9833c9de9ea275405cdd240eda1f193112e398a", size = 259083, upload-time = "2026-09-30T04:38:08.311Z" }, { url = "https://files.pythonhosted.org/packages/cc/9d/e41588b777965e5031a43128a1e96173ebb35ac75fc53ec3b517e7c21cd4/charset_normalizer-3.5.2-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:443eae2bf318abeaf6f15d785138f71fd6de770e99a92158b8b814265e079115", size = 253081, upload-time = "2026-09-30T04:38:10.402Z" }, { url = "https://files.pythonhosted.org/packages/81/35/b761eb6d8c1eb218b9b42b9b4d5ac902afdc399fb6dac6f9a9aac7bda589/charset_normalizer-3.5.2-cp315-cp315t-musllinux_1_2_armv7l.whl", hash = "sha256:58f361dcbab699cf8f42db3f47c8e7fd1036f138c23a5d08de9fde5f425a730c", size = 248712, upload-time = "2026-09-30T04:38:12.317Z" }, { url = "https://files.pythonhosted.org/packages/4d/2c/147169a041b747759f37405c0a97157e8e92de967968373101ff14915cba/charset_normalizer-3.5.2-cp315-cp315t-musllinux_1_2_ppc64le.whl", hash = "sha256:1b4cbc7c3491ccb4aa17fcd8165649d01cf39f76de1696da8631b5f71b85401d", size = 274176, upload-time = "2026-09-30T04:38:14.138Z" }, { url = "https://files.pythonhosted.org/packages/f0/2d/0ff8db0d373ba8538db686db11cd7e8912031490b9e4f383b41912e8d594/charset_normalizer-3.5.2-cp315-cp315t-musllinux_1_2_riscv64.whl", hash = "sha256:ba0b1d2620edf869789c3879223f52bf2afc5d31b3cb47cc57b3a12c05e2aa9d", size = 259413, upload-time = "2026-09-30T04:38:15.841Z" }, { url = "https://files.pythonhosted.org/packages/8a/8e/b4a085fb47c9d3a7e43576a4784fdd8fe23f907514a972de8086edaf7a48/charset_normalizer-3.5.2-cp315-cp315t-musllinux_1_2_s390x.whl", hash = "sha256:5e2b6b57e9733d39f0c9fd3185efa6b8e29652c4cd8fe94180272cf6ed9a78c4", size = 269434, upload-time = "2026-09-30T04:38:17.626Z" }, { url = "https://files.pythonhosted.org/packages/83/1c/d8d8d7322a7c3eecdf3237a4a419cf41d2eaad8e006ce7dfdd9d4c8fa2eb/charset_normalizer-3.5.2-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:51cf45226a9b588d0d2b4880c62d686934b63ab0bd79ca23ab0e9762eb27441b", size = 262716, upload-time = "2026-09-30T04:38:19.214Z" }, { url = "https://files.pythonhosted.org/packages/a0/16/0e4c6ba9b44e97a2da150e52d331e8f9c968b21b358fbffa6c856cebcd89/charset_normalizer-3.5.2-cp315-cp315t-win32.whl", hash = "sha256:5fb29fb8cd1a46c27a1bf9613ad5ec2599310d46b4025d9556404a6b6a292800", size = 197159, upload-time = "2026-09-30T04:38:21.037Z" }, { url = "https://files.pythonhosted.org/packages/be/33/e90bc2b1374f7f36ef106f56620de5a783907e19ca857efe2277e31cac3e/charset_normalizer-3.5.2-cp315-cp315t-win_amd64.whl", hash = "sha256:a192e2c40070d92c3ccf777e3a5c4ff515573cd2bb7ed0c537fdadbbec5bbf21", size = 221322, upload-time = "2026-09-30T04:38:22.886Z" }, { url = "https://files.pythonhosted.org/packages/66/89/dfa6dcb08c200b7830ab56439e8c1890f2971d51aafbb3937894a2e7fcfc/charset_normalizer-3.5.2-cp315-cp315t-win_arm64.whl", hash = "sha256:749e97e1b32313717a565abbe321bc2190bc8b35f1a67e4cdbc7c56c8d8ffe58", size = 209192, upload-time = "2026-09-30T04:38:24.648Z" }, { url = "https://files.pythonhosted.org/packages/8c/ab/176fbfd5b64939c55d652366aa5b9ef1d767af207a3aa6ebeb0d226c484d/charset_normalizer-3.5.2-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:4275811936e2f06feff5e598fb42a1b7ae852da8e39605211892b56b81a34efd", size = 331815, upload-time = "2026-09-30T04:38:26.216Z" }, { url = "https://files.pythonhosted.org/packages/7e/84/371eac6b30bdbcbf2d632a1a01809103459216fcaae61b8b8d922c1bfb8a/charset_normalizer-3.5.2-cp37-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1c50fe28bbc2ced33386f298650d91218076c05420e6cbd790b913adc41659e7", size = 253276, upload-time = "2026-09-30T04:38:28.032Z" }, { url = "https://files.pythonhosted.org/packages/43/6f/c4fbae58febff71709c51bc7e18fdfa55341dc382704740f9f0cbf03817b/charset_normalizer-3.5.2-cp37-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d19fbd981a488e22cd04883659ca6b08f50b5974f9fd7c95655ef6a043e5893f", size = 241239, upload-time = "2026-09-30T04:38:29.732Z" }, { url = "https://files.pythonhosted.org/packages/61/71/458c3f42164a07d0c5210798e9e704b39e540a6793b05aba67f3a35243a9/charset_normalizer-3.5.2-cp37-abi3-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0fed1d06615f022ee3b13caf5e8b180cfea32bb2c5aded8a9d44277afc040f93", size = 231121, upload-time = "2026-09-30T04:38:31.462Z" }, { url = "https://files.pythonhosted.org/packages/09/54/ab9e89367076f6331bb6c65c4bf14a5361fa5191cb6561bf534f18504e1b/charset_normalizer-3.5.2-cp37-abi3-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:838dcc90063569a0448120554591a1d6c4a4ffe11babf048908793154ab86ade", size = 260350, upload-time = "2026-09-30T04:38:33.239Z" }, { url = "https://files.pythonhosted.org/packages/7c/c1/061431ecc688d9d76602502cb57cc01e691e682c18f1beb45f9673b5bbd2/charset_normalizer-3.5.2-cp37-abi3-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2ce45c6627b22c47e390bc91a41c3d13032192e699fa0bea96e9671b373d69b0", size = 255430, upload-time = "2026-09-30T04:38:34.865Z" }, { url = "https://files.pythonhosted.org/packages/8d/1f/20c8949f0676f7ab811abdeb7f4d7f1cbc6e61ff20bef08b44edeb092bc8/charset_normalizer-3.5.2-cp37-abi3-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0774bf9bf620249fee3e0b8b9fd3065de213be30f3aa94ce2494b3b638949e26", size = 250612, upload-time = "2026-09-30T04:38:36.649Z" }, { url = "https://files.pythonhosted.org/packages/2b/9e/46f2fa4c431fc98c4ae76a8cb5bdca54e0341e3cfc3fcfd8e82740250818/charset_normalizer-3.5.2-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1db38f4c5496827c1a501846d64d14c3b80c7e6714e406cd7dc36a9899fa1011", size = 242083, upload-time = "2026-09-30T04:38:38.26Z" }, { url = "https://files.pythonhosted.org/packages/bd/39/559be29a0c0f086e0bba6922babd38916cc5e0b58ced4de13ee01ea05508/charset_normalizer-3.5.2-cp37-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:304d8e4d493af723536393eee0c689eb7813f4a474c8b479dee63f1fdd98f621", size = 232738, upload-time = "2026-09-30T04:38:39.81Z" }, { url = "https://files.pythonhosted.org/packages/ff/6c/387b0e4f756a282831c1d9fc6aeb6c51ca4507ca202767c8de15ce9b12e2/charset_normalizer-3.5.2-cp37-abi3-musllinux_1_2_ppc64le.whl", hash = "sha256:9b7f416ff0978e2f2249330527f0ad6fa02f4932e6199692d3b52da2048c19e4", size = 260703, upload-time = "2026-09-30T04:38:41.346Z" }, { url = "https://files.pythonhosted.org/packages/96/92/1fdf015f09ef449f50d3ac4b67c90887c9c318b727daa95cc4f866e6521d/charset_normalizer-3.5.2-cp37-abi3-musllinux_1_2_riscv64.whl", hash = "sha256:01077390b03f7988f11d700a2194e69b119741a86b1a638b1db88891e3eced8e", size = 247622, upload-time = "2026-09-30T04:38:42.937Z" }, { url = "https://files.pythonhosted.org/packages/dc/3c/8e7b8a5671ad5d433669fb2a76f1a0164df2d9b1718b0206bc2a16d840cc/charset_normalizer-3.5.2-cp37-abi3-musllinux_1_2_s390x.whl", hash = "sha256:7e841fb9010836c992c9f12fcbd43a831de93a5f726fc1ccd8ca1d0268c5014c", size = 257500, upload-time = "2026-09-30T04:38:44.604Z" }, { url = "https://files.pythonhosted.org/packages/b4/f0/45b579df5cabc1d5d53ea1cc35e8437d3ca768c0acccc7041517cb6fbb32/charset_normalizer-3.5.2-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:9cae88599c7219005d879f98e5ed53341e9a122af585e1091200358a3003d2a0", size = 255100, upload-time = "2026-09-30T04:38:46.289Z" }, { url = "https://files.pythonhosted.org/packages/31/68/fdec18a343f5fb3f310588dd478b09ac4799e0b187dbade3a8cd776f03ef/charset_normalizer-3.5.2-cp37-abi3-win32.whl", hash = "sha256:01b0c0d2262a9e28e8484a278c7e1b5d650e3ac8cf2683d2967e25899f208bdf", size = 174499, upload-time = "2026-09-30T04:38:47.999Z" }, { url = "https://files.pythonhosted.org/packages/9d/8a/b618149cc5207943a0242068d7a27897f56a62947b5a039085f2a22029f8/charset_normalizer-3.5.2-cp37-abi3-win_amd64.whl", hash = "sha256:9f56f72050826f63dcee7a7f55b0a77168cb3bfc553fd405e7f8f9ece75a4036", size = 200092, upload-time = "2026-09-30T04:38:49.707Z" }, { url = "https://files.pythonhosted.org/packages/03/cf/4c66866fa9e2b1c78e3c911516d1de497a677b7ac60f1eceda74ce777ca3/charset_normalizer-3.5.2-cp37-abi3-win_arm64.whl", hash = "sha256:40ab6bffa02ae10a0581e6c198be7d2d8ca5c2a0c64e4ed3465d766df457573e", size = 294363, upload-time = "2026-09-30T04:38:51.312Z" }, { url = "https://files.pythonhosted.org/packages/fc/ad/d07d7862a62ffa6d79d68074d14823243dd235a77c45262acbf6adeb28bf/charset_normalizer-3.5.2-py3-none-any.whl", hash = "sha256:b6b751274acb69d77b3323d6b7dbaa3c7fdfc1eb829b7eb61d262f32e1af9685", size = 68872, upload-time = "2026-09-30T04:39:21.828Z" }, ] [[package]] name = "colorama" version = "0.4.6" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, ] [[package]] name = "coverage" version = "7.16.2" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/2f/55/d1eaf3e73781174340a00dc1ba2aee8a65f82fadb18e2797b192b6b3925b/coverage-7.16.2.tar.gz", hash = "sha256:ca64d9f1f384f151b9511bec01126072acd2f313439f8ed015a22d8790aab6fa", size = 971999, upload-time = "2026-09-27T12:29:01.118Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/60/72/db17bf5f87568ab524413693385be2eeb03e652ab56c54ea05fa85515675/coverage-7.16.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:23219888477edd736b6fcaec1272d47d93b926e999641ffea7e53a1738e70b2b", size = 223670, upload-time = "2026-09-27T12:25:34.675Z" }, { url = "https://files.pythonhosted.org/packages/d1/e1/285727a8a74d48de256e8605413ee4cf82301228253ea58e5ab4270138b0/coverage-7.16.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:40c0f00899fe6181ae7f434ceb200e51f5ee4b8ed10e3b5f0b605f0cae15da87", size = 224191, upload-time = "2026-09-27T12:25:36.476Z" }, { url = "https://files.pythonhosted.org/packages/50/c7/c737b73bac9bf5034f5ff45a4237b7a189d417a4e36751faf5d10c082cbe/coverage-7.16.2-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a4624f80732f6b427ac58f1f59c577a0994a12e8174b5af6a027b4b58795d4c3", size = 250921, upload-time = "2026-09-27T12:25:37.857Z" }, { url = "https://files.pythonhosted.org/packages/29/4e/e1d38d27817d91776ca543d01276a67eace3df675a673cac32b12c167d58/coverage-7.16.2-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:191803c4996b499fcd78c2ad5e5f767dcc53cb4dc6de6d6a741b443a1821ef02", size = 252751, upload-time = "2026-09-27T12:25:39.291Z" }, { url = "https://files.pythonhosted.org/packages/0e/19/14a8e44cbb2ad36ae62aaa03c5eec4a06a7f7df220ea3776af26927acbe2/coverage-7.16.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9fd670ac43b709c575aefc25bf52d8a598a3bc5017bddfd0a179152ab06a2deb", size = 254616, upload-time = "2026-09-27T12:25:40.506Z" }, { url = "https://files.pythonhosted.org/packages/f9/72/f5bcad0d9a9b450080032344fbff7ec60c1b0e3d38019f7735dee2b69645/coverage-7.16.2-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:705e5af11d34647efdc170c7840b6857c81cf74be96419a553f237e68e62cb72", size = 256541, upload-time = "2026-09-27T12:25:41.785Z" }, { url = "https://files.pythonhosted.org/packages/ae/9a/8c735234e8abb52bf5d063f98c780fa942e77c4c0225f9fcb9b33effc346/coverage-7.16.2-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8afd9bf35cc6a1f22eb3634808fa8e0b91902459c5721ef2e4461dfe771d7f08", size = 251589, upload-time = "2026-09-27T12:25:43.269Z" }, { url = "https://files.pythonhosted.org/packages/35/6a/1bf6d32e55642d6972aa842640e0a8850e612d19ac7d05e2c32fa59dfd34/coverage-7.16.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3f43bac1856ba269b905302778d4df433d6006489a192174ad77ac528e395032", size = 252660, upload-time = "2026-09-27T12:25:45.051Z" }, { url = "https://files.pythonhosted.org/packages/53/5b/05b1c0d0e9495cb056155a16066259adc1e935e7411a82a62779bf729975/coverage-7.16.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:f8475460aa33ee28ac896ab1156d0bb3b6c639f7f8383c2677d3359eb35f8205", size = 250660, upload-time = "2026-09-27T12:25:46.51Z" }, { url = "https://files.pythonhosted.org/packages/05/33/5bc3db57fc9c56b4ef055725c38c34faa818a27d17d65e251371f7f0e3a0/coverage-7.16.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d6276d78f6fca7d0ac066d5da4165c5acd07829e8305c2cb900b738fb3a75a72", size = 254479, upload-time = "2026-09-27T12:25:47.819Z" }, { url = "https://files.pythonhosted.org/packages/f6/0f/4a5de66daef26eb919213f63b84f45d5065ab2df94cd767fc7c1174ac5e2/coverage-7.16.2-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:736fde09ea39646d11f8e3b76bd3425c075aa4dd45f24891970bb77c14ff20f5", size = 250940, upload-time = "2026-09-27T12:25:49.227Z" }, { url = "https://files.pythonhosted.org/packages/57/d3/84cd6a11e707e422194739e9734d947746efa5e5b3358ff2d601f823ee45/coverage-7.16.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c85d54e7e8a2ca932fe8399301af9b8d5907ea2a455ffaff6e7d1208db83b943", size = 251543, upload-time = "2026-09-27T12:25:50.554Z" }, { url = "https://files.pythonhosted.org/packages/ab/bc/3d84c2e2a95f38e346ce3730d9f0e53114f4e8aace72e6e51e014afb9992/coverage-7.16.2-cp310-cp310-win32.whl", hash = "sha256:5139009b5efd2194fc168ee9362f0e191ba612ef5d29242f9269c22f9b8f80c7", size = 225732, upload-time = "2026-09-27T12:25:51.945Z" }, { url = "https://files.pythonhosted.org/packages/07/86/31f1f3170571a345ab9d8361a7b2f8e0c5698173fbecd1f7149b6e2089ee/coverage-7.16.2-cp310-cp310-win_amd64.whl", hash = "sha256:c3305c38a2fa21a4254f2ace7dd9ef5fc569c9a558b66e7017650b3d637fb95e", size = 226357, upload-time = "2026-09-27T12:25:53.272Z" }, { url = "https://files.pythonhosted.org/packages/58/fa/ce3baf63d85b730398d92a7162f486f3a5e4e2cc3382a02488b3943725ba/coverage-7.16.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:732d950e51f3ba4fb6209c73250f3e8924fefca42953ee04a9e65d8c02414d7d", size = 223797, upload-time = "2026-09-27T12:25:54.756Z" }, { url = "https://files.pythonhosted.org/packages/7a/57/9ba29c2aac7f756d479f03d45762120060f0f988788001001bf36e0e6fca/coverage-7.16.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5dca0bb66b4c3d624ba047887bf70270030c150692d543cb501293dc38a9f4b5", size = 224303, upload-time = "2026-09-27T12:25:56.214Z" }, { url = "https://files.pythonhosted.org/packages/5d/7b/0d6d60906dca7d28cc1e3fce12a9861801c4fbb6cbf220ad78cd059c9467/coverage-7.16.2-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:af2a2a8c7c74de0559e0c368d94c8def9e16c58faaee33a0bf081057c4227e3b", size = 254715, upload-time = "2026-09-27T12:25:57.755Z" }, { url = "https://files.pythonhosted.org/packages/cd/b8/9198b865679379fb165c689c64f6e11105ef380f6bd1c7673e83f73d9f5c/coverage-7.16.2-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:db5f8394e17f877a625b257f2ba0ce8e728a499c2c1579ad66220272cd3df510", size = 256627, upload-time = "2026-09-27T12:25:59.131Z" }, { url = "https://files.pythonhosted.org/packages/98/79/9521462cb6072fe394701bc8974b74afd576c9c9355156c7844e1a86a42b/coverage-7.16.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5b3146d2317c75f70df2509066d979dadd941f7021cdf9b5db4bcd8568258e25", size = 258724, upload-time = "2026-09-27T12:26:00.691Z" }, { url = "https://files.pythonhosted.org/packages/a6/76/8d7d5d633db9fe0f3182fedc731bf09f9bcf2366055735152504ad614677/coverage-7.16.2-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9e1d0ced76318bab499693ff25f64faa343415187cb2e4d7befdfdd391a1cf6a", size = 260692, upload-time = "2026-09-27T12:26:02.083Z" }, { url = "https://files.pythonhosted.org/packages/4e/a7/76cb09c89ba46d74d37428bf93251fc14fb0bbe9e05cc2a5ef61773d318a/coverage-7.16.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:af98ad5ed9d6daaca956201e00bb429a7eb2b080426686f70a20353e0f9839f5", size = 254800, upload-time = "2026-09-27T12:26:03.369Z" }, { url = "https://files.pythonhosted.org/packages/72/b6/2351c1979aaeb5b4a8091a75b90ca997ad60de36e181ddba267cf61dac97/coverage-7.16.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d56e4d21c56d2046447733f8b118409597db48c01efe898ee9ac24e858ec2d6", size = 256423, upload-time = "2026-09-27T12:26:04.751Z" }, { url = "https://files.pythonhosted.org/packages/0f/f4/ad9a4f8b5cb2d494fa9452b546fe742ed2f9d3847cc14c05e36279a3e649/coverage-7.16.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1d5d0e3b660506fb84f995814e3118a21efdc0c8eb80127da1be627d90093c17", size = 254487, upload-time = "2026-09-27T12:26:06.082Z" }, { url = "https://files.pythonhosted.org/packages/6c/1f/a520470472f3e8b01169bf42162b1470c9ba992230432f62ca36269bf3a0/coverage-7.16.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:17228fbca0f22976f797be94e975dcd237799c657d49551c7de1e0654d1202e9", size = 258259, upload-time = "2026-09-27T12:26:07.513Z" }, { url = "https://files.pythonhosted.org/packages/09/d2/ff26d5938274745855fa61cfcba0245c88ccc10d98d2cbd96064f16cd5a7/coverage-7.16.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:bc0b0ac781d489304b741269857f1f8338b7a26b1b89c06c0344658001ec0035", size = 254216, upload-time = "2026-09-27T12:26:08.982Z" }, { url = "https://files.pythonhosted.org/packages/a4/1d/5d832d3b06785d9f53267e4f2724a9f60c312eee6ebed9063a461d0d3b45/coverage-7.16.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bf1bd822ec4e387ed245bed0d71151582cf7be9e5309bc4145eefe36083d5878", size = 255125, upload-time = "2026-09-27T12:26:10.35Z" }, { url = "https://files.pythonhosted.org/packages/55/4d/1d33edbc2fcf7d99e384e393e712aa5a2ebbbd8409825357815982207976/coverage-7.16.2-cp311-cp311-win32.whl", hash = "sha256:7ed238d227e23cc300c3d464babdaf9f6ddc740aa1b15a77ae96136e6a7c4516", size = 225898, upload-time = "2026-09-27T12:26:11.7Z" }, { url = "https://files.pythonhosted.org/packages/6f/7c/676df4882118756c4f8f560c954eddb93e166d84dda8c5f0b6a829689bde/coverage-7.16.2-cp311-cp311-win_amd64.whl", hash = "sha256:a90700f743e29aa3d75a6ff5f01953176a889c00e526194bc4d281731b88d99d", size = 226369, upload-time = "2026-09-27T12:26:13.375Z" }, { url = "https://files.pythonhosted.org/packages/7a/0e/a457f4a461b3c5610d845137fdd45fa465e011a64c25af440518ab1f4e41/coverage-7.16.2-cp311-cp311-win_arm64.whl", hash = "sha256:a336eec40e3520d369b8a6cdabb4f596e69a8b42927ca074aa1452fed943238a", size = 226344, upload-time = "2026-09-27T12:26:15.127Z" }, { url = "https://files.pythonhosted.org/packages/5e/2c/f8296c63c5d542f3d21aed685e56b7031a419037d155bb3382fc0940d249/coverage-7.16.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:218d742afca2b5ad5ca759e93eddedfbcc6eadf8322f080dcefc40b7bd4e2d48", size = 223969, upload-time = "2026-09-27T12:26:16.753Z" }, { url = "https://files.pythonhosted.org/packages/90/23/6f3dcb1423a0d43216e402ea1746e4a7c7c44f38896b97dd573790f56a40/coverage-7.16.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a9a638be322a8d76a41cdb17781c7f82aaee6a66493d8ffb7e2c09ee22423d99", size = 224328, upload-time = "2026-09-27T12:26:18.15Z" }, { url = "https://files.pythonhosted.org/packages/ac/7d/8f3b6dc920e3fc6732f7678785a2091db439f186afbec30dbf2214d9b1f7/coverage-7.16.2-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:724bd0f1e81856b35e59fc98cf7b4e544a3cb662e4e0864dca73d4326ee9d808", size = 255832, upload-time = "2026-09-27T12:26:19.799Z" }, { url = "https://files.pythonhosted.org/packages/d1/36/6c45f15be4eca4ac1062c6a55a323286494c99726a7e58951fe85967ac08/coverage-7.16.2-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5375ebd99038021b35e99dc88255022912c06565d316212f4a576e4b08d30f5d", size = 258571, upload-time = "2026-09-27T12:26:21.199Z" }, { url = "https://files.pythonhosted.org/packages/34/fb/b54cbeba3ad89082c2e441278681859e538322cc34b84b2af7ebff00080f/coverage-7.16.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7a076277ca9f5750cc230f0f578ebd2620cec60255b25707361699fef6fb465c", size = 259680, upload-time = "2026-09-27T12:26:22.822Z" }, { url = "https://files.pythonhosted.org/packages/6e/a2/0dc65ec3d61930e1e4c2e371763b15eb4290896eb343a12d5d3091308116/coverage-7.16.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:58d4a54c6ea672afef66d49be922a2c69826c5ae1a42a9cd94f0c9c2bacdf800", size = 261945, upload-time = "2026-09-27T12:26:24.336Z" }, { url = "https://files.pythonhosted.org/packages/d6/93/5fad7a61f2c14e08e98946fc31c1c7ffc1195061bf3fdc351db3be77a863/coverage-7.16.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0dcbcfcc059117284c603ff8cb61a65872512882f84a8cf0339241f7f7c2f148", size = 256191, upload-time = "2026-09-27T12:26:25.89Z" }, { url = "https://files.pythonhosted.org/packages/2d/47/74e5de9227b939ece9f64e729645ddc4296bea10dbfa98721c1333c8be2e/coverage-7.16.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:afdf43b72ef3876c1fe66423b91466e37877c9e81e8cec70542b7e8525b9d1b7", size = 257610, upload-time = "2026-09-27T12:26:27.35Z" }, { url = "https://files.pythonhosted.org/packages/13/fe/2cf28d40b43645d1b72388fe3ee7f7c747533a6a9557bb8c24a7ae74fe1a/coverage-7.16.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9acc7f7ec4a1b5f89bd929fde5b8a714f6fafdc6cc18725413d510aa082b47ad", size = 255757, upload-time = "2026-09-27T12:26:28.949Z" }, { url = "https://files.pythonhosted.org/packages/d7/3d/7c149fd99fc8bbc39c80db5e688d1d39fd040be2ecb78b8335a51a55b9c0/coverage-7.16.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:80d3f7b48d43ee8fc5e8707a8adb43d743a5a1a85256c25a24f9d6d0e2238fa6", size = 259822, upload-time = "2026-09-27T12:26:30.515Z" }, { url = "https://files.pythonhosted.org/packages/e6/3f/b283fce09d5995e227bd8e513358dd7471bedc0f78abc85a925ebdb0a2f6/coverage-7.16.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:126d1af8804d7224421fe991ff65d3ce649081560df7a98b1a5ffff07f9923bd", size = 255325, upload-time = "2026-09-27T12:26:32.037Z" }, { url = "https://files.pythonhosted.org/packages/bf/91/f3325edf0c4223fb1fe1532b8dbef2a1d2f729459a9a7d1a44d073bae534/coverage-7.16.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c19cd6d025c1673f22afcd22c7df8a662d779e05d8e3fa6820c22afb895b0206", size = 257191, upload-time = "2026-09-27T12:26:33.525Z" }, { url = "https://files.pythonhosted.org/packages/c4/89/21eb5e83ecf2eed523c4eb3d65ae513cd082c8fd1b6deb34c4cb6c332f97/coverage-7.16.2-cp312-cp312-win32.whl", hash = "sha256:152877cdc8a07264882cfcd503ba56a3ef6cba56a70e8c70f6eb8ffd7384789a", size = 226034, upload-time = "2026-09-27T12:26:35.021Z" }, { url = "https://files.pythonhosted.org/packages/db/de/e3ad6d864c0833624b4f1f9b53f9e58e116c945e5e965c3f1e172c5e84cd/coverage-7.16.2-cp312-cp312-win_amd64.whl", hash = "sha256:e6c52d3307824ff93b39efd99e4185d557db40bd841452abfb32e5d9151ca162", size = 226569, upload-time = "2026-09-27T12:26:36.604Z" }, { url = "https://files.pythonhosted.org/packages/3e/c1/bccc58ebe5489cc70628f635c1932fd371f5d7da850dbcf960f95f4c4afc/coverage-7.16.2-cp312-cp312-win_arm64.whl", hash = "sha256:a678c0b6b22086ec2427359d22e37445d4a792f5fdbbc744112c7dade65cad02", size = 226372, upload-time = "2026-09-27T12:26:38.406Z" }, { url = "https://files.pythonhosted.org/packages/f0/f6/8eb4f220ef24f84fb27d852d4f9bf83e0c73ec1a4a08dd9a87e3f4529739/coverage-7.16.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1a37c6e478cf687e1aa30a593d19c92c02fad9d122b51ab73f51b8dc7a0c0fc9", size = 223993, upload-time = "2026-09-27T12:26:40.164Z" }, { url = "https://files.pythonhosted.org/packages/40/23/d4bbaf0c154e0b0c2b5264890dbf6ef098dcb50ec8f2469be9490d191660/coverage-7.16.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0993d0e90858c03943d3cb152e068a20dd4707924deec84dd2230261baae3b1b", size = 224368, upload-time = "2026-09-27T12:26:41.762Z" }, { url = "https://files.pythonhosted.org/packages/7f/48/fc1e88fd571ec5cb38150b7f89f7696ca1bdf9920e01432febb69774cc85/coverage-7.16.2-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bb2fc905bbf4e6b7f40806ea79e31515abf6349594cdf0adf27c4215f0463204", size = 255358, upload-time = "2026-09-27T12:26:43.442Z" }, { url = "https://files.pythonhosted.org/packages/1d/56/6785397d07c29c8e70fbb9a07e97d062b43c21ffc5f12385917847f09f63/coverage-7.16.2-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:4358b9c8c0125b460407f3017c6cce8156e904b32772c5630d27112f52bdbfe5", size = 257955, upload-time = "2026-09-27T12:26:45.725Z" }, { url = "https://files.pythonhosted.org/packages/27/3b/c8cdd07721e5f99abd81cea970d971997f99bf158c0b85f51bd284179c8b/coverage-7.16.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1f15254427c9b33eedac4f198eaf9e356eb4f6214551afb43da6194a2c088ad7", size = 259183, upload-time = "2026-09-27T12:26:47.208Z" }, { url = "https://files.pythonhosted.org/packages/9b/11/606b192fe43d32574ec6238549d48de588fdcc18485682a5ec0a8ac357f2/coverage-7.16.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9a75a4704ff640e46170042eec1f984385a121227c505d5a16ad8e495f452541", size = 261325, upload-time = "2026-09-27T12:26:49.084Z" }, { url = "https://files.pythonhosted.org/packages/67/90/eea481f8b0305ceeb33f081a5f47e298391dbd1b589de0c4b3b3aa50d3f2/coverage-7.16.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:14253fc7bb15749b849795a06f5d3b6d8bc3fb8a4b5ddc341faf7a89dce205fc", size = 255531, upload-time = "2026-09-27T12:26:50.509Z" }, { url = "https://files.pythonhosted.org/packages/6b/be/dedbf9aea1457b120c27ac10b8fc2a357f37fa2b54c3e7286d42980a0a2a/coverage-7.16.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:921415102a90637fcc2e3f169f61dad7699ecf690e8639fc21b813acbedc0967", size = 257329, upload-time = "2026-09-27T12:26:52.005Z" }, { url = "https://files.pythonhosted.org/packages/fa/cb/b25c19d5bb2bd0f2e4e27fe8e2ffcae80c7a91ae181c0dc749ed60e9b1a4/coverage-7.16.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cce2bc991293f15cc4084ca116827b5900c5f34e1a54dfe83f10ab5c43162eb7", size = 255294, upload-time = "2026-09-27T12:26:53.634Z" }, { url = "https://files.pythonhosted.org/packages/5f/a2/892c5c5f4ad44b7b2ca009aee705191f3f268f15052244f2f9e3539b2e35/coverage-7.16.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:e1fa594c887365b69745f25a416806e61085dd07b94c9eae68a6e20730629b23", size = 259444, upload-time = "2026-09-27T12:26:55.243Z" }, { url = "https://files.pythonhosted.org/packages/ed/99/a562537deba0a3e370182ae71c149be796c39d8087365f17a09188f27145/coverage-7.16.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:11e597173af1dc33d5f8a7332ada544199269a223af1ee1770ddd5e245ad0fe8", size = 255111, upload-time = "2026-09-27T12:26:56.851Z" }, { url = "https://files.pythonhosted.org/packages/2d/20/854ec68641a9b3362ff068a32dfa41637299761617ef253791dbade6fc76/coverage-7.16.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:3e7f99698ba3a7d13988bdd984b7ebf13af4dbe2166dc8502eef90d77603b0a4", size = 256882, upload-time = "2026-09-27T12:26:58.41Z" }, { url = "https://files.pythonhosted.org/packages/db/0d/748e4518b0ac0f9ff2687c248a6e5f8c0737306e709372632a2556f84443/coverage-7.16.2-cp313-cp313-win32.whl", hash = "sha256:f80bd9f9633eafc73d0a913ba2645c96ba58bba1befc30590f7c0fbfde59d865", size = 226045, upload-time = "2026-09-27T12:26:59.983Z" }, { url = "https://files.pythonhosted.org/packages/31/fa/6e46edba66a183fe4d99d4bb52c173287e9b8dddabe0888d24cb8210e580/coverage-7.16.2-cp313-cp313-win_amd64.whl", hash = "sha256:8be099e979fc42559328a21828281b4578304191ae46ed4e80a407048a82eee6", size = 226581, upload-time = "2026-09-27T12:27:01.494Z" }, { url = "https://files.pythonhosted.org/packages/1b/d9/9ef6845367600b336ff75d000444a0d32497d6972c833141bd39356abf68/coverage-7.16.2-cp313-cp313-win_arm64.whl", hash = "sha256:28ff850182a67d117990fa2ce5ea1032836d8c9630dae867e8bdd3bff4533b79", size = 226409, upload-time = "2026-09-27T12:27:03.116Z" }, { url = "https://files.pythonhosted.org/packages/59/4c/577fc0803dab4155dcf808faffbdd7b159256781c0874a8586e17b81b149/coverage-7.16.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:4ee546b9e4872ffa194bf07ac87bfa1202ebb824d0795dc1ef22f175545ca90a", size = 224138, upload-time = "2026-09-27T12:27:05.141Z" }, { url = "https://files.pythonhosted.org/packages/75/9e/e3785ba3ecba2bd11efc74bfe2801ca4b78c4480b15a375648d809a59da3/coverage-7.16.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a2fac6895eb299a2e52d7bbb8fb3903502b9da8d3f5309ceb16ec40c646b58ee", size = 224445, upload-time = "2026-09-27T12:27:06.805Z" }, { url = "https://files.pythonhosted.org/packages/f0/d0/963ff22d3fd27117da3b8cc442f5bdc91196f783321e1a8ff0ec43476772/coverage-7.16.2-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:57ff3783f99d75a1e81dd56a9737eb5665e6736a5d93258ba596b6dcad8fd05b", size = 256112, upload-time = "2026-09-27T12:27:08.43Z" }, { url = "https://files.pythonhosted.org/packages/a8/d4/a306940c81c6ae759e82fff27d20b7fdc6896e422b821f51313cce212b6c/coverage-7.16.2-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:35f37886699cb9abd29958247d718628d5bc6f39e623dff66a09e546c42a7e03", size = 258727, upload-time = "2026-09-27T12:27:09.927Z" }, { url = "https://files.pythonhosted.org/packages/b9/a3/d3d99d93b02517087aa05bc0cf2d04d372956b849e5443e059079901429b/coverage-7.16.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0fd7a86fdda7cb6d616d178654bd0ad6bc0f3f33c2e478aa598500a1a9e34eda", size = 259909, upload-time = "2026-09-27T12:27:11.55Z" }, { url = "https://files.pythonhosted.org/packages/08/44/39dd599181726758dd185ae4dc0c0ab3aeabf7ca70e68e145060feeaaa16/coverage-7.16.2-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ac0f3b379c94acc2f7dce5f5f0b24d44fa1cc6a509717ef83dfee07450c2117c", size = 262481, upload-time = "2026-09-27T12:27:13.17Z" }, { url = "https://files.pythonhosted.org/packages/99/e8/91ee43f6ded411460c359d7e1aebde4d6fd8f00a2e5394182d9d212eb23c/coverage-7.16.2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7d0732c83746bc24123c581a85d9dd96b70ddb538c9076020aa1a041790361e9", size = 256012, upload-time = "2026-09-27T12:27:14.91Z" }, { url = "https://files.pythonhosted.org/packages/11/8c/e9499ddc33197bd7eabcb1118ca81756fc874457b324e2b479a4804b2ad2/coverage-7.16.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7b451c68218c150f616bc9649783ec8de76a59792c759b43aa0c9c0466a465e4", size = 257898, upload-time = "2026-09-27T12:27:16.588Z" }, { url = "https://files.pythonhosted.org/packages/5f/6e/c081cb5991a0afba99f9c4ad6c74a5fce9513a38ddc64e3e6680c6fed9af/coverage-7.16.2-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:a56ac4fa5a75c7e182e8f62600cfb4aff43c5ed7356a034f3557659c3bec1d90", size = 255938, upload-time = "2026-09-27T12:27:18.19Z" }, { url = "https://files.pythonhosted.org/packages/b2/42/1c3d819e8f9b6eb01c2fe90874d67a8882adb9507e0bbb09361ed131ea89/coverage-7.16.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:4cc4f73aa3fabc36e32046d6cd2971405948d8a903636508a3d3b2f9128b3a95", size = 260368, upload-time = "2026-09-27T12:27:19.903Z" }, { url = "https://files.pythonhosted.org/packages/19/4f/d70eac07901fd587b6ab05e659b52afe13959992aa5113bf6cce059cc572/coverage-7.16.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:723dcdab91357159b722935b500ee8abc0a66c8c432e1e9fabf4cc7598952de8", size = 255620, upload-time = "2026-09-27T12:27:21.621Z" }, { url = "https://files.pythonhosted.org/packages/34/5e/6d87af88317d3d9a9b18a9ca1bc1673eb516917f296e579d0d4a55cb3490/coverage-7.16.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5397e21a90dde0e9c6896b77ded8f0be26b66f8b22b33aed41f6043ed95d55e6", size = 257521, upload-time = "2026-09-27T12:27:23.358Z" }, { url = "https://files.pythonhosted.org/packages/79/bb/90c2641170d2fa1a6757b3f8450ba2740197317b0ddd749e9604b914e886/coverage-7.16.2-cp314-cp314-win32.whl", hash = "sha256:848893e1d361448c113dc2f0913503522a6f7be231d0e38333d2a22d9698a011", size = 226248, upload-time = "2026-09-27T12:27:25.153Z" }, { url = "https://files.pythonhosted.org/packages/30/08/d8d0478bb02c8eb0ae20a496fc80c40fcf4d3450bd184300d682ba2d28a6/coverage-7.16.2-cp314-cp314-win_amd64.whl", hash = "sha256:5a27b731c171e43dc8b5f32b76a5051dde2ec9b9366c87028f08a7088ebc2c7b", size = 226732, upload-time = "2026-09-27T12:27:26.907Z" }, { url = "https://files.pythonhosted.org/packages/32/3f/0001da22155b0a8ce063ec0f7e64ecbe17b373f306e7a74435f6d6accb72/coverage-7.16.2-cp314-cp314-win_arm64.whl", hash = "sha256:1c569a9fd25505f1cd6bea90588818f90373ce90e2632e2cacf19ddbd6e14fdb", size = 226645, upload-time = "2026-09-27T12:27:28.588Z" }, { url = "https://files.pythonhosted.org/packages/d7/85/6d8813aff9b8b8586691a9d33c43c5604f7227622574da7cdc3d91a86861/coverage-7.16.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d93db87adb6b1c1b408dce4763314b55d76a9f589e96783a84ac9e7689e48bdf", size = 224871, upload-time = "2026-09-27T12:27:30.32Z" }, { url = "https://files.pythonhosted.org/packages/5c/70/444f3a4981ac2cda40fdcf4cc9b56a4e1a33c222abeb33e51ed3e3eb2a6b/coverage-7.16.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:aa62c85046473959c13ba9edca9dc90a77d5c1095b1ba313556314d77fe5b036", size = 225123, upload-time = "2026-09-27T12:27:32.33Z" }, { url = "https://files.pythonhosted.org/packages/d0/c1/980681cd7b33eb66ac835044116ef0a92e11fcc7bdd866cc89d10b1130b9/coverage-7.16.2-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:db76506aa5416081f3e8974ae0f7965c58ada0bb0ef7339ac86099588dbb20d3", size = 265049, upload-time = "2026-09-27T12:27:34.085Z" }, { url = "https://files.pythonhosted.org/packages/b2/e3/87679875c33bb2191f0f05544a1cc9adcc940fe0c35443a10f2df753dde5/coverage-7.16.2-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a0f2285329dac10ab08f79cb11f5692c497018e6c7c511f95e6fd63a70b8f831", size = 267717, upload-time = "2026-09-27T12:27:36.025Z" }, { url = "https://files.pythonhosted.org/packages/76/64/5d372776d6eb523d4e93bafba2253f96984e3b18261c4cc56a50863c6d0d/coverage-7.16.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:382d3346d56b0eec1b793d53a4c88799c8053f516aa3a8d7c44315696954bacf", size = 270047, upload-time = "2026-09-27T12:27:37.96Z" }, { url = "https://files.pythonhosted.org/packages/be/c1/44082ff0cbf9f97d0043f57970a71204097ec7ba606361a9fd2065393669/coverage-7.16.2-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:648352b94507179d82637292e7ae8802508d95f78e2f00a705a50b6c48011681", size = 271360, upload-time = "2026-09-27T12:27:39.766Z" }, { url = "https://files.pythonhosted.org/packages/b8/17/9a215efe25b5e0ecc87c89dbe525c4a87d14d87c8c0c7316ef140a5f6f3e/coverage-7.16.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fb2bde05838fffae1a1bf75e5d411a6cac3e4e9bb97e6640fed8cd47888b33f0", size = 264736, upload-time = "2026-09-27T12:27:42.072Z" }, { url = "https://files.pythonhosted.org/packages/a2/da/7f0a31af8e448107d4d32844bd684757f51ea907bc0c68c8fd537b2123ff/coverage-7.16.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6a75180829efb8ae62b4aded25be6ddca1c888d138d2d82e21d93bfbd88f41cb", size = 267600, upload-time = "2026-09-27T12:27:43.85Z" }, { url = "https://files.pythonhosted.org/packages/dd/a4/3bfecbd3366b775bacdcb3330394d356cf384b5d8f5b2146ac4b14b252b5/coverage-7.16.2-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:99704f73721e23859112072d522076e11c31744fc96b5652e5dd2018aa4359f7", size = 264767, upload-time = "2026-09-27T12:27:45.768Z" }, { url = "https://files.pythonhosted.org/packages/b8/3f/5d62163732d87e4a0c4710a0eab30f0fd6a2d480112abe2029f014fe8c9d/coverage-7.16.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:29309ccc86b7f33df7db12813c299f215bbbc470ed6292d0bedd63ffae1ebf64", size = 269026, upload-time = "2026-09-27T12:27:47.787Z" }, { url = "https://files.pythonhosted.org/packages/49/4d/8e4579f225426535085a9be371cc75e3b026d058d679b80affbdfb4c3ef0/coverage-7.16.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:30c1b65d529e46569899fadca59e4a87c1faf2886923f1307ba61e654d4f3c20", size = 264147, upload-time = "2026-09-27T12:27:49.681Z" }, { url = "https://files.pythonhosted.org/packages/d1/36/ef1f77e2c3f7bb03c2b13b9a2006f88700fdd75535ef158d70049f425c1c/coverage-7.16.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:dcf4bc2aab4e16b1c4c0c2005918f23a7dd5d7821ddae82caed9e3342dc2fcce", size = 266376, upload-time = "2026-09-27T12:27:51.551Z" }, { url = "https://files.pythonhosted.org/packages/be/79/0cb2bf4428830dec971c718c2c841a039c084415c99e67281f5a72841aab/coverage-7.16.2-cp314-cp314t-win32.whl", hash = "sha256:a9cd3de0a5bfe7b0e21ee10e1a14e3d61bf52efc88217ab1d95d6ace6970bd46", size = 226585, upload-time = "2026-09-27T12:27:53.945Z" }, { url = "https://files.pythonhosted.org/packages/3c/f9/da17121c16667fd84998e972200ae226a41540f6ea4795776c6d99e8976f/coverage-7.16.2-cp314-cp314t-win_amd64.whl", hash = "sha256:611a44e5229a59d7483ce830160e1a0e85f700562c7a5651c7c63fb8f4eb528c", size = 227378, upload-time = "2026-09-27T12:27:55.778Z" }, { url = "https://files.pythonhosted.org/packages/74/89/01179c62d1b7e6e33bd5001566b02d7f778cf33d3ec1e81e94ca170c517f/coverage-7.16.2-cp314-cp314t-win_arm64.whl", hash = "sha256:22957cef43ce038641de78ba995de7568d2d6a37c6ddbf7fa0fd7d1ae2344d91", size = 227064, upload-time = "2026-09-27T12:27:57.496Z" }, { url = "https://files.pythonhosted.org/packages/4c/57/52935003c3f627ba6e5203d7179aad32448c10899663a30336aba8e81a2c/coverage-7.16.2-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:414c26dfdb96aac2d570a54e03008f001e32eb2d413705365503648c6bd361d8", size = 224140, upload-time = "2026-09-27T12:27:59.343Z" }, { url = "https://files.pythonhosted.org/packages/31/38/df472520f3e626524d7e2fc9d6da0afe7895a2f1489d36b48af8ca40bb41/coverage-7.16.2-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:00d3eb96e9988c45f50cccd1f1496571ac5c1f91386ac02c4d55516eeda19a24", size = 224449, upload-time = "2026-09-27T12:28:01.299Z" }, { url = "https://files.pythonhosted.org/packages/0c/aa/3be084d5b82e63ccdad4ed751e4acbae294673573e30481d29f8b7402eec/coverage-7.16.2-cp315-cp315-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:4dbbd1155ca46e6e0b6b89d204428c56ef6a459af21333f365d135a2820e5a09", size = 256060, upload-time = "2026-09-27T12:28:03.185Z" }, { url = "https://files.pythonhosted.org/packages/de/29/48fca82a7ebf7ff7b2e35019cc9537e7f65e4d2aa1215cc5a8792c989251/coverage-7.16.2-cp315-cp315-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8fc15cc8d0d06e873c00ef18e1372d605f9aaf3de27d8c24e50782e75bc8b843", size = 259106, upload-time = "2026-09-27T12:28:05.15Z" }, { url = "https://files.pythonhosted.org/packages/06/3d/b2d5986f2dd53fe201aa1be2e4ab204fa1aed5101e67c0dbbb419b850aee/coverage-7.16.2-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9c6afdd69218202bc1758c9a14b86b8cf1084f37ed2ca143e567a103772b16d1", size = 260674, upload-time = "2026-09-27T12:28:06.868Z" }, { url = "https://files.pythonhosted.org/packages/ce/7e/b50160be3506ead12e6480d14279af7f0f17627694300a2d1fd2c42d2ff5/coverage-7.16.2-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:aba5c63b7afdc749cc9eae943d5b868cba2b261a176378fa1c5a30bc8bc89982", size = 263139, upload-time = "2026-09-27T12:28:08.771Z" }, { url = "https://files.pythonhosted.org/packages/14/5e/7c805ac9a32606de1399bd7e9bd375aa2f973dc61b12680d9e6403c2e891/coverage-7.16.2-cp315-cp315-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9174f0af24e5eff248b9dbfe76ec5275a3d19d37edbc2810543f12cf97347a34", size = 256591, upload-time = "2026-09-27T12:28:10.842Z" }, { url = "https://files.pythonhosted.org/packages/ab/9e/76f1ed129a2daf658a3ea17122824cf2e3b91fea0460d8d3664fc5a61018/coverage-7.16.2-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:80e9fdb4c3d926b6ba721d4bf7435bdb869c3527ae7803290361d0ab73db13b6", size = 258708, upload-time = "2026-09-27T12:28:12.962Z" }, { url = "https://files.pythonhosted.org/packages/5a/b7/8d62e75f48b527619239a65294f842d4b7fd02a0839d43ae1de80184e2df/coverage-7.16.2-cp315-cp315-musllinux_1_2_i686.whl", hash = "sha256:7b3bce4a0d05401d70b7d0d5ca783e686bc9d30e81dbd7d980d532609bf809e4", size = 256562, upload-time = "2026-09-27T12:28:14.934Z" }, { url = "https://files.pythonhosted.org/packages/b8/8d/0a15f95c3afb78e947c52644786ba4bc9de259905687dd720d5e6fae2e76/coverage-7.16.2-cp315-cp315-musllinux_1_2_ppc64le.whl", hash = "sha256:44f21e407b278efdfc1ee5e481e00518bd1d500310a30a5fbf2bcbedfef4aaf0", size = 261077, upload-time = "2026-09-27T12:28:17.215Z" }, { url = "https://files.pythonhosted.org/packages/25/00/88389987305a47d732866c07c8a500000ab574df9505e3114ac69c8d027f/coverage-7.16.2-cp315-cp315-musllinux_1_2_riscv64.whl", hash = "sha256:59c3926585e1cd1f2190f4b2ac9014de1bbeaf0d5d0587b0dc6b0aa90d17896a", size = 256034, upload-time = "2026-09-27T12:28:19.08Z" }, { url = "https://files.pythonhosted.org/packages/92/02/34d079d4952ad461bde037d353f9a6e037a7edc45fe0f9ee8781ff73f028/coverage-7.16.2-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:066429634299e14dd2d511e1e85f8f9cecc500781f6b41907c0dd6f1baea7e63", size = 258034, upload-time = "2026-09-27T12:28:21.242Z" }, { url = "https://files.pythonhosted.org/packages/f6/d8/3e59a62879285b464ec1b10fd824fbc1af9ce66e842cd39974f80a0becc4/coverage-7.16.2-cp315-cp315-win32.whl", hash = "sha256:893ea9cf86cb8d2546812ac93d973aaf2ee1fb45110a873b014214fd23e3725e", size = 226252, upload-time = "2026-09-27T12:28:23.102Z" }, { url = "https://files.pythonhosted.org/packages/f4/e1/128026e1b2836e9ad6b219207ba9edf1c5e0088a7869e23088aee7fbbe7a/coverage-7.16.2-cp315-cp315-win_amd64.whl", hash = "sha256:01c6908bc613b420c26c818fe948e1b97dfd041a53c98b01c63bd8321f5c9aae", size = 226728, upload-time = "2026-09-27T12:28:25.21Z" }, { url = "https://files.pythonhosted.org/packages/a8/f4/c9fa8e7cf525ca7748ac52b0ee89331d13fe09808e45c679830708782e90/coverage-7.16.2-cp315-cp315-win_arm64.whl", hash = "sha256:967d72c835d7a8cf0af99ec813a2d06e3db6df706402f1fe85b31b437645f495", size = 226648, upload-time = "2026-09-27T12:28:27.136Z" }, { url = "https://files.pythonhosted.org/packages/a2/13/e96b045447a856666f36f9c653e2a80bdaa732aaaf72412b19aa2c26a473/coverage-7.16.2-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:98d9c97f51b334b0adce7b964442a9af33c1a00c6ac856984cc5dc8d18f81c75", size = 224858, upload-time = "2026-09-27T12:28:29.169Z" }, { url = "https://files.pythonhosted.org/packages/23/90/087f6ad1bd3df059632ca3407a4e6552ed1053ee35354de0a771acf35423/coverage-7.16.2-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:3e861f1071dcc2fec1e88bef0920f6b1eaa66a143555b4f8ab79ba2b0f30ef55", size = 225139, upload-time = "2026-09-27T12:28:31.131Z" }, { url = "https://files.pythonhosted.org/packages/7e/8e/285dcef0184358044e7cbcd810a1bdc9566bc620f54702d605477155df4a/coverage-7.16.2-cp315-cp315t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:fb9d92ecfe2d5b494367c67f7446f8b75b68d8d0c8cf3bc3e6997478be25d9e2", size = 265090, upload-time = "2026-09-27T12:28:33.04Z" }, { url = "https://files.pythonhosted.org/packages/06/b2/cc83f3a6e5789a4e89059c69555bc641c2efcde568405a1c06fc702951ab/coverage-7.16.2-cp315-cp315t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:eb57acff4a74246ae513c142d4b36e18c389c3aed8661914a53f7cd0071031b2", size = 268254, upload-time = "2026-09-27T12:28:35.135Z" }, { url = "https://files.pythonhosted.org/packages/ac/41/f548c19530f5d66ac6e3c92bbcbc49da7261de3a458b9f3e54a3efb1a0b2/coverage-7.16.2-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:444889f7f66b74e4455c0a97e0e166dd41177f1dca8c0239a47cff25e05ba7e1", size = 270695, upload-time = "2026-09-27T12:28:36.959Z" }, { url = "https://files.pythonhosted.org/packages/94/61/4dc27cf82ef96434d2874110ad0cc10ea4621025705dc5049862bd3bd181/coverage-7.16.2-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a740ea6f083c6db7b926534d159508f80ba275ab35e722522de0d18d0f56e55f", size = 271853, upload-time = "2026-09-27T12:28:38.821Z" }, { url = "https://files.pythonhosted.org/packages/38/29/bf8072b1b8bd5f2de8b21460a404460b1a2b97e80a9464c78ec0271f6199/coverage-7.16.2-cp315-cp315t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8e209591f7c41ae4a9171335cf6156afda0b21de73b02f73f5aa95b2d5fbb08d", size = 265644, upload-time = "2026-09-27T12:28:40.815Z" }, { url = "https://files.pythonhosted.org/packages/7c/2f/0aecb8721be5cdeb8afd9d6d9f6b463f074e4d8d37f00f4c42442522709f/coverage-7.16.2-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:396bb16e04ce04efbb3df91456ae4e3da918e69ecdf67fb711b0a0fdf35ccce0", size = 268530, upload-time = "2026-09-27T12:28:42.725Z" }, { url = "https://files.pythonhosted.org/packages/ab/0b/92b4b7628268ee711249958e68fc0328779bd3d9a7ab4715379465aedb84/coverage-7.16.2-cp315-cp315t-musllinux_1_2_i686.whl", hash = "sha256:9cdf19874e0d247f32f03609200370343c3c7aa260b191d8c2bb251d36198283", size = 265154, upload-time = "2026-09-27T12:28:44.684Z" }, { url = "https://files.pythonhosted.org/packages/7b/d9/41c95c1ab29b3dcd357cd1227181d1c98185632aca41ce670ce671b23a43/coverage-7.16.2-cp315-cp315t-musllinux_1_2_ppc64le.whl", hash = "sha256:fd3d72233eb8b48acc94fa57d44e2d32ce8e7abed02882ccb6d855ccc4ed33ec", size = 269799, upload-time = "2026-09-27T12:28:46.672Z" }, { url = "https://files.pythonhosted.org/packages/80/07/ebeb259aa5362b033a137b86d7274ff4b109d59be8cc9913889b783bf75a/coverage-7.16.2-cp315-cp315t-musllinux_1_2_riscv64.whl", hash = "sha256:bb4ffe96aa663cee727659db5a2afeb38c95f8677b747d447b90d6d4874ea2c5", size = 265196, upload-time = "2026-09-27T12:28:48.996Z" }, { url = "https://files.pythonhosted.org/packages/b2/18/8437620f90d023680a072eee02f968055f3658bbfb7d386d0ea34cfb7f30/coverage-7.16.2-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:dba2edfb054f6d4a08df9d1637c39a5aa3865bca6617c13c86be21e45658a59c", size = 267266, upload-time = "2026-09-27T12:28:51.361Z" }, { url = "https://files.pythonhosted.org/packages/28/6c/f08e8ee4293e6434035424180bef4d45e028e8ecc006c61bf9453e74405e/coverage-7.16.2-cp315-cp315t-win32.whl", hash = "sha256:251aed777c47c77aba047096d4542889db089227655711dfc2b9c54ef0e15e35", size = 226583, upload-time = "2026-09-27T12:28:53.33Z" }, { url = "https://files.pythonhosted.org/packages/f7/fd/3f939c2847f4a72c20cff8b1ac33da78ea91a2d38d9b43336e60db719103/coverage-7.16.2-cp315-cp315t-win_amd64.whl", hash = "sha256:2aca0bdfa9e91621d5b09d815357bf63def4fc0e9cb66da67bf2cf93f3b1a6f5", size = 227374, upload-time = "2026-09-27T12:28:55.158Z" }, { url = "https://files.pythonhosted.org/packages/5a/35/b98cdc354c952402132e675a87f2cc3227fb68f959c84aaa491fbe15933d/coverage-7.16.2-cp315-cp315t-win_arm64.whl", hash = "sha256:b88841e654f09732804809e435b3e005a929ffd9998b872b7b213957b8759cb8", size = 227064, upload-time = "2026-09-27T12:28:57.075Z" }, { url = "https://files.pythonhosted.org/packages/3f/0c/7a64e1ac90541a8edf50daef0914848011fb057a5bf55284a4811e21939a/coverage-7.16.2-py3-none-any.whl", hash = "sha256:11d28e9123a9156cb405d8d27b44256c9a58fb5decc2073a8f17862057e3aa0f", size = 215754, upload-time = "2026-09-27T12:28:59.075Z" }, ] [package.optional-dependencies] toml = [ { name = "tomli", marker = "python_full_version <= '3.11'" }, ] [[package]] name = "docutils" version = "0.21.2" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version < '3.11'", ] sdist = { url = "https://files.pythonhosted.org/packages/ae/ed/aefcc8cd0ba62a0560c3c18c33925362d46c6075480bfa4df87b28e169a9/docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f", size = 2204444, upload-time = "2024-04-23T18:57:18.24Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2", size = 587408, upload-time = "2024-04-23T18:57:14.835Z" }, ] [[package]] name = "docutils" version = "0.22.4" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.15'", "python_full_version >= '3.12' and python_full_version < '3.15'", "python_full_version == '3.11.*'", ] sdist = { url = "https://files.pythonhosted.org/packages/ae/b6/03bb70946330e88ffec97aefd3ea75ba575cb2e762061e0e62a213befee8/docutils-0.22.4.tar.gz", hash = "sha256:4db53b1fde9abecbb74d91230d32ab626d94f6badfc575d6db9194a49df29968", size = 2291750, upload-time = "2025-12-18T19:00:26.443Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/02/10/5da547df7a391dcde17f59520a231527b8571e6f46fc8efb02ccb370ab12/docutils-0.22.4-py3-none-any.whl", hash = "sha256:d0013f540772d1420576855455d050a2180186c91c15779301ac2ccb3eeb68de", size = 633196, upload-time = "2025-12-18T19:00:18.077Z" }, ] [[package]] name = "exceptiongroup" version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" }, ] [[package]] name = "idna" version = "3.20" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/f5/08/8eea9d4b8302028f3abb2c0813953f7aec26d33b7a8960ed760e65ff29fa/idna-3.20.tar.gz", hash = "sha256:a7db850025b95ded1eae8a46181a1a6c56c92c96f0e2b005d9ff8dc0210cab44", size = 216463, upload-time = "2026-09-17T14:11:04.752Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/58/a2/bb081bab032533a855d44de1d56f8e8426114ff1ba5d1f07a438a0a654f8/idna-3.20-py3-none-any.whl", hash = "sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c", size = 69583, upload-time = "2026-09-17T14:11:03.168Z" }, ] [[package]] name = "imagesize" version = "2.0.1" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/fb/5e/513ff06670c84e7b9887c1fdf61b2d42b4f574a831f2f1d2222023049d8a/imagesize-2.0.1.tar.gz", hash = "sha256:b2ba6a4dea487a7ebcd53248d3476aca449d30db12a2dde5e0c5ca9624fd77e5", size = 1883774, upload-time = "2026-08-24T12:35:19.13Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/01/f9/575c8d760eae1fc99651b7cc5efd96ad5379ca4d6b53750b0fb4fe983f34/imagesize-2.0.1-py3-none-any.whl", hash = "sha256:ea0c9a0384df69ed86a943a15cde37d0360b82491b3910dc2215e202e62b5b02", size = 14794, upload-time = "2026-08-24T12:35:12.548Z" }, ] [[package]] name = "iniconfig" version = "2.3.1" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/01/e1/2069291243c926a2ff1cd706c7f3eeb9b62144bf60f77c9fb9ff2fb26bd3/iniconfig-2.3.1.tar.gz", hash = "sha256:67f4b9c50da0dedf52af349e7749a80a9057a5031199791b906c3bb3ae878960", size = 21209, upload-time = "2026-10-06T22:48:38.076Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/56/43/4ca9e49d27a1fcf6bece6f6aec0ea46bb9112489b93d4b688fb415457bdb/iniconfig-2.3.1-py3-none-any.whl", hash = "sha256:9121e2c1fdb355232495be3194c8dfe87ccc2d5dee45947b78e68f499790d7a7", size = 7552, upload-time = "2026-10-06T22:48:36.959Z" }, ] [[package]] name = "jinja2" version = "3.1.6" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markupsafe" }, ] sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, ] [[package]] name = "librt" version = "0.16.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/04/f5/9dc696772d241814bacac7880bac32f2930b5a6ebc1f85317b83161a011c/librt-0.16.0.tar.gz", hash = "sha256:ac38d6d8d66bf3d744148dbbc0b8e193e195a51e364ed55e224631f5721891fc", size = 219839, upload-time = "2026-09-29T00:55:32.891Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/ec/77/900294b3c9a81415323d81b3f3f271a7f5d7ed9d01e824fc38ffa49470b6/librt-0.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:96f576f2711f8519152ec76d0e599243555c1f07679fa73606ca8c8c868c0be6", size = 148668, upload-time = "2026-09-29T00:44:20.282Z" }, { url = "https://files.pythonhosted.org/packages/55/3b/c301e8cc47758e4518b93e926a0111080155cc79fa03651d202ac2025065/librt-0.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2bec3818c7da7c96ceae0ef5915a3d16c52dd08f3ea913bf1fe8568c447c7978", size = 153562, upload-time = "2026-09-29T00:44:21.672Z" }, { url = "https://files.pythonhosted.org/packages/62/b1/4d5b98114a58bf17e3832cd33400e40f2582f68c2fb7ce25b4468cb1afd3/librt-0.16.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:64c79520414a3fdfc6aabd7593e6169afa14d5f8d9908d4b498db068868b08dd", size = 494337, upload-time = "2026-09-29T00:44:23.096Z" }, { url = "https://files.pythonhosted.org/packages/88/36/14223c9b0dc38982eb4f399732c8cb27b19c7e027ae0faef5ca51d08d19f/librt-0.16.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:f81b5b19ce748ef68d4746656b7929762eb2fe99269b266e4be07e2ee4de7144", size = 485440, upload-time = "2026-09-29T00:44:24.555Z" }, { url = "https://files.pythonhosted.org/packages/ec/9e/d7155e6800d0c33e297e529b217649f7361d706491ebf9d2fc0fc627309e/librt-0.16.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c71d1b76210a36729fedfc5115069b50a3d8619054745f8758fe5d6f19e86671", size = 498363, upload-time = "2026-09-29T00:44:26.03Z" }, { url = "https://files.pythonhosted.org/packages/d3/ce/d5f1fb9f913ac0979d6fc5db9fb9c0bf28cc3470988528957922f15ed40c/librt-0.16.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:473eebc7866bb0a0c8849a292b5e7157c1aba5d14d0f0f610c52158d6d964262", size = 515453, upload-time = "2026-09-29T00:44:27.566Z" }, { url = "https://files.pythonhosted.org/packages/b4/d4/ca0fca1a27c26080d1a25b2b31f271e532078a5719878c3daca0c3d4c539/librt-0.16.0-cp310-cp310-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4eb1313a19847089ee81e88742abedf285c60538816640b99742d8534b81d26a", size = 509537, upload-time = "2026-09-29T00:44:29.14Z" }, { url = "https://files.pythonhosted.org/packages/ee/c0/26807bf2221a53a2c66f2e23a5c4d57f1c0eaa4afed7cb81d841cf3d1903/librt-0.16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ebefd60b42e2a82b32d136bb5f7c94eadfcd29f772b547df6f3291d1ed855a1c", size = 532541, upload-time = "2026-09-29T00:44:30.745Z" }, { url = "https://files.pythonhosted.org/packages/0e/50/c329d509907e1bc061abeec3796f94d255d43ba25d28c3854d2138ed5ab2/librt-0.16.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:6c5da27e8056439f927ea896735da60e616c477a8293feaa3233d4e7781a6726", size = 537059, upload-time = "2026-09-29T00:44:32.102Z" }, { url = "https://files.pythonhosted.org/packages/84/d6/4571b9c9e65d98e5503734166dce2fd3e216f526dc3c59a3773faa8a60e3/librt-0.16.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:67e718c7a43f8db325abbbf1404e2d535f12f8f7a1a82259568385cc5274b82a", size = 536614, upload-time = "2026-09-29T00:44:33.653Z" }, { url = "https://files.pythonhosted.org/packages/c8/d3/a2ed8a292e4ab7889792a9c3f4ad5d1caf6557afce7f6b452e77f8ed20b7/librt-0.16.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:314e703f0c19320dc8094e7a784b9cf29e1b67402515abf580069a6363c0b4f1", size = 517199, upload-time = "2026-09-29T00:44:35.115Z" }, { url = "https://files.pythonhosted.org/packages/9e/24/276e5218b4b7adb6258a42b7403cb1b7cef25616238d0c2152288a9d2f53/librt-0.16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:943c6bbecbdf7fa575a4f2952fcfd848c88ef95507c3fca411e89d4ac3ff8143", size = 558746, upload-time = "2026-09-29T00:44:36.656Z" }, { url = "https://files.pythonhosted.org/packages/7c/5c/9156df81a1726e1efc9567379def2b8777a6d56f464d2f1b760bf951b8af/librt-0.16.0-cp310-cp310-win32.whl", hash = "sha256:7cc365f006891afb006b52d5ee5ee74c09306ffa20e2f8705a32a4450af2f3ba", size = 104424, upload-time = "2026-09-29T00:44:38.123Z" }, { url = "https://files.pythonhosted.org/packages/0b/62/4fd172cb3f49ab2cf5ef17de519a93cfb935202c1270ba9d44c6a64178c3/librt-0.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:0314058469f4d2fd279ce7c62ac274ac82c3918ef7db62ef0697c4c359370155", size = 124267, upload-time = "2026-09-29T00:44:39.455Z" }, { url = "https://files.pythonhosted.org/packages/ba/0e/b04fd2d76b6a78a02286938251b2c119fb36ddece92c76cb4886ef7d44b8/librt-0.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:fe4372c52d4849096c6cc1cda2817d293ec51440c890474ed59ef38d46556f18", size = 148058, upload-time = "2026-09-29T00:44:40.903Z" }, { url = "https://files.pythonhosted.org/packages/a3/fc/e1ed24aadb32d38603c0c07f579d739eb4d90e64e90d525b024e4a999b4d/librt-0.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c72c5295a84bd249526da9bdca38f2e176d15c31c13bb0063c5053f4ca023421", size = 153073, upload-time = "2026-09-29T00:44:42.165Z" }, { url = "https://files.pythonhosted.org/packages/be/38/133ab655409420e0c34a9a9836a7f4e5ae75fba758d7fe177099130d58ba/librt-0.16.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be56ba9c884143495b517f23fe794ae367d58cd89ea0fdd6d437e3c024a87f9f", size = 493052, upload-time = "2026-09-29T00:44:44.043Z" }, { url = "https://files.pythonhosted.org/packages/94/42/aaa663bc9421f5bf7bbbe9d3316d7219749698ec7688ac3b519770a89c04/librt-0.16.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:ef46c1a29ffb8c72e882e22618ec618778eacd0578fb22c6e7cf9c11d15f357b", size = 485506, upload-time = "2026-09-29T00:44:45.479Z" }, { url = "https://files.pythonhosted.org/packages/7b/59/83a6eb5087ba8b45b083859e2085256963e06d4c2531944cdd962670bfb5/librt-0.16.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d3c94211ee0c4f8d649ec06b7c115c0ec4eadb873a0e3154ca15cef3f814b071", size = 498708, upload-time = "2026-09-29T00:44:46.916Z" }, { url = "https://files.pythonhosted.org/packages/a0/e4/15a8d62b2bc12935080ec7277e2e0b9b233047781eb784a51d3e25af669a/librt-0.16.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:94aed6a8308818b91677957d1bd03188869cd7aeb23c5dba7912a6c0402f7602", size = 515981, upload-time = "2026-09-29T00:44:48.316Z" }, { url = "https://files.pythonhosted.org/packages/46/4f/287cc282ac5dd815204c0779e79401bb0a568c3a1335fb319bf0838fb566/librt-0.16.0-cp311-cp311-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:349c0bcb87ebd07481b6ff781e25cdc699723dbe2212e57dabb27f7a13b7b87d", size = 508670, upload-time = "2026-09-29T00:44:49.726Z" }, { url = "https://files.pythonhosted.org/packages/bf/5b/ab7292add898ade0d2b5b75d32a923aae315861671aa5c39f5491309f7ae/librt-0.16.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:001bfd59a7d45b17e3e75f2a8c6405280b35e7b84471792778e718c4f368950e", size = 530393, upload-time = "2026-09-29T00:44:51.356Z" }, { url = "https://files.pythonhosted.org/packages/7a/9e/8e6bcf027d4bcbc16a4e864b3d158a1d3e5f55ffa53af0238020cad89271/librt-0.16.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:28e038895b998d7a0c7798922ce8a1dc157675df5cf1c9ef0aca809ed804b7a1", size = 534302, upload-time = "2026-09-29T00:44:52.893Z" }, { url = "https://files.pythonhosted.org/packages/96/a4/8c5ab4f3b3a8e905ff8305d76976a2e666f52fe049edd398aed2402beb36/librt-0.16.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:0dbe4096a7ecc00fa835d24510ad8545a4efef738dac96e0e63516783ccde905", size = 536150, upload-time = "2026-09-29T00:44:54.421Z" }, { url = "https://files.pythonhosted.org/packages/ea/5e/7c4bc267e3cd4b8bd288de9f62d61fff203829c9cc649ea2aa12e9218cf0/librt-0.16.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:5cd5b092441053364af968ea12084692cb9d4a22f3ce9524e377880bf028761e", size = 514316, upload-time = "2026-09-29T00:44:55.998Z" }, { url = "https://files.pythonhosted.org/packages/e0/75/c8bc6b50f43c73819334233f5a3259c81216742cef56d2140c3dd377c3f0/librt-0.16.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3ddeb3c9dedb461bb457c6c7d9aa7fbf35329da313d1a7543d00c8d0f3473c96", size = 557731, upload-time = "2026-09-29T00:44:57.581Z" }, { url = "https://files.pythonhosted.org/packages/93/fb/e241f91bc8de6c7ac1c6a20ea6dd381bc52312b44d711ffcd97140db1e57/librt-0.16.0-cp311-cp311-win32.whl", hash = "sha256:e05108e0849966f53a8d2d3112a7af881d0efaa479bc735bba91108f9f2350a7", size = 104922, upload-time = "2026-09-29T00:44:59.078Z" }, { url = "https://files.pythonhosted.org/packages/d1/38/c892383d2bb1a6a80b2ec8ede84970a265a792c56614a06282bf3008517c/librt-0.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:5f49cff01bd608ef7d97104cb035c75455e79c2d70bf4a506cf773338ac1860d", size = 125093, upload-time = "2026-09-29T00:49:01.621Z" }, { url = "https://files.pythonhosted.org/packages/e4/56/8bbde1ed0b21480163617648f638fdaec9374cf5e9c846ebcee34ec02a42/librt-0.16.0-cp311-cp311-win_arm64.whl", hash = "sha256:1d28ae980ae2218f9c5b95d191e947296f918c9bf0b400d467a9430275bbe678", size = 115910, upload-time = "2026-09-29T00:52:40.131Z" }, { url = "https://files.pythonhosted.org/packages/ad/76/bbdaeb87b7c47b5c7343e90222b9bfa4e4a8a83f647e02933ad0129225b1/librt-0.16.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fe52bf4641069e7978a14253b036cb9002def1926317e710f2e249f8a8c47742", size = 151028, upload-time = "2026-09-29T00:52:41.508Z" }, { url = "https://files.pythonhosted.org/packages/fd/0c/ab8ed3dab0085931aec4a792c7eaac8dc6c5ff4691fda3a5360d9d8a9cd2/librt-0.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5bcc2c4726ced915b00de0c9856a4eeabfb3fddb93e10e0b8f735b7709358b6d", size = 155283, upload-time = "2026-09-29T00:52:42.873Z" }, { url = "https://files.pythonhosted.org/packages/eb/36/494e79d460c80c1f030661e8287c9eca5e1ad652dc2b2180b6cd42abce0a/librt-0.16.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff7baa55f8e7c69851419e50a666015d02a74198716fd45c0125a2112e0a389f", size = 503185, upload-time = "2026-09-29T00:52:44.638Z" }, { url = "https://files.pythonhosted.org/packages/9b/34/a8464038dd9db6e4381fa2b6eb73dc9a50888d77102c4c139304ac35cddc/librt-0.16.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:b95d5d92ab83d39e760a52091bb1baba664f3a2351e39b1e16801e5747c2f0e9", size = 496738, upload-time = "2026-09-29T00:52:46.441Z" }, { url = "https://files.pythonhosted.org/packages/6a/53/e0e5e334ef0c6ed27039d323819368b9ef6712be87d55ee2bf9799398afd/librt-0.16.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b6d085d70bce51d43c5c7c36d63490770180d8779e71c49305c87b4213918de7", size = 513818, upload-time = "2026-09-29T00:52:48.068Z" }, { url = "https://files.pythonhosted.org/packages/ad/f7/7ce72cbf19d0addd05090b339152fd0548a02562c2866a603e6e3b3da2df/librt-0.16.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:36e53948e99bbe3ffea257124cfcae1cfb01831555c9a9c903c9f9a72db7fd07", size = 531952, upload-time = "2026-09-29T00:52:49.816Z" }, { url = "https://files.pythonhosted.org/packages/83/22/0b1bcb6a8e723c8b4fd60dfc8ae8ec6461c54073fbc8685efeb8d900d407/librt-0.16.0-cp312-cp312-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:54d11f726aae9df5a6ffbbf0a03a52449bbac84a53ef03669cb41cdfd4ae41bf", size = 524465, upload-time = "2026-09-29T00:52:51.354Z" }, { url = "https://files.pythonhosted.org/packages/64/2e/e9c23b8b9df1813da1be205deca9606beb7ddd033972246cd426d05374a0/librt-0.16.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4323193ac0cd025f85af531df8ba91bf24d1973b401697347a6282e8fd3fcf5e", size = 543191, upload-time = "2026-09-29T00:52:53.284Z" }, { url = "https://files.pythonhosted.org/packages/bc/e5/6a8b21b342c03ed7e230fa3afbfd2edc58e6e87ef1f0d11fa2b9a748c252/librt-0.16.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e42f8e098b9c5396fefa05fb1cc7e33b0e08fc51da106b5de4a45fd22aac6743", size = 546979, upload-time = "2026-09-29T00:52:54.932Z" }, { url = "https://files.pythonhosted.org/packages/84/9e/b5129023eced1be01e01c22757f53be551d463b1bb7264f787927404c1d6/librt-0.16.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:39ec1d5a14e37baf1450a6cabf03fe552340808bf1ad9d71824ab90117716459", size = 555317, upload-time = "2026-09-29T00:52:56.869Z" }, { url = "https://files.pythonhosted.org/packages/71/89/28bba5938c725fe91f06bf93f7fa6c6b150229df53a87b454b0d5c2a796e/librt-0.16.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d1aabe3925cbb4a08d15b7b20ba4011b53019da0c4173a25155139b7b1baed65", size = 535846, upload-time = "2026-09-29T00:52:58.475Z" }, { url = "https://files.pythonhosted.org/packages/22/92/63773026614f888c5d4e370e395ce42ca604b89f70b3acdfedbf94851b80/librt-0.16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:300c3ffdc459f4a779a8411ecb188e3ac0b1ff3a3a7b099642555dedae06c69b", size = 573700, upload-time = "2026-09-29T00:53:00.127Z" }, { url = "https://files.pythonhosted.org/packages/66/8f/347d4677eefb57cd9f8e01d95a1dcee9a91b4e44e664173c32ff6f3752e5/librt-0.16.0-cp312-cp312-win32.whl", hash = "sha256:c17194318e4c0c0348b36f36c2ec7534436fe0a4c15582403162a4f08c80797a", size = 106158, upload-time = "2026-09-29T00:53:02.031Z" }, { url = "https://files.pythonhosted.org/packages/f0/2c/5193dc81127cd5ddfad031391b046bf32dda219b38463ab872407ca30646/librt-0.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:25a58a19ea8d83b68209f04912df765e9260635ef77646542ed4b4abe6bc7940", size = 126176, upload-time = "2026-09-29T00:53:03.445Z" }, { url = "https://files.pythonhosted.org/packages/ff/3d/9668a400c8dd81d162eba38b33fa49fa6205f1a64493570a13fbb815c3ee/librt-0.16.0-cp312-cp312-win_arm64.whl", hash = "sha256:f7be7cf555bc30ec12622e9447299cc4a9b8ff307548b634794353db0c2065dc", size = 116572, upload-time = "2026-09-29T00:53:04.815Z" }, { url = "https://files.pythonhosted.org/packages/46/cd/ae5e0e9dba45d1399aa04a5395bcc0bead40d9fa06dc903634a7b4d7473d/librt-0.16.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c5e6144e68b577f157519f2ba88ca20e3ed61c29b00e5cdfa76cd2d45acf059a", size = 151036, upload-time = "2026-09-29T00:53:06.284Z" }, { url = "https://files.pythonhosted.org/packages/41/5a/48a16e323c5f9447a94cce7b59babf60fa04e62c3365ecf060c77ed8b320/librt-0.16.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:33f41443a1f4e1f099331b3d8120e409fbff84b9760bc1cc9ea496f37ddaa5cc", size = 155211, upload-time = "2026-09-29T00:53:07.72Z" }, { url = "https://files.pythonhosted.org/packages/3f/29/0f59299eb4251a409b2e690ad4b7d9f8a676db829d7817ec961f32b44f7e/librt-0.16.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7e510b7770bee609617a3374a96548eb114cae048023e3f049ee449e7ff2db32", size = 502587, upload-time = "2026-09-29T00:53:09.191Z" }, { url = "https://files.pythonhosted.org/packages/de/ba/d6fb4ef8d1537c396079d72289f16be7cd35a366e5065c51253fea2760b6/librt-0.16.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:efc49c462d4516b8a58b00b490078fa64689fd1fe66970cc190131d7afb8027e", size = 496146, upload-time = "2026-09-29T00:53:11.016Z" }, { url = "https://files.pythonhosted.org/packages/52/fc/8c50dd4d7cc97c0ee8f252c8a3104980f234391cf1519b554e8b9de08b60/librt-0.16.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:92caf82ebef5e12d21c72242b70d1e92536f1711cf2a727a4c276de4b4469087", size = 513336, upload-time = "2026-09-29T00:53:12.655Z" }, { url = "https://files.pythonhosted.org/packages/a9/59/16c409c56f708eda2db9a0553662845d45e3871c77d70a240dae3f3bdc56/librt-0.16.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:17bac7f7a16b328fff77e440287693eb017abde913595b5827ebccbc21ecd8a6", size = 531689, upload-time = "2026-09-29T00:53:14.39Z" }, { url = "https://files.pythonhosted.org/packages/88/82/d34772a6c29d1446dcca6e64d74062efd508523ab351aa16625a4689d5cc/librt-0.16.0-cp313-cp313-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5b976054553670829985ed767feb78fb6bcede0175327c4844dd5c281c1be659", size = 524537, upload-time = "2026-09-29T00:53:16.064Z" }, { url = "https://files.pythonhosted.org/packages/77/8f/24c5631313746131ccee53bc91fdc8374f9cf25e0082a1fee9c93bb98acc/librt-0.16.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0058f9d68721094105917254c72ac0569117bb7b13b9769cf45d26d89f9d21cd", size = 543231, upload-time = "2026-09-29T00:53:17.939Z" }, { url = "https://files.pythonhosted.org/packages/f2/cb/5f8e0d41dbd8b499c2265e939c31acc9ba59845565bf99539ad1c06aebcf/librt-0.16.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:30b7beaf3f4487b7d8adef1f158b49067cb4d5a19fa7a3bf31a4e7a820e435c5", size = 546499, upload-time = "2026-09-29T00:53:19.666Z" }, { url = "https://files.pythonhosted.org/packages/be/61/063052de441d1385f59cea4223f184bf9e5d125de1ae3239b490aa1e486e/librt-0.16.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:468df902df016a06eb0e40b0747dc8d14e47d7a38b18b63b1fb167d85cb94d63", size = 555261, upload-time = "2026-09-29T00:53:21.292Z" }, { url = "https://files.pythonhosted.org/packages/14/11/a2ada0529372268d6401afa9d457a095b68cd7753532b6f7f33049a19b43/librt-0.16.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:aea7b1f2b125dad5de85f049136651bff256c883c65e6b9209b2da0a1ac3cdef", size = 536029, upload-time = "2026-09-29T00:53:23.07Z" }, { url = "https://files.pythonhosted.org/packages/23/9d/5bb6d38853382986dca702fc7e06c8256d30f5fa0676d882773b744610dc/librt-0.16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a8afb6557920860b7a3a596eb804cf37e09e7cf8a803db2478c202acc72d8c2e", size = 573748, upload-time = "2026-09-29T00:53:24.696Z" }, { url = "https://files.pythonhosted.org/packages/99/f6/0025cde35ff7f607684dc775a2b2d732cce2561cec050a6ee1fb2e1fc6fe/librt-0.16.0-cp313-cp313-pyemscripten_2025_0_wasm32.whl", hash = "sha256:77c7a2b4fe2c1369e0d5aa1cade26740a7b14be32fbc9a5535d617d20065c39d", size = 79861, upload-time = "2026-09-29T00:53:26.089Z" }, { url = "https://files.pythonhosted.org/packages/93/93/303b8592909bd583f83f02818ffbea3f7647ca1e22b1cd5465d04b8145fe/librt-0.16.0-cp313-cp313-win32.whl", hash = "sha256:02d89c813d5ff74b17df72d3a34819d132cd168e56b81bf755b809bd9e46b8c4", size = 106236, upload-time = "2026-09-29T00:53:27.43Z" }, { url = "https://files.pythonhosted.org/packages/cf/24/80bbb463c60ed18e29cb26aba386ddb76609580e4e7160710e550587018c/librt-0.16.0-cp313-cp313-win_amd64.whl", hash = "sha256:14ed6ebe3e4f85f326d7920011ad30ff49ed9334e62cf88caef9ba973d9e3a92", size = 126180, upload-time = "2026-09-29T00:53:28.7Z" }, { url = "https://files.pythonhosted.org/packages/43/80/b1a6fbdd7da825cdd55c71aa81eb6cfa82c513c360774152eacb50b4a771/librt-0.16.0-cp313-cp313-win_arm64.whl", hash = "sha256:83d4041a3d9b2fd053a8a4e1f22878b3e5833e2712956382d5c048d791454e91", size = 116557, upload-time = "2026-09-29T00:53:30.012Z" }, { url = "https://files.pythonhosted.org/packages/1e/93/9e0cf7da129a93c3dc7f45bc3cd4a660f2aaa995aa8a6f95c2583ef41239/librt-0.16.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:931a0bb0fcac88f263e269e46eb30ba8e21402cd3c62ca40cb97034c0693fab1", size = 149844, upload-time = "2026-09-29T00:53:31.391Z" }, { url = "https://files.pythonhosted.org/packages/8f/26/8a90d2a8f2b2e471bb486b7aec117b8ae622715ed6c39853aec48ea20073/librt-0.16.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1bc17e54e5305f8d40b7ca203671ff5a9e59c1d0f8ea0f625dcca53a3984de11", size = 154111, upload-time = "2026-09-29T00:53:32.718Z" }, { url = "https://files.pythonhosted.org/packages/35/ce/67abb46258da4d3e42ff5b141db6f38c59357bef84c7979f183b22f924f1/librt-0.16.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:877698bf6bca5721d8be345f2fe09778e40ecadea8b58c73075f2b1a53666bf2", size = 494234, upload-time = "2026-09-29T00:53:34.466Z" }, { url = "https://files.pythonhosted.org/packages/12/f9/ea7162414a16f8f1bbd3b493ad6d22b926c5471916e078350bdbca8c4e5f/librt-0.16.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:5981c011b306781ce561e18e14230a14524a3d8109b97553666c942c18f31a96", size = 491173, upload-time = "2026-09-29T00:53:36.124Z" }, { url = "https://files.pythonhosted.org/packages/b1/09/9b3e869060dd33f9989b80ba4fea306f6db8cecefcdfe6d7346ef0603f65/librt-0.16.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:afced3dfc17cd805ecf7a3d77996a71cf5f2c75aa66eb0c21a9930f4fc992f86", size = 505547, upload-time = "2026-09-29T00:53:37.686Z" }, { url = "https://files.pythonhosted.org/packages/50/07/79007d2165f649ea93e08c0962d1d62c70af9cde77965255095bf9d96f9a/librt-0.16.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ca8052401c55d7511dda6760719fda7618067e83535d7d0010096d216c34b667", size = 523057, upload-time = "2026-09-29T00:53:39.301Z" }, { url = "https://files.pythonhosted.org/packages/61/0c/8fbaff66d0ba376d8864653f5acce1569bae27e89648671f26f7eca67ab8/librt-0.16.0-cp314-cp314-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1e511762a074005bb0aa569166779834e75e438370226930d0ce1866d4b6a33b", size = 515158, upload-time = "2026-09-29T00:53:41.012Z" }, { url = "https://files.pythonhosted.org/packages/df/2e/23ff0dece76f07a4124413a57682efa0bbeb5765ac0122bc0955513f82ca/librt-0.16.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f1e8591bd8a5a628cd7f07954c6a1592359a878bf032957a8e9057a41d644311", size = 534183, upload-time = "2026-09-29T00:53:42.451Z" }, { url = "https://files.pythonhosted.org/packages/26/c4/e11dea21d9a29486eba78887380374189d472734fa32cc50cb37ca44d3d0/librt-0.16.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:a4aaefb4ba6c07e1aeebb2795c8958148f1d6f9af3b555b53d23d766edb6d67a", size = 540663, upload-time = "2026-09-29T00:53:44.272Z" }, { url = "https://files.pythonhosted.org/packages/44/75/e873ae158a8b7f5359be33e7fd6c1fbe02d9a78a3e89a77de6b0e837f476/librt-0.16.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:d92db7a0f6aee44f1baee94750457e8d2d1c6ccea41842de6268d34e8dc7eddd", size = 545908, upload-time = "2026-09-29T00:53:45.812Z" }, { url = "https://files.pythonhosted.org/packages/ba/36/8939d3f6a93e11bd9592e6fe28d2b44f1c2dc4bed6e22e72359a91e18ffb/librt-0.16.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:378dfaffb38e59c24a87cde5713cd865d51ff7383fa12947f3907f306ea1ca55", size = 523302, upload-time = "2026-09-29T00:53:47.596Z" }, { url = "https://files.pythonhosted.org/packages/71/14/35309f44a077f0f42ade0e2e7cd88c0cea760c661af205c01ea90d3c0e1f/librt-0.16.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:3e0c39bdc85370422e8b637be76eb1fd07d30967551b03e62267dd156f553152", size = 565911, upload-time = "2026-09-29T00:53:49.278Z" }, { url = "https://files.pythonhosted.org/packages/78/0c/df6255b94967f3159ebc46f08d8e783c12da6ee269ddb74b2efed63c640c/librt-0.16.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:1b384b90ab79a7bc30b566895809a636e0666f21f3cf12b54823d025b7e83839", size = 79119, upload-time = "2026-09-29T00:53:50.938Z" }, { url = "https://files.pythonhosted.org/packages/6b/44/d30d5a5461378c9d33f36736c6791c3b4c4ba4b1ffe0da7350aedcb2c9a0/librt-0.16.0-cp314-cp314-win32.whl", hash = "sha256:52327da75a94012e7f932f913d20d3876bed3c102be00e6c3e8600ff7bdd58a7", size = 100140, upload-time = "2026-09-29T00:53:52.205Z" }, { url = "https://files.pythonhosted.org/packages/c2/98/769712f356a1e897df3581bb0c3100375d054a000de26099360ea65b5111/librt-0.16.0-cp314-cp314-win_amd64.whl", hash = "sha256:3f0b8114c44b2ac06ff5dacd08e07e8e807ff4f46083f2a1602685122559be41", size = 120464, upload-time = "2026-09-29T00:53:53.495Z" }, { url = "https://files.pythonhosted.org/packages/bf/d3/ae2abccc8bdc8b063c1613a77686e17b74e9d3d60cfe6f12c63fa2821b9f/librt-0.16.0-cp314-cp314-win_arm64.whl", hash = "sha256:8caf96a4ef8fb27d0ac0d1ad8337d26a240acd4a02fe4345d0a8f264753e8f99", size = 110889, upload-time = "2026-09-29T00:53:54.817Z" }, { url = "https://files.pythonhosted.org/packages/e4/26/0737d4be058dd6376eade7dd8b380d4b869b6394cee929393a5a431c45bb/librt-0.16.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:953107e2f68d0f3512c48f898b0dbf0ce5cc52bba0f318d847c985dc555ee4cc", size = 159838, upload-time = "2026-09-29T00:53:56.22Z" }, { url = "https://files.pythonhosted.org/packages/01/96/9bc96531d7c620e9949af904470f02e3fa8f35129ab8e8f281c51eaa3788/librt-0.16.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ad37d5b9abd49c9a655dcda7ea52a8a752884062ef1ee71ae17c2f2a0f81fe6a", size = 162018, upload-time = "2026-09-29T00:53:57.532Z" }, { url = "https://files.pythonhosted.org/packages/0e/fa/b0289dcb186eb3f97221ba00da5f4bd3ba7fa5e99752d48aa8d336615334/librt-0.16.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2c4aa329c17bd1aaea4f6e89335d8ccd494b3a5830b6654462273e50e11023f0", size = 703983, upload-time = "2026-09-29T00:53:59.024Z" }, { url = "https://files.pythonhosted.org/packages/d9/ab/05ebbbde7530fc5eeb58fbd1581522a9f64f132fa703c4c595eed6e14760/librt-0.16.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:0ead24d2562a49473dddd9efef8581f020007eb0054389c3ee3ffad38b1ca4c9", size = 683847, upload-time = "2026-09-29T00:54:00.671Z" }, { url = "https://files.pythonhosted.org/packages/a3/75/f52aeecd4dbadbddf80725ba7de126d8bd5d0eb66247eae17a81ed90dd4d/librt-0.16.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:02118f56a9c36ddd07dfd9b919d9ecc117ba20a90987d56aa4c429fa34509188", size = 698045, upload-time = "2026-09-29T00:54:02.247Z" }, { url = "https://files.pythonhosted.org/packages/e6/55/fa277a835cd6eb42380591ceb85f48c5b4d2b2d7e2cb9869e1e17d24d237/librt-0.16.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4e29522c62e28595ff7e324c6834ade51127707f0e255b18d1c1cf03d39c1048", size = 724640, upload-time = "2026-09-29T00:54:04.078Z" }, { url = "https://files.pythonhosted.org/packages/25/e4/2cf64354f3fde8ebd591b3b48f96510bee24ac5f7d1e567adbbe210abdbd/librt-0.16.0-cp314-cp314t-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3ff4b2367926b69c6215635902cccb04048e73094e9862900d27cb2c6bbff143", size = 731748, upload-time = "2026-09-29T00:54:05.741Z" }, { url = "https://files.pythonhosted.org/packages/f8/c9/c180af3e94e01aa529fa93d7733fec2abc47f222345400cf21d5481d5f8a/librt-0.16.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c6f1b27bf1632a7e016af9f145f82be95e1edd7721a646505c21059257cb5a04", size = 754960, upload-time = "2026-09-29T00:54:07.38Z" }, { url = "https://files.pythonhosted.org/packages/95/d6/01073aa78c58f356b10d9c57b3fe9abb143df338142bcd316df417b89db0/librt-0.16.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:5696d7f52e7b37217cb3a8f92c744fe835942602fdd4c1a8bc4741d3bfdce15e", size = 747000, upload-time = "2026-09-29T00:54:09.06Z" }, { url = "https://files.pythonhosted.org/packages/f7/d8/1de3783908658d697a8cfc00582f61299ffba7796d7260c112e4700b1109/librt-0.16.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:6072e92dd876ff6ceeb6cf371e35e51f479349837391341f479b08df4564242b", size = 749569, upload-time = "2026-09-29T00:54:10.702Z" }, { url = "https://files.pythonhosted.org/packages/b7/32/e817f66c96d6caa8bb8435ff93c4c220624d59efc506be59ab98fcd01d0c/librt-0.16.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:39ca4f2f2fe05de8e63493da592d84311adabe5bef52b193851981da9816b302", size = 729483, upload-time = "2026-09-29T00:54:12.25Z" }, { url = "https://files.pythonhosted.org/packages/7c/c9/23992ccd2b9d22798fdd0f61353183a47414e651da782ad83eb680f50833/librt-0.16.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f9807485a908f00355820f18e91e045ffdcdc5adb68aaec40a1e2b88c5f7bba1", size = 776584, upload-time = "2026-09-29T00:54:13.837Z" }, { url = "https://files.pythonhosted.org/packages/67/3b/e8af957f08e6e2e8e566b099e43d2748418aa565df6ee1d9d3331209fdfe/librt-0.16.0-cp314-cp314t-win32.whl", hash = "sha256:94be5cb7bca4df6201f4183e9e4fa2086c655283d20b38cd84500a69057575a7", size = 104402, upload-time = "2026-09-29T00:54:15.568Z" }, { url = "https://files.pythonhosted.org/packages/ca/1c/946e6443d7cd32347a086043395e421e52fd603c9163d2ec970ceab8eed6/librt-0.16.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d46ca272b251d033dd4527b0dec5f261a28a52bd5fa0f99c117b0a1f8588cc2d", size = 126227, upload-time = "2026-09-29T00:54:17.165Z" }, { url = "https://files.pythonhosted.org/packages/c2/a3/bc4f9959d3c62bcbf9e5fd3470a8bbd8bf33224ed4c25d7fba173201b8ac/librt-0.16.0-cp314-cp314t-win_arm64.whl", hash = "sha256:b9d6d4b14e92d876f8026b54c20c445f36425214c1081dc76f74e40db386b82b", size = 116493, upload-time = "2026-09-29T00:54:18.567Z" }, { url = "https://files.pythonhosted.org/packages/b6/4b/10fdb42dfab4c1533e1570e686b18e86ff4328b406361b39fb3016667638/librt-0.16.0-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:6fe436af2eaf630474f491af5d032cbe45f93fcff5c3b9fe4ab194a7255b20ff", size = 149829, upload-time = "2026-09-29T00:54:19.933Z" }, { url = "https://files.pythonhosted.org/packages/8e/30/a90ca13f1d3d91af1680000a4038536907018fbd51764767287a05d28b8b/librt-0.16.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:8ff5d26c529336be9bd7ae04483235d77778ee7d6444a95353102b542601ce81", size = 154522, upload-time = "2026-09-29T00:54:21.306Z" }, { url = "https://files.pythonhosted.org/packages/5c/dd/bcf364eacfa070bb1fc88d503111ae7177914197ba1fa717c748926e7930/librt-0.16.0-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:909d8e3c1faee44cb762b1c519ff8613dcc5ceae5c99987a00917b5a31fd1d6a", size = 497593, upload-time = "2026-09-29T00:54:22.798Z" }, { url = "https://files.pythonhosted.org/packages/18/c1/2c4e81e347bdabfe8346bfc6dc37ae5e154d61c88e30848ec0606025a5e0/librt-0.16.0-cp315-cp315-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:6d4a64283ee61824b5790de882bc68e2d9d7a5143537cb7a966f7354f71646d4", size = 480459, upload-time = "2026-09-29T00:54:24.364Z" }, { url = "https://files.pythonhosted.org/packages/ab/d7/fef2a3cb8400701be496f6e459876f650b3451f407e30cb243de571ae615/librt-0.16.0-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5810ba811297fdf37a1531a57667cb8ace0842013ca8606bf9eb7c24cf4be154", size = 507814, upload-time = "2026-09-29T00:54:25.997Z" }, { url = "https://files.pythonhosted.org/packages/e1/6f/53762927a32e9dc9eb1d1c1f3528da281290c86d96929a8af652f671266e/librt-0.16.0-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e56aaf8c167548dc8e5d6f3bd0f48dcdd299a23c73be3f744aab79d99e9c7f5d", size = 525114, upload-time = "2026-09-29T00:54:27.747Z" }, { url = "https://files.pythonhosted.org/packages/6c/67/0b9d031f303c4e8c691a9a8ef9d272f13b530c11cc563b819df621b6a348/librt-0.16.0-cp315-cp315-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8f36c58e33b304b525c6c9c5076399c6ebf1109e17b9051a05a407b091b9215b", size = 520465, upload-time = "2026-09-29T00:54:29.331Z" }, { url = "https://files.pythonhosted.org/packages/ae/d5/2056a3a85864e882eb17a203a10ddb26fa748bc9718ec67e79059ab46cae/librt-0.16.0-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:242e00b3d4fa37c3d3c1ca5f5c9adb7d909ddb1eac9c41f2787320d00caa0af2", size = 537257, upload-time = "2026-09-29T00:54:30.915Z" }, { url = "https://files.pythonhosted.org/packages/54/57/e0d79790c163cbc0909e209a6f62e30bb713b647f905a176cdc64848fd4d/librt-0.16.0-cp315-cp315-musllinux_1_2_i686.whl", hash = "sha256:0253721561787b8df8443eb347b7a6461015354e5bdd37ee38a41fef220d2bb0", size = 527442, upload-time = "2026-09-29T00:54:32.478Z" }, { url = "https://files.pythonhosted.org/packages/aa/50/1c0c95aba7af51f4752ea34fbf2eb79b36e7cae3a72536248e8c735de735/librt-0.16.0-cp315-cp315-musllinux_1_2_ppc64le.whl", hash = "sha256:3e483a8d69ede8067db70c0e83007423b6925de6fd53afed01d66160f2e9398c", size = 548139, upload-time = "2026-09-29T00:54:34.183Z" }, { url = "https://files.pythonhosted.org/packages/98/91/a8a43dd5138d4f55f88846b8f0c85454a4fad69952cebfcff9948f831290/librt-0.16.0-cp315-cp315-musllinux_1_2_riscv64.whl", hash = "sha256:69ba927445cfaaffb4081003ef5224c55a5c2ab67ef956f416ef744916e44121", size = 529708, upload-time = "2026-09-29T00:54:35.761Z" }, { url = "https://files.pythonhosted.org/packages/2d/41/d5226881ab2b7c20d9d587b37bdd4a0ec8775a96d00ca87ac9f385587db4/librt-0.16.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:d6a365f2ab45a984d0e00eee0dd17f599ceab8cadab6ea07b6111c8132fc0e42", size = 567781, upload-time = "2026-09-29T00:54:37.409Z" }, { url = "https://files.pythonhosted.org/packages/bb/bf/2345ba57a626e8c78c4ddcc724636a8df5a593fe46c1ee76bbf477e32b0d/librt-0.16.0-cp315-cp315-pyemscripten_2026_5_wasm32.whl", hash = "sha256:f01f3805f2dae4781c0c34b440e31740d082950bdaf89a6f601ad589a28af57a", size = 79177, upload-time = "2026-09-29T00:54:38.792Z" }, { url = "https://files.pythonhosted.org/packages/1e/40/99e77936cc9207f629b077bf7cbc5e2f0827cddd7c29792f04ef881bd2c3/librt-0.16.0-cp315-cp315-win32.whl", hash = "sha256:b0e3e721c75d2e79a76d4422c79d7ba705fe1bbafec907037fe7a657a480a0e3", size = 100127, upload-time = "2026-09-29T00:54:40.251Z" }, { url = "https://files.pythonhosted.org/packages/56/1e/801fe26bc622061b9dfd010e166d94142cb774b733217e6d98d1c0cf2638/librt-0.16.0-cp315-cp315-win_amd64.whl", hash = "sha256:bc02954b1295de798bbdb0b4e2d8a28c2117de8b5c73dcbeb27dc32572dfb971", size = 120480, upload-time = "2026-09-29T00:54:41.722Z" }, { url = "https://files.pythonhosted.org/packages/bb/a9/d533983055bd36e112627384c2c038845d1df882540b8bcefb566475640b/librt-0.16.0-cp315-cp315-win_arm64.whl", hash = "sha256:c5db585d43449a5f54303d4b2774e45e1babd975cfe1630a3d708c0b80c3e560", size = 110915, upload-time = "2026-09-29T00:54:43.052Z" }, { url = "https://files.pythonhosted.org/packages/55/fe/d62238fa9c653b0e0613290349467cb65711b5800e8e474f45e942a0ad95/librt-0.16.0-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:f06c689cb14afd9b612727553a5ec5a40febf113ca41c4413a2b0b334285884b", size = 159714, upload-time = "2026-09-29T00:54:44.497Z" }, { url = "https://files.pythonhosted.org/packages/f3/ac/f31efe7818700be72ba4f9af8a80fa67c39808c8d26dacc55dc1f6f35172/librt-0.16.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:13b4e8aba90b0b1c82474e9844aa9ffe7ad3faa484350e1da64cb8188d903134", size = 162086, upload-time = "2026-09-29T00:54:45.968Z" }, { url = "https://files.pythonhosted.org/packages/d9/16/4d7487bf86a9d7e8e18f37ba5538789233ea693637379b75701bd35ec9de/librt-0.16.0-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5a269c46ae327d8e6f8c1f85f7516cb52c0fa48127565a1105a4f4a05ff2a0b4", size = 712727, upload-time = "2026-09-29T00:54:47.486Z" }, { url = "https://files.pythonhosted.org/packages/77/74/50cd550ccc1a517b9ed62347625c01ddf8c4afad66490312677c011458f6/librt-0.16.0-cp315-cp315t-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:a33e0dae1f8592146a4764d54ce842b278732d21a84e17c3bbe6b1bc158a2248", size = 681106, upload-time = "2026-09-29T00:54:49.126Z" }, { url = "https://files.pythonhosted.org/packages/df/5d/7293f712975ee6fdd2251411fd9ef1c62bc99c7b83ecbe62dbc999b1fab7/librt-0.16.0-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:47ada6ea32636492c61aa8ad27ae3b9404bfe7a97e3ba946d1984236cc741da0", size = 705921, upload-time = "2026-09-29T00:54:50.905Z" }, { url = "https://files.pythonhosted.org/packages/67/f7/8aab946f11d59d1bece9ffc65d994b200c789a8ca5a95c17e17e609f912a/librt-0.16.0-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43bd6e642d8a248c114327f98dd25ac5a7cb5aa168ef02f0559b91874df16b8", size = 731786, upload-time = "2026-09-29T00:54:52.584Z" }, { url = "https://files.pythonhosted.org/packages/43/76/1c42ab31e7cb8384ebf6d3af607213c495222474f4940443ae7639ab7685/librt-0.16.0-cp315-cp315t-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c3d1bb7841a816ace6449bb26d3f9560dbfa20e71c568d23f0f62bf1e68f50b1", size = 744964, upload-time = "2026-09-29T00:54:54.217Z" }, { url = "https://files.pythonhosted.org/packages/6f/2e/4b19982d933d2dfced671e840b219e4c1cd3f507df6e6dabb51bbd4e3850/librt-0.16.0-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:3931f7a3db322e7f44e02a280e3949326ce9579ad388ee8d691dc7c76da9fb70", size = 765305, upload-time = "2026-09-29T00:54:55.815Z" }, { url = "https://files.pythonhosted.org/packages/b8/1b/e872583de2dcb3ac7746e7a2321aeeb168274f3952a87dc66e05ddb29faf/librt-0.16.0-cp315-cp315t-musllinux_1_2_i686.whl", hash = "sha256:f4462528b6000afe8f16907b5c7c2553abf1df005ba5140e6eb394541c3624c3", size = 744959, upload-time = "2026-09-29T00:54:57.532Z" }, { url = "https://files.pythonhosted.org/packages/10/de/a18c6bcfb297af2674233e90b3c3661c3a0af0f1434a0c966d2ef708a835/librt-0.16.0-cp315-cp315t-musllinux_1_2_ppc64le.whl", hash = "sha256:80039ba9b6a7d5f1a0175a4cca6bbefead87bd854c80abad1cb30afe47a830db", size = 758138, upload-time = "2026-09-29T00:54:59.484Z" }, { url = "https://files.pythonhosted.org/packages/22/1c/0df1d732539c297bb1a093e1fe3204d2faf76a9022cf4e1d1c2fce059790/librt-0.16.0-cp315-cp315t-musllinux_1_2_riscv64.whl", hash = "sha256:7a1d272724b581bb6bc769dfdafed6da2ecc9886ba2450311de55a4ac2e1e9cd", size = 744268, upload-time = "2026-09-29T00:55:01.179Z" }, { url = "https://files.pythonhosted.org/packages/a2/f7/ccaf31331f20c91a5bd9bd48ffc3f743f9c81bb5720cc7b2a720ca204f0a/librt-0.16.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:fbe4fb8c5445f7496d7f7f6bb0807875d09d47e6771ffa175fb2df2895fb86ba", size = 785783, upload-time = "2026-09-29T00:55:02.938Z" }, { url = "https://files.pythonhosted.org/packages/c1/ea/7421d9e6db894cd6cd788b604b3394a163ded6b942052b6f96c23ccf08e1/librt-0.16.0-cp315-cp315t-win32.whl", hash = "sha256:375bfe6b572a8f6cfc398709356046173bf27e64c4c5edaf5f7062f051fb4bf9", size = 104355, upload-time = "2026-09-29T00:55:04.533Z" }, { url = "https://files.pythonhosted.org/packages/85/6d/7c31a506eb847bc58aeb2402d58e17605e821f68ab5df5e66fe274a6df41/librt-0.16.0-cp315-cp315t-win_amd64.whl", hash = "sha256:bd3150023d3dc2bc70f3784e59ffa1140d56ddba3d8125b3d6f9f85221279bfc", size = 126134, upload-time = "2026-09-29T00:55:06.017Z" }, { url = "https://files.pythonhosted.org/packages/36/69/7a5d10ac409c4da0355e054a14371871da9b5557fcc42772cd00181c6cce/librt-0.16.0-cp315-cp315t-win_arm64.whl", hash = "sha256:8ceafb70f2a4f0826f11031942e59c0728fd98da112dc346d4352bde1e486866", size = 116391, upload-time = "2026-09-29T00:55:07.484Z" }, ] [[package]] name = "markupsafe" version = "3.0.4" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/38/9b/e422a865e1d5d57d0e509b4e0bf1c1a70a7f6382c29a5aa428df994c8bc8/markupsafe-3.0.4.tar.gz", hash = "sha256:2e9ad7dd851bf45fab9f75cbff4cb493fee9979e8d8c7c9c3ee119022518edd6", size = 153777, upload-time = "2026-10-02T23:07:22.29Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/41/aa/9a65962e364bf19745f6bec7bde398fb1f5ca53ad2e734258e6198cc32ba/markupsafe-3.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dd8ea6ebee7aedbf7c749fa80521d9ccf1ba473e0d1e14805caafbaad281c889", size = 11521, upload-time = "2026-10-02T23:04:20.141Z" }, { url = "https://files.pythonhosted.org/packages/14/36/927999a34b7d1def6957de89153d327fedc4030061940b5a468584e6c5a8/markupsafe-3.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dff05cb7016dff1e9fd68f4122c127b65dfc59de5306cfb7ad92f956f230bee2", size = 12066, upload-time = "2026-10-02T23:04:21.275Z" }, { url = "https://files.pythonhosted.org/packages/17/54/69e7b0db9bd687bfd83451eed5666384d67cfed3be062bfc59a06a15474e/markupsafe-3.0.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cf63c214fe879a65e69a386f915e36104fc84254ab141240f8854602d8e0be2a", size = 22081, upload-time = "2026-10-02T23:04:22.221Z" }, { url = "https://files.pythonhosted.org/packages/bd/14/f6f5c97903f7d2db76bbfaced31509a47d360a103b3aaf4849f6536591ec/markupsafe-3.0.4-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2a6ef68ae94aed8721934072b27a3b654ea2100b97e4ab864cf1489c90926fbc", size = 26079, upload-time = "2026-10-02T23:04:23.346Z" }, { url = "https://files.pythonhosted.org/packages/d0/04/c3cc9b75f94f8b54d7e503c44cebd4b4a115ec1d6f1b996b999807daba99/markupsafe-3.0.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:fd9f8797427910198f95bced71ddfed61130d7e349213bfb8466c9c99e2c46a8", size = 22611, upload-time = "2026-10-02T23:04:24.401Z" }, { url = "https://files.pythonhosted.org/packages/00/26/c4708ed3b0f08e8e6d7cbce3314ac130cb5352d1f62951b6fef7878f2b1e/markupsafe-3.0.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d1aca03ede943eb80ab3d63bb082c84b7aab85ea83bd0fd0c200260945fb49d9", size = 20712, upload-time = "2026-10-02T23:04:25.386Z" }, { url = "https://files.pythonhosted.org/packages/d9/b9/f3894d6aae3d7a52c9363317f4baf2fcadc052163d6dbc871266e32639ed/markupsafe-3.0.4-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0764a13d34cae40db7bbf3a09b7e9b491bf4603e20b263a7a9d6b8e324975d0a", size = 20742, upload-time = "2026-10-02T23:04:26.403Z" }, { url = "https://files.pythonhosted.org/packages/59/7c/8e248ddbfe286ab6bddb462bdac0851cbb1510d2cbbb815a415fcb0511af/markupsafe-3.0.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9388003072b95f2f1e3fd908604194d653ba21330d811961a78b7da1a77e9e36", size = 21560, upload-time = "2026-10-02T23:04:27.522Z" }, { url = "https://files.pythonhosted.org/packages/df/26/2353fef7d4bcf2b18e16bad81979fcecff2915156ca6882447917205b8e2/markupsafe-3.0.4-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:8698d70a8081ee8c090dbb394768b5789a1da8b131b5499f89d071dd3cfaf6be", size = 20973, upload-time = "2026-10-02T23:04:28.573Z" }, { url = "https://files.pythonhosted.org/packages/67/6f/a9561d98d9a6ee3494b0b970a1c766e58bab128cc84841d56ec009456dbd/markupsafe-3.0.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:bf053da3c97a4bc5ecfbb218cdd2983febd91c617be8367d139882aa11e490aa", size = 22036, upload-time = "2026-10-02T23:04:29.568Z" }, { url = "https://files.pythonhosted.org/packages/55/83/6217df9192eca95af3ff0cad955c9854a93fa43b288cf7411ae24713eb52/markupsafe-3.0.4-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:9438a2648b2195980cb2dd8e53ed7b8df91319e2d0b70ae61a9e1d1bc8d3bec9", size = 20314, upload-time = "2026-10-02T23:04:30.881Z" }, { url = "https://files.pythonhosted.org/packages/35/7c/9cd8081dae70e17fdab3558121fa618d459c7950c8abd8fc10fc024486d7/markupsafe-3.0.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:88d59b473bfb03259722600839af9bbd7fa13a2eb514beefeedb95997882f69a", size = 20780, upload-time = "2026-10-02T23:04:31.975Z" }, { url = "https://files.pythonhosted.org/packages/44/37/c5f2f45f4d8f0c24e4af7b9dc711640c888044cbf5f7e2ba2c0bb74cbb55/markupsafe-3.0.4-cp310-cp310-win32.whl", hash = "sha256:4a540e2d3192792fc84eced57bef37851ccb2b41f73291bb17408eea77bcd278", size = 14096, upload-time = "2026-10-02T23:04:33.129Z" }, { url = "https://files.pythonhosted.org/packages/50/50/394a1c61c9b9972cb4f76875c332af7109bd39bdad09d3a0ec5327a339dc/markupsafe-3.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:5c22873ad1f0532ba40fa1727f3c0fc1bbbaab6d373d4cbe3f0dc74b2e2521c7", size = 14329, upload-time = "2026-10-02T23:04:34.168Z" }, { url = "https://files.pythonhosted.org/packages/d1/9a/86d03d2f32ba41a57baa124a7bcb76d0a6d39b1622e9bd4d550074e8b61a/markupsafe-3.0.4-cp310-cp310-win_arm64.whl", hash = "sha256:3d23795802fc8bd72534836d64489bbf0f67c088959091bdb22e10735a5107bf", size = 14196, upload-time = "2026-10-02T23:04:35.201Z" }, { url = "https://files.pythonhosted.org/packages/32/55/18dbb4778b30ada5ce071608503cc3edc9e14e13d868c17a6d178fc30f7a/markupsafe-3.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9e25feb9e330b63edb0278a0acdf85e50d0cb0fbf49c3084abbe4e24ae195346", size = 11520, upload-time = "2026-10-02T23:04:36.299Z" }, { url = "https://files.pythonhosted.org/packages/6c/14/0b05f79b4733e264a18d08fe08fa1df7347630ff32a6cb82180d9dccec55/markupsafe-3.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7d3391b2188d18737cb2fa147028b1096236eaa7e156446c650a489fa2cadc91", size = 12063, upload-time = "2026-10-02T23:04:37.291Z" }, { url = "https://files.pythonhosted.org/packages/ca/3a/63ba10b6c1463216b3e4df669a9f0e5a3b0c3071557d2e8229e3968c79fb/markupsafe-3.0.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:849dd2bb0e5e4ab2b71c7191726a4a8d5aa8a610daa584728cbee0b710ddc4ef", size = 24321, upload-time = "2026-10-02T23:04:38.262Z" }, { url = "https://files.pythonhosted.org/packages/1a/2e/5f015261b76ad633d187ef6f388b413aedd64a8773c4df59e530a0be5525/markupsafe-3.0.4-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:befb4158af32106b9a93db8d6d1d1cbbd418c0d5aca0cabb7b1780abf0c89169", size = 28845, upload-time = "2026-10-02T23:04:39.295Z" }, { url = "https://files.pythonhosted.org/packages/33/cf/26e594b26be40c2f1fec63ccf8a8b99d0335a5b2cbe84835c7d82a994375/markupsafe-3.0.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:71f88e749ea29f67f21f3b36433c1dc54c7729ed2a6d9e2da2e0d9e0d7b224eb", size = 24701, upload-time = "2026-10-02T23:04:40.348Z" }, { url = "https://files.pythonhosted.org/packages/81/a5/a513b76c139a3915b43404324e55c0b7979ae4f0d39eb6f075b0282e90a8/markupsafe-3.0.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6da83a088f8ef93b2d483a8232a4dbf4d69d3d8496b568a03c56becac43e1808", size = 22961, upload-time = "2026-10-02T23:04:41.372Z" }, { url = "https://files.pythonhosted.org/packages/46/cf/4c66192c100b4542bcbe392ae06696b670f66927be3ac38a213234778ff9/markupsafe-3.0.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8f0fac8b13d14bb06c68195f849371924ae53dd7b1c00fed24650f704383b692", size = 21920, upload-time = "2026-10-02T23:04:42.429Z" }, { url = "https://files.pythonhosted.org/packages/cb/17/ac3662678bfbad649893117ada2ba44dc30bf56884e84f13154a792b10f1/markupsafe-3.0.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4a7cdc2a420ca01058182da4253329764d4bfa055564d1eced90e6ba1e8b1d3d", size = 23726, upload-time = "2026-10-02T23:04:43.531Z" }, { url = "https://files.pythonhosted.org/packages/f7/af/fe47cee339180a69ebca3c57fb3483d0f5cbd1e8337d1871fb1d9c1aebee/markupsafe-3.0.4-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:83b3944fea42a8400edf92fd1770fb8d0d4f7de651353bd2d8525a92dba69a21", size = 22539, upload-time = "2026-10-02T23:04:44.618Z" }, { url = "https://files.pythonhosted.org/packages/12/32/d55440ba140442800e02d799c9cb5ab597bf6ebdb1177b5ea39a11f797bd/markupsafe-3.0.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:8138eb83940ec7299024d92d4dee45f601b9e6c5ffde9d25f4e35e326203c707", size = 23963, upload-time = "2026-10-02T23:04:45.656Z" }, { url = "https://files.pythonhosted.org/packages/50/9d/9c86042cb364c2ad4c971e6d1247929effd25f714cd7ee11b05e6316445b/markupsafe-3.0.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:811d02d5122171c1941357efd8f9bf4ffe907b7f0a1a4e729a880e4be3f46e3e", size = 21506, upload-time = "2026-10-02T23:04:46.671Z" }, { url = "https://files.pythonhosted.org/packages/75/ef/5b824f03ba40c3b3652b6272d083d2fc4fcdd440de519a3a39ba2c3e7262/markupsafe-3.0.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:50b5bedc9ed8a94fc8857a42ef4f84a81ea88f8d4f05dc8705fb23ee6d8dcca7", size = 22955, upload-time = "2026-10-02T23:04:47.698Z" }, { url = "https://files.pythonhosted.org/packages/1e/e8/44cfcb5ea40e5e43cec7793ef90704ed0c475280839076c4345757eb8e59/markupsafe-3.0.4-cp311-cp311-win32.whl", hash = "sha256:2e5a7cd7fdd14fcb1ae5d7d8bf23d24fbd1daefd1fbca2580132e1ea75f098b5", size = 14094, upload-time = "2026-10-02T23:04:48.788Z" }, { url = "https://files.pythonhosted.org/packages/91/89/f2b509f7bf79352e40117824c1070dbeafd4df67031d3fa98165a3134228/markupsafe-3.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:fdb4ca07ab75ffadab4a8b135ad59cdbb3156b99310f3d565370da74a15d6bd3", size = 14328, upload-time = "2026-10-02T23:04:49.801Z" }, { url = "https://files.pythonhosted.org/packages/2b/5a/ccf22672a0f64dc682306e288f0dabcb06c7a201f3bb6e6cbf86d9e8ad03/markupsafe-3.0.4-cp311-cp311-win_arm64.whl", hash = "sha256:569d65055d367e3dcdf30c3f41119467b73d9ee9faf332bdf40402644f5ac08e", size = 14188, upload-time = "2026-10-02T23:04:50.847Z" }, { url = "https://files.pythonhosted.org/packages/81/09/4c59d56b8461ae8eb0d8ba34bb25b7e618547044679d58a82ef9b2479fc1/markupsafe-3.0.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:61631e08084be9e21a8967ec3139c7616ed7c5e9368e05c86d1b39562c8a57b6", size = 11658, upload-time = "2026-10-02T23:04:51.876Z" }, { url = "https://files.pythonhosted.org/packages/a2/f0/d6613774d86fbf6d145751d43c59875e47a6f9f17daee0aef173bd36d90e/markupsafe-3.0.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0930db9bdc62d22944e10b066448bb65dc9abe9112880c7cab8da54db4284d5f", size = 12050, upload-time = "2026-10-02T23:04:52.931Z" }, { url = "https://files.pythonhosted.org/packages/0d/f2/8f18e0b806eb13c1f8d07d917a720831ead54253a6dec011fbc78098a6f8/markupsafe-3.0.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6a45c3d514f2436064db00d7fc8778d888f0236ebfed649b53d13a59e69ad51b", size = 24363, upload-time = "2026-10-02T23:04:53.895Z" }, { url = "https://files.pythonhosted.org/packages/60/ce/fa07dbe8a5675558fa36dea033e19995bc783de2dec5f540ccb9030b06aa/markupsafe-3.0.4-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:1e1451fab512d1bcc3dc26988ec1edb0b82c2db909132872cd9356070a6b63df", size = 28525, upload-time = "2026-10-02T23:04:54.905Z" }, { url = "https://files.pythonhosted.org/packages/85/40/be87c01f3868ec217f8a2015089d71c22c8c5a75324822e5ed1cdd87210d/markupsafe-3.0.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bd3ce56ae2cbae3ba82b683bc425cd7e48d2ed8b10f3e818186b6f5646d9271c", size = 24733, upload-time = "2026-10-02T23:04:56.229Z" }, { url = "https://files.pythonhosted.org/packages/4f/a7/aeedb5140afa41fc74c225e9184ab96723a6e873b6ee1c9fede7283456d8/markupsafe-3.0.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e124f974786f831d6043728e38296969d3579db8896fe004682f5758e613581", size = 22985, upload-time = "2026-10-02T23:04:57.521Z" }, { url = "https://files.pythonhosted.org/packages/c3/fc/e91352bb08c6a59da3ef0909d457bf95a5f5908fbf151b30a06d9dbcfbb4/markupsafe-3.0.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c02e8f18bdedba082cef725942ac823b9b60656db07f7e265cb31618dfd00d77", size = 22001, upload-time = "2026-10-02T23:04:58.597Z" }, { url = "https://files.pythonhosted.org/packages/5d/f8/bffee5e7d2a3deb59748a797650a48af7e672025cf641a79344a771ad106/markupsafe-3.0.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9f098115c247e11d138ab83a28fa0323c77015007ea2df73ba5fd714dfefd67c", size = 23793, upload-time = "2026-10-02T23:04:59.686Z" }, { url = "https://files.pythonhosted.org/packages/ed/59/b853d6628ecb4d658e1d637224846d5e9bb4adf4f8df97f3be9f29dce2ec/markupsafe-3.0.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:d5f93ebbeb8032d47e349328ec8662d973d9b05a70b3c35df1f91fe419b84749", size = 22640, upload-time = "2026-10-02T23:05:00.768Z" }, { url = "https://files.pythonhosted.org/packages/09/b2/1506df394f0f075797c418d0301498f49e43be194e3ffcb49e6fe6ccf022/markupsafe-3.0.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:64511c54db4e4987aef4c41923235927428729e8174c5dba488429be70a998ed", size = 24074, upload-time = "2026-10-02T23:05:01.813Z" }, { url = "https://files.pythonhosted.org/packages/c7/81/5ed69cda630ac69ef60d06c09ba5a7f84ff66a2e28cf986fd5614ab3c6e6/markupsafe-3.0.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:e1a622f13970d81f95d0c72f9dc090dce9085fccfa4c9f2174377ee32bd15786", size = 21563, upload-time = "2026-10-02T23:05:03.239Z" }, { url = "https://files.pythonhosted.org/packages/0c/fe/fb1e79be0fea60aa32602ebefc9c35a82bb42b4df157285ab7dfec12341a/markupsafe-3.0.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c9a7f43c0b202b334cc9184af09bb8f21d3a209e038efaf106936fb69e6b026e", size = 23048, upload-time = "2026-10-02T23:05:04.479Z" }, { url = "https://files.pythonhosted.org/packages/c8/52/7632a53360671a9b750cdbabaf9cdd89f18b42248b8e4cb42c0b0296e459/markupsafe-3.0.4-cp312-cp312-win32.whl", hash = "sha256:f0ec3b750b59375eab5b0fb2b9254810c00a3375be6d789899f1055a1d556237", size = 14108, upload-time = "2026-10-02T23:05:05.513Z" }, { url = "https://files.pythonhosted.org/packages/3f/bf/62495e180b7000aaf30000fff849e933f74264638057176cf46852500adc/markupsafe-3.0.4-cp312-cp312-win_amd64.whl", hash = "sha256:11935df9bf455ed0c04eb87bcd720f02b1fe5e02128a9430f23aed6f93336fc7", size = 14303, upload-time = "2026-10-02T23:05:06.538Z" }, { url = "https://files.pythonhosted.org/packages/c5/8e/4c24208776a65878d656996945aacfbfe010d3720d1a98fc0eb8491fc03b/markupsafe-3.0.4-cp312-cp312-win_arm64.whl", hash = "sha256:a4bbd2d87dd233b9fc5812160c3d0ffbe42edc22a26ce0469f58479ede633fe9", size = 14174, upload-time = "2026-10-02T23:05:07.617Z" }, { url = "https://files.pythonhosted.org/packages/6d/18/4bc5ba32499e87bb2b0ef5b3a9bb9c00a131fa961ddf0be548cb550f548b/markupsafe-3.0.4-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:de8b364c423ef0a4bad9069657d617f9a5d2b2062457a89b1fa16ee199c399c1", size = 12786, upload-time = "2026-10-02T23:05:08.709Z" }, { url = "https://files.pythonhosted.org/packages/4e/6f/17f0c099bf25f3e31e63cc19244d9f6af861a9a4ab778c203997903cfdd0/markupsafe-3.0.4-cp313-cp313-android_24_x86_64.whl", hash = "sha256:34bdde374c5932765d7dc685c4a1d191a3207852d67e8e0a9eb6ea85156181f1", size = 12510, upload-time = "2026-10-02T23:05:09.93Z" }, { url = "https://files.pythonhosted.org/packages/11/af/1a141081b905036ee904ec4bd945e1f70b4e1b32d33c4e59e8cf1d58b247/markupsafe-3.0.4-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:6bd9e1788e15bfcf6a9082de42e30387e7b85d211ab21e57a939bb8cfaaf8d96", size = 11583, upload-time = "2026-10-02T23:05:10.884Z" }, { url = "https://files.pythonhosted.org/packages/e7/0a/a89385ae590232622a03e091805cff12f24fabe6c11e0e8bae096cece81c/markupsafe-3.0.4-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:5066b244f576f91afc8ee3ba029a89f99d39c79b1853fe9d39bea9f0afbec148", size = 11801, upload-time = "2026-10-02T23:05:11.913Z" }, { url = "https://files.pythonhosted.org/packages/ed/85/ea548dc013962eb73653124bc595635fbf9e0fa41d1f181a967ccb784dfb/markupsafe-3.0.4-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:7a83aa6e4805df46fed18e989d3d16f86ef60cb50bbc8d9ce3a6be89165fbf6e", size = 11443, upload-time = "2026-10-02T23:05:12.887Z" }, { url = "https://files.pythonhosted.org/packages/cc/72/15f2e5ec9cf2eb00d5cdfe968d94e4156a7bd7303832c3f3b2c403a36839/markupsafe-3.0.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2d1b7d9308288661f56672b1b157d75fc536714d3638487bbea17b6318a78248", size = 11665, upload-time = "2026-10-02T23:05:13.829Z" }, { url = "https://files.pythonhosted.org/packages/ca/e0/4030bea613677e333c8a2c901fd405055f657f9d06acba5b7357984b6ef7/markupsafe-3.0.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:73e77980c7207854f00fc4e71fb1626868d5740ab4012623d55c7a99ad122a72", size = 12061, upload-time = "2026-10-02T23:05:14.807Z" }, { url = "https://files.pythonhosted.org/packages/f3/a5/28b76a7449eb702966b88bef599e2360b411fbb3afeee8fe560939be06ec/markupsafe-3.0.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7018d4af1cd272e847aa5917983ab5e83e4f6579f9dbfecd4a79c0ca80b144c2", size = 24395, upload-time = "2026-10-02T23:05:15.909Z" }, { url = "https://files.pythonhosted.org/packages/07/6c/21232811afc3a063b5e934b1ae2efda52f46154ec382f585149c020e61fe/markupsafe-3.0.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c90d5b3d4e944e065a301d741b3c1d784f6bd1f503aa68b4967e32b2ba313d85", size = 27183, upload-time = "2026-10-02T23:05:16.976Z" }, { url = "https://files.pythonhosted.org/packages/14/38/6ccdfa5b59049cb36fb80cbc80aee9cf1fc9bb77d1335ad435f2070b08cf/markupsafe-3.0.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:18a801868a884f216e784d7d14db2a4077143ce7610440aee2ce8f734e7cfcde", size = 24772, upload-time = "2026-10-02T23:05:18.209Z" }, { url = "https://files.pythonhosted.org/packages/63/e0/cec6865dfe88cb48fedd4b20aed6af5158e41092adcbf3e028bcc6ec2108/markupsafe-3.0.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:434139499bb20b502ed3baa1f169e618f924a97e7a777fea1a49446d80106cf6", size = 23017, upload-time = "2026-10-02T23:05:19.286Z" }, { url = "https://files.pythonhosted.org/packages/ee/76/6ed4940bb7648a9aac457c14f870cfdd5105f139a0fb1f29cd61fafa47d1/markupsafe-3.0.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9e227f3dbe6bde7491cf0a9965d00b88c6b1a4a95d11480ddf88bb96d397c19f", size = 22036, upload-time = "2026-10-02T23:05:20.352Z" }, { url = "https://files.pythonhosted.org/packages/a1/4f/ed476226d4fe46a09090a36025bf319296810028df55eb12f1253b540f3a/markupsafe-3.0.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b8cd1f918b26fd7b1832ece557cc18f2d8747309ff8b3f0ef9d4250c5ad67a39", size = 23786, upload-time = "2026-10-02T23:05:21.576Z" }, { url = "https://files.pythonhosted.org/packages/9a/35/66ff30450e35ef5fba9ebc930c9411747e537fd9447b65e44f5007e2b84d/markupsafe-3.0.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:a5fcffb37e602b0b3c1638a97746b9b96125caa9bcf6fa41d337a9261de231ee", size = 22672, upload-time = "2026-10-02T23:05:22.922Z" }, { url = "https://files.pythonhosted.org/packages/32/0b/72f45ce4b4efcbca4b80cf1b06703eff0be8d37e82abb78f66c85a7ead1e/markupsafe-3.0.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:5989cb26b2e1efc6a42216a9f6b5ee495ce5ace2e5b352a9af489976b32d1ee2", size = 24107, upload-time = "2026-10-02T23:05:24.175Z" }, { url = "https://files.pythonhosted.org/packages/d2/03/71776e5fdcba04614b384cc102e8a4198208579d896fd1394cb7cb9aa900/markupsafe-3.0.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:add96447a86d205ab616665d53b2950ee81083757f56e6ea833c8b2917646b46", size = 21615, upload-time = "2026-10-02T23:05:25.215Z" }, { url = "https://files.pythonhosted.org/packages/ab/5f/801ce02a02e7aee0f784b1ec7843026178f6adeb9c93ac67eb1992a9a84d/markupsafe-3.0.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2628d3a8cb648ecebb3c5d6b0a1052d400e4d8b7ac0fb786be8d285b50040d17", size = 23076, upload-time = "2026-10-02T23:05:26.423Z" }, { url = "https://files.pythonhosted.org/packages/4a/85/c43776625428f3bb4a61e8633940400e3efe6409e3c6f5bff26de5e45618/markupsafe-3.0.4-cp313-cp313-win32.whl", hash = "sha256:672d207103e6b16ca098611b0f9efad6bc00afd47c03d6ef62186495ca677dc0", size = 14118, upload-time = "2026-10-02T23:05:27.716Z" }, { url = "https://files.pythonhosted.org/packages/6f/36/163da64de88a13db79214ef75fa041be7fa13bdb42261cf5b7484de14bfb/markupsafe-3.0.4-cp313-cp313-win_amd64.whl", hash = "sha256:1f1f9477e174582b0a1b583d60b66e1f2cf5d3fe12cee985e4aedf44766600e5", size = 14313, upload-time = "2026-10-02T23:05:28.749Z" }, { url = "https://files.pythonhosted.org/packages/9f/a8/9b662783ffaa1149221432a923cee562f78b9cbbb8baa3df9b3753e63e1e/markupsafe-3.0.4-cp313-cp313-win_arm64.whl", hash = "sha256:06de8ef6331f6e822c28d577dc8bf43fe398800477c49498f38fc38b67ff33fc", size = 14189, upload-time = "2026-10-02T23:05:29.917Z" }, { url = "https://files.pythonhosted.org/packages/5c/c3/a944f3b0df22bd129e96915b9f4e98d2eeca6516687d7618304a966c3c74/markupsafe-3.0.4-cp314-cp314-android_24_arm64_v8a.whl", hash = "sha256:4ed644d75aa94a2baf7ec3a96eaa160ea58c742eb9d27c6506053c5c40fc84ed", size = 12787, upload-time = "2026-10-02T23:05:30.971Z" }, { url = "https://files.pythonhosted.org/packages/d4/d6/a44863f69d88b6c7e27889108f70d47aed259edf89d5df3c5fca1eac87d6/markupsafe-3.0.4-cp314-cp314-android_24_x86_64.whl", hash = "sha256:6d2a9efe686f9de00d0d1ea32a4a5a86d558a2277501bd78d964214eab625e59", size = 12525, upload-time = "2026-10-02T23:05:32.263Z" }, { url = "https://files.pythonhosted.org/packages/17/8f/168ba80e532dd6a93f96f8f706f1ad41d7990b6e1aeedc1cc0d211a33497/markupsafe-3.0.4-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:8781a792a070cf2bd1b86d3aa943894115faaba6e88122a7bf32d62072742453", size = 11589, upload-time = "2026-10-02T23:05:33.251Z" }, { url = "https://files.pythonhosted.org/packages/32/b3/aa2c95a574d3af39403a469b295886eb9b6d448da568cbebb5a2cbfdc2e5/markupsafe-3.0.4-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:971a3bbb75d97ae4e2e8f7d4834236f86f85f0c85e04ab2e191db1123b04f80b", size = 11801, upload-time = "2026-10-02T23:05:34.315Z" }, { url = "https://files.pythonhosted.org/packages/60/d0/34b810107d83840e768bf485de795893ebbae35b26ab061b487adfa0a692/markupsafe-3.0.4-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:8909c2f1c6dd65e054ac4b573a91c8384d1492281e55d82d159d653f7a13adf6", size = 11447, upload-time = "2026-10-02T23:05:35.302Z" }, { url = "https://files.pythonhosted.org/packages/6c/ab/2f8488f0f817a39fca068d2b17daf446bf5cdb3eae28c3720af534d873b4/markupsafe-3.0.4-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:4cf3468d5ec187ffffcaca8e61929a37448f215dafc1386a12c750a72fe53634", size = 11722, upload-time = "2026-10-02T23:05:36.363Z" }, { url = "https://files.pythonhosted.org/packages/ad/40/e2d117b048d47282ade906fbfd92814cbee5647afc13fda88a3406039372/markupsafe-3.0.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:52704c5d36eb6dda8866493decd61111fff86244c9b1ad225ca01b9e91e5970f", size = 12061, upload-time = "2026-10-02T23:05:37.397Z" }, { url = "https://files.pythonhosted.org/packages/9a/a8/73a81135e85ba66217f5af7facb03bbb386807e1a729ab64532e4c802652/markupsafe-3.0.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1caa2fa5a6184fb233153b35f654e6687bd555476f6170f29d8ee9be1a8b0af9", size = 24434, upload-time = "2026-10-02T23:05:38.407Z" }, { url = "https://files.pythonhosted.org/packages/ac/ca/fa9216dd01efee2dfdacafe7df32b4d0170fbac694b0c258a193d6e53999/markupsafe-3.0.4-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:387d8cd30e69b3f0a72877b9ae717033396404e19095b17fe89753a981fda44f", size = 27183, upload-time = "2026-10-02T23:05:39.581Z" }, { url = "https://files.pythonhosted.org/packages/fa/4e/a469509e538d37af51103b17b073126973f2b1cbf197ff32c7ddf025cfe5/markupsafe-3.0.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:051417f74bcaaefa316276e0ff723f541616ca51043d070da00249d9bddd3e3c", size = 24813, upload-time = "2026-10-02T23:05:40.671Z" }, { url = "https://files.pythonhosted.org/packages/8f/db/d7282caf7ab03af44d5d6fdbaa019b35c7d7f1c90588b839c07cba640d6a/markupsafe-3.0.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8e9f292fcda89b324f2f5c91d13f1424a153e40fc2756f38ee23b15835ff300", size = 23049, upload-time = "2026-10-02T23:05:41.864Z" }, { url = "https://files.pythonhosted.org/packages/30/f3/b6a425206e6964efda6acee544d0eb01d1501784d0b8e2dcc74986f33b17/markupsafe-3.0.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:df1ae86ff54725a01fa1a0510b914ca53a161b7050be74f6204e24aded5971d0", size = 22088, upload-time = "2026-10-02T23:05:43.014Z" }, { url = "https://files.pythonhosted.org/packages/ea/8a/84d3582fc1f0d5bd466cdf2eebf175e172158a6e70701aacec1de1b35430/markupsafe-3.0.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8965520ac587c94a4ac48b729be3d8b8de00af39699b17585dfb599babe77977", size = 23846, upload-time = "2026-10-02T23:05:44.098Z" }, { url = "https://files.pythonhosted.org/packages/1c/65/db101cce51b7ba4864ac491a9859d297dd1adf0e55b103fee9db9c47c527/markupsafe-3.0.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:340cbb1957ba99929cbf19a75626d36ba1ae21d1730b287d1cf7f824a20c4fc7", size = 22674, upload-time = "2026-10-02T23:05:45.23Z" }, { url = "https://files.pythonhosted.org/packages/e0/49/ddee9813d71db0c7a5c9d97c832125e6758a0c844777f1cf076569bb0e22/markupsafe-3.0.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:3a93d9616ddecfb393727a0041a562cf0b15a244e20f2bd25efc7949be4c4f17", size = 24104, upload-time = "2026-10-02T23:05:46.398Z" }, { url = "https://files.pythonhosted.org/packages/aa/0e/7d8518d726726870a2399d69fd30d0fa36c5e57a2132c336b58d7c491073/markupsafe-3.0.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:d2e56fd3b00222722abfb3f5f0759ddbae4b90811b5ad4343c64030ad1bde70c", size = 21637, upload-time = "2026-10-02T23:05:47.48Z" }, { url = "https://files.pythonhosted.org/packages/b4/b0/b505e8a361ba557dbf3b3aa7331ea39b00d2022a26e925ff8463b9714bb3/markupsafe-3.0.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:0d9c47709875fdb321452056622e930c52afbc07a7d780762fbb8b4d91ce6fa4", size = 23081, upload-time = "2026-10-02T23:05:48.611Z" }, { url = "https://files.pythonhosted.org/packages/1c/ea/9cc3cea873f980c75cbdb6f4277ce30ee955de38be0b3d02f14c108e0698/markupsafe-3.0.4-cp314-cp314-win32.whl", hash = "sha256:38fc55594dab834470b6733dead2ee9e3f657fb0608c769dcafa0ba5ab52f45c", size = 14272, upload-time = "2026-10-02T23:05:49.707Z" }, { url = "https://files.pythonhosted.org/packages/80/f0/5792ff768a410f93ee3f84fc19345295ffc352d2c936b424cb37e514714c/markupsafe-3.0.4-cp314-cp314-win_amd64.whl", hash = "sha256:c1bc67752d5f21013cfe430df4062441714eab79f65a6a05e01505957e9c35fe", size = 14501, upload-time = "2026-10-02T23:05:50.788Z" }, { url = "https://files.pythonhosted.org/packages/5f/cf/3d074a8edffcc6899355232ff2543ae8d929733239596423b7db79698bc9/markupsafe-3.0.4-cp314-cp314-win_arm64.whl", hash = "sha256:7e1636da3d8dfc220b6dd10264db5f2b165e4888c4518594898fbe381049af8a", size = 14364, upload-time = "2026-10-02T23:05:51.857Z" }, { url = "https://files.pythonhosted.org/packages/d9/31/87ce42159aae2163cf3bbbd0c44bc87780510eecab1ea3859099aed95dcb/markupsafe-3.0.4-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:805c8b84534fa10891890f0e4be39f3a99e94615d93e8836bf9fa1fdca2feeb2", size = 11759, upload-time = "2026-10-02T23:05:52.951Z" }, { url = "https://files.pythonhosted.org/packages/5f/53/b047207eeb7752e960aca3eb1df5fb7eefa7dd4c62ac49bb156456c8a702/markupsafe-3.0.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:fa95848c929b6a75f6848d3c9793e59db365ee436776e57db835cdbfa79ba977", size = 12096, upload-time = "2026-10-02T23:05:54.066Z" }, { url = "https://files.pythonhosted.org/packages/ee/51/4326c88a13c7b755657d44b4bb986f8c3d9843ecba7e22d98661d87f9a57/markupsafe-3.0.4-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e916035e3e9930cbdfdd10abf48861340221857f45509565898e012263f7b289", size = 25699, upload-time = "2026-10-02T23:05:55.15Z" }, { url = "https://files.pythonhosted.org/packages/f2/bb/990581b7474bfcf2cf34bed6ba5ea23bd87adb9d671213d68e88620e7a6b/markupsafe-3.0.4-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b4d12837e0203bbace818ff4a7461afdcd78bcd782351cea148139180d7bcffe", size = 27804, upload-time = "2026-10-02T23:05:56.29Z" }, { url = "https://files.pythonhosted.org/packages/6b/89/89491878c28e8291f5aa2fffe2c2d57230d10ae366d55dd810b840513d78/markupsafe-3.0.4-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5086f9975abb1ab531ee6afca1761e4b59a19b446f3f6522ed776963228cfe5a", size = 25912, upload-time = "2026-10-02T23:05:57.416Z" }, { url = "https://files.pythonhosted.org/packages/30/77/680998b54efdea06fc114565cd739b6d059f826a0279219b218dfa750d29/markupsafe-3.0.4-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b4a635a0487774f841cb1fb62e907e7195cc95bc761e053184b8acc3ceb20733", size = 23623, upload-time = "2026-10-02T23:05:58.557Z" }, { url = "https://files.pythonhosted.org/packages/ae/75/2709f5ac5de9467b40b10e2bb8f89cc63dfb74582e09aa734b1124a217de/markupsafe-3.0.4-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb96e6e088d6cf71c1ea977510948320234824cf226e32f6f6e044f7a9c82b34", size = 23301, upload-time = "2026-10-02T23:05:59.94Z" }, { url = "https://files.pythonhosted.org/packages/a0/c8/39eadc6c5b14c9c7679bfb98f4d4c6a97863b5beb91839aca4d2d6e16e55/markupsafe-3.0.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8b5d563170ff8ba3181caa967c99a3c804d1dedb702c7cb93a6a7c32247da978", size = 24950, upload-time = "2026-10-02T23:06:01.289Z" }, { url = "https://files.pythonhosted.org/packages/1a/5e/01037f8a43e8ccb0bffb4fbdc5212db05bf080fdd7286cd392332d58128a/markupsafe-3.0.4-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:396ec4e65cc889f69786b3b89478b471cee5a3bcf468b9d9bb03e1a30fb291fc", size = 23330, upload-time = "2026-10-02T23:06:02.441Z" }, { url = "https://files.pythonhosted.org/packages/d4/f4/23e83ce0596bb0cbe670502d31df8f757bbd01a392aa486fa3b40d1ed399/markupsafe-3.0.4-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:15ba9e28640feef770374b116a6f019c21f52404aeabe516aa7f800587b98cfc", size = 25239, upload-time = "2026-10-02T23:06:03.579Z" }, { url = "https://files.pythonhosted.org/packages/88/5b/3708897368073cc683d524750474f41a77d2986152c380dcc55b20fdf340/markupsafe-3.0.4-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:d920abdfa61279ba1a2ef9484aab07bf03331f8c08a10120fa332353d06e6932", size = 22767, upload-time = "2026-10-02T23:06:04.699Z" }, { url = "https://files.pythonhosted.org/packages/c6/61/ebda1307864b409e6b3115757a3d4a09cca46cfb6cc65191b5de226b424b/markupsafe-3.0.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a9f54054101545a9a9cccefddf54316aa6e4491611fcbef9e91b3b6bebec04f6", size = 23668, upload-time = "2026-10-02T23:06:05.9Z" }, { url = "https://files.pythonhosted.org/packages/09/15/98075cceac3b5ba0dbb8e4762a847be967d2befc349a2cf2d0ac77f62c9d/markupsafe-3.0.4-cp314-cp314t-win32.whl", hash = "sha256:12a606a492de952afcb43b59a14aaaaad120e708d3663dd0fdf2d738d427a691", size = 14301, upload-time = "2026-10-02T23:06:07.109Z" }, { url = "https://files.pythonhosted.org/packages/0b/a3/768b560fcc4156685cb563d922b217810cfa7bc135773367f62f1f9d2078/markupsafe-3.0.4-cp314-cp314t-win_amd64.whl", hash = "sha256:a18f38cafc329bac5e3c2b96c765b4c96d3d103421ed22ab7988c1e3fce27464", size = 14526, upload-time = "2026-10-02T23:06:08.276Z" }, { url = "https://files.pythonhosted.org/packages/93/63/da554b4c97a6b0ea3229ca7fe8cbfb620be81613d517f482e85958550537/markupsafe-3.0.4-cp314-cp314t-win_arm64.whl", hash = "sha256:eba154571c16e032112afac0dc2dfe9e63c2ceb7aedd07bb7eecf2ce26d4dd4c", size = 14421, upload-time = "2026-10-02T23:06:09.402Z" }, { url = "https://files.pythonhosted.org/packages/a9/30/54d11c8ca027114898cab97421fb39e4ffd9ddf47cdbc44df2ec76722da9/markupsafe-3.0.4-cp315-cp315-android_24_arm64_v8a.whl", hash = "sha256:737c9c3981998eba27f11786f84fddcbabc74068b72a4a1f454ea02094b57b65", size = 12791, upload-time = "2026-10-02T23:06:10.485Z" }, { url = "https://files.pythonhosted.org/packages/10/6d/97c913e253a14bd3cd0e15a5c56d13203b823fa7ee32498342896a072dc4/markupsafe-3.0.4-cp315-cp315-android_24_x86_64.whl", hash = "sha256:489505b03f692c3f376394e49194fa7a7f9e8558d6e293a7056a0032b0c38163", size = 12527, upload-time = "2026-10-02T23:06:11.834Z" }, { url = "https://files.pythonhosted.org/packages/26/f9/b86d032042a4d597d9e1997f0e5f63a3eedaf11258e0a05760b0a0a826ea/markupsafe-3.0.4-cp315-cp315-ios_13_0_arm64_iphoneos.whl", hash = "sha256:077293e425f28ec737dbcad442a71752e28f8ae27cde3d68acd1fb212091cd92", size = 11602, upload-time = "2026-10-02T23:06:13.122Z" }, { url = "https://files.pythonhosted.org/packages/f2/dc/73c14c1eedf0ac5fa3292ba43435e6c49d2c2050f33cebde541f8f4807f1/markupsafe-3.0.4-cp315-cp315-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:9348cbb300d224fe3b89793262cb093504d4ae927004468463f745188a193e4a", size = 11817, upload-time = "2026-10-02T23:06:14.227Z" }, { url = "https://files.pythonhosted.org/packages/8f/69/2c2fcaa5fcee22d72c7819c0d536fd181c74a688e6143845419579cd2863/markupsafe-3.0.4-cp315-cp315-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:b807e598953730f82e4eae3bd30f6a122cf6b31c398c6b504c0e04c13c170429", size = 11446, upload-time = "2026-10-02T23:06:15.574Z" }, { url = "https://files.pythonhosted.org/packages/88/54/9e5ec76c62e6e2834d5a93623018c943e8b3bb41d663e3fd4c03303b9b85/markupsafe-3.0.4-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:799c39bdf5e2f1292fedd3009f7b3c9e760f10b2420cb9638d56920840ff6db8", size = 11719, upload-time = "2026-10-02T23:06:16.701Z" }, { url = "https://files.pythonhosted.org/packages/96/24/3ec292b44064c16229e064d770b2625bd8ea941aa61f44905a9fa44942c0/markupsafe-3.0.4-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:ae9dcb8fbe244cb82f8a6458b455b927a03685e383d9bacf1ea5ce180b96dc97", size = 12075, upload-time = "2026-10-02T23:06:17.855Z" }, { url = "https://files.pythonhosted.org/packages/aa/85/b64fdb1f304848518742136983c24e96d967bfb59a0ea160e92736901ab0/markupsafe-3.0.4-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4bced6e2a6dba6a28f7dd3c6ce14df1b2dd495923f16ea484cad03decd463b2b", size = 24656, upload-time = "2026-10-02T23:06:18.963Z" }, { url = "https://files.pythonhosted.org/packages/9c/18/23997d4c65b355da6390d61cd56e0ab3befd6ba8dda25cb40c602bd0fa6b/markupsafe-3.0.4-cp315-cp315-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3882fb412298575bae3b9c46868251f15cc69307359f87bb1b382e53d6e5a2c9", size = 27737, upload-time = "2026-10-02T23:06:20.117Z" }, { url = "https://files.pythonhosted.org/packages/d4/36/35998dead3c6af88c38265a56e58100211f036234ab88eb2283fd4cbce44/markupsafe-3.0.4-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:04e7902ba80ee4bac1d50a549606527a1dcf0476cd81403db41099d3b60ec653", size = 25003, upload-time = "2026-10-02T23:06:21.284Z" }, { url = "https://files.pythonhosted.org/packages/82/96/ef49135ce260db4ca4a12b119ed468449cd248db6b1468e2112b546d7a2e/markupsafe-3.0.4-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:925f929d6b59a8b3f8b8c6ac363cd0af7eecc81efb3071770b3c6717c450a369", size = 23111, upload-time = "2026-10-02T23:06:22.524Z" }, { url = "https://files.pythonhosted.org/packages/50/7d/83126e338bd88c17a220668235368ad719fd4638e426739858cbb8508f77/markupsafe-3.0.4-cp315-cp315-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f68edfc67aabac33708941f26f22a7b8e9f81429bc0cf249fcf7d66b23af8d19", size = 22403, upload-time = "2026-10-02T23:06:23.785Z" }, { url = "https://files.pythonhosted.org/packages/83/dd/daf7e420de23c8206c365204e7b85e1251d8e19d34196a56336f316e5ed2/markupsafe-3.0.4-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:e5c802729725bd07e2bc3ab7b76dc7e0bbfc53129d8f1eb1c002c24cf774717e", size = 24083, upload-time = "2026-10-02T23:06:25.037Z" }, { url = "https://files.pythonhosted.org/packages/19/3c/11eecdc06bc44ad5570350085b572ebf049e8f9a38d1ece6d76640b739cd/markupsafe-3.0.4-cp315-cp315-musllinux_1_2_armv7l.whl", hash = "sha256:55ffd6ce583d97dc71dc92e930324c8c0d25aea7e3ade6ae54ef77cedb096811", size = 22931, upload-time = "2026-10-02T23:06:26.328Z" }, { url = "https://files.pythonhosted.org/packages/0d/9e/ac0fd77f2a726e56ecc3ca0235d095feace1358d1b822406c2a2ef26a4dc/markupsafe-3.0.4-cp315-cp315-musllinux_1_2_ppc64le.whl", hash = "sha256:2cb3dd71fc6be918ad4264346a8ed69485f9b7ed7bf35495d8e22807cd6b8bea", size = 24299, upload-time = "2026-10-02T23:06:27.742Z" }, { url = "https://files.pythonhosted.org/packages/d7/09/c6bd842ad58ff5b3bc76eeed7e9a42a6f11adc5d090ec697b72c9672731e/markupsafe-3.0.4-cp315-cp315-musllinux_1_2_riscv64.whl", hash = "sha256:94f5407f7bc64fa6463906b896f9904beeeb7dd8dc116ee8e9056c8714ff9916", size = 21948, upload-time = "2026-10-02T23:06:29.274Z" }, { url = "https://files.pythonhosted.org/packages/a3/46/82f586711fed61e86faa1ee1bc317d68cd45a10c8bdbe3f7d1fdf9026ad8/markupsafe-3.0.4-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:2dad610540cb2e6272855c178f08ae9a1c7ac258a7fb71660553a5f104b42741", size = 23150, upload-time = "2026-10-02T23:06:30.583Z" }, { url = "https://files.pythonhosted.org/packages/19/2d/2dfdce99318abbfa26925195fbc17db188c46a1ec6457be121b6f9cfeb42/markupsafe-3.0.4-cp315-cp315-win32.whl", hash = "sha256:03470d1a8268e692ecf79ecd565593e59d44219377a7ead61f1f1b94c1f7ff6b", size = 14269, upload-time = "2026-10-02T23:06:31.949Z" }, { url = "https://files.pythonhosted.org/packages/5b/ec/6000fd82e8791e58fcd0456ec20f098957e2b03d5ed02eb73241a577c0ba/markupsafe-3.0.4-cp315-cp315-win_amd64.whl", hash = "sha256:d882a373d8093c2941e01291b7ced96e9cbe4781da9a7751ca7e6c70385e5214", size = 14496, upload-time = "2026-10-02T23:06:33.258Z" }, { url = "https://files.pythonhosted.org/packages/bc/66/e73bd5016421d5d6e2fb6de7dd609f9de020942ac8c626526bd8c6eeaf82/markupsafe-3.0.4-cp315-cp315-win_arm64.whl", hash = "sha256:353bd63081912ab8cfa6a0c7d185934cdf8426f04c618bba6bc4b394f2069b67", size = 14361, upload-time = "2026-10-02T23:06:34.539Z" }, { url = "https://files.pythonhosted.org/packages/90/df/cb8c3dc98d313a951df2f8968f44e4cb5643df6d3cab749a530ce2f7d972/markupsafe-3.0.4-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:c61750fadcd119d0825bcb7d7d675dd264dcc89cc05292aab5be68ebdbb374ad", size = 11760, upload-time = "2026-10-02T23:06:35.807Z" }, { url = "https://files.pythonhosted.org/packages/d6/bb/4af9b3ca0753d654ac75f9531d5bd741bb77ca6e696f36807c475ffc099a/markupsafe-3.0.4-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:1c0df495a977d10460a94941799c72d5b5ab03d3858d949b55b5a66c8f371c99", size = 12108, upload-time = "2026-10-02T23:06:37.089Z" }, { url = "https://files.pythonhosted.org/packages/3f/d4/b56429313aee5fd59b079c3df5615299959e25e7113eb6d8caadbdd7d38a/markupsafe-3.0.4-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:02fa4acbc6a3fc5c693c34d4dd8c1130b7fe99cc915181b0ddd6f72aeb296002", size = 25762, upload-time = "2026-10-02T23:06:38.419Z" }, { url = "https://files.pythonhosted.org/packages/65/f5/34c181e891aa4f7d59c918584672e0c5eb7fffe76c1387d1246008bf4081/markupsafe-3.0.4-cp315-cp315t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:05295589e619b9bed252a86b532b8e27350abc372d18ba89b59375325e91ec1e", size = 28400, upload-time = "2026-10-02T23:06:39.819Z" }, { url = "https://files.pythonhosted.org/packages/ce/b5/ad14694fd0ac9a5ce30bc6498f2999378f418583dd1679cca5a1b512957e/markupsafe-3.0.4-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:be6cb0c799abb0e2ba3e618e6d28ddddf7e485f6c2ce938dfa237daf3905072c", size = 25946, upload-time = "2026-10-02T23:06:41.381Z" }, { url = "https://files.pythonhosted.org/packages/d6/a8/26b606445387d0ceb1eb1f21840094b84e4e3c3c3983d80d10b89823b490/markupsafe-3.0.4-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:26e9867520db70d37f7fb421a7f0d8adb40171011fb84ce869afa1a83370dfa8", size = 23634, upload-time = "2026-10-02T23:06:42.748Z" }, { url = "https://files.pythonhosted.org/packages/39/a2/b8814de672f1f0094d498bf646f2fec9d6356b503d28ef500b71c5095377/markupsafe-3.0.4-cp315-cp315t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f03460ff076f70ab595bb45a0205ccea1971443575b6920c52e755dec2b3fbfe", size = 23488, upload-time = "2026-10-02T23:06:44.176Z" }, { url = "https://files.pythonhosted.org/packages/db/c7/287223376fb73335a3cc5d6eb22c6ab01358cf33945a9c39c06b9dac3f4b/markupsafe-3.0.4-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:436e3ffc6310d3c41878c601db29098102fe5d8a467c49da4a4125254e0980f2", size = 25037, upload-time = "2026-10-02T23:06:45.646Z" }, { url = "https://files.pythonhosted.org/packages/f9/29/4df8355e313426d19e62ba33e0253c009ca12a0894ee77d67fa67255361c/markupsafe-3.0.4-cp315-cp315t-musllinux_1_2_armv7l.whl", hash = "sha256:4e2c4809c14559aa7ef426f27fb35afbb38104c349a903bf8f3600456764bb38", size = 23543, upload-time = "2026-10-02T23:06:47.264Z" }, { url = "https://files.pythonhosted.org/packages/71/e5/8377731e8495668dcc768f645e717df18318c841edaf023a99395f6da9b4/markupsafe-3.0.4-cp315-cp315t-musllinux_1_2_ppc64le.whl", hash = "sha256:da2af0d7aebfc2074080d72efa6ab8317c62481ef1f896f65d9999c1c01f4494", size = 25282, upload-time = "2026-10-02T23:06:48.795Z" }, { url = "https://files.pythonhosted.org/packages/ed/5f/373456e37ceb1478d657d6fe769cbe0a39f0a8dfc1548eeb19c471eefdd9/markupsafe-3.0.4-cp315-cp315t-musllinux_1_2_riscv64.whl", hash = "sha256:aa2c838cc024642cc04c6854232f32b43e5e22833dd11119c1766c7873b8370d", size = 22993, upload-time = "2026-10-02T23:06:50.31Z" }, { url = "https://files.pythonhosted.org/packages/d7/93/2cbd5628435afb6f541bbaced4bce0c2edac4b09a142e6e928b8b0da9858/markupsafe-3.0.4-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:b91cc9d336957239ff200f30097e6fea2dc6d6fb3c81e853eaa09eac904fd894", size = 23712, upload-time = "2026-10-02T23:06:51.759Z" }, { url = "https://files.pythonhosted.org/packages/81/99/157e10966b033b363aeda5263e82596ee232a0b1d082fdbf90aa417ff083/markupsafe-3.0.4-cp315-cp315t-win32.whl", hash = "sha256:e49fb0d1ce92cfa0cb198cc5b1b11cdf9d0638658e2a2db2687e39db7c87fc78", size = 14300, upload-time = "2026-10-02T23:06:53.241Z" }, { url = "https://files.pythonhosted.org/packages/33/05/55884815414c9706a23deca150b72c25a62109e65b0b6ce232077802c719/markupsafe-3.0.4-cp315-cp315t-win_amd64.whl", hash = "sha256:4f6e0852a0283b1b1fd776eeb7b766a5f440b3e2bd31ab51af3b400585f3965c", size = 14522, upload-time = "2026-10-02T23:06:54.729Z" }, { url = "https://files.pythonhosted.org/packages/92/f9/ecbde7149e95b8a0f18e16d5d747f7dc06049d5da2e4f77f6f5e4a1f46a8/markupsafe-3.0.4-cp315-cp315t-win_arm64.whl", hash = "sha256:39dbacefc411633db5b4378b066a9aca70a3d7e2922c9e578d825f844026eeba", size = 14417, upload-time = "2026-10-02T23:06:56.246Z" }, ] [[package]] name = "mistune" source = { editable = "." } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] [package.dev-dependencies] docs = [ { name = "shibuya" }, { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.11.*'" }, { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, { name = "sphinx-copybutton" }, { name = "sphinx-design", version = "0.6.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "sphinx-design", version = "0.7.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, ] lint = [ { name = "mypy" }, { name = "ruff" }, ] test = [ { name = "mypy" }, { name = "pytest" }, { name = "pytest-cov" }, { name = "ruff" }, ] [package.metadata] requires-dist = [{ name = "typing-extensions", marker = "python_full_version < '3.11'" }] [package.metadata.requires-dev] docs = [ { name = "shibuya" }, { name = "sphinx" }, { name = "sphinx-copybutton" }, { name = "sphinx-design" }, ] lint = [ { name = "mypy" }, { name = "ruff" }, ] test = [ { name = "mypy" }, { name = "pytest" }, { name = "pytest-cov" }, { name = "ruff" }, ] [[package]] name = "mypy" version = "2.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "ast-serialize" }, { name = "librt", marker = "platform_python_implementation != 'PyPy'" }, { name = "mypy-extensions" }, { name = "pathspec" }, { name = "tomli", marker = "python_full_version < '3.11'" }, { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/34/4e/64300736cf0a0373a27b94a91b664ee7382e36f77b0621bae6381da3e180/mypy-2.4.0.tar.gz", hash = "sha256:77bdaebd452f43fcfc4cc3ba94352a3ea537cd01e3f2d0879f48673d2ec00d6e", size = 4064425, upload-time = "2026-10-01T20:40:39.229Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/5c/0a/78c9ac93933e2ecd51d807021f78c03ffe98640f33951a8be159f5fd55bc/mypy-2.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ffda5244fd1ad71a1e54405e35f50d09b80c3978efa120f58bd1252ae32c62d2", size = 14408618, upload-time = "2026-10-01T20:39:46.766Z" }, { url = "https://files.pythonhosted.org/packages/aa/4f/5f5f4429fd5a4218ce6268164a66afeed75c7e2ce5522a4d163faaa5fe85/mypy-2.4.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:615b03922d40e186fd1df73156473db0ba525c639bb4fd1cf28e1694879c9b23", size = 14552749, upload-time = "2026-10-01T20:40:08.325Z" }, { url = "https://files.pythonhosted.org/packages/54/78/fa1c319cd51db7a6027b46117460d5a361c6bba0c0f0f0670a2dab8ce2a5/mypy-2.4.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:13fa24f439c0e48a290a3922fa14ccd22f2762bae99d2142931b3e40a9055080", size = 15505846, upload-time = "2026-10-01T20:39:15.475Z" }, { url = "https://files.pythonhosted.org/packages/e2/5a/14c02690776fb04e9fa60b81173cb9ae6315e0745fad3813b303737f2f0c/mypy-2.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3adef556a19eb3b630bf86a79c29d7da3d61e541472d0d897ca01b171c0abf8f", size = 15823059, upload-time = "2026-10-01T20:39:35.429Z" }, { url = "https://files.pythonhosted.org/packages/76/d8/d29afa819f8cb765018d6e2773e390a41ea4592f75abe417135969646857/mypy-2.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:1dc0f64b0a92ae27a49d2175f0bacfa56e15bdc5b420cf92e0c1f79292219cbb", size = 11312927, upload-time = "2026-10-01T20:39:28.509Z" }, { url = "https://files.pythonhosted.org/packages/bc/c8/966dec4d80303855d824e6bf67fe1da812d88adfe4d75e24d8545dab4826/mypy-2.4.0-cp310-cp310-win_arm64.whl", hash = "sha256:4a378fc15fb33e321f04652c166ce73eeb8833a97c3d218132844e938cd93220", size = 10879252, upload-time = "2026-10-01T20:38:41.545Z" }, { url = "https://files.pythonhosted.org/packages/26/67/e53965e67d23d48e78dd603aa7525a8d77e7818c23954cc217ccde5cd5c0/mypy-2.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5d20e6c7c35fcbf2a0ebdd0eaeacfbc243009dfd33ab7822d54e213912e6dbbd", size = 14315745, upload-time = "2026-10-01T20:39:25.03Z" }, { url = "https://files.pythonhosted.org/packages/b1/5d/a588ccd57625822d8484d7aff4e9c70f88d042a91c2ec84324a2bc14b3f3/mypy-2.4.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3011537be6cf1de4511c0255a324362a812b58184bbe61e15f59c8b31033bd74", size = 14465652, upload-time = "2026-10-01T20:38:57.19Z" }, { url = "https://files.pythonhosted.org/packages/05/af/b4978a5566cb829ca563dc08e3ad8d944f116078786ad54ba3dff2bcb64d/mypy-2.4.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a96b07a49b7b1d025ce59c1b3acbcf24bead9a83da4523c4a6bde1bb94e7a0e1", size = 15419180, upload-time = "2026-10-01T20:40:27.808Z" }, { url = "https://files.pythonhosted.org/packages/b2/8c/52c71f31c54d0a749d832cc73b933c6e38c52d9b270d5503e031c73723dc/mypy-2.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7c4f8f8d1d1c0e2832d8ee7113dd08f6df6c7aad9e863fcbed9f25832be0b8c4", size = 15669212, upload-time = "2026-10-01T20:39:20.443Z" }, { url = "https://files.pythonhosted.org/packages/e8/55/ba63121494404fd7d3787ec176ccd02820d6ec125ac4e7c4c0b79f2cc6c7/mypy-2.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:ba05652540bf12828e52abae807b024b09ca144ff4f75e2450a81d69c376425b", size = 11299572, upload-time = "2026-10-01T20:40:03.627Z" }, { url = "https://files.pythonhosted.org/packages/9c/9c/385c81b5c0d3a2917f077c4da660d0493f9521ccfd4b058e33b860f72d02/mypy-2.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:6306086b87cf7f8a29aa618d9fd9bffb56c59247166b9660fdb54d86d7714ecd", size = 10869751, upload-time = "2026-10-01T20:40:25.483Z" }, { url = "https://files.pythonhosted.org/packages/68/ed/e5d7cf4017e74a1c1e1c4058ce8f614fc1e3e7606564f47166e22bfc9f95/mypy-2.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e05ff2925d8b37ad26c80c1b9dc43ae5d455da2df1e23c24c095a6425917c57e", size = 14378593, upload-time = "2026-10-01T20:38:48.222Z" }, { url = "https://files.pythonhosted.org/packages/30/7d/12d994886a922f0f1997becc9c6625198d61eeb5962558a886af7dd38d54/mypy-2.4.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:29243242cf72582b65f9582ad9e56e8cb281566ed3519f4cd70bb8b9f2977e90", size = 14464697, upload-time = "2026-10-01T20:39:11.059Z" }, { url = "https://files.pythonhosted.org/packages/f3/9e/bcc9af755425ad17790bf11d73c2ea7592914cf309ee1340997670f9d57a/mypy-2.4.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:29eb0b9427a6b11b992e452f6cceb8af724f4dceb47e779d0b35e405e996ea5e", size = 15552257, upload-time = "2026-10-01T20:39:56.269Z" }, { url = "https://files.pythonhosted.org/packages/af/0c/3343fc4525d6f00d75ad17a93a9f052d5163641cb8911840d4a12cb59ff2/mypy-2.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e3ebe2f72a2a1156065a9851570ffbf50c0a93cdccadef9c6e05c508a4fd10b1", size = 15800443, upload-time = "2026-10-01T20:38:54.815Z" }, { url = "https://files.pythonhosted.org/packages/8f/0e/69aac6b8159da7c53e6115a2be1bf48e85503402cadbf506dd708e8b2ad7/mypy-2.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:236e0d68f6941992b0811128e652590f590db444ab29ad8f1324765b9298b946", size = 11381574, upload-time = "2026-10-01T20:39:49.406Z" }, { url = "https://files.pythonhosted.org/packages/6e/d3/d32ce4feb5993eec09d2024bef16cedc9b93701b1446b86092f08b24491b/mypy-2.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:82d0f94c8587ccb472622ee7795280aaa38a06640d5f45b3f16909d6dd86a989", size = 10944729, upload-time = "2026-10-01T20:40:15.203Z" }, { url = "https://files.pythonhosted.org/packages/44/f2/eb15183c97c69d7cbfac990a6efd33a19ecfd97dab9e714c742fa78a784f/mypy-2.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7da85fbcff6dac1abcc636707bed38b45598131fb7a605d9719c70b5cc733af8", size = 14213395, upload-time = "2026-10-01T20:40:21.178Z" }, { url = "https://files.pythonhosted.org/packages/8c/b5/ba91b6ff65e4d6b6ff53b2b3b3ac5f1babf0c7c27d0b43a0196b1c967926/mypy-2.4.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4209da39d85cf240f762af622d8180fcdfcb4727d021f44ade62d613a1a43324", size = 14373009, upload-time = "2026-10-01T20:39:58.86Z" }, { url = "https://files.pythonhosted.org/packages/d5/c4/484275efc935c0003e55e4e8a33e4b8e99528ee956c12256ece4708f903f/mypy-2.4.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6be721bd4bd57576193653b75b4af3461c9d0bf7dd8b528f782e9be210dc75bb", size = 15465557, upload-time = "2026-10-01T20:39:01.794Z" }, { url = "https://files.pythonhosted.org/packages/50/30/66eb6fdd0875e3c9025a02f0bb0ea2e524b74274b658c37fde0068c4939d/mypy-2.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e1fde197ae65be856a034a91b70ed747a16562ca69577785f06c661548424bf1", size = 15728673, upload-time = "2026-10-01T20:38:43.724Z" }, { url = "https://files.pythonhosted.org/packages/58/bc/2aa98fd7f49c42dba8e9c065886fadffdd00f3c654cff3f2a7103a797ac8/mypy-2.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:295ecf2e57542cd836ca537486951289678c8c7d1ee6ad74ebe29b2168a003cf", size = 11389803, upload-time = "2026-10-01T20:39:37.547Z" }, { url = "https://files.pythonhosted.org/packages/49/41/17b60df2d946792ef6af43b89351f5c9ddabc69053206b2304945572a744/mypy-2.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:bc378bdad4e9f12b5bd96466083d1e71acf00594ec9c7b2bdb5e02816f77f303", size = 10951060, upload-time = "2026-10-01T20:39:04.015Z" }, { url = "https://files.pythonhosted.org/packages/e0/66/924be0b653372ed31ad5c48e26044cc00840e591943a56e61621cf05b60e/mypy-2.4.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:058165f564ccf559c68c70fec2091fca5891110480210c22594635e3f6683437", size = 14234230, upload-time = "2026-10-01T20:39:44.535Z" }, { url = "https://files.pythonhosted.org/packages/56/39/c4f176880a4177123576de6cec6309feea8f42fca2bf2f6584e88054f656/mypy-2.4.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9fa247e02b505a45a2775f69df38d360d197e3790bc60f717595db9eda358b6e", size = 14392944, upload-time = "2026-10-01T20:40:05.78Z" }, { url = "https://files.pythonhosted.org/packages/bc/1c/26e16977e25ef2494a74f8ffc872a76ec2c3aa43c3156057cbdf88f352c5/mypy-2.4.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:20e9a5cd875837520c43db98dea0b6d0c2197833d95c30127d8f570fb9b1f00b", size = 15441463, upload-time = "2026-10-01T20:40:32.412Z" }, { url = "https://files.pythonhosted.org/packages/31/9c/9e4b049f0ecefbfd6817ca2a16eea55dd74a07950268edc6cffd29ccfe98/mypy-2.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:9f03a7828cca2b0adcd6662aee8f2711ff8830e1027641fdea3ab0b787483566", size = 15705406, upload-time = "2026-10-01T20:40:34.844Z" }, { url = "https://files.pythonhosted.org/packages/4a/5e/e861b5f6c5ef9ee6cd24683aed1edecf82a26dbd536049f9b7850b586267/mypy-2.4.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:9279488933040b638c0ab739084c0ca100efeea6db581bf5d7628d8e89de53fe", size = 7897523, upload-time = "2026-10-01T20:39:39.861Z" }, { url = "https://files.pythonhosted.org/packages/3a/87/61ffee58b25a956532a6006fae84918a2de849ed25f397492b2e815fe7b3/mypy-2.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:2106b55105ba5ea9be4f53a24517fc5fa927ff1585edc9bc1a975abb72caef89", size = 11576345, upload-time = "2026-10-01T20:39:41.553Z" }, { url = "https://files.pythonhosted.org/packages/a1/88/a331c20698971c2ce8d1c30f317fd61b5be13a85b1f053e12dfa22ac6568/mypy-2.4.0-cp314-cp314-win_arm64.whl", hash = "sha256:528c8744b8b5e3ecb8774f86af38d2376216816e9908317ad055f3c9c2d74799", size = 11172062, upload-time = "2026-10-01T20:38:59.534Z" }, { url = "https://files.pythonhosted.org/packages/47/c0/4f7daa73270dced8e86c6f4a911c68082d03a84e6c1ec9bd916028d66131/mypy-2.4.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0bb95cf34899e4619c61ab0a8667804e139e580b30d5df12af2102dfe44d0c97", size = 15711208, upload-time = "2026-10-01T20:39:30.597Z" }, { url = "https://files.pythonhosted.org/packages/2f/05/f1afa303c678be24cf7a266d38fb24b3de4599a024c2f9ba0d5905a3efa3/mypy-2.4.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:86d616fe84c6eab8026f8c50ab5bcb90db780d2ccd233d971e34e92bede9b359", size = 15935442, upload-time = "2026-10-01T20:39:22.781Z" }, { url = "https://files.pythonhosted.org/packages/9d/d6/6a1a45459b63716e0d035f4892a926d3054f0a8cbfa02551d228a9946083/mypy-2.4.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a3f86fd1313dd69d013e265f1fdcd12ea7a9d606f9875b2a3db946cd334555f3", size = 17240044, upload-time = "2026-10-01T20:39:32.95Z" }, { url = "https://files.pythonhosted.org/packages/87/85/ae33bee66c13f98d421964d87bf0888be941063bc75c1204a4cf142cf1cc/mypy-2.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:720434d48542ecfe84d32d287b727569d3fc8f5769acd39051130e490a5c295c", size = 17545856, upload-time = "2026-10-01T20:39:08.827Z" }, { url = "https://files.pythonhosted.org/packages/df/de/eeff209b65c3e267818d79333bb9f058da6e4e73761461bd94748a2eb628/mypy-2.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:a6e851b82c0661f69f1630fc16172c68787a6a9cf0991e7c6437d60976cdcd76", size = 12369342, upload-time = "2026-10-01T20:40:10.516Z" }, { url = "https://files.pythonhosted.org/packages/2b/43/e62d8d5c1dd737aa248968302ff7d6eabf997c3301773ed8bcb64932ca77/mypy-2.4.0-cp314-cp314t-win_arm64.whl", hash = "sha256:3bd0e340f0ebe65c548210f53be3fd8192e83964760caf0c28bef368e68b0d37", size = 11849099, upload-time = "2026-10-01T20:39:51.834Z" }, { url = "https://files.pythonhosted.org/packages/2e/5f/335b8980055118dc131355155883fb676bb2161a0d97e08658e479c776fb/mypy-2.4.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:afa89837d9be67e0cadfa33bca3bb7efdda98c3b07e74dc3b635ebfb1c8a926a", size = 14241302, upload-time = "2026-10-01T20:39:13.227Z" }, { url = "https://files.pythonhosted.org/packages/18/37/1482fdc49332b145828912b15f16eee0c4ca70a8bce0f6514ece79b14680/mypy-2.4.0-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fb443e81057896132d3642d6be219e6efd158691ac7883e3ba8fcb469865f05d", size = 14408200, upload-time = "2026-10-01T20:38:52.576Z" }, { url = "https://files.pythonhosted.org/packages/04/09/dce2e8f6c1b31053c430ef6963f6f7a38ccb49b90c5e01e37ed0129b7d5a/mypy-2.4.0-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7f38f57d344f8b6accb40e01c3d83cfc590498231724d16c07ffb7940f157818", size = 15444409, upload-time = "2026-10-01T20:39:18.1Z" }, { url = "https://files.pythonhosted.org/packages/43/c5/91b68306da4cd280cb15be35dbb5ffc343cabd67c4b121b6625bf2d13177/mypy-2.4.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:e76172710bd4e5eeae061abfd68347e5264632e02778be61784671ae3a2132f5", size = 15731186, upload-time = "2026-10-01T20:40:23.426Z" }, { url = "https://files.pythonhosted.org/packages/64/71/2d0340182a8f27352fb1e25531355951108b506097c433937e9eec452ffd/mypy-2.4.0-cp315-cp315-pyemscripten_2026_5_wasm32.whl", hash = "sha256:f83353e47ab520bf6fd4df8f5897d9fe081211f2fbc4b7d37736a3e3c166cbcf", size = 7897838, upload-time = "2026-10-01T20:38:50.779Z" }, { url = "https://files.pythonhosted.org/packages/3e/08/32703c117e134c02efa2a82705bb40cee91eaedea10b6530e20eba651b1f/mypy-2.4.0-cp315-cp315-win_amd64.whl", hash = "sha256:970b221ed5842213d98e3c480c08f795ace4b1f81fb21e1b126bd0476bce1c34", size = 11575700, upload-time = "2026-10-01T20:39:53.982Z" }, { url = "https://files.pythonhosted.org/packages/ab/08/08bb269feafdaad031046ee2d771528a64467e6a180f962afc28c4a3ccd8/mypy-2.4.0-cp315-cp315-win_arm64.whl", hash = "sha256:502b94b0b331f7dafe32fd6b151797ddbb4f32385b362e722c783a025e5954a3", size = 11172908, upload-time = "2026-10-01T20:40:12.91Z" }, { url = "https://files.pythonhosted.org/packages/fb/3f/c5c92626006ca92c7686adfbece47fc6a0daa0e54753952a9ad13ce0561c/mypy-2.4.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:c9de622fd397495695d0598ddc789222bfcfec9d7c9ec3a1e385c855e3bc5e01", size = 15705970, upload-time = "2026-10-01T20:40:17.79Z" }, { url = "https://files.pythonhosted.org/packages/10/f3/863365f7997a76a5a1dd42d7902ab05afa4124e8419089cbca1ce2554db1/mypy-2.4.0-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9f459f0b4f0596d9d51fe7716b404b35287b99e77da98a7af90a65dd5fd61141", size = 15942234, upload-time = "2026-10-01T20:40:37.243Z" }, { url = "https://files.pythonhosted.org/packages/f6/30/2f45b1f425a2c95dbe1a3f4d076bfd42b76e9615dba5906230703b14e4eb/mypy-2.4.0-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f9b028548b3af480e2b1ed8df14ccaac86f99c9f600d1580770ab7ba3dcd40f0", size = 17218364, upload-time = "2026-10-01T20:39:06.497Z" }, { url = "https://files.pythonhosted.org/packages/43/8b/5b2bbfc69e84800b78fa2dba16d995b003f93b573558e412c5490d6e6c37/mypy-2.4.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:cb734b2668c1f40d07ce093bbeb4407e9527c67901627b0e1679825be3f09975", size = 17557934, upload-time = "2026-10-01T20:38:46.077Z" }, { url = "https://files.pythonhosted.org/packages/df/c0/1a5dc601c22041a7bbfe1ff71cf097fbbd4fb49930867c6789baf5102106/mypy-2.4.0-cp315-cp315t-win_amd64.whl", hash = "sha256:172e30b8fea631fe310f0c665477f52d9ea40bb4e99e0c81dc30118563b13710", size = 12350955, upload-time = "2026-10-01T20:40:01.52Z" }, { url = "https://files.pythonhosted.org/packages/1c/bc/697e9e26fc2a86c094ad67ee1e419971b7f01ded66ee66231b09e9f3e12e/mypy-2.4.0-cp315-cp315t-win_arm64.whl", hash = "sha256:5786ef987b3767e51aaa53f20aec104c0252b42ecda7aef8e8b4cbae279b05c5", size = 11842738, upload-time = "2026-10-01T20:40:30.026Z" }, { url = "https://files.pythonhosted.org/packages/81/12/46ae8670c98a3cd0286ca5645c2f918f8f6be65edfed81b916010619f668/mypy-2.4.0-py3-none-any.whl", hash = "sha256:d01c5d26a352acc6d5cf3128225477e1e8465e8d3029d4c345807fbf7f3cf093", size = 2800734, upload-time = "2026-10-01T20:39:26.837Z" }, ] [[package]] name = "mypy-extensions" version = "1.1.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, ] [[package]] name = "packaging" version = "26.3" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/7d/fa/3944b40b07da9ce895c0e6303a5ab7d53da063554f534556b134a54d6093/packaging-26.3.tar.gz", hash = "sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79", size = 313412, upload-time = "2026-08-04T18:15:28.737Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/63/34/ba1c580383c9eada3711951fef0795c80b829a078d72188184bcab9dd527/packaging-26.3-py3-none-any.whl", hash = "sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c", size = 129956, upload-time = "2026-08-04T18:15:27.159Z" }, ] [[package]] name = "pathspec" version = "1.1.1" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/5a/82/42f767fc1c1143d6fd36efb827202a2d997a375e160a71eb2888a925aac1/pathspec-1.1.1.tar.gz", hash = "sha256:17db5ecd524104a120e173814c90367a96a98d07c45b2e10c2f3919fff91bf5a", size = 135180, upload-time = "2026-04-27T01:46:08.907Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl", hash = "sha256:a00ce642f577bf7f473932318056212bc4f8bfdf53128c78bbd5af0b9b20b189", size = 57328, upload-time = "2026-04-27T01:46:07.06Z" }, ] [[package]] name = "pluggy" version = "1.7.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/bf/db/7fc19e6f2dc92a966727031389fc2e08b558f0f25eb7403c1119ad4713cd/pluggy-1.7.0.tar.gz", hash = "sha256:d1eaa46ebb595891b860ab086b4d09c8588af65ebd4361b8e8f4bb8920b90ba8", size = 123304, upload-time = "2026-10-15T09:50:58.343Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/40/9e/2b38731e0fc536806f16490e1a12d7f0dc2a1235aa8cc07bcc75416a7daa/pluggy-1.7.0-py3-none-any.whl", hash = "sha256:7dd7b0d8832ba3cb632c306926ded123429211b83641b35dc5c41ad2d34f9bec", size = 27082, upload-time = "2026-10-15T09:50:56.808Z" }, ] [[package]] name = "pygments" version = "2.21.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/49/2e/ced460408999b33da6b31b0021b0f37d329e202d4169aeb164493778f25b/pygments-2.21.0.tar.gz", hash = "sha256:610ca751c9bc2492b38eb9a38a7fbc93edbbb2d7182edaf34e66ae493dee5c8c", size = 5005329, upload-time = "2026-08-17T08:02:48.824Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/71/46/17f022dd3e953bf20a04a028a21ec746d942f8d2af30fa0f124fa0e6a684/pygments-2.21.0-py3-none-any.whl", hash = "sha256:2363c69b61c4a97c838da3b130dcd6468f4848992b21a82f2a63ec34377137d9", size = 1250147, upload-time = "2026-08-17T08:02:44.912Z" }, ] [[package]] name = "pygments-styles" version = "0.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pygments" }, ] sdist = { url = "https://files.pythonhosted.org/packages/1c/2c/3886ed4783dd78bb62ccab7d43380f526a7e2ff0db8c77d9c87559b2f5de/pygments_styles-0.3.0.tar.gz", hash = "sha256:67746b8fc6ff72c1179ca4d9a8bc89c7f54c196c2ff9d087f07392cd6fde3ecf", size = 15258, upload-time = "2025-11-04T13:15:23.512Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/8f/64/7e0266f0c541e26df86c31d2add9be3dd9914ae83785ce0aba7cbb693667/pygments_styles-0.3.0-py3-none-any.whl", hash = "sha256:c6c45e9939eb7590345bc9084113bac46c45f12b009d13422be02e80e84a034c", size = 36617, upload-time = "2025-11-04T13:15:21.989Z" }, ] [[package]] name = "pytest" version = "9.1.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, { name = "iniconfig" }, { name = "packaging" }, { name = "pluggy" }, { name = "pygments" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" }, ] [[package]] name = "pytest-cov" version = "7.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "coverage", extra = ["toml"] }, { name = "pluggy" }, { name = "pytest" }, ] sdist = { url = "https://files.pythonhosted.org/packages/b1/51/a849f96e117386044471c8ec2bd6cfebacda285da9525c9106aeb28da671/pytest_cov-7.1.0.tar.gz", hash = "sha256:30674f2b5f6351aa09702a9c8c364f6a01c27aae0c1366ae8016160d1efc56b2", size = 55592, upload-time = "2026-03-21T20:11:16.284Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl", hash = "sha256:a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678", size = 22876, upload-time = "2026-03-21T20:11:14.438Z" }, ] [[package]] name = "requests" version = "2.34.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi" }, { name = "charset-normalizer" }, { name = "idna" }, { name = "urllib3" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ac/c3/e2a2b89f2d3e2179abd6d00ebd70bff6273f37fb3e0cc209f48b39d00cbf/requests-2.34.2.tar.gz", hash = "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed", size = 142856, upload-time = "2026-05-14T19:25:27.735Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0", size = 73075, upload-time = "2026-05-14T19:25:26.443Z" }, ] [[package]] name = "roman-numerals" version = "4.1.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/ae/f9/41dc953bbeb056c17d5f7a519f50fdf010bd0553be2d630bc69d1e022703/roman_numerals-4.1.0.tar.gz", hash = "sha256:1af8b147eb1405d5839e78aeb93131690495fe9da5c91856cb33ad55a7f1e5b2", size = 9077, upload-time = "2025-12-17T18:25:34.381Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/04/54/6f679c435d28e0a568d8e8a7c0a93a09010818634c3c3907fc98d8983770/roman_numerals-4.1.0-py3-none-any.whl", hash = "sha256:647ba99caddc2cc1e55a51e4360689115551bf4476d90e8162cf8c345fe233c7", size = 7676, upload-time = "2025-12-17T18:25:33.098Z" }, ] [[package]] name = "ruff" version = "0.17.1" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/f9/e7/e6d5749983b020e6cb1055abec0a6f361a8e94f0184cdcf56d4760995f02/ruff-0.17.1.tar.gz", hash = "sha256:5bb796c5112e9fb9527f2ef2faa0a130d6312d19de92bcfaddd70dbb2d41020f", size = 5323349, upload-time = "2026-10-15T15:23:18.64Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/2e/78/90c46ca6250709f7c37e397b60d06061adee8d0f7d13959ed6a8e49b14fd/ruff-0.17.1-py3-none-linux_armv6l.whl", hash = "sha256:1796c41eafec66f4635125dd1e074a7aa27b8d20c187d484360acf11d247fc4a", size = 10147528, upload-time = "2026-10-15T15:22:33.667Z" }, { url = "https://files.pythonhosted.org/packages/aa/d2/a2e28bc35b083ae51fa07dfba5280a667c8b01ecaee7802fc8849dcd5c46/ruff-0.17.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:8eadb09a788010be29c895418bdfa513e4e1c65e64b94e5b19e4cd381f6cc7fb", size = 10225974, upload-time = "2026-10-15T15:22:36.328Z" }, { url = "https://files.pythonhosted.org/packages/8e/71/7a9029a81c8206ee01a98f6cfeeb56e6c095af86857581a37045c46d7e94/ruff-0.17.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:29b454f18ca3eeaf37fbf140841dcf27d36109e29dee9aae8acecb68c26c6f74", size = 9270361, upload-time = "2026-10-15T15:22:38.651Z" }, { url = "https://files.pythonhosted.org/packages/c0/8c/e075e9c917cb0575297880c96768304e881240171c870cbd8d9b7b54bec2/ruff-0.17.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:872e03dd231744d6c5ec5c8af6be52b71323fc6ee096e4c8b34d9f844ee3b978", size = 9938300, upload-time = "2026-10-15T15:22:41.284Z" }, { url = "https://files.pythonhosted.org/packages/87/27/0b4bb926a49de2383f161272b4d863571a4c7ecdbf595a6bc58813a13367/ruff-0.17.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4c0d6cb5f8fbac77eec9af49f4fc0eaf856b05545e372b0694d24b4e76b1c640", size = 9948464, upload-time = "2026-10-15T15:22:43.681Z" }, { url = "https://files.pythonhosted.org/packages/14/27/518d57e0e02aecb8ea4acac6b57b51a53173d25fa734952bfdd7d531e88e/ruff-0.17.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78beced4a3c94dfedbee4b999b95b6a27b35820fdc0afbacc6d37a8da26c1cd1", size = 10638639, upload-time = "2026-10-15T15:22:46.081Z" }, { url = "https://files.pythonhosted.org/packages/01/82/d89a4e498ade59e6cee52d67f8da569019372212b87468c1fdeae884601c/ruff-0.17.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7feefc63921202894f0e158b0e32f45a5950d70a7fb693ccb9264816c25b1c05", size = 11337238, upload-time = "2026-10-15T15:22:48.894Z" }, { url = "https://files.pythonhosted.org/packages/a2/7c/3b0fdef9352656317c977086fe1d802902406e4f2a0d8578da90c0e6d1c5/ruff-0.17.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:684154861a819bf1f433669d2a0ce9c3e54677c65b8ebb866cc2a7ec86345785", size = 10896327, upload-time = "2026-10-15T15:22:51.45Z" }, { url = "https://files.pythonhosted.org/packages/62/86/5566290219708ce2928f3a29c4f843a1185b341ec6111c4631a33c5ceced/ruff-0.17.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6ef98e51de8ef38082f90653ceeb84944bd7673783eea13e1647c5b9b064189", size = 10350811, upload-time = "2026-10-15T15:22:54.401Z" }, { url = "https://files.pythonhosted.org/packages/ad/d2/ca8462dabb3c413990d49703ba306c30c862195a75448d080fa8fcce9775/ruff-0.17.1-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:8f9aa5b5bd5fa1937803ea609c8f153b8de39bf3e0e149897ae34b0c5b52f467", size = 10569994, upload-time = "2026-10-15T15:22:57.142Z" }, { url = "https://files.pythonhosted.org/packages/e3/ad/dd1864c1f1db17c8cfb297ce70b352388e6977620f66f7182c52855407df/ruff-0.17.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:80e53b0e5faa3c5667f035daaa032893ae42b7cfe708c886d39ed131e54688ab", size = 10059672, upload-time = "2026-10-15T15:23:00.084Z" }, { url = "https://files.pythonhosted.org/packages/65/45/3f56cf1d2168c2165cdd5ac6f9668aee66a4cfdd4caf2b2cc5ccb2b1d568/ruff-0.17.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:056c5d5fa0ac790051ae165d7035c7bf956d02de2db557f2e9b31d877a505fca", size = 9947803, upload-time = "2026-10-15T15:23:03.132Z" }, { url = "https://files.pythonhosted.org/packages/aa/4b/5457cb2be4c1d1ea5e919558131a0f197a4a454a0530d9e30820e8206e4c/ruff-0.17.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:bd8f5a55b10f371642eacd0e8665a42a8b97da15c9a7187c79e697b77b5e0ce4", size = 10351807, upload-time = "2026-10-15T15:23:05.628Z" }, { url = "https://files.pythonhosted.org/packages/49/fb/db15b4f8fa24a1e36b99e1401f42ef6df16ee299a48670d5d262b771e7d7/ruff-0.17.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:ce05e6f3973611d9550a600e04bb531061e368baba31610eb57c1509a8f21a0a", size = 10765716, upload-time = "2026-10-15T15:23:08.092Z" }, { url = "https://files.pythonhosted.org/packages/0a/e8/1e186578076aff7a80735f625005fde678412ab609cd323ed182eb7d6b87/ruff-0.17.1-py3-none-win32.whl", hash = "sha256:1de0030a8aa78c65c5fecb84b2e5c390ac684c0452875a02afc7c083d49a496a", size = 9895093, upload-time = "2026-10-15T15:23:10.582Z" }, { url = "https://files.pythonhosted.org/packages/6a/2e/da3d9589bae8e8b58f3a48bd5bc0b980232fb14a83bf02c3be7660f87c1b/ruff-0.17.1-py3-none-win_amd64.whl", hash = "sha256:5df76f16580fab58d0f6c98a3ac254a4abceb7b2489b8b678335869cff77b3d7", size = 10097955, upload-time = "2026-10-15T15:23:13.309Z" }, { url = "https://files.pythonhosted.org/packages/df/c9/0f2a4dea06a5e12c1191ee3d96b1e1233797d0d5e18f97a2b909a95a9836/ruff-0.17.1-py3-none-win_arm64.whl", hash = "sha256:42400b9a6ff8515ff27796f07f92e0195be011c86e81e381606f58ea5502fef4", size = 9853542, upload-time = "2026-10-15T15:23:16.05Z" }, ] [[package]] name = "shibuya" version = "2026.7.12" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pygments-styles" }, { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.11.*'" }, { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ba/d2/8017988e02791162b286576116fedd200ed33e8d8af3579ab3587df3d3d0/shibuya-2026.7.12.tar.gz", hash = "sha256:9496606f5b95595511ad86b773d74b4b8d694a4dcc2f848e6ec34e2ad71d9060", size = 86545, upload-time = "2026-07-11T15:41:16.342Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/84/70/9ca2b8187666be1bcfa82b938107247159f5b566a22b5e43be27df45039d/shibuya-2026.7.12-py3-none-any.whl", hash = "sha256:0a2c0c109e7cc47fc650b01feb671d267c0ffe2e39c98f3529e32d723a9c9d9b", size = 104092, upload-time = "2026-07-11T15:41:14.936Z" }, ] [[package]] name = "snowballstemmer" version = "3.1.1" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/43/f8/0a71edf031f03c40db17503cb8ca78a69a171254e568e7db241b0ab57ea1/snowballstemmer-3.1.1.tar.gz", hash = "sha256:e07bbc54a0d798fe6010a12398422e62a8bfbba95c394fd0956ef58cb4d3e260", size = 123314, upload-time = "2026-06-03T00:56:40.194Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/4c/07/2ebca9b11fb9be7340a818d8d6f63feaebb146be2c4afbd6061701d6df6e/snowballstemmer-3.1.1-py3-none-any.whl", hash = "sha256:7e207fa178741da09cdee59d3ecec3827ad5f92b1fc5c9ff3755b639f71f5752", size = 104164, upload-time = "2026-06-03T00:56:38.614Z" }, ] [[package]] name = "sphinx" version = "8.1.3" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version < '3.11'", ] dependencies = [ { name = "alabaster" }, { name = "babel" }, { name = "colorama", marker = "sys_platform == 'win32'" }, { name = "docutils", version = "0.21.2", source = { registry = "https://pypi.org/simple" } }, { name = "imagesize" }, { name = "jinja2" }, { name = "packaging" }, { name = "pygments" }, { name = "requests" }, { name = "snowballstemmer" }, { name = "sphinxcontrib-applehelp" }, { name = "sphinxcontrib-devhelp" }, { name = "sphinxcontrib-htmlhelp" }, { name = "sphinxcontrib-jsmath" }, { name = "sphinxcontrib-qthelp" }, { name = "sphinxcontrib-serializinghtml" }, { name = "tomli" }, ] sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/be0b61178fe2cdcb67e2a92fc9ebb488e3c51c4f74a36a7824c0adf23425/sphinx-8.1.3.tar.gz", hash = "sha256:43c1911eecb0d3e161ad78611bc905d1ad0e523e4ddc202a58a821773dc4c927", size = 8184611, upload-time = "2024-10-13T20:27:13.93Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/26/60/1ddff83a56d33aaf6f10ec8ce84b4c007d9368b21008876fceda7e7381ef/sphinx-8.1.3-py3-none-any.whl", hash = "sha256:09719015511837b76bf6e03e42eb7595ac8c2e41eeb9c29c5b755c6b677992a2", size = 3487125, upload-time = "2024-10-13T20:27:10.448Z" }, ] [[package]] name = "sphinx" version = "9.0.4" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version == '3.11.*'", ] dependencies = [ { name = "alabaster" }, { name = "babel" }, { name = "colorama", marker = "sys_platform == 'win32'" }, { name = "docutils", version = "0.22.4", source = { registry = "https://pypi.org/simple" } }, { name = "imagesize" }, { name = "jinja2" }, { name = "packaging" }, { name = "pygments" }, { name = "requests" }, { name = "roman-numerals" }, { name = "snowballstemmer" }, { name = "sphinxcontrib-applehelp" }, { name = "sphinxcontrib-devhelp" }, { name = "sphinxcontrib-htmlhelp" }, { name = "sphinxcontrib-jsmath" }, { name = "sphinxcontrib-qthelp" }, { name = "sphinxcontrib-serializinghtml" }, ] sdist = { url = "https://files.pythonhosted.org/packages/42/50/a8c6ccc36d5eacdfd7913ddccd15a9cee03ecafc5ee2bc40e1f168d85022/sphinx-9.0.4.tar.gz", hash = "sha256:594ef59d042972abbc581d8baa577404abe4e6c3b04ef61bd7fc2acbd51f3fa3", size = 8710502, upload-time = "2025-12-04T07:45:27.343Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/c6/3f/4bbd76424c393caead2e1eb89777f575dee5c8653e2d4b6afd7a564f5974/sphinx-9.0.4-py3-none-any.whl", hash = "sha256:5bebc595a5e943ea248b99c13814c1c5e10b3ece718976824ffa7959ff95fffb", size = 3917713, upload-time = "2025-12-04T07:45:24.944Z" }, ] [[package]] name = "sphinx" version = "9.1.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.15'", "python_full_version >= '3.12' and python_full_version < '3.15'", ] dependencies = [ { name = "alabaster" }, { name = "babel" }, { name = "colorama", marker = "sys_platform == 'win32'" }, { name = "docutils", version = "0.22.4", source = { registry = "https://pypi.org/simple" } }, { name = "imagesize" }, { name = "jinja2" }, { name = "packaging" }, { name = "pygments" }, { name = "requests" }, { name = "roman-numerals" }, { name = "snowballstemmer" }, { name = "sphinxcontrib-applehelp" }, { name = "sphinxcontrib-devhelp" }, { name = "sphinxcontrib-htmlhelp" }, { name = "sphinxcontrib-jsmath" }, { name = "sphinxcontrib-qthelp" }, { name = "sphinxcontrib-serializinghtml" }, ] sdist = { url = "https://files.pythonhosted.org/packages/cd/bd/f08eb0f4eed5c83f1ba2a3bd18f7745a2b1525fad70660a1c00224ec468a/sphinx-9.1.0.tar.gz", hash = "sha256:7741722357dd75f8190766926071fed3bdc211c74dd2d7d4df5404da95930ddb", size = 8718324, upload-time = "2025-12-31T15:09:27.646Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/73/f7/b1884cb3188ab181fc81fa00c266699dab600f927a964df02ec3d5d1916a/sphinx-9.1.0-py3-none-any.whl", hash = "sha256:c84fdd4e782504495fe4f2c0b3413d6c2bf388589bb352d439b2a3bb99991978", size = 3921742, upload-time = "2025-12-31T15:09:25.561Z" }, ] [[package]] name = "sphinx-copybutton" version = "0.5.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.11.*'" }, { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/fc/2b/a964715e7f5295f77509e59309959f4125122d648f86b4fe7d70ca1d882c/sphinx-copybutton-0.5.2.tar.gz", hash = "sha256:4cf17c82fb9646d1bc9ca92ac280813a3b605d8c421225fd9913154103ee1fbd", size = 23039, upload-time = "2023-04-14T08:10:22.998Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/9e/48/1ea60e74949eecb12cdd6ac43987f9fd331156388dcc2319b45e2ebb81bf/sphinx_copybutton-0.5.2-py3-none-any.whl", hash = "sha256:fb543fd386d917746c9a2c50360c7905b605726b9355cd26e9974857afeae06e", size = 13343, upload-time = "2023-04-14T08:10:20.844Z" }, ] [[package]] name = "sphinx-design" version = "0.6.1" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version < '3.11'", ] dependencies = [ { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" } }, ] sdist = { url = "https://files.pythonhosted.org/packages/2b/69/b34e0cb5336f09c6866d53b4a19d76c227cdec1bbc7ac4de63ca7d58c9c7/sphinx_design-0.6.1.tar.gz", hash = "sha256:b44eea3719386d04d765c1a8257caca2b3e6f8421d7b3a5e742c0fd45f84e632", size = 2193689, upload-time = "2024-08-02T13:48:44.277Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/c6/43/65c0acbd8cc6f50195a3a1fc195c404988b15c67090e73c7a41a9f57d6bd/sphinx_design-0.6.1-py3-none-any.whl", hash = "sha256:b11f37db1a802a183d61b159d9a202314d4d2fe29c163437001324fe2f19549c", size = 2215338, upload-time = "2024-08-02T13:48:42.106Z" }, ] [[package]] name = "sphinx-design" version = "0.7.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.15'", "python_full_version >= '3.12' and python_full_version < '3.15'", "python_full_version == '3.11.*'", ] dependencies = [ { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" }, { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/13/7b/804f311da4663a4aecc6cf7abd83443f3d4ded970826d0c958edc77d4527/sphinx_design-0.7.0.tar.gz", hash = "sha256:d2a3f5b19c24b916adb52f97c5f00efab4009ca337812001109084a740ec9b7a", size = 2203582, upload-time = "2026-01-19T13:12:53.297Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/30/cf/45dd359f6ca0c3762ce0490f681da242f0530c49c81050c035c016bfdd3a/sphinx_design-0.7.0-py3-none-any.whl", hash = "sha256:f82bf179951d58f55dca78ab3706aeafa496b741a91b1911d371441127d64282", size = 2220350, upload-time = "2026-01-19T13:12:51.077Z" }, ] [[package]] name = "sphinxcontrib-applehelp" version = "2.0.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/ba/6e/b837e84a1a704953c62ef8776d45c3e8d759876b4a84fe14eba2859106fe/sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1", size = 20053, upload-time = "2024-07-29T01:09:00.465Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/5d/85/9ebeae2f76e9e77b952f4b274c27238156eae7979c5421fba91a28f4970d/sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5", size = 119300, upload-time = "2024-07-29T01:08:58.99Z" }, ] [[package]] name = "sphinxcontrib-devhelp" version = "2.0.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/f6/d2/5beee64d3e4e747f316bae86b55943f51e82bb86ecd325883ef65741e7da/sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad", size = 12967, upload-time = "2024-07-29T01:09:23.417Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/35/7a/987e583882f985fe4d7323774889ec58049171828b58c2217e7f79cdf44e/sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2", size = 82530, upload-time = "2024-07-29T01:09:21.945Z" }, ] [[package]] name = "sphinxcontrib-htmlhelp" version = "2.1.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/43/93/983afd9aa001e5201eab16b5a444ed5b9b0a7a010541e0ddfbbfd0b2470c/sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9", size = 22617, upload-time = "2024-07-29T01:09:37.889Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/0a/7b/18a8c0bcec9182c05a0b3ec2a776bba4ead82750a55ff798e8d406dae604/sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8", size = 98705, upload-time = "2024-07-29T01:09:36.407Z" }, ] [[package]] name = "sphinxcontrib-jsmath" version = "1.0.1" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/b2/e8/9ed3830aeed71f17c026a07a5097edcf44b692850ef215b161b8ad875729/sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8", size = 5787, upload-time = "2019-01-21T16:10:16.347Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/c2/42/4c8646762ee83602e3fb3fbe774c2fac12f317deb0b5dbeeedd2d3ba4b77/sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", size = 5071, upload-time = "2019-01-21T16:10:14.333Z" }, ] [[package]] name = "sphinxcontrib-qthelp" version = "2.0.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/68/bc/9104308fc285eb3e0b31b67688235db556cd5b0ef31d96f30e45f2e51cae/sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab", size = 17165, upload-time = "2024-07-29T01:09:56.435Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/27/83/859ecdd180cacc13b1f7e857abf8582a64552ea7a061057a6c716e790fce/sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb", size = 88743, upload-time = "2024-07-29T01:09:54.885Z" }, ] [[package]] name = "sphinxcontrib-serializinghtml" version = "2.0.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/3b/44/6716b257b0aa6bfd51a1b31665d1c205fb12cb5ad56de752dfa15657de2f/sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d", size = 16080, upload-time = "2024-07-29T01:10:09.332Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/52/a7/d2782e4e3f77c8450f727ba74a8f12756d5ba823d81b941f1b04da9d033a/sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331", size = 92072, upload-time = "2024-07-29T01:10:08.203Z" }, ] [[package]] name = "tomli" version = "2.5.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/b0/78/9ad63712633ed3ab5cc1a648d863d7e7da371e9425e209555a0fe711b695/tomli-2.5.0.tar.gz", hash = "sha256:264507556cd8b8c8e7c6ee037cdf443a463f03f4c958e57195e3d369711b8ff6", size = 17662, upload-time = "2026-10-07T12:23:37.892Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/22/a6/ab99b60ee52acd949684febabc3005d0045d0f66bebd9cdebd67372d26dd/tomli-2.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c4dc1c1781f2f716de763d1e9a7b34c6a894e167e291c7c5d16c72f7a9538545", size = 163901, upload-time = "2026-10-07T12:22:15.601Z" }, { url = "https://files.pythonhosted.org/packages/bc/00/ee01b7ed4579180fff07142d290257f25ba786f23f3ec6005f620933c2f5/tomli-2.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:eff8babca5a7999bc137acbc7482a8b7e17ffca5075ab41f5d770ab408c7bfef", size = 163756, upload-time = "2026-10-07T12:22:16.957Z" }, { url = "https://files.pythonhosted.org/packages/72/c2/4efebf65372f6583185f79799312109dddb61102d47e5c33dcfd1a297aca/tomli-2.5.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:86665cee9c4835b7a7f1e8ec2c719b5258d4dc782887aded5a8ae7352a96843b", size = 268038, upload-time = "2026-10-07T12:22:18.135Z" }, { url = "https://files.pythonhosted.org/packages/53/07/5850468e925d898abb36038666f9c333a94d2a223e802a8ba5b6d319d23f/tomli-2.5.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d7e369fd63331746182360977b1892bfc215476a30d61612d732425311639f56", size = 276422, upload-time = "2026-10-07T12:22:19.567Z" }, { url = "https://files.pythonhosted.org/packages/b4/87/f293984cdcf83c054196d4fd3dad44fc68ae55b4b8c44bc76cef360c3150/tomli-2.5.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7ad1ea345759240d6463efa0ed1c704402752e49aa21476620738d74d72d8aa1", size = 272616, upload-time = "2026-10-07T12:22:20.794Z" }, { url = "https://files.pythonhosted.org/packages/ce/ce/db582886b3c1219d3fec93ebd669332482e5aee7a91e0f7838d84f2d1759/tomli-2.5.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:96243987194634bd411066ce40c952e108f86af04db533ecd8ac3ff2a85b1885", size = 276593, upload-time = "2026-10-07T12:22:22.12Z" }, { url = "https://files.pythonhosted.org/packages/bf/72/7619b87dea4261fc27dd7b54c4461c129c1f7d9bb7ba3aec89c797a431b8/tomli-2.5.0-cp311-cp311-win32.whl", hash = "sha256:610b27d99f28ec5f191c7064a48f3ddb179a1fe6ca73d571483ae859f57b605e", size = 101830, upload-time = "2026-10-07T12:22:23.651Z" }, { url = "https://files.pythonhosted.org/packages/1e/74/220106da34502304b6751a2a9b8a9fbca6c3fd47e737a2e2e3da7c61c9db/tomli-2.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:c804ae44fe7b4bab5da295e4f980a1ff04670bca9d23fe0a4e887e08ebd741a8", size = 112742, upload-time = "2026-10-07T12:22:24.972Z" }, { url = "https://files.pythonhosted.org/packages/27/99/7d9c8b41837a7773613e169504147375c157a290167aa59ad74a085f521f/tomli-2.5.0-cp311-cp311-win_arm64.whl", hash = "sha256:cfac177ebd6236003846ea339981f71457cb6eb748f23381eb257e45092e3980", size = 109332, upload-time = "2026-10-07T12:22:26.117Z" }, { url = "https://files.pythonhosted.org/packages/52/ed/7baa86f87493646a594de388c7c1c40a39dd0461f7e9c0359cbeefc91fe8/tomli-2.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:1f4a40d03fb9f63424f0979855bdeaf44dd7696b8d59501822c10ed30ba532df", size = 164854, upload-time = "2026-10-07T12:22:27.444Z" }, { url = "https://files.pythonhosted.org/packages/a5/b1/44c0341f2224397855723c7a8a39f718ea6fcbcc3dacc66e5aeca0f334e3/tomli-2.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9ebf8d19b17bd0daeb7b7dec81a946a439b753942fd0210d6e96c532249eea6b", size = 164074, upload-time = "2026-10-07T12:22:28.679Z" }, { url = "https://files.pythonhosted.org/packages/23/04/e2d5b7d3fba47adedb23de616c16d428ea076c79a3d8e1d95d649ffe197e/tomli-2.5.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bf0b5e8e0f68ebb494356e577c06c139161efd8d3b9050f93b39b7c26cc54ff0", size = 274274, upload-time = "2026-10-07T12:22:29.804Z" }, { url = "https://files.pythonhosted.org/packages/43/90/6090e706ff27a6f89f4a40578e3324b95c3cd8c4150868aabf33a8f414c3/tomli-2.5.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6cf74416bdc94ae458b14e37286c1073081850ac8459a00d0c5efef5d44294c6", size = 286435, upload-time = "2026-10-07T12:22:31.297Z" }, { url = "https://files.pythonhosted.org/packages/0a/9e/a2c40768df16c408f22430afb0a73e9d7e5f79c950884954649d1146b74d/tomli-2.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:61ea1ebe1e55a34ea8199cc8dbff398d35027b82271c8ac4802fd3a1fd5b1bcc", size = 278119, upload-time = "2026-10-07T12:22:32.601Z" }, { url = "https://files.pythonhosted.org/packages/12/25/3c0cb485b98e9cfac495629b1c93c87ccf0b72fbe9d2689fd8fe62c6d5a3/tomli-2.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ed53f7e89bb04f6d9e8e7799112360b0c4d5cbff067de0814c98c37c39b920f7", size = 286177, upload-time = "2026-10-07T12:22:33.745Z" }, { url = "https://files.pythonhosted.org/packages/77/8b/0144c65f0e37e51c18d04ae15c21b19431c165002d0131fe9aa8b0b8b1e8/tomli-2.5.0-cp312-cp312-win32.whl", hash = "sha256:e7ad033e27a516a233bea839cdb77b80146facb3b4f40bf02cd0cac165cdd5c2", size = 102760, upload-time = "2026-10-07T12:22:34.887Z" }, { url = "https://files.pythonhosted.org/packages/de/32/5d6d8f42fc9a05fce69354e00ff256484192f5f2fc9a2165718fa0de61ec/tomli-2.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:bd05de8c1698f8413dd7d869492693a0bf2211543b787ac78cd5e7536af1a6d7", size = 112722, upload-time = "2026-10-07T12:22:36.162Z" }, { url = "https://files.pythonhosted.org/packages/30/65/df18032218db0fb9b769fb23c8039a051f15c811993995ea04c350273a32/tomli-2.5.0-cp312-cp312-win_arm64.whl", hash = "sha256:069435bd5480429b98c5e5afb02ab21c219b6f0064680671c6dc0d46817346ea", size = 109534, upload-time = "2026-10-07T12:22:37.296Z" }, { url = "https://files.pythonhosted.org/packages/42/e5/51736d70da209350969e15aca5c5ab6e2ce1ea87a0a892a6c13aec172a86/tomli-2.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:943276cf269e0071948d9ff697159c1735e623c1151d88abb09b74659ef0cbea", size = 163328, upload-time = "2026-10-07T12:22:38.373Z" }, { url = "https://files.pythonhosted.org/packages/ec/55/086f80dab4ab497602644274e6dea7ec5dd0b4e262e443a8ad3bb7edee2d/tomli-2.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:463b16086865b97facd8d0b3fb4cb7c544e3f58d2a69dc3113d6db9653fdb043", size = 162246, upload-time = "2026-10-07T12:22:39.673Z" }, { url = "https://files.pythonhosted.org/packages/aa/eb/3ecc94459f3635c92321f4e7bde571323fdb2267c50e19e3188a281eae3b/tomli-2.5.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1245a6638fc4bb0a60af38a7d45413db34a13842027c77597c712c998c62fdf0", size = 272655, upload-time = "2026-10-07T12:22:41.08Z" }, { url = "https://files.pythonhosted.org/packages/c0/d7/494fd1f0c37a621f1ad9975c2efadb523e8101f144ed6edb2e7fe64738f2/tomli-2.5.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5d8bac3d603c97e6854424e5b2b5b741bdbde387e09f162fb0446812b4a8362b", size = 283595, upload-time = "2026-10-07T12:22:42.222Z" }, { url = "https://files.pythonhosted.org/packages/70/51/bb8d62b1317e6640866f6949b2d5855e5300f2c99d46de1cd245570bba65/tomli-2.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:21e4cae4114aba25aa0d4f85cdf486d290fb35c0954d7bba536248da64d43066", size = 276253, upload-time = "2026-10-07T12:22:43.625Z" }, { url = "https://files.pythonhosted.org/packages/66/f4/f46bd7f0763cd47de2db697dca9257c6a4adfd1a93b018cc75c8190ed5a8/tomli-2.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bbaefc84548d754be821bba7c4141c4787dda182f9e77f2f87b71213529efa7b", size = 283582, upload-time = "2026-10-07T12:22:44.983Z" }, { url = "https://files.pythonhosted.org/packages/ac/03/70f2bcb2923a6db37818d917e124270a7f4cfd38ea576f5aa753a91c0ef5/tomli-2.5.0-cp313-cp313-win32.whl", hash = "sha256:abdbf6313b8d9efe157edeb7ab6eae4de064b1300ad31abf73755154b30abe68", size = 102628, upload-time = "2026-10-07T12:22:46.508Z" }, { url = "https://files.pythonhosted.org/packages/dc/98/d52024bb5b0ff68b4f0d276d867f634c84a67319a7e9f6b7708a37742333/tomli-2.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:fd4dc129784e0c5335bd4e61dfcc4487499a013419e655cf2da1d091b7e0efdc", size = 113301, upload-time = "2026-10-07T12:22:47.647Z" }, { url = "https://files.pythonhosted.org/packages/6f/f2/540db3a70572a8c23a28aba3e9c358ce0ffffbafc990905c1343aa265b31/tomli-2.5.0-cp313-cp313-win_arm64.whl", hash = "sha256:69491c143d2fe063046e0301e62a810bed338fa4d1ce0fd870c27dc1e09b0d84", size = 109744, upload-time = "2026-10-07T12:22:48.925Z" }, { url = "https://files.pythonhosted.org/packages/e4/49/caf6b307766eb9567664a8707e9d6be5fcc0e8903f18781c6677a60d80c7/tomli-2.5.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d3182ee2d887e507bd67319a0a61105d1dd33facc111329559a233b772c1a105", size = 162899, upload-time = "2026-10-07T12:22:50.088Z" }, { url = "https://files.pythonhosted.org/packages/d3/c8/68cfce773a2733a49c74f99d627fb461bd990756860099eac25617889585/tomli-2.5.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:521345fd1f19d45b8df87657aaa38b6f2ca3800059fadf428e7ebf479a383646", size = 162080, upload-time = "2026-10-07T12:22:51.558Z" }, { url = "https://files.pythonhosted.org/packages/7e/b2/e5bb8651fdad593f670501a7d718b1a7f73f064d44dea15e04c04dfef45d/tomli-2.5.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e95c7614e705bfe2b04b27aa124adec59752d15813df37e2156747cab3a006b", size = 273380, upload-time = "2026-10-07T12:22:52.918Z" }, { url = "https://files.pythonhosted.org/packages/8d/d2/9e2d7f8b1dfe0e2b34c245986ebd55c4c553ea4ce6c47c443b332673253f/tomli-2.5.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7ac2027d37c3afbdf4bdd377f2676f6f1d2122a5be1f1137b49dced590b37e75", size = 283228, upload-time = "2026-10-07T12:22:54.173Z" }, { url = "https://files.pythonhosted.org/packages/ba/df/ec7b876b7b1a2718bd74a3743c076fff565b04029ba33e8f61fac262739f/tomli-2.5.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c414be4ed9d3cac80c42e348fa5a956117d1a48227f48026e31f59cb4a7671eb", size = 277189, upload-time = "2026-10-07T12:22:55.342Z" }, { url = "https://files.pythonhosted.org/packages/7d/7b/e192d9eed0b9cb80da799f4d77052297fb9a2c3cc9b19f571f56ea88add6/tomli-2.5.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:9b03d7dc168353b4132965bde20feceabaa470e570c6f59660dfae59b1f9eeb3", size = 283632, upload-time = "2026-10-07T12:22:56.735Z" }, { url = "https://files.pythonhosted.org/packages/84/50/ff94454e75461d75623e47401ed323d65c10aab8fe9033242c20cd2fdf32/tomli-2.5.0-cp314-cp314-win32.whl", hash = "sha256:6f041843c4d3a37245c0c056fd955b186bf8b1fb85690cbe40b81230891dc34b", size = 103535, upload-time = "2026-10-07T12:22:58.084Z" }, { url = "https://files.pythonhosted.org/packages/54/0b/bdacf05f963bd6026ebf6eeb0beda847d1d60e03e440725c64a4e08a0afd/tomli-2.5.0-cp314-cp314-win_amd64.whl", hash = "sha256:f4b653094e18f9031102d3a1da5c729c8f222d85225b18037dac621695e46e1a", size = 114621, upload-time = "2026-10-07T12:22:59.2Z" }, { url = "https://files.pythonhosted.org/packages/61/99/53f438fa6ae4f9d4ed0ddde3e7242b3bdc34b48c8f9948b72b9e9b127676/tomli-2.5.0-cp314-cp314-win_arm64.whl", hash = "sha256:3f89d10c1ff6a38d992c27fc8a4816af71a909e08a40ec66934240b1e74347c3", size = 111572, upload-time = "2026-10-07T12:23:00.479Z" }, { url = "https://files.pythonhosted.org/packages/b9/20/1f88f19427d380a40e90a770e087489eaafe4aeee070ae88ed2bbec00acd/tomli-2.5.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:e9e15b4a6c7dd6b85b5fbab29488a73f1f70de516942308daa266bf0e0aeb0d4", size = 171814, upload-time = "2026-10-07T12:23:01.914Z" }, { url = "https://files.pythonhosted.org/packages/d0/56/cbe5079c9f9a54b9b3e27fc82f08f3cb36edee75561679f53d2380c801d6/tomli-2.5.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e12bbcd32897272fb05929110362ae9ff4c1b9bb26bd9e971e71dcd3275b4c3d", size = 171324, upload-time = "2026-10-07T12:23:03.18Z" }, { url = "https://files.pythonhosted.org/packages/2b/30/1d53fd3b0f1cb3ba542e345ec32c26aefdddc4e829e4f3429af8a4f27782/tomli-2.5.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:20aa36de8f2cf87237143bc1fa1aae8d6612c09118f4da21c6a684db5dd1f6f9", size = 297441, upload-time = "2026-10-07T12:23:04.345Z" }, { url = "https://files.pythonhosted.org/packages/66/d9/0800acb6a111686f764c1b91ef15cc42a20a66a46013bb42220f1d2c61c1/tomli-2.5.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22185fad8a1e622f064e78008018a0dd3323550dcb479cb7a1d296888d74024f", size = 307476, upload-time = "2026-10-07T12:23:05.671Z" }, { url = "https://files.pythonhosted.org/packages/e8/63/30a8f3cd51b5bec37f04744bad0b0dc6160df84aad4f27b0e9283d66f221/tomli-2.5.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:984012f71908165449a951de2050d52f276bfe3aa5d5f570f63ddad814370374", size = 296113, upload-time = "2026-10-07T12:23:07.202Z" }, { url = "https://files.pythonhosted.org/packages/ab/18/0b9ffc597e69c5a1e20a7823cb60d54b39a9f54e91edcb8574f022186758/tomli-2.5.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f79203b3965b4000e91808aaa7c040206093f2b8bf86f455982f2274c9ccf442", size = 307725, upload-time = "2026-10-07T12:23:08.508Z" }, { url = "https://files.pythonhosted.org/packages/ab/c7/18f8baae0b5607a60e8e19b4a7fedee43a8ff6458e3896dcbbadeeac9c22/tomli-2.5.0-cp314-cp314t-win32.whl", hash = "sha256:91294a9fb94a75542f6e46e4a2ae709bd8d9b51134098cae5cf3bea5478b6d03", size = 108546, upload-time = "2026-10-07T12:23:09.956Z" }, { url = "https://files.pythonhosted.org/packages/72/34/4cca9739254130627bde87500b3f2b512154fe2f278efa7e2a5e10ad4bcb/tomli-2.5.0-cp314-cp314t-win_amd64.whl", hash = "sha256:f15e3e0b835a6d68b10c86bf80a3149780498d6911c93c3ffd1861d19f9200f1", size = 117814, upload-time = "2026-10-07T12:23:11.486Z" }, { url = "https://files.pythonhosted.org/packages/7d/fb/afa530d47dd80a78fce43beac6bc6e00f84558eafcffbc6f37b21e80d056/tomli-2.5.0-cp314-cp314t-win_arm64.whl", hash = "sha256:6664b7ae7af7294256c53960a6103077f4914cec8ff98479c352f622c6f6b2f0", size = 115188, upload-time = "2026-10-07T12:23:12.728Z" }, { url = "https://files.pythonhosted.org/packages/66/98/316fdc00f8c0939e6fe50461dd343c162d3ad51d1286eb25b7db54361d50/tomli-2.5.0-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:a525685c2f97da40762b8695eb7aa0af4c8344ca1905c73e4e29cb04d34607dc", size = 162775, upload-time = "2026-10-07T12:23:13.941Z" }, { url = "https://files.pythonhosted.org/packages/c5/22/7b10fa5bb01c9539f53f69b619361b19350acc73657772ea7ac70ba309a8/tomli-2.5.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:9dbb18c1cfb2f6517942fc9314437f66aa06d94436ffb1f06102ef3572f35276", size = 161406, upload-time = "2026-10-07T12:23:15.215Z" }, { url = "https://files.pythonhosted.org/packages/9c/e7/1a069d86dfd20f1f84f71c63faed9f83c1d890bc06c27d82dc7d888fb573/tomli-2.5.0-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:752e8b1aa6a4367ef8bf6a1a1e005540f7ed055ba36d7193796812ca5404eb52", size = 273855, upload-time = "2026-10-07T12:23:16.471Z" }, { url = "https://files.pythonhosted.org/packages/ae/83/d1ef43d1687d092ab9c235455c76e6e709483b346b056f086095c7c263a5/tomli-2.5.0-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c47300f9bf791808f77d82747691c4bb09cb14bdf3060cca99b42cdc4361d5a7", size = 284910, upload-time = "2026-10-07T12:23:18.166Z" }, { url = "https://files.pythonhosted.org/packages/cc/05/f4d9cf7de61822ece0c3873f30d291e324911c71a378b8bfe5ced13fd9f5/tomli-2.5.0-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:19b0dd8749f4ea2f112c5fcfb3c5248390c899d7e2e173f1d91abee1fa0ff391", size = 277723, upload-time = "2026-10-07T12:23:19.355Z" }, { url = "https://files.pythonhosted.org/packages/42/28/78262493141fa543151cf005760c3cb01d09fc28a11f993c05109902cb8c/tomli-2.5.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:57b1c3b01fab802e2899bc3d168dca320e14165e2fd9fd584760fb4ca5826859", size = 285115, upload-time = "2026-10-07T12:23:20.698Z" }, { url = "https://files.pythonhosted.org/packages/1a/b9/e1dab9a30bcb677b5cc5cee810609cfd64f24306a3055767dd3fda00b1e0/tomli-2.5.0-cp315-cp315-win32.whl", hash = "sha256:667e521b37a6c5ccaa044202c235b530f90177ffe2cd4a64ecc213c7dd535feb", size = 103475, upload-time = "2026-10-07T12:23:21.941Z" }, { url = "https://files.pythonhosted.org/packages/4c/bd/31a3790c11d6ea95fcf5e6022ac0f8d0543c9b61120b730fc481bd43d3b4/tomli-2.5.0-cp315-cp315-win_amd64.whl", hash = "sha256:d747252933c8a65ef6bd8da0fbb7ce28a90eb6119d8cd00772cd528aa07b68d5", size = 114589, upload-time = "2026-10-07T12:23:23.098Z" }, { url = "https://files.pythonhosted.org/packages/47/a2/4f6310fa699364f0e3af7ee3af88dddd9af066d33e716a0265bbe2b3ea84/tomli-2.5.0-cp315-cp315-win_arm64.whl", hash = "sha256:75dbcde8751b0a960aa3de173aa5e894d590755c6d7758b7e774c06f1dc3cbdd", size = 111493, upload-time = "2026-10-07T12:23:24.233Z" }, { url = "https://files.pythonhosted.org/packages/68/14/00853f0b396d8971107ae1921bb5b322fdee1650d2f16bf06c20adb532e5/tomli-2.5.0-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:2419c2a189551987b59d80e63ec355671283336f41c6b9b89462df679c7d0c57", size = 171380, upload-time = "2026-10-07T12:23:25.512Z" }, { url = "https://files.pythonhosted.org/packages/89/ad/fa6949321dadee46b27363974fb197b94c911c3b0f7a5fd26d7dc18fc2a0/tomli-2.5.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:0dc598040da8d42cf20f0be588ed7004f46db12a0ac6c32e03a59dccedaaadcd", size = 170553, upload-time = "2026-10-07T12:23:26.855Z" }, { url = "https://files.pythonhosted.org/packages/53/aa/3056c919eb3e084df3752b2cf5f865dcc04af0b27dba2f66d7b28af4633a/tomli-2.5.0-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:49096930c8d886c9bbdab62d2d0d17ce823ddeea522309a190b36245d5b49e01", size = 294428, upload-time = "2026-10-07T12:23:28.132Z" }, { url = "https://files.pythonhosted.org/packages/96/b2/faeeb5d8769ea3832021d73e892c8391eae7b4b4f8b55a789127bd8b18a9/tomli-2.5.0-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8ade5023067f99fe72b88accd30d0ea05a158e9e32a11f124e731ea9695313f", size = 304909, upload-time = "2026-10-07T12:23:29.381Z" }, { url = "https://files.pythonhosted.org/packages/f6/52/f094c09e73fb654b621716d019acb5d29bdfd1be01df80c281d552bda48d/tomli-2.5.0-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:b69564772b5c8f22ea5f498dff08cfa825045b4d4c4400529000bdf818aa3b2a", size = 293220, upload-time = "2026-10-07T12:23:30.608Z" }, { url = "https://files.pythonhosted.org/packages/86/f5/0c30541078ca4b505ce3bd76ed931facbfec524dd018535d691d1af0a6d2/tomli-2.5.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:8ff3a2ca028c7eee0c777f9a092038d0a594a9fa04e215f929a22c329e2cb142", size = 305705, upload-time = "2026-10-07T12:23:32.181Z" }, { url = "https://files.pythonhosted.org/packages/05/74/590e7d19d6a118fc5cc5704ff358e21d95b8573f6b9443b1519f29ca8825/tomli-2.5.0-cp315-cp315t-win32.whl", hash = "sha256:62fc1bc8eb03e3a9cadfca713d65614ed8e09d974a283295ffe3a831976b4dc5", size = 108432, upload-time = "2026-10-07T12:23:33.496Z" }, { url = "https://files.pythonhosted.org/packages/1c/b8/63a75cfb27a17c38550e44025d3a6e7be64516fd8608a3b75703bf37d81b/tomli-2.5.0-cp315-cp315t-win_amd64.whl", hash = "sha256:f3fcbc57b1791fa6cbe5d8434179d51de12be1a4811469529f47f6e7487a2571", size = 117281, upload-time = "2026-10-07T12:23:34.648Z" }, { url = "https://files.pythonhosted.org/packages/72/01/e8c1debb2173973372934c68fc8e46170ab60ef23ed4592dff4dec6e8993/tomli-2.5.0-cp315-cp315t-win_arm64.whl", hash = "sha256:d2ba24db8a9376921b5e87b4762b9adb0f3f1deaea68f2b8b0bb2c11efb9c3e7", size = 115069, upload-time = "2026-10-07T12:23:35.77Z" }, { url = "https://files.pythonhosted.org/packages/60/3f/3e3f8fd0919249b0200c80fbc4f9a1e70be19f9883da71dfb7f8b9ab8aca/tomli-2.5.0-py3-none-any.whl", hash = "sha256:32a7b79ac57a2e83670ce329ccf675798bc5a2094783a63676866b70503f2e2b", size = 14765, upload-time = "2026-10-07T12:23:36.875Z" }, ] [[package]] name = "typing-extensions" version = "4.16.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" }, ] [[package]] name = "urllib3" version = "2.8.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/e3/05/b17359e1cefb4f909b5e40b1b90a496d987258916dbbf88e842c729f510e/urllib3-2.8.0.tar.gz", hash = "sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63", size = 458972, upload-time = "2026-09-15T19:29:36.253Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/92/9d/c4e665119135114480843e7ab388fa94d8480650450e6f8e26b70d323a4c/urllib3-2.8.0-py3-none-any.whl", hash = "sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3", size = 135717, upload-time = "2026-09-15T19:29:34.577Z" }, ] ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������