diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 904c1e3..193ec92 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -13,12 +13,12 @@ jobs: - uses: actions/checkout@v2 - name: Run Tox tests id: test - uses: fedora-python/tox-github-action@master + uses: fedora-python/tox-github-action@main with: tox_env: ${{ matrix.tox_env }} strategy: matrix: - tox_env: [py37, py38, py39, py310, py311] + tox_env: [py38, py39, py310, py311, py312] # Use GitHub's Linux Docker host runs-on: ubuntu-latest diff --git a/README.md b/README.md index 5590e73..e4ac771 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,14 @@ licensed under the same license. ## Changelog +### naucse_render 2.0 + +* Update to mistune 3.x & nbconvert 7.x. This changes parsing & formatting + for Markdown, syntax highlighting, and Notebooks. In most cases the + differences should be superficial. + +* Tested with Python 3.8-3.12 + ### naucse_render 1.10 * `naucse_render compile` now checks for links to missing lessons and diff --git a/naucse_render/markdown.py b/naucse_render/markdown.py index 3cb9bfa..0abb534 100644 --- a/naucse_render/markdown.py +++ b/naucse_render/markdown.py @@ -12,57 +12,62 @@ import pygments.formatters.html -ansi_convertor = Ansi2HTMLConverter(inline=True) - -pygments_formatter = pygments.formatters.html.HtmlFormatter( - cssclass='highlight' -) - -_admonition_leading_pattern = re.compile(r'^ *> ?', flags=re.M) - - -class BlockGrammar(mistune.BlockGrammar): - admonition = re.compile(r'^> *\[(\S+)\]([^\n]*)\n((>[^\n]*[\n]{0,1})*)') - deflist = re.compile(r'^(([^\n: ][^\n]*\n)+)((:( {0,3})[^\n]*\n)( \5[^\n]*\n|\n)+)') - - -class BlockLexer(mistune.BlockLexer): - grammar_class = BlockGrammar +def naucse_admonition_plugin(md): + """Parse blockquote-based admonitions - default_rules = [ - 'admonition', - 'deflist', - ] + mistune.BlockLexer.default_rules + Like this: - def parse_admonition(self, m): - self.tokens.append({ - 'type': 'admonition_start', - 'name': m.group(1), - 'title': m.group(2).strip(), - }) + > [note] Note Title + > rest of note goes here + """ + # Based on Mistune's "spoiler" plugin (the documentation says: + # "take a look at the source code in mistune/plugins to find + # 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 = block.extract_block_quote(m, state) + name_match = ADMONITION_NAME_PATTERN.match(text) + if name_match: + # It's an admonition + token = { + 'type': 'naucse_admonition', + 'attrs': { + 'name': name_match[1].strip(), + 'title': name_match[2].strip(), + }, + } + text = text[name_match.end():] + else: + token = { + 'type': 'block_quote', + } + + child = state.child_state(text) + rules = block.block_quote_rules + block.parse(child, rules) + token['children'] = child.tokens + if end_pos: + state.prepend_token(token) + return end_pos + state.append_token(token) + return state.cursor + + md.block.register( + 'block_quote', + None, + parse_naucse_admonition, + before='block_quote', + ) - text = _admonition_leading_pattern.sub('', m.group(3)) - self.parse(dedent(text)) - self.tokens.append({ - 'type': 'admonition_end', - }) +ansi_convertor = Ansi2HTMLConverter(inline=True) - def parse_deflist(self, m): - self.tokens.append({ - 'type': 'deflist_term_start', - }) - self.parse(dedent(m.group(1))) - self.tokens.append({ - 'type': 'deflist_term_end', - }) - self.tokens.append({ - 'type': 'deflist_def_start', - }) - self.parse(dedent(' ' + m.group(3)[1:])) - self.tokens.append({ - 'type': 'deflist_def_end', - }) +pygments_formatter = pygments.formatters.html.HtmlFormatter( + cssclass='highlight' +) def ansi_convert(code): @@ -76,11 +81,6 @@ def style_space_after_prompt(html): html) -def matrix_multiplication_operator(html): - return html.replace('@', - '@') - - class MSDOSSessionVenvLexer(RegexLexer): """Lexer for simplistic MSDOS sessions with optional venvs. @@ -129,23 +129,26 @@ def text_to_id(text): return text -class Renderer(mistune.Renderer): +class NaucseRenderer(mistune.HTMLRenderer): code_tmpl = '
{}
' - def __init__(self, convert_url, *args, **kwargs): + def __init__(self, convert_url, *args, escape=False, **kwargs): self._convert_url = convert_url - super().__init__(*args, **kwargs) + super().__init__(*args, **kwargs, escape=False) - def admonition(self, name, content): - return '
{}
'.format(name, content) + def naucse_admonition(self, text, title, name): + if title: + text = f'

