readthedocs / recommonmark

A markdown parser for docutils
https://recommonmark.readthedocs.io/
MIT License
340 stars 252 forks source link

auto_toc_tree not support file path with directory prefixed? #153

Closed idnsunset closed 2 years ago

idnsunset commented 5 years ago

For a piece of code like

* [title](dir/somefile.md)

Sphinx yields toctree contains reference to nonexisting document 'dir\\somefile', I have to set url_resolver to dir/ to make it work. The problem is there might be several subdirs in the top directory for better control over big project.

Am I missing something or there is no way right now to handle markdown files scattered in difference subdirs as with toctree directive for rst?

gibfahn commented 5 years ago

Seems like it works for me with either /dir/somefile.md (for an absolute path) or ./dir/somefile.md (for a relative path).

idnsunset commented 5 years ago

This issue only occurs on Windows due to the difference of the path separator. I've commented on the source code that produce the issue.

        abspath = os.path.abspath(os.path.join(self.file_dir, uri))
        relpath = os.path.relpath(abspath, self.root_dir)
        # !!! abspath has no suffix as the value of `refuri` attribute in doctuils node
        # has already got stripped.
        suffix = abspath.rsplit('.', 1)
        if len(suffix) == 2 and suffix[1] in AutoStructify.suffix_set and (
                os.path.exists(abspath) and abspath.startswith(self.root_dir)):
            # !!! we will never reach here
            # replace the path separator if running on non-UNIX environment
            if os.path.sep != '/':
                relpath = relpath.replace(os.path.sep, '/')
            docpath = '/' + relpath.rsplit('.', 1)[0]
            # rewrite suffix to html, this is suboptimal
            uri = docpath + '.html'
            if anchor is None:
                return (title, uri, docpath)
            else:
                return (title, uri + '#' + anchor, None)
        else:
            # use url resolver
            if self.url_resolver:
                # !!! here relpath's separator is not processed, '\' is still '\'.
                uri = self.url_resolver(relpath)
            if anchor:
                uri += '#' + anchor
            return (title, uri, None)
gibfahn commented 5 years ago

This issue only occurs on Windows due to the difference of the path separator.

I'm not running on Windows so that might explain it. Building in docker might do as a workaround.

I'm just a fellow user, but if you don't go into the if condition there then you should hit the else, which uses the url_resolver you can provide right? So maybe you could also work around the issue with a custom resolver.

Also FWIW removing the suffix so it's just /dir/somefile seemed to work better for me, YMMV...

idnsunset commented 5 years ago

I've added a url_resolver for replacing the path separator in my conf.py, thought I think it's not intended for fixing this kind of issue The code mentioned above comes from recommonmark.transform.AutoStructify.parse_ref method where docpath is dedicated for local markdown or rst documents while uri is for web links. Now docpath block looks like not playing it's role at all.