sphinx-contrib / sphinxcontrib-versioning

Sphinx extension that allows building versioned docs for self-hosting.
https://sphinxcontrib-versioning.readthedocs.io/en/latest/
MIT License
127 stars 80 forks source link

Consider using pathto() instead of manually defining URLs. #11

Closed Robpol86 closed 8 years ago

Robpol86 commented 8 years ago

pathto() in the Jinja2 context is a function and may be the "right" way to link to other versions/etc.

Sphinx RTD theme uses it in layout.html.

Robpol86 commented 8 years ago

Nevermind about this, pathto() is only for docs known to Sphinx. SCVersioning is about links not known to the local Sphinx instance building docs for one version.

Robpol86 commented 8 years ago

This is a good idea after all. Implement something similar. Something like:

def vhasdoc(self, other_version):
    """Return True if the other version has the current document. Like Sphinx's hasdoc().

    :raise KeyError: If other_version doesn't exist.

    :param str other_version: Version to link to.

    :return: If current document is in the other version.
    :rtype: bool
    """
    if self.context['current_version'] == other_version:
        return True
    other_remote = self[other_version]
    return self.context['pagename'] in other_remote['found_docs']

def vpathto(self, other_version):
    """Return relative path to current document in another version. Like Sphinx's pathto().

    If the current document doesn't exist in the other version its master_doc path is returned instead.

    :raise KeyError: If other_version doesn't exist.

    :param str other_version: Version to link to.

    :return: Relative path.
    :rtype: str
    """
    current_version = self.context['current_version']
    has_doc = self.vhasdoc(other_version)
    is_root_ref = self.context['scv_is_root_ref']
    pagename = self.context['pagename']
    if current_version == other_version and not is_root_ref and has_doc:
        return '{}.html'.format(pagename.split('/')[-1])  # User already in this directory, just link to other file.
    level = pagename.count('/')
    if not has_doc:
        pagename = self[other_version]['master_doc']
    if is_root_ref:
        return '{}.html'.format('/'.join(['..'] * level + [other_version, pagename]))
    return '{}.html'.format('/'.join(['..'] * level + ['..', other_version, pagename]))

Then remove Versions.copy() and Versions.remotes['url']. Have Versions.__iter__() call Versions.vpathto() instead. Also benchmark self.__getitem__() with 20 or so remotes. Since __iter__ will call vpathto much much maybe it's better to give vpathto kwargs to do __getitem__() call once.

Robpol86 commented 8 years ago

⚠️ I forgot about collisions. Make sure vpathto() handles versions with different directory names (e.g. a branch called _static).

Robpol86 commented 8 years ago

Mostly done in 941cbf0c3c9514e1445a2db4b066c72bf42c9122.

Robpol86 commented 8 years ago

Pretty much done in that commit.