{title}

\n{text}' + return '
{}
'.format(name, text) - def header(self, text, level, raw=None): + def heading(self, text, level, raw=None): header_id = text_to_id(text) return f'''{text} # \n''' - def block_code(self, code, lang): + def block_code(self, code, info=None): + lang = info if lang is not None: lang = lang.strip() if not lang or lang == 'plain': @@ -157,56 +160,13 @@ def block_code(self, code, lang): lexer = get_lexer_by_name(lang) html = pygments.highlight(code, lexer, pygments_formatter).strip() html = style_space_after_prompt(html) - if lang in ('python', 'pycon'): - html = matrix_multiplication_operator(html) return html - def deflist(self, items): - tags = {'term': 'dt', 'def': 'dd'} - return '
\n{}
'.format(''.join( - '<{tag}>{text}'.format(tag=tags[type], text=text) - for type, text in items - )) - - def link(self, link, title, text): - return super().link(self._convert_url(link), title, text) - - def image(self, src, title, text): - return super().image(self._convert_url(src), title, text) - - -class Markdown(mistune.Markdown): - def output_admonition(self): - name = self.token['name'] - body = self.renderer.placeholder() - if self.token['title']: - template = '

{}

\n' - body += template.format(self.token['title']) - while self.pop()['type'] != 'admonition_end': - body += self.tok() - return self.renderer.admonition(name, body) - - def output_deflist_term(self): - items = [['term', self.renderer.placeholder()]] - while True: - end_token = 'deflist_{}_end'.format(items[-1][0]) - while self.pop()['type'] not in (end_token, 'paragraph'): - items[-1][1] += self.tok() - if self.token['type'] == 'paragraph': - if items[-1][0] == 'term': - items.append(['term', self.renderer.placeholder()]) - items[-1][1] += self.token['text'] - else: - items[-1][1] += self.output_paragraph() - elif self.peek()['type'] == 'deflist_term_start': - self.pop() - items.append(['term', self.renderer.placeholder()]) - elif self.peek()['type'] == 'deflist_def_start': - self.pop() - items.append(['def', self.renderer.placeholder()]) - else: - break - return self.renderer.deflist(items) + def link(self, text, url, title=None): + return super().link(text, self._convert_url(url), title) + + def image(self, alt, url, title=None): + return super().image(alt, self._convert_url(url), title) def convert_markdown(text, convert_url=None, *, inline=False): @@ -214,10 +174,9 @@ def convert_markdown(text, convert_url=None, *, inline=False): text = dedent(text) - markdown = Markdown( - escape=False, - block=BlockLexer(), - renderer=Renderer(convert_url), + markdown = mistune.create_markdown( + plugins=['def_list', naucse_admonition_plugin], + renderer=NaucseRenderer(convert_url), ) result = markdown(text).strip() diff --git a/naucse_render/templates.py b/naucse_render/templates.py index ecb03a7..7b57da9 100644 --- a/naucse_render/templates.py +++ b/naucse_render/templates.py @@ -67,6 +67,9 @@ def solution(ctx, text): solution = ctx['$markdown'](text) solutions.append(solution) + # make sure there are no empty lines, which exit Markdown's raw-HTML mode + solution = solution.replace('\n', Markup('\n')) + return Markup(textwrap.dedent("""

Řešení

diff --git a/pyproject.toml b/pyproject.toml index deb30ea..53dfcca 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,18 +4,18 @@ build-backend = "setuptools.build_meta" [project] name = "naucse_render" -version = '1.10' +version = '2.0' description = 'Converts course material to naucse.python.cz API' readme = "README.md" -requires-python = ">=3.7" +requires-python = ">=3.8" classifiers = [ "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", ] dependencies = [ 'ansi2html', - 'mistune', - 'nbconvert>=6.0.7,<7.0', + 'mistune>=2.0.3,<4', + 'nbconvert>=7.0,<8.0', 'traitlets', 'click', 'PyYAML', diff --git a/test_naucse_render/fixtures/expected-compiled/courses/extra-lessons/tasks/index.html b/test_naucse_render/fixtures/expected-compiled/courses/extra-lessons/tasks/index.html index e447fc1..f8921ec 100644 --- a/test_naucse_render/fixtures/expected-compiled/courses/extra-lessons/tasks/index.html +++ b/test_naucse_render/fixtures/expected-compiled/courses/extra-lessons/tasks/index.html @@ -1,9 +1,7 @@
    -
  1. A task

  2. -
  3. Task with list:

      @@ -11,9 +9,7 @@
    • b
  4. -
  5. -

    Static files handled with a smile.

    +

    Static files handled with a smile.

  6. -
\ No newline at end of file diff --git a/test_naucse_render/fixtures/expected-compiled/default/course.json b/test_naucse_render/fixtures/expected-compiled/default/course.json index 0c82844..eb6ca1d 100644 --- a/test_naucse_render/fixtures/expected-compiled/default/course.json +++ b/test_naucse_render/fixtures/expected-compiled/default/course.json @@ -69,6 +69,7 @@ }, "ids": [ "co_programatorsky_editor_umi", + "solution-0", "volba_a_nastaveni_editoru" ], "license": "cc-by-sa-40", @@ -77,10 +78,15 @@ "#volba_a_nastaveni_editoru", "naucse:page?lesson=beginners/install-editor&page=atom", "naucse:page?lesson=beginners/install-editor&page=gedit", - "naucse:page?lesson=beginners/install-editor&page=gedit#nacvik_odsazovani" + "naucse:page?lesson=beginners/install-editor&page=gedit#nacvik_odsazovani", + "naucse:solution?solution=0" ], "slug": "index", - "solutions": [], + "solutions": [ + { + "content": "
# Třikrát:\nfor i in range(3):\n\n    # Nakresli čtverec (kód zkopírovaný z předchozí úlohy a odsazený)\n    for j in range(4):\n        forward(50)\n        left(90)\n\n    # Otoč se o 20°\n    left(20)\n
" + } + ], "source_file": "lessons/beginners/install-editor/index.md", "title": "Instalace editoru", "vars": {} diff --git a/test_naucse_render/fixtures/expected-compiled/default/install-editor/gedit.html b/test_naucse_render/fixtures/expected-compiled/default/install-editor/gedit.html index 50617e2..af68a81 100644 --- a/test_naucse_render/fixtures/expected-compiled/default/install-editor/gedit.html +++ b/test_naucse_render/fixtures/expected-compiled/default/install-editor/gedit.html @@ -3,19 +3,27 @@

Instalace Geditu

Na Linuxu se Gedit instaluje jako ostatní programy:

-
Fedora
$ sudo dnf install gedit
-
Ubuntu
$ sudo apt-get install gedit
-

Používáš-li jiný Linux, předpokládám že programy instalovat umíš. :)

+
Fedora
+
$ sudo dnf install gedit
+
+
Ubuntu
+
$ sudo apt-get install gedit
+
+ +

Používáš-li jiný Linux, předpokládám že programy instalovat umíš. :)

Pro Windows a macOS se Gedit dá stáhnout z domovské stránky.

Nastavení #

...

-
Číslování řádků

V sekci Zobrazit/View vyber +

Číslování řádků
+

V sekci Zobrazit/View vyber Zobrazovat čísla řádků/Display Line Numbers.

-

...

+ + +

...

Nácvik odsazování #

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 c796b08..eb28f9a 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 @@ -4,11 +4,14 @@

Co programátorský editor umí

...

-
Podpora více souborů

Větší projekty sestávají z více souborů, které můžeš mít v editoru -otevřené všechny najednou.

-
Číslování řádků

Před každým řádkem se ukazuje číslo. -To se bude velice hodit, až Python bude nadávat, že chyba je na řádku 183.

-

...

+
Podpora více souborů
+
Větší projekty sestávají z více souborů, které můžeš mít v editoru +otevřené všechny najednou.
+
Číslování řádků
+
Před každým řádkem se ukazuje číslo. +To se bude velice hodit, až Python bude nadávat, že chyba je na řádku 183.
+ +

...

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

    1  @app.route('/courses/<course:course>/')
     2  def course_page(course):
@@ -28,4 +31,23 @@ 

Co programátorský editor umí -

...

\ No newline at end of file +

...

+
+

Řešení

+ + +
\ No newline at end of file diff --git a/test_naucse_render/fixtures/expected-compiled/lessons/course.json b/test_naucse_render/fixtures/expected-compiled/lessons/course.json index 1c470a8..280e35c 100644 --- a/test_naucse_render/fixtures/expected-compiled/lessons/course.json +++ b/test_naucse_render/fixtures/expected-compiled/lessons/course.json @@ -70,6 +70,7 @@ }, "ids": [ "co_programatorsky_editor_umi", + "solution-0", "volba_a_nastaveni_editoru" ], "license": "cc-by-sa-40", @@ -78,10 +79,15 @@ "#volba_a_nastaveni_editoru", "naucse:page?lesson=beginners/install-editor&page=atom", "naucse:page?lesson=beginners/install-editor&page=gedit", - "naucse:page?lesson=beginners/install-editor&page=gedit#nacvik_odsazovani" + "naucse:page?lesson=beginners/install-editor&page=gedit#nacvik_odsazovani", + "naucse:solution?solution=0" ], "slug": "index", - "solutions": [], + "solutions": [ + { + "content": "
# Třikrát:\nfor i in range(3):\n\n    # Nakresli čtverec (kód zkopírovaný z předchozí úlohy a odsazený)\n    for j in range(4):\n        forward(50)\n        left(90)\n\n    # Otoč se o 20°\n    left(20)\n
" + } + ], "source_file": "lessons/beginners/install-editor/index.md", "title": "Instalace editoru", "vars": {} diff --git a/test_naucse_render/fixtures/expected-compiled/lessons/install-editor/gedit.html b/test_naucse_render/fixtures/expected-compiled/lessons/install-editor/gedit.html index 50617e2..af68a81 100644 --- a/test_naucse_render/fixtures/expected-compiled/lessons/install-editor/gedit.html +++ b/test_naucse_render/fixtures/expected-compiled/lessons/install-editor/gedit.html @@ -3,19 +3,27 @@

Instalace Geditu

Na Linuxu se Gedit instaluje jako ostatní programy:

-
Fedora
$ sudo dnf install gedit
-
Ubuntu
$ sudo apt-get install gedit
-

Používáš-li jiný Linux, předpokládám že programy instalovat umíš. :)

+
Fedora
+
$ sudo dnf install gedit
+
+
Ubuntu
+
$ sudo apt-get install gedit
+
+ +

Používáš-li jiný Linux, předpokládám že programy instalovat umíš. :)

Pro Windows a macOS se Gedit dá stáhnout z domovské stránky.

Nastavení #

...

-
Číslování řádků

V sekci Zobrazit/View vyber +

Číslování řádků
+

V sekci Zobrazit/View vyber Zobrazovat čísla řádků/Display Line Numbers.

-

...

+ + +

...

Nácvik odsazování #

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 c796b08..eb28f9a 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 @@ -4,11 +4,14 @@

Co programátorský editor umí

...

-
Podpora více souborů

Větší projekty sestávají z více souborů, které můžeš mít v editoru -otevřené všechny najednou.

-
Číslování řádků

Před každým řádkem se ukazuje číslo. -To se bude velice hodit, až Python bude nadávat, že chyba je na řádku 183.

-

...

+
Podpora více souborů
+
Větší projekty sestávají z více souborů, které můžeš mít v editoru +otevřené všechny najednou.
+
Číslování řádků
+
Před každým řádkem se ukazuje číslo. +To se bude velice hodit, až Python bude nadávat, že chyba je na řádku 183.
+ +

...

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

    1  @app.route('/courses/<course:course>/')
     2  def course_page(course):
@@ -28,4 +31,23 @@ 

Co programátorský editor umí -

...

\ No newline at end of file +

...

+
+

Řešení

+ + +
\ No newline at end of file diff --git a/test_naucse_render/fixtures/expected-compiled/lessons/tasks/index.html b/test_naucse_render/fixtures/expected-compiled/lessons/tasks/index.html index e447fc1..f8921ec 100644 --- a/test_naucse_render/fixtures/expected-compiled/lessons/tasks/index.html +++ b/test_naucse_render/fixtures/expected-compiled/lessons/tasks/index.html @@ -1,9 +1,7 @@
    -
  1. A task

  2. -
  3. Task with list:

      @@ -11,9 +9,7 @@
    • b
  4. -
  5. -

    Static files handled with a smile.

    +

    Static files handled with a smile.

  6. -
\ No newline at end of file diff --git a/test_naucse_render/fixtures/expected-compiled/lessons/test_static_tree/index.html b/test_naucse_render/fixtures/expected-compiled/lessons/test_static_tree/index.html index 3abd2a0..87f365f 100644 --- a/test_naucse_render/fixtures/expected-compiled/lessons/test_static_tree/index.html +++ b/test_naucse_render/fixtures/expected-compiled/lessons/test_static_tree/index.html @@ -1,2 +1,2 @@ -

smile

+

smile

Output should have '/' as the directory separator, regardless of OS.

\ No newline at end of file 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 1c31e54..f305c88 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 d7e50f9..2a2be7c 100644 --- a/test_naucse_render/fixtures/expected-dumps/beginners/install-editor.yaml +++ b/test_naucse_render/fixtures/expected-dumps/beginners/install-editor.yaml @@ -42,24 +42,27 @@ data: content: "

Instalace Geditu\n#\n

\n

Na\ \ Linuxu se Gedit instaluje jako ostatn\xED programy:

\n
\n\ -
Fedora
$ sudo dnf install gedit\n
Ubuntu
$ sudo\
-                    \ apt-get install gedit\n

Pou\u017E\xED\ +

Fedora
\n
$ sudo dnf install gedit\n\
+                    
\n
Ubuntu
\n
$ sudo apt-get install gedit\n
\n\n

Pou\u017E\xED\ v\xE1\u0161-li jin\xFD Linux, p\u0159edpokl\xE1d\xE1m \u017Ee\ \ programy instalovat um\xED\u0161. :)

\n

Pro Windows a macOS\ \ se Gedit d\xE1 st\xE1hnout z\_domovsk\xE9 str\xE1nky.

\n

Nastaven\xED\ \n#\n

\n\ -

...

\n
\n
\u010C\xEDslov\xE1n\xED \u0159\xE1\ - dk\u016F

V\_sekci Zobrazit/View\ +

...

\n
\n
\u010C\xEDslov\xE1n\xED \u0159\xE1dk\u016F\ +
\n

V\_sekci Zobrazit/View\ \ vyber\nZobrazovat \u010D\xEDsla \u0159\xE1dk\u016F/Display Line Numbers.

\n

\"\"

\n\ -

...

\n

N\xE1cvik odsazov\xE1\ - n\xED\n#\n\ -

\n

...

" +
\n
\n

...

\n

N\xE1cvik\ + \ odsazov\xE1n\xED\n#\n

\n

...

" ids: - instalace_geditu - nacvik_odsazovani @@ -81,14 +84,14 @@ data: - Pro PyLadies Brno napsal Petr Viktorin, 2014-2017 content: "

...

\n

Co program\xE1\ torsk\xFD editor um\xED\n#\n

\n

...

\n
\n
Podpora\ - \ v\xEDce soubor\u016F

V\u011Bt\u0161\xED projekty\ - \ sest\xE1vaj\xED z\_v\xEDce soubor\u016F, kter\xE9 m\u016F\u017E\ - e\u0161 m\xEDt v\_editoru\notev\u0159en\xE9 v\u0161echny najednou.

\n\ -
\u010C\xEDslov\xE1n\xED \u0159\xE1dk\u016F

P\u0159\ + \ class=\"header-link\">#\n\n

...

\n
\n
Podpora\ + \ v\xEDce soubor\u016F
\n
V\u011Bt\u0161\xED projekty sest\xE1\ + vaj\xED z\_v\xEDce soubor\u016F, kter\xE9 m\u016F\u017Ee\u0161\ + \ m\xEDt v\_editoru\notev\u0159en\xE9 v\u0161echny najednou.
\n\ +
\u010C\xEDslov\xE1n\xED \u0159\xE1dk\u016F
\n
P\u0159\ ed ka\u017Ed\xFDm \u0159\xE1dkem se ukazuje \u010D\xEDslo.\nTo\ \ se bude velice hodit, a\u017E Python bude nad\xE1vat, \u017E\ - e chyba je na \u0159\xE1dku 183.

\n

...

\n\n
\n

...

\n

Pro ilustraci, takhle m\u016F\u017E\ e v\_editoru vypadat kousek k\xF3du:

\n
    1  \n

...

\n\n

...

" + >N\xE1cvik odsazov\xE1n\xED.\n\n\n\n

...

\n\ +
\n

\u0158e\u0161\ + en\xED

\n \n
\n
# T\u0159ikr\xE1t:\n\
+                    for i\
+                    \ in range(3):\n\n    # Nakresli \u010Dtverec (k\xF3d zkop\xEDrovan\xFD z p\u0159\
+                    edchoz\xED \xFAlohy a odsazen\xFD)\n    for j in range(4):\n\
+                            forward(50)\n\
+                            left(90)\n\
+                    \n    # Oto\u010D\
+                    \ se o 20\xB0\n    left(20)\n
\n
\n
" ids: - co_programatorsky_editor_umi + - solution-0 - volba_a_nastaveni_editoru license: cc-by-sa-40 links: @@ -117,8 +144,27 @@ data: - naucse:page?lesson=beginners/install-editor&page=atom - naucse:page?lesson=beginners/install-editor&page=gedit - naucse:page?lesson=beginners/install-editor&page=gedit#nacvik_odsazovani + - naucse:solution?solution=0 slug: index - solutions: [] + solutions: + - content: "
# T\u0159ikr\xE1t:\nfor\
+                        \ i in\
+                        \ range(3):\n\n   \
+                        \ # Nakresli \u010Dtverec (k\xF3d zkop\xED\
+                        rovan\xFD z p\u0159edchoz\xED \xFAlohy a odsazen\xFD)\n\
+                        \    for j\
+                        \ in range(4):\n        forward(50)\n        left(90)\n\n    # Oto\u010D se o 20\xB0\
+                        \n    left(20)\n\
+                        
" source_file: lessons/beginners/install-editor/index.md title: Instalace editoru vars: {} diff --git a/test_naucse_render/fixtures/expected-dumps/homework/tasks.yaml b/test_naucse_render/fixtures/expected-dumps/homework/tasks.yaml index 40fe978..2b482f6 100644 --- a/test_naucse_render/fixtures/expected-dumps/homework/tasks.yaml +++ b/test_naucse_render/fixtures/expected-dumps/homework/tasks.yaml @@ -7,11 +7,11 @@ data: index: attribution: - Pro PyLadies Brno napsal Petr Viktorin, 2014-2019 - content: "
    \n\n
  1. \n

    A task

    \n
  2. \n\n \ - \
  3. \n

    Task with list:

    \n
      \n
    • a
    • \n
    • b
    • \n\ -
    \n
  4. \n\n
  5. \n

    Static files handled\ - \ with a \"\.

    \n
  6. \n\n
" + content: "
    \n
  1. \n

    A task

    \n
  2. \n
  3. \n\ + \

    Task with list:

    \n
      \n
    • a
    • \n
    • b
    • \n\ +
    \n
  4. \n
  5. \n

    Static files handled with\ + \ a \"smile\"\.

    \n
  6. \n
" ids: [] license: cc-by-sa-40 links: diff --git a/test_naucse_render/fixtures/expected-dumps/testcases/test_static_tree.yaml b/test_naucse_render/fixtures/expected-dumps/testcases/test_static_tree.yaml index d6e204c..d9693f6 100644 --- a/test_naucse_render/fixtures/expected-dumps/testcases/test_static_tree.yaml +++ b/test_naucse_render/fixtures/expected-dumps/testcases/test_static_tree.yaml @@ -8,7 +8,7 @@ data: attribution: - Petr Viktorin content: '

smile

+ alt="smile" />

Output should have ''/'' as the directory separator, regardless of OS.

' 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 518aa88..337ab2e 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/fixtures/test_content/lessons/beginners/install-editor/index.md b/test_naucse_render/fixtures/test_content/lessons/beginners/install-editor/index.md index d943d52..d0bac26 100644 --- a/test_naucse_render/fixtures/test_content/lessons/beginners/install-editor/index.md +++ b/test_naucse_render/fixtures/test_content/lessons/beginners/install-editor/index.md @@ -39,3 +39,19 @@ Podpora více souborů * Můžeme odkázat na [Nácvik odsazování]({{ subpage_url('gedit') }}#nacvik_odsazovani). ... + +{% filter solution %} +```python +# Třikrát: +for i in range(3): + + # Nakresli čtverec (kód zkopírovaný z předchozí úlohy a odsazený) + for j in range(4): + forward(50) + left(90) + + # Otoč se o 20° + left(20) + +``` +{% endfilter %} diff --git a/test_naucse_render/fixtures/test_content/lessons/homework/tasks/index.md b/test_naucse_render/fixtures/test_content/lessons/homework/tasks/index.md index f4fc44d..4c450cb 100644 --- a/test_naucse_render/fixtures/test_content/lessons/homework/tasks/index.md +++ b/test_naucse_render/fixtures/test_content/lessons/homework/tasks/index.md @@ -1,7 +1,7 @@
    -{% for item in data.tasks %} +{%- for item in data.tasks %}
  1. {{ item.markdown | markdown }}
  2. -{% endfor %} +{%- endfor %}
diff --git a/test_naucse_render/test_markdown.py b/test_naucse_render/test_markdown.py index 4bbfe87..787cf94 100644 --- a/test_naucse_render/test_markdown.py +++ b/test_naucse_render/test_markdown.py @@ -99,8 +99,10 @@ def test_markdown_definition_list(): expected = dedent("""

Bla Bla

-
The Term

Its Definition

-

More Text

+
The Term
+
Its Definition
+ +

More Text

""").strip() assert convert_markdown(src).strip() == expected @@ -123,11 +125,15 @@ def test_markdown_definition_list_advanced(): expected = dedent("""

Bla Bla

-
The Term

Its Definition +

The Term
+

Its Definition More Definition

Even More

-
Another Term

Define this

-

More Text

+ +
Another Term
+
Define this
+ +

More Text

""").strip() print(convert_markdown(src)) assert convert_markdown(src).strip() == expected @@ -160,7 +166,8 @@ def test_markdown_ansi_colors(): (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) - modified: test_naucse/test_markdown.py
+ modified: test_naucse/test_markdown.py +
""").strip() assert convert_markdown(src) == expected @@ -287,7 +294,7 @@ def test_convert_full_dosvenv_prompt(): """) expected = dedent(r"""
> whoami
-        helena
+        helena
         > venv\Scripts\activate  # activate virtualenv
         (venv)> dir
          Directory of C:\Users\helena
diff --git a/test_naucse_render/test_notebook.py b/test_naucse_render/test_notebook.py
index 208415f..5c85571 100644
--- a/test_naucse_render/test_notebook.py
+++ b/test_naucse_render/test_notebook.py
@@ -33,7 +33,7 @@ def notebook(_notebook):
 def test_notebook_markdown_cell_conversion(notebook):
     markdown = dedent(r"""
         

Markdown - # + #

This is Markdown cell!

It even has some $\LaTeX$:

@@ -43,7 +43,7 @@ def test_notebook_markdown_cell_conversion(notebook): def test_notebook_has_input_prompt(notebook): - input_prompt = '
In [1]:
' + input_prompt = '
In [1]:
' assert input_prompt in notebook @@ -54,7 +54,7 @@ def test_notebook_has_output_prompt(notebook): def test_notebook_has_highlighted_input_area(notebook): input_area = dedent(""" -
+
         print(
         'foo')
diff --git a/tox.ini b/tox.ini
index b82ae6c..5b3e97d 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,9 +1,9 @@
 [tox]
-envlist = py{37,38,39,310,311}
+envlist = py{38,39,310,311,312}
 isolated_build = True
 
 [testenv]
 deps=
     pytest
 commands=
-    python -m pytest
+    python -m pytest -vv