From 9010219283aa5ac5cdbf903041d39b2f3e10de83 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Sat, 15 Aug 2026 15:04:06 +0200 Subject: [PATCH 1/8] Bump minimum Python to 3.11 Test on 3.11-3.15 --- .github/workflows/main.yaml | 2 +- pyproject.toml | 2 +- tox.ini | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 193ec92..dc64570 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -18,7 +18,7 @@ jobs: tox_env: ${{ matrix.tox_env }} strategy: matrix: - tox_env: [py38, py39, py310, py311, py312] + tox_env: [py311, py312, py313, py314, py315] # Use GitHub's Linux Docker host runs-on: ubuntu-latest diff --git a/pyproject.toml b/pyproject.toml index 53dfcca..b86569e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ name = "naucse_render" version = '2.0' description = 'Converts course material to naucse.python.cz API' readme = "README.md" -requires-python = ">=3.8" +requires-python = ">=3.11" classifiers = [ "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", diff --git a/tox.ini b/tox.ini index 5b3e97d..3692f57 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py{38,39,310,311,312} +envlist = py{311,312,313,314,315} isolated_build = True [testenv] From f13fdc88758722a83067c582e5ed204be3cf005c Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Sat, 15 Aug 2026 15:04:26 +0200 Subject: [PATCH 2/8] Pin Mistune to <3.3 for now --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index b86569e..6e0e79e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,7 +14,7 @@ classifiers = [ ] dependencies = [ 'ansi2html', - 'mistune>=2.0.3,<4', + 'mistune<3.3.0', 'nbconvert>=7.0,<8.0', 'traitlets', 'click', From 9cda89c95779273e870882bae59b3731a9775ca3 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Sat, 15 Aug 2026 15:05:55 +0200 Subject: [PATCH 3/8] Update expected output to newer library versions - `&` -> `&` - some spaces are newly highlighted as whitespace --- .../default/install-editor/index.html | 2 +- .../lessons/install-editor/index.html | 2 +- .../lessons/test_subpages/index.html | 2 +- .../expected-dumps/beginners/install-editor.yaml | 14 +++++++------- .../expected-dumps/testcases/test_subpages.yaml | 6 +++--- test_naucse_render/test_markdown.py | 4 ++-- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/test_naucse_render/fixtures/expected-compiled/default/install-editor/index.html b/test_naucse_render/fixtures/expected-compiled/default/install-editor/index.html index eb28f9a..6351001 100644 --- a/test_naucse_render/fixtures/expected-compiled/default/install-editor/index.html +++ b/test_naucse_render/fixtures/expected-compiled/default/install-editor/index.html @@ -14,7 +14,7 @@

Co programátorský editor umí

...

Pro ilustraci, takhle může v editoru vypadat kousek kódu:

    1  @app.route('/courses/<course:course>/')
-    2  def course_page(course):
+    2  def course_page(course):
     3      ...
 

Volba a nastavení editoru # diff --git a/test_naucse_render/fixtures/expected-compiled/lessons/install-editor/index.html b/test_naucse_render/fixtures/expected-compiled/lessons/install-editor/index.html index eb28f9a..6351001 100644 --- a/test_naucse_render/fixtures/expected-compiled/lessons/install-editor/index.html +++ b/test_naucse_render/fixtures/expected-compiled/lessons/install-editor/index.html @@ -14,7 +14,7 @@

Co programátorský editor umí

...

Pro ilustraci, takhle může v editoru vypadat kousek kódu:

    1  @app.route('/courses/<course:course>/')
-    2  def course_page(course):
+    2  def course_page(course):
     3      ...
 

Volba a nastavení editoru # diff --git a/test_naucse_render/fixtures/expected-compiled/lessons/test_subpages/index.html b/test_naucse_render/fixtures/expected-compiled/lessons/test_subpages/index.html index f305c88..1c31e54 100644 --- a/test_naucse_render/fixtures/expected-compiled/lessons/test_subpages/index.html +++ b/test_naucse_render/fixtures/expected-compiled/lessons/test_subpages/index.html @@ -1 +1 @@ -

