Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-mistune for openSUSE:Factory checked in at 2026-03-17 19:03:02 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-mistune (Old) and /work/SRC/openSUSE:Factory/.python-mistune.new.8177 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-mistune" Tue Mar 17 19:03:02 2026 rev:26 rq:1339433 version:3.2.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-mistune/python-mistune.changes 2025-09-20 22:03:57.818377060 +0200 +++ /work/SRC/openSUSE:Factory/.python-mistune.new.8177/python-mistune.changes 2026-03-17 19:04:24.308441940 +0100 @@ -1,0 +2,9 @@ +Mon Mar 16 20:49:11 UTC 2026 - Dirk Müller <[email protected]> + +- update to 3.2.0: + * Announce supports for python 3.14 + * Fix footnotes plugins for code blocks, ref links, blockquote + and etc. + * Fix ref links in TOC. + +------------------------------------------------------------------- Old: ---- mistune-3.1.4.tar.gz New: ---- mistune-3.2.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-mistune.spec ++++++ --- /var/tmp/diff_new_pack.ElxDV5/_old 2026-03-17 19:04:24.888465977 +0100 +++ /var/tmp/diff_new_pack.ElxDV5/_new 2026-03-17 19:04:24.892466143 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-mistune # -# Copyright (c) 2025 SUSE LLC +# Copyright (c) 2026 SUSE LLC and contributors # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -19,7 +19,7 @@ %define modname mistune %{?sle15_python_module_pythons} Name: python-%{modname} -Version: 3.1.4 +Version: 3.2.0 Release: 0 Summary: Python Markdown parser with renderers and plugins License: BSD-3-Clause ++++++ mistune-3.1.4.tar.gz -> mistune-3.2.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mistune-3.1.4/.github/workflows/pypi.yml new/mistune-3.2.0/.github/workflows/pypi.yml --- old/mistune-3.1.4/.github/workflows/pypi.yml 2025-08-29 09:19:20.000000000 +0200 +++ new/mistune-3.2.0/.github/workflows/pypi.yml 2025-12-23 12:28:42.000000000 +0100 @@ -1,9 +1,5 @@ name: Release to PyPI -permissions: - contents: write - id-token: write - on: push: tags: @@ -15,9 +11,9 @@ runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - - uses: actions/setup-python@v5 + - uses: actions/setup-python@v6 with: python-version: 3.9 @@ -27,13 +23,15 @@ - name: build dist run: python -m build - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v6 with: name: artifacts path: dist/* if-no-files-found: error publish: + permissions: + id-token: write environment: name: pypi-release @@ -42,7 +40,7 @@ runs-on: ubuntu-latest steps: - - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@v7 with: name: artifacts path: dist @@ -51,17 +49,19 @@ 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@v4 + - uses: actions/checkout@v6 with: fetch-depth: 0 - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v6 with: - node-version: 18 + node-version: 24 - run: npx changelogithub --no-group continue-on-error: true env: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mistune-3.1.4/.github/workflows/tests.yml new/mistune-3.2.0/.github/workflows/tests.yml --- old/mistune-3.1.4/.github/workflows/tests.yml 2025-08-29 09:19:20.000000000 +0200 +++ new/mistune-3.2.0/.github/workflows/tests.yml 2025-12-23 12:28:42.000000000 +0100 @@ -20,12 +20,12 @@ max-parallel: 6 matrix: os: [ubuntu-latest, macos-latest, windows-latest] - python: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "pypy3.9"] + python: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14", "pypy3.11"] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Python ${{ matrix.python }} on ${{ matrix.os }} - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: ${{ matrix.python }} @@ -44,7 +44,7 @@ run: pytest --cov=mistune --cov-report=xml - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v5 with: token: ${{ secrets.CODECOV_TOKEN }} files: ./coverage.xml diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mistune-3.1.4/.readthedocs.yaml new/mistune-3.2.0/.readthedocs.yaml --- old/mistune-3.1.4/.readthedocs.yaml 2025-08-29 09:19:20.000000000 +0200 +++ new/mistune-3.2.0/.readthedocs.yaml 2025-12-23 12:28:42.000000000 +0100 @@ -3,7 +3,7 @@ build: os: "ubuntu-20.04" tools: - python: "3.10" + python: "3.13" sphinx: configuration: docs/conf.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mistune-3.1.4/README.md new/mistune-3.2.0/README.md --- old/mistune-3.1.4/README.md 2025-08-29 09:19:20.000000000 +0200 +++ new/mistune-3.2.0/README.md 2025-12-23 12:28:42.000000000 +0100 @@ -67,7 +67,10 @@ ## Benchmarks +<details> +<summary> Here is the benchmark score on my computer. Check the `benchmark/bench.py` script. +</summary> ``` mistune (3.0.0) - atx: 13.901472091674805ms @@ -192,6 +195,28 @@ markdown_it (2.1.0) - readme: 247.9879856109619ms ``` +</details> + +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 | <mark>13.12</mark> | 13.25 | 15.45 | 48.41 | 379.31 | 25.46 | 42.38 | +| **setext** | 8.43 | 8.98 | <mark>8.12</mark> | 9.53 | 30.75 | 218.91 | 20.47 | 27.01 | +| **normal_ul** | 60.91 | <mark>59.70</mark> | 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 | <mark>85.93</mark> | +| **normal_ol** | <mark>25.10</mark> | 25.32 | 25.11 | 25.95 | 43.30 | 75.88 | 33.64 | 40.31 | +| **insane_ol** | 46.20 | 49.15 | <mark>45.97</mark> | 47.54 | 50.15 | 210.49 | 84.08 | 83.62 | +| **blockquote** | 15.48 | 16.13 | <mark>15.35</mark> | 16.10 | 63.04 | 702.44 | 28.56 | 37.35 | +| **blockhtml** | 7.90 | <mark>7.08</mark> | 7.41 | 8.56 | 46.66 | 122.10 | 12.24 | 26.84 | +| **fenced** | 4.28 | 4.09 | <mark>4.02</mark> | 4.45 | 33.84 | 92.49 | 9.19 | 12.50 | +| **paragraph** | 95.94 | 561.28 | <mark>93.60</mark> | 110.10 | 304.13 | 267.85 | 779.32 | 825.52 | +| **emphasis** | 23.59 | 16.93 | 23.23 | 25.28 | 76.50 | <mark>9.39</mark> | 33.69 | 60.91 | +| **auto_links** | 3.80 | <mark>3.39</mark> | 3.66 | 3.92 | 23.05 | 6.54 | 8.36 | 19.73 | +| **std_links** | 21.92 | 17.49 | 19.88 | 24.51 | 39.12 | <mark>14.52</mark> | 22.85 | 32.61 | +| **ref_links** | 47.67 | 39.45 | 44.82 | 52.38 | 87.66 | <mark>23.12</mark> | 59.14 | 80.45 | +| **readme** | 56.61 | 68.82 | <mark>53.86</mark> | 61.26 | 211.03 | 533.41 | 110.13 | 247.99 | + ## License Mistune is licensed under BSD. Please see LICENSE for licensing details. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mistune-3.1.4/docs/changes.rst new/mistune-3.2.0/docs/changes.rst --- old/mistune-3.1.4/docs/changes.rst 2025-08-29 09:19:20.000000000 +0200 +++ new/mistune-3.2.0/docs/changes.rst 2025-12-23 12:28:42.000000000 +0100 @@ -3,6 +3,15 @@ Here is the full history of mistune v3. +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 ------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mistune-3.1.4/pyproject.toml new/mistune-3.2.0/pyproject.toml --- old/mistune-3.1.4/pyproject.toml 2025-08-29 09:19:20.000000000 +0200 +++ new/mistune-3.2.0/pyproject.toml 2025-12-23 12:28:42.000000000 +0100 @@ -24,6 +24,7 @@ "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Text Processing :: Markup", @@ -40,7 +41,7 @@ [dependency-groups] dev = [ - "mypy", + "mypy<1.19", "pytest", "pytest-cov", "ruff", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mistune-3.1.4/requirements-dev.lock new/mistune-3.2.0/requirements-dev.lock --- old/mistune-3.1.4/requirements-dev.lock 2025-08-29 09:19:20.000000000 +0200 +++ new/mistune-3.2.0/requirements-dev.lock 2025-12-23 12:28:42.000000000 +0100 @@ -3,17 +3,25 @@ -e . colorama==0.4.6 ; sys_platform == 'win32' coverage==7.6.1 ; python_full_version < '3.9' -coverage==7.7.0 ; python_full_version >= '3.9' -exceptiongroup==1.2.2 ; python_full_version < '3.11' -iniconfig==2.0.0 +coverage==7.10.7 ; python_full_version == '3.9.*' +coverage==7.13.0 ; python_full_version >= '3.10' +exceptiongroup==1.3.1 ; python_full_version < '3.11' +iniconfig==2.1.0 ; python_full_version < '3.10' +iniconfig==2.3.0 ; python_full_version >= '3.10' mypy==1.14.1 ; python_full_version < '3.9' -mypy==1.15.0 ; python_full_version >= '3.9' -mypy-extensions==1.0.0 -packaging==24.2 -pluggy==1.5.0 -pytest==8.3.5 +mypy==1.18.2 ; python_full_version >= '3.9' +mypy-extensions==1.1.0 +packaging==25.0 +pathspec==0.12.1 ; python_full_version >= '3.9' +pluggy==1.5.0 ; python_full_version < '3.9' +pluggy==1.6.0 ; python_full_version >= '3.9' +pygments==2.19.2 ; python_full_version >= '3.9' +pytest==8.3.5 ; python_full_version < '3.9' +pytest==8.4.2 ; python_full_version == '3.9.*' +pytest==9.0.2 ; python_full_version >= '3.10' pytest-cov==5.0.0 ; python_full_version < '3.9' -pytest-cov==6.0.0 ; python_full_version >= '3.9' -ruff==0.11.0 -tomli==2.2.1 ; python_full_version <= '3.11' -typing-extensions==4.12.2 +pytest-cov==7.0.0 ; python_full_version >= '3.9' +ruff==0.14.10 +tomli==2.3.0 ; python_full_version <= '3.11' +typing-extensions==4.13.2 ; python_full_version < '3.9' +typing-extensions==4.15.0 ; python_full_version >= '3.9' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mistune-3.1.4/requirements-docs.lock new/mistune-3.2.0/requirements-docs.lock --- old/mistune-3.1.4/requirements-docs.lock 2025-08-29 09:19:20.000000000 +0200 +++ new/mistune-3.2.0/requirements-docs.lock 2025-12-23 12:28:42.000000000 +0100 @@ -5,33 +5,48 @@ alabaster==0.7.16 ; python_full_version == '3.9.*' alabaster==1.0.0 ; python_full_version >= '3.10' babel==2.17.0 -certifi==2025.1.31 -charset-normalizer==3.4.1 +certifi==2025.11.12 +charset-normalizer==3.4.4 colorama==0.4.6 ; sys_platform == 'win32' +coverage==7.6.1 ; python_full_version < '3.9' +coverage==7.10.7 ; python_full_version == '3.9.*' +coverage==7.13.0 ; python_full_version >= '3.10' docutils==0.20.1 ; python_full_version < '3.9' docutils==0.21.2 ; python_full_version >= '3.9' -exceptiongroup==1.2.2 ; python_full_version < '3.11' -idna==3.10 +exceptiongroup==1.3.1 ; python_full_version < '3.11' +idna==3.11 imagesize==1.4.1 importlib-metadata==8.5.0 ; python_full_version < '3.9' -importlib-metadata==8.6.1 ; python_full_version == '3.9.*' -iniconfig==2.0.0 +importlib-metadata==8.7.1 ; python_full_version == '3.9.*' +iniconfig==2.1.0 ; python_full_version < '3.10' +iniconfig==2.3.0 ; python_full_version >= '3.10' jinja2==3.1.6 markupsafe==2.1.5 ; python_full_version < '3.9' -markupsafe==3.0.2 ; python_full_version >= '3.9' +markupsafe==3.0.3 ; python_full_version >= '3.9' mypy==1.14.1 ; python_full_version < '3.9' -mypy==1.15.0 ; python_full_version >= '3.9' -mypy-extensions==1.0.0 -packaging==24.2 -pluggy==1.5.0 -pygments==2.19.1 -pytest==8.3.5 -pytz==2025.1 ; python_full_version < '3.9' -requests==2.32.3 -roman-numerals-py==3.1.0 ; python_full_version >= '3.11' -ruff==0.11.0 -shibuya==2025.2.28 -snowballstemmer==2.2.0 +mypy==1.18.2 ; python_full_version >= '3.9' +mypy-extensions==1.1.0 +packaging==25.0 +pathspec==0.12.1 ; python_full_version >= '3.9' +pluggy==1.5.0 ; python_full_version < '3.9' +pluggy==1.6.0 ; python_full_version >= '3.9' +pygments==2.19.2 +pygments-styles==0.3.0 ; python_full_version >= '3.9' +pytest==8.3.5 ; python_full_version < '3.9' +pytest==8.4.2 ; python_full_version == '3.9.*' +pytest==9.0.2 ; python_full_version >= '3.10' +pytest-cov==5.0.0 ; python_full_version < '3.9' +pytest-cov==7.0.0 ; python_full_version >= '3.9' +pytz==2025.2 ; python_full_version < '3.9' +requests==2.32.4 ; python_full_version < '3.9' +requests==2.32.5 ; python_full_version >= '3.9' +roman-numerals==4.1.0 ; python_full_version >= '3.11' +roman-numerals-py==4.1.0 ; python_full_version >= '3.11' +ruff==0.14.10 +shibuya==2025.5.30 ; python_full_version < '3.9' +shibuya==2025.10.21 ; python_full_version == '3.9.*' +shibuya==2025.12.19 ; python_full_version >= '3.10' +snowballstemmer==3.0.1 sphinx==7.1.2 ; python_full_version < '3.9' sphinx==7.4.7 ; python_full_version == '3.9.*' sphinx==8.1.3 ; python_full_version == '3.10.*' @@ -50,9 +65,10 @@ sphinxcontrib-qthelp==2.0.0 ; python_full_version >= '3.9' sphinxcontrib-serializinghtml==1.1.5 ; python_full_version < '3.9' sphinxcontrib-serializinghtml==2.0.0 ; python_full_version >= '3.9' -tomli==2.2.1 ; python_full_version < '3.11' -typing-extensions==4.12.2 +tomli==2.3.0 ; python_full_version <= '3.11' +typing-extensions==4.13.2 ; python_full_version < '3.9' +typing-extensions==4.15.0 ; python_full_version >= '3.9' urllib3==2.2.3 ; python_full_version < '3.9' -urllib3==2.3.0 ; python_full_version >= '3.9' +urllib3==2.6.2 ; python_full_version >= '3.9' zipp==3.20.2 ; python_full_version < '3.9' -zipp==3.21.0 ; python_full_version == '3.9.*' +zipp==3.23.0 ; python_full_version == '3.9.*' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mistune-3.1.4/src/mistune/__init__.py new/mistune-3.2.0/src/mistune/__init__.py --- old/mistune-3.1.4/src/mistune/__init__.py 2025-08-29 09:19:20.000000000 +0200 +++ new/mistune-3.2.0/src/mistune/__init__.py 2025-12-23 12:28:42.000000000 +0100 @@ -97,5 +97,5 @@ "markdown", ] -__version__ = "3.1.4" +__version__ = "3.2.0" __homepage__ = "https://mistune.lepture.com/" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mistune-3.1.4/src/mistune/directives/toc.py new/mistune-3.2.0/src/mistune/directives/toc.py --- old/mistune-3.1.4/src/mistune/directives/toc.py 2025-08-29 09:19:20.000000000 +0200 +++ new/mistune-3.2.0/src/mistune/directives/toc.py 2025-12-23 12:28:42.000000000 +0100 @@ -73,7 +73,7 @@ # adding ID for each heading for i, tok in enumerate(headings): tok["attrs"]["id"] = self.generate_heading_id(tok, i) - toc_items.append(normalize_toc_item(md, tok)) + toc_items.append(normalize_toc_item(md, tok, parent=state)) for sec in sections: _min = sec["attrs"]["min_level"] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mistune-3.1.4/src/mistune/list_parser.py new/mistune-3.2.0/src/mistune/list_parser.py --- old/mistune-3.1.4/src/mistune/list_parser.py 2025-08-29 09:19:20.000000000 +0200 +++ new/mistune-3.2.0/src/mistune/list_parser.py 2025-12-23 12:28:42.000000000 +0100 @@ -1,7 +1,9 @@ """because list is complex, split list parser in a new file""" +from __future__ import annotations + import re -from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Optional, Tuple, Match +from typing import TYPE_CHECKING, Any, Iterable, Optional, Match from .util import expand_leading_tab, expand_tab, strip_end if TYPE_CHECKING: @@ -30,7 +32,7 @@ marker = m.group("list_2") ordered = len(marker) > 1 depth = state.depth() - token: Dict[str, Any] = { + token: dict[str, Any] = { "type": "list", "children": [], "tight": True, @@ -51,7 +53,7 @@ token["attrs"]["start"] = start state.cursor = m.end() + 1 - groups: Optional[Tuple[str, str, str]] = (m.group("list_1"), marker, text) + groups: Optional[tuple[str, str, str]] = (m.group("list_1"), marker, text) if depth >= block.max_nested_level - 1: rules = list(block.list_rules) @@ -68,13 +70,13 @@ if end_pos: index = token.pop("_tok_index") state.tokens.insert(index, token) - return end_pos + return end_pos # type: ignore[no-any-return] state.append_token(token) return state.cursor -def _transform_tight_list(token: Dict[str, Any]) -> None: +def _transform_tight_list(token: dict[str, Any]) -> None: if token["tight"]: # reset tight list item for list_item in token["children"]: @@ -88,11 +90,11 @@ def _parse_list_item( block: "BlockParser", bullet: str, - groups: Tuple[str, str, str], - token: Dict[str, Any], + groups: tuple[str, str, str], + token: dict[str, Any], state: "BlockState", - rules: List[str], -) -> Optional[Tuple[str, str, str]]: + rules: list[str], +) -> tuple[str, str, str] | None: spaces, marker, text = groups leading_width = len(spaces) + len(marker) @@ -216,7 +218,7 @@ ) -def _compile_continue_width(text: str, leading_width: int) -> Tuple[str, int]: +def _compile_continue_width(text: str, leading_width: int) -> tuple[str, int]: text = expand_leading_tab(text, 3) text = expand_tab(text) @@ -255,7 +257,7 @@ return "\n".join(rv) -def _is_loose_list(tokens: Iterable[Dict[str, Any]]) -> bool: +def _is_loose_list(tokens: Iterable[dict[str, Any]]) -> bool: paragraph_count = 0 for tok in tokens: if tok["type"] == "blank_line": diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mistune-3.1.4/src/mistune/plugins/footnotes.py new/mistune-3.2.0/src/mistune/plugins/footnotes.py --- old/mistune-3.1.4/src/mistune/plugins/footnotes.py 2025-08-29 09:19:20.000000000 +0200 +++ new/mistune-3.2.0/src/mistune/plugins/footnotes.py 2025-12-23 12:28:42.000000000 +0100 @@ -16,10 +16,10 @@ _PARAGRAPH_SPLIT = re.compile(r"\n{2,}") # https://michelf.ca/projects/php-markdown/extra/#footnotes REF_FOOTNOTE = ( - r"^(?P<footnote_lead> {0,3})" - r"\[\^(?P<footnote_key>" + LINK_LABEL + r")]:[ \t]" + r"^(?P<footnote_lead> {0,4})" + r"\[\^(?P<footnote_key>" + LINK_LABEL + r")]:[ \t\n]" r"(?P<footnote_text>[^\n]*(?:\n+|$)" - r"(?:(?P=footnote_lead) {1,3}(?! )[^\n]*\n+)*" + r"(?:(?P=footnote_lead) {1,4}(?! )[^\n]*\n+)*" r")" ) @@ -70,8 +70,11 @@ spaces = len(second_line) - len(second_line.lstrip()) pattern = re.compile(r"^ {" + str(spaces) + r",}", flags=re.M) text = pattern.sub("", text).strip() - items = _PARAGRAPH_SPLIT.split(text) - children = [{"type": "paragraph", "text": s} for s in items] + + footer_state = BlockState() + footer_state.process(text) + block.parse(footer_state) + children = footer_state.tokens else: text = text.strip() children = [{"type": "paragraph", "text": text}] @@ -86,7 +89,7 @@ return result children = [parse_footnote_item(md.block, k, i + 1, state) for i, k in enumerate(notes)] - state = BlockState() + state = BlockState(parent=state) state.tokens = [{"type": "footnotes", "children": children}] output = md.render_state(state) return result + output # type: ignore[operator] @@ -105,7 +108,11 @@ 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()[:-4] + back + "</p>" + 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" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mistune-3.1.4/src/mistune/renderers/markdown.py new/mistune-3.2.0/src/mistune/renderers/markdown.py --- old/mistune-3.1.4/src/mistune/renderers/markdown.py 2025-08-29 09:19:20.000000000 +0200 +++ new/mistune-3.2.0/src/mistune/renderers/markdown.py 2025-12-23 12:28:42.000000000 +0100 @@ -51,7 +51,7 @@ return out + "[" + label + "]" attrs = token["attrs"] - url = attrs["url"] + url: str = attrs["url"] title = attrs.get("title") if text == url and not title: return "<" + text + ">" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mistune-3.1.4/src/mistune/toc.py new/mistune-3.2.0/src/mistune/toc.py --- old/mistune-3.1.4/src/mistune/toc.py 2025-08-29 09:19:20.000000000 +0200 +++ new/mistune-3.2.0/src/mistune/toc.py 2025-12-23 12:28:42.000000000 +0100 @@ -48,7 +48,7 @@ toc_items = [] for i, tok in enumerate(headings): tok["attrs"]["id"] = heading_id(tok, i) - toc_items.append(normalize_toc_item(md, tok)) + toc_items.append(normalize_toc_item(md, tok, parent=state)) # save items into state state.env["toc_items"] = toc_items @@ -56,9 +56,9 @@ md.before_render_hooks.append(toc_hook) -def normalize_toc_item(md: "Markdown", token: Dict[str, Any]) -> Tuple[int, str, str]: +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, {}) + tokens = md.inline(text, parent.env if parent else {}) assert md.renderer is not None html = md.renderer(tokens, BlockState()) text = striptags(html) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mistune-3.1.4/tests/fixtures/fenced_toc.txt new/mistune-3.2.0/tests/fixtures/fenced_toc.txt --- old/mistune-3.1.4/tests/fixtures/fenced_toc.txt 2025-08-29 09:19:20.000000000 +0200 +++ new/mistune-3.2.0/tests/fixtures/fenced_toc.txt 2025-12-23 12:28:42.000000000 +0100 @@ -182,15 +182,19 @@ ```````````````````````````````` 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> ```````````````````````````````` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mistune-3.1.4/tests/fixtures/footnotes.txt new/mistune-3.2.0/tests/fixtures/footnotes.txt --- old/mistune-3.1.4/tests/fixtures/footnotes.txt 2025-08-29 09:19:20.000000000 +0200 +++ new/mistune-3.2.0/tests/fixtures/footnotes.txt 2025-12-23 12:28:42.000000000 +0100 @@ -31,15 +31,124 @@ three four + + five . <p>multiple lines <sup class="footnote-ref" id="fnref-1"><a href="#fn-1">1</a></sup></p> -<pre><code>four</code></pre> +<pre><code> five</code></pre> <section class="footnotes"> <ol> <li id="fn-1"><p>foo</p> <p>one</p> <p>two</p> -<p>three<a href="#fnref-1" class="footnote">↩</a></p></li> +<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> ```````````````````````````````` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mistune-3.1.4/tests/fixtures/hook_toc.txt new/mistune-3.2.0/tests/fixtures/hook_toc.txt --- old/mistune-3.1.4/tests/fixtures/hook_toc.txt 2025-08-29 09:19:20.000000000 +0200 +++ new/mistune-3.2.0/tests/fixtures/hook_toc.txt 2025-12-23 12:28:42.000000000 +0100 @@ -103,10 +103,14 @@ ```````````````````````````````` 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> ```````````````````````````````` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mistune-3.1.4/tests/fixtures/rst_toc.txt new/mistune-3.2.0/tests/fixtures/rst_toc.txt --- old/mistune-3.1.4/tests/fixtures/rst_toc.txt 2025-08-29 09:19:20.000000000 +0200 +++ new/mistune-3.2.0/tests/fixtures/rst_toc.txt 2025-12-23 12:28:42.000000000 +0100 @@ -173,13 +173,17 @@ ```````````````````````````````` 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> ````````````````````````````````
