miyuchina / mistletoe

A fast, extensible and spec-compliant Markdown parser in pure Python.
MIT License
791 stars 110 forks source link

Render Heading to markdown: ValueError: list.remove(x): x not in list #200

Closed nschloe closed 6 months ago

nschloe commented 8 months ago

I'm trying to get the Markdown representation of a Heading I've parsed and manipulated before, but

with MarkdownRenderer() as renderer:
    md = renderer.render(heading)

gives

token_cls = <class 'mistletoe.block_token.Footnote'>

    def remove_token(token_cls):
        """
        Allows external manipulation of the parsing process.
        This function is usually called in BaseRenderer.__exit__.

        Arguments:
            token_cls (BlockToken): token to be removed from the parsing process.
        """
>       _token_types.remove(token_cls)
E       ValueError: list.remove(x): x not in list

../../../venv/lib/python3.11/site-packages/mistletoe/block_token.py:61: ValueError

I'd like to provide an MWE, but it seems that Headings cannot be constructed explicitly like

from mistletoe.block_token import Heading
from mistletoe.span_token import RawText

header = Heading(
    [RawText("1"), RawText("\u2003Intro")],
    level=2,
)
pbodnar commented 8 months ago

@nschloe, I think you are describing 2 mistletoe problems in here:

  1. mistletoe isn't made in a way that would support nesting renderers (or maybe just in some cases) - that is the only way I can think of how you can get the ValueError: list.remove(x): x not in list exception from your report. E.g.:

    with MarkdownRenderer() as renderer:
       md = renderer.render(header)
       print(md)
    
       with MarkdownRenderer() as renderer: # fails, because we are globally removing token class for the 2nd time - which is no longer present
           md = renderer.render(header)
           print(md)
  2. mistletoe doesn't let you create tokens via their constructors in a nice way, like e.g. the archived mistletoe-ebp fork does. So right now, you need to use e.g. this code instead in order to construct a Heading without parsing:
    header = Heading(
       [2, 'My Title', '']
    )
pbodnar commented 6 months ago

Closing this as answered, feel free to "reopen" by commenting. I think to implement the 2 things as described in my latest comment, both would require some major refactoring and both would deserve a separate issue to discuss it thoroughly...