This is the main page with links to subpages one, two and three.

\ No newline at end of file +

This is the main page with links to subpages one, two and three.

\ No newline at end of file diff --git a/test_naucse_render/fixtures/expected-dumps/beginners/install-editor.yaml b/test_naucse_render/fixtures/expected-dumps/beginners/install-editor.yaml index 2a2be7c..abbc023 100644 --- a/test_naucse_render/fixtures/expected-dumps/beginners/install-editor.yaml +++ b/test_naucse_render/fixtures/expected-dumps/beginners/install-editor.yaml @@ -98,13 +98,13 @@ data: nd\">@app.route('/courses/<course:course>/')\n 2 def course_page(course):\n 3 ...\n

Volba a nastaven\xED editoru\n#\n

\n

...

\n
    \n
  • def course_page(course):\n 3 ...\nVolba a nastaven\xED editoru\n\ + #\n\ +

\n

...

\n
    \n
  • Atom \u2013 doporu\u010Den\xFD editor pro\nWindows a macOS.
  • \n\
\n

...

\n
    \n
  • Gedit \u2013 b\xFDv\xE1 na syst\xE9mech s\_prost\u0159ed\xED\ diff --git a/test_naucse_render/fixtures/expected-dumps/testcases/test_subpages.yaml b/test_naucse_render/fixtures/expected-dumps/testcases/test_subpages.yaml index 337ab2e..518aa88 100644 --- a/test_naucse_render/fixtures/expected-dumps/testcases/test_subpages.yaml +++ b/test_naucse_render/fixtures/expected-dumps/testcases/test_subpages.yaml @@ -20,9 +20,9 @@ data: index: attribution: - Petr Viktorin - content:

    This is the main page with links to subpages one, - two - and three.

    + content:

    This is the main page with links to subpages one, + two + and three.

    ids: [] license: cc0 links: diff --git a/test_naucse_render/test_markdown.py b/test_naucse_render/test_markdown.py index 787cf94..c8a68ab 100644 --- a/test_naucse_render/test_markdown.py +++ b/test_naucse_render/test_markdown.py @@ -226,8 +226,8 @@ def test_convert_with_prompt_spaces_pycon(): """) expected = dedent("""
    
    -        >>> def
    -         foo(
    +        >>> def
    +         foo(
             req):
             ... 
                 return req
    
    From f83c054ea792ff07b9b4e66082ea03f38848a25b Mon Sep 17 00:00:00 2001
    From: Petr Viktorin 
    Date: Sat, 15 Aug 2026 15:21:37 +0200
    Subject: [PATCH 4/8] Update admonition plugin for new Mistune
    
    Based on the new 'spoiler' plugin
    ---
     naucse_render/markdown.py | 17 ++++++++++++-----
     pyproject.toml            |  2 +-
     2 files changed, 13 insertions(+), 6 deletions(-)
    
    diff --git a/naucse_render/markdown.py b/naucse_render/markdown.py
    index 0abb534..e636f36 100644
    --- a/naucse_render/markdown.py
    +++ b/naucse_render/markdown.py
    @@ -25,12 +25,13 @@ def naucse_admonition_plugin(md):
         # out how to write a plugin")
     
         ADMONITION_NAME_PATTERN = re.compile(r' *\[(\S+)\]([^\n]*)\n')
    -
         def parse_naucse_admonition(block, m, state):
    +        text, end_pos, lazy_line_starts = block.extract_block_quote(m, state)
     
    -        text, end_pos = block.extract_block_quote(m, state)
             name_match = ADMONITION_NAME_PATTERN.match(text)
    -        if name_match:
    +
    +        depth = state.depth()
    +        if not depth and name_match:
                 # It's an admonition
                 token = {
                     'type': 'naucse_admonition',
    @@ -45,8 +46,14 @@ def parse_naucse_admonition(block, m, state):
                     'type': 'block_quote',
                 }
     
    -        child = state.child_state(text)
    -        rules = block.block_quote_rules
    +        # 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['children'] = child.tokens
             if end_pos:
    diff --git a/pyproject.toml b/pyproject.toml
    index 6e0e79e..631e480 100644
    --- a/pyproject.toml
    +++ b/pyproject.toml
    @@ -14,7 +14,7 @@ classifiers = [
     ]
     dependencies = [
         'ansi2html',
    -    'mistune<3.3.0',
    +    'mistune>=3.3.0,<4',
         'nbconvert>=7.0,<8.0',
         'traitlets',
         'click',
    
    From 8169a8ce4bb800375f45d0642f6f2fdfd45d103e Mon Sep 17 00:00:00 2001
    From: Petr Viktorin 
    Date: Sat, 15 Aug 2026 15:40:53 +0200
    Subject: [PATCH 5/8] Allow "harmful protocols" in Markdown (for `naucse:`)
    
    ---
     naucse_render/markdown.py | 17 +++++++++++++++--
     1 file changed, 15 insertions(+), 2 deletions(-)
    
    diff --git a/naucse_render/markdown.py b/naucse_render/markdown.py
    index e636f36..ff9f81f 100644
    --- a/naucse_render/markdown.py
    +++ b/naucse_render/markdown.py
    @@ -139,9 +139,22 @@ def text_to_id(text):
     class NaucseRenderer(mistune.HTMLRenderer):
         code_tmpl = '
    {}
    ' - def __init__(self, convert_url, *args, escape=False, **kwargs): + def __init__( + self, + convert_url, + *args, + escape=False, + allow_harmful_protocols=True, + **kwargs, + ): self._convert_url = convert_url - super().__init__(*args, **kwargs, escape=False) + super().__init__( + *args, **kwargs, + # We check the resulting HTML, so we don't sanitization + # in the Markdown->HTML translation + escape=False, + allow_harmful_protocols=True, + ) def naucse_admonition(self, text, title, name): if title: From 10e438bbf8d3254b1d3fad3601c73fc4d5460cb5 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Sat, 15 Aug 2026 16:08:46 +0200 Subject: [PATCH 6/8] Update changelog --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index e4ac771..0f7cd85 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,13 @@ licensed under the same license. ## Changelog +### naucse_render 2.1 + +* Update to mistune 3.3. This changes parsing & formatting for Markdown again. + In most cases the differences should be superficial. + +* Tested with Python 3.11-3.15 + ### naucse_render 2.0 * Update to mistune 3.x & nbconvert 7.x. This changes parsing & formatting From 2584ed56a46996d33065147af36a2242d50bb5c7 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Sat, 15 Aug 2026 16:14:56 +0200 Subject: [PATCH 7/8] Don't test 3.15 on GHA yet --- .github/workflows/main.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index dc64570..3703405 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -18,7 +18,7 @@ jobs: tox_env: ${{ matrix.tox_env }} strategy: matrix: - tox_env: [py311, py312, py313, py314, py315] + tox_env: [py311, py312, py313, py314] # Use GitHub's Linux Docker host runs-on: ubuntu-latest From 6de4c0fb1211ef0b09e742722e9dc81debb5cf86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Sat, 15 Aug 2026 20:08:50 +0200 Subject: [PATCH 8/8] Apply suggestion from @hroncok --- naucse_render/markdown.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/naucse_render/markdown.py b/naucse_render/markdown.py index ff9f81f..b5dc026 100644 --- a/naucse_render/markdown.py +++ b/naucse_render/markdown.py @@ -143,8 +143,6 @@ def __init__( self, convert_url, *args, - escape=False, - allow_harmful_protocols=True, **kwargs, ): self._convert_url = convert_url