pydata / pydata-sphinx-theme

A clean, three-column Sphinx theme with Bootstrap for the PyData community
https://pydata-sphinx-theme.readthedocs.io
BSD 3-Clause "New" or "Revised" License
592 stars 309 forks source link

Suggested way to customize "Edit this page" link based on document #477

Open djhoese opened 2 years ago

djhoese commented 2 years ago

The vispy library uses the sphinxcontrib.apidoc extension to automatically generate our API documents at build time. These generated files just use apidoc/autodoc tools to pull the information from the python package's source code. The issue with this is that the default "Edit this page" link in the pydata-sphinx-theme points to where the API doc file would be if it was committed to the repository. Since they aren't you get a 404.

I've hacked something together that seems to work, but wondering if anyone here had suggestions to make it better using either smarter jinja2 tips or features in the theme that I'm not aware of. You can find all the details here: https://github.com/vispy/vispy/pull/2220

But the main context changes make it pretty obvious what I'm doing:

html_context = {
    "github_user": "vispy",
    "github_repo": "vispy",
    "github_version": "main",
    "doc_path": "doc",
    "edit_page_url_template": "{{ vispy_custom_edit_url(github_user, github_repo, github_version, doc_path, file_name, default_edit_page_url_template) }}",
    "default_edit_page_url_template": "https://github.com/{github_user}/{github_repo}/edit/{github_version}/{doc_path}{file_name}",
    "vispy_custom_edit_url": _custom_edit_url,
}
choldgraf commented 2 years ago

Hmm just a quick thought, if the main thing you want to do is prevent the button on some pages, could you just a very short JavaScript snipped that checks the current url and removed the button if it's a part of some pages?

djhoese commented 2 years ago

I could, but in the best case I don't want to hide/remove it but rather update the URL to point to a different location (python source file instead of .rst doc file).

12rambau commented 2 years ago

I have a slightly different approach:

I am making a documentation for a platform that use many modules coming from different repositories. the doc page thus lives in these repositories and I simply add it from github with a urlretreive in my conf.py.

as you @djhoese I end up with "edit this page" btn that doesn't point to the correct location and that would be super nice if I was able to customize it.

djhoese commented 2 years ago

@12rambau one "workaround" for your situation is that you could create git submodules for those other repositories in your "main" repository. That way those files still "live" in your main repository even though they are controlled/versioned in the sub-repositories.

12rambau commented 2 years ago

I'll have a look, I'm not really using the sub-module git fonctionnality, but I'll stay tuned in htis thread for the customization

djhoese commented 2 years ago

Git submodules are 50% good and 50% bad. In your case it may make things easier. In the vispy project I got annoyed by the single git submodule we had for our docs (one code repos with one doc repos) so I just moved the doc repository content into the main repository.

If you want to see one way of working around the issue I had see the PR I referenced for vispy linked above. It has been merged and seems to be working fine.

12rambau commented 2 years ago

@djhoese I didn't managed to use Git submodules and lost myself in the documentation. At least now I know it exists. Instead I decided to build a custom directive to overwrite the link via JS. here is my code if your are interested:

# -*- coding: utf-8 -*-

"""
ReST directive for dynamically change the value of the "edit this page btn". only compatblie with the current theme.
The directive require the complete raw file path (from github).
Example::
    .. custom-edit:: https://raw.githubusercontent.com/openforis/sepal-doc/custom_edit/README.rst
"""

from docutils import nodes
from docutils.parsers.rst import Directive, directives

class CustomEdit(Directive):
    has_content = False
    required_arguments = 1
    optional_arguments = 0
    final_argument_whitespace = False
    option_spec = {}
    html = """
    <script>
        var div = document.getElementsByClassName("tocsection editthispage")[0];
        var link = div.getElementsByTagName("a")[0];
        link.href = "{}";
    </script>
    """

    def run(self):

        # get the raw link 
        raw_link = directives.uri(self.arguments[0])

        # transform it into an edit link 
        raw = "raw.githubusercontent.com"
        github = "github.com"
        edit = "edit"
        list_ = raw_link.replace(raw, github).split("/")
        list_.insert(5, edit)
        link = "/".join(list_)

        return [nodes.raw('', self.html.format(link), format='html')]

def setup(builder):
    directives.register_directive('custom-edit', CustomEdit)

sorry for the noise, I assume you were expecting something more systematic but I least if anyone needs it, it's here...