MyST-Parser icon indicating copy to clipboard operation
MyST-Parser copied to clipboard

[Sphinx] `eval-rst` fails to parse links correctly

Open chrysle opened this issue 2 years ago • 2 comments

Describe the bug

context

The MyST parser is used as an extension to the Sphinx build system.

I converted the Sphinx index, which was written in ReStructuredText, to Markdown, and included the RST README, as described here. Then the documentation was built running sphinx.

expectation I expected the RST content of the included file to be parsed correctly.

bug However, MyST parser was unable to connect links with separate target definition with their targets.

Instead there was the following error:

../README.rst:<line>: ERROR: Unknown target name: "<target name>"

for each such link.

problem This is a big problem for Markdown-RST compatbility.

Reproduce the bug

See jazzband/pip-tools#1874 for a demonstration of the problem.

List your environment

Sphinx: 7.0.1 MyST-Parser: 1.0.0 Python: 3.7+ OS: Ubuntu 22.04 LTS x86_64

chrysle avatar Jun 04 '23 07:06 chrysle

Thanks for opening your first issue here! Engagement like this is essential for open source projects! :hugs:
If you haven't done so already, check out EBP's Code of Conduct. Also, please try to follow the issue template as it helps other community members to contribute more effectively.
If your issue is a feature request, others may react to it, to raise its prominence (see Feature Voting).
Welcome to the EBP community! :tada:

welcome[bot] avatar Jun 04 '23 07:06 welcome[bot]

I was able to hack together a patch (in myst_parser/mdit_to_docutils/base.py that fixes this issue. However, as I'm not too familiar with how docutils works, I'm not entirely sure if this is a proper fix or just a hack.

def render_restructuredtext(self, token: SyntaxTreeNode) -> None:
    """Render the content of the token as restructuredtext."""
    # copy necessary elements (source, line no, env, reporter)
    newdoc = make_document()
    newdoc["source"] = self.document["source"]
    newdoc.settings = self.document.settings
    newdoc.reporter = self.reporter
    # pad the line numbers artificially so they offset with the fence block
    pseudosource = ("\n" * token_line(token)) + token.content
    # actually parse the rst into our document
    MockRSTParser().parse(pseudosource, newdoc)
    
    for node in newdoc:
        if node["names"]:
            self.document.note_explicit_target(node, node)
    
    for name, nodes in newdoc.refnames.items():
        self.document.note_refname(nodes[0])
    
    for name, node in newdoc.substitution_defs.items():
        self.document.note_substitution_def(node, name, newdoc)
    
    self.current_node.extend(newdoc.children)

The main issue that I'm experiencing with this is that I can define the same target name mutliple times without raising a Duplicate target name error.

NMAC427 avatar Jul 10 '23 13:07 NMAC427