frostming/marko

`ext/codehilite.py`: Putting "````t`ext like this" causes `ValueError` in `_parse_extras`

llllvvuu opened this issue · 0 comments

Hi, I noticed that I was getting this stack trace:

  File "/Users/llwu/git/@llllvvuu/contributor-tools/github_issues/test.py", line 6, in <module>
    markdown.convert("```python my_script.py\nprint('hello world')\n```")
  File "/Users/llwu/.pyenv/versions/scripts/lib/python3.11/site-packages/marko/__init__.py", line 111, in convert
    return self.render(self.parse(text))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/llwu/.pyenv/versions/scripts/lib/python3.11/site-packages/marko/__init__.py", line 131, in render
    return r.render(parsed)
           ^^^^^^^^^^^^^^^^
  File "/Users/llwu/.pyenv/versions/scripts/lib/python3.11/site-packages/marko/renderer.py", line 71, in render
    return self.render_children(element)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/llwu/.pyenv/versions/scripts/lib/python3.11/site-packages/marko/renderer.py", line 85, in render_children
    rendered = [self.render(child) for child in element.children]  # type: ignore
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/llwu/.pyenv/versions/scripts/lib/python3.11/site-packages/marko/renderer.py", line 85, in <listcomp>
    rendered = [self.render(child) for child in element.children]  # type: ignore
                ^^^^^^^^^^^^^^^^^^
  File "/Users/llwu/.pyenv/versions/scripts/lib/python3.11/site-packages/marko/renderer.py", line 70, in render
    return render_func(element)
           ^^^^^^^^^^^^^^^^^^^^
  File "/Users/llwu/.pyenv/versions/scripts/lib/python3.11/site-packages/marko/ext/codehilite.py", line 40, in render_fenced_code
    options.update(_parse_extras(getattr(element, "extra", None)))
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/llwu/.pyenv/versions/scripts/lib/python3.11/site-packages/marko/ext/codehilite.py", line 30, in _parse_extras
    return {k: json.loads(v) for part in line.split(",") for k, v in [part.split("=")]}
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/llwu/.pyenv/versions/scripts/lib/python3.11/site-packages/marko/ext/codehilite.py", line 30, in <dictcomp>
    return {k: json.loads(v) for part in line.split(",") for k, v in [part.split("=")]}
                                                             ^^^^
ValueError: not enough values to unpack (expected 2, got 1)

while parsing the markdown of this GitHub issue. From this, I was able to create a minimal repro:

from marko import Markdown

markdown = Markdown(extensions=['codehilite'])
markdown.convert("```Error: Unable\n```")

What's happening here is that Marko thinks we are highlighting language Error: with options Unable.

In fact, I noticed something else; the example given in the docstring will also error by this same logic!

    from marko import Markdown

    markdown = Markdown(extensions=['codehilite'])
    markdown.convert(```python my_script.py\nprint('hello world')\n```)

Indeed it does throw a ValueError. It should be python filename="my_script.py".

I have attached a PR which fixes this issue. It simply ignores tokens which are not of the form key=JSON