From 959042d8974a93ad4df0a3eeb50efccd4550cbd9 Mon Sep 17 00:00:00 2001 From: Rambaud Pierrick <12rambau@users.noreply.github.com> Date: Fri, 30 Sep 2022 11:24:40 +0200 Subject: [PATCH] ENH: Automatically shorten links for GitHub/GitLab (#957) * shorten links * typo * add icons scss * add example * check uri existence * fix: docutil deprecation warning * manage smaller links (user, repository, github itself) * fix: workaround for reference without body * set up the example as a link * update the tests * typo * typo * fix: test uses 1 space indentation * test: add the gitlab link * add a normal link * use > instead of >= for tests * parse_path cannot be called if platform is None * Update docs/user_guide/theme-elements.md Co-authored-by: Chris Holdgraf * Update docs/user_guide/theme-elements.md Co-authored-by: Chris Holdgraf * Update src/pydata_sphinx_theme/__init__.py Co-authored-by: Chris Holdgraf * Update src/pydata_sphinx_theme/__init__.py Co-authored-by: Chris Holdgraf * refactor: new function names * maint: use fontawesome 6 Co-authored-by: Chris Holdgraf --- docs/user_guide/theme-elements.md | 6 ++ src/pydata_sphinx_theme/__init__.py | 78 +++++++++++++++++++ .../assets/styles/base/_base.scss | 15 ++++ .../assets/styles/content/_admonitions.scss | 2 +- .../assets/styles/variables/_icons.scss | 2 + tests/sites/base/page1.rst | 4 + tests/test_build.py | 12 +++ tests/test_build/github_link.html | 3 + tests/test_build/gitlab_link.html | 3 + 9 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 tests/test_build/github_link.html create mode 100644 tests/test_build/gitlab_link.html diff --git a/docs/user_guide/theme-elements.md b/docs/user_guide/theme-elements.md index 664a521f4..a7ae4f0d1 100644 --- a/docs/user_guide/theme-elements.md +++ b/docs/user_guide/theme-elements.md @@ -143,3 +143,9 @@ For example, the admonition sidebar was created with the following markdown: Some sidebar content. ``` ```` + +## Link shortening for git repository services + +Many projects have links back to their issues / PRs hosted on platforms like **GitHub** or **GitLab**. Instead of displaying these as raw links, this theme does some lightweight formatting for these platforms specifically. Here is an example from the issue requesting this feature: [https://github.com/pydata/pydata-sphinx-theme/issues/841](https://github.com/pydata/pydata-sphinx-theme/issues/841). + +Links provided with a text body won't be changed. diff --git a/src/pydata_sphinx_theme/__init__.py b/src/pydata_sphinx_theme/__init__.py index 61b63c919..aca7fff12 100644 --- a/src/pydata_sphinx_theme/__init__.py +++ b/src/pydata_sphinx_theme/__init__.py @@ -5,12 +5,16 @@ import warnings from pathlib import Path from functools import lru_cache +from urllib.parse import urlparse import jinja2 from bs4 import BeautifulSoup as bs +from docutils import nodes from sphinx import addnodes from sphinx.environment.adapters.toctree import TocTree from sphinx.addnodes import toctree as toctree_node +from sphinx.transforms.post_transforms import SphinxPostTransform +from sphinx.util.nodes import NodeMatcher from sphinx.errors import ExtensionError from sphinx.util import logging from pygments.formatters import HtmlFormatter @@ -816,6 +820,78 @@ def _overwrite_pygments_css(app, exception=None): f.write(get_pygments_stylesheet(light_theme, dark_theme)) +# ------------------------------------------------------------------------------ +# customize rendering of the links +# ------------------------------------------------------------------------------ + + +class ShortenLinkTransform(SphinxPostTransform): + """ + Shorten link when they are coming from github or gitlab and add an extra class to the tag + for further styling. + Before:: + + https://github.com/2i2c-org/infrastructure/issues/1329 + + After:: + + 2i2c-org/infrastructure#1329 + + """ # noqa + + default_priority = 400 + formats = ("html",) + supported_platform = {"github.com": "github", "gitlab.com": "gitlab"} + platform = None + + def run(self, **kwargs): + matcher = NodeMatcher(nodes.reference) + for node in self.document.findall(matcher): + uri = node.attributes.get("refuri") + text = next(iter(node.children), None) + # only act if the uri and text are the same + # if not the user has already customized the display of the link + if uri is not None and text is not None and text == uri: + uri = urlparse(uri) + # only do something if the platform is identified + self.platform = self.supported_platform.get(uri.netloc) + if self.platform is not None: + node.attributes["classes"].append(self.platform) + node.children[0] = nodes.Text(self.parse_url(uri.path)) + + def parse_url(self, path): + """ + parse the content of the url with respect to the selected platform + """ + + # split the url content + # be careful the first one is a "/" + s = path.split("/") + + # check the platform name and read the information accordingly + if self.platform == "github": + text = "github" + if len(s) > 1: + text = s[1] + if len(s) > 2: + text += f"/{s[2]}" + if len(s) > 3: + if s[3] in ["issues", "pull", "discussions"]: + text += f"#{s[-1]}" + + elif self.platform == "gitlab": + text = "gitlab" + if len(s) > 1: + text = s[1] + if len(s) > 2: + text += f"/{s[2]}" + if len(s) > 3: + if s[4] in ["issues", "merge_requests"]: + text += f"#{s[-1]}" + + return text + + # ----------------------------------------------------------------------------- @@ -825,6 +901,8 @@ def setup(app): app.add_html_theme("pydata_sphinx_theme", str(theme_path)) + app.add_post_transform(ShortenLinkTransform) + app.set_translator("html", BootstrapHTML5Translator) # Read the Docs uses ``readthedocs`` as the name of the build, and also # uses a special "dirhtml" builder so we need to replace these both with diff --git a/src/pydata_sphinx_theme/assets/styles/base/_base.scss b/src/pydata_sphinx_theme/assets/styles/base/_base.scss index b608458d3..6efc7f75c 100644 --- a/src/pydata_sphinx_theme/assets/styles/base/_base.scss +++ b/src/pydata_sphinx_theme/assets/styles/base/_base.scss @@ -59,6 +59,21 @@ a { opacity: 1; } } + + // set up a icon next to the shorten links from github and gitlab + &::before { + color: var(--pst-color-text-muted); + font-family: "Font Awesome 6 Brands"; + margin-right: 0.25rem; + } + + &.github::before { + content: var(--pst-icon-github); + } + + &.gitlab::before { + content: var(--pst-icon-gitlab); + } } .heading-style { diff --git a/src/pydata_sphinx_theme/assets/styles/content/_admonitions.scss b/src/pydata_sphinx_theme/assets/styles/content/_admonitions.scss index ed965cd8c..21ffdc255 100644 --- a/src/pydata_sphinx_theme/assets/styles/content/_admonitions.scss +++ b/src/pydata_sphinx_theme/assets/styles/content/_admonitions.scss @@ -242,7 +242,7 @@ div.topic, div.topic.contents, // Docutils >= 0.18 nav.contents, -aside.topic, { +aside.topic { display: flex; flex-direction: column; background-color: var(--pst-color-surface); diff --git a/src/pydata_sphinx_theme/assets/styles/variables/_icons.scss b/src/pydata_sphinx_theme/assets/styles/variables/_icons.scss index 3cbbb22c4..0799876da 100644 --- a/src/pydata_sphinx_theme/assets/styles/variables/_icons.scss +++ b/src/pydata_sphinx_theme/assets/styles/variables/_icons.scss @@ -18,4 +18,6 @@ --pst-icon-angle-right: "\f105"; // fa-solid fa-angle-right --pst-icon-external-link: "\f35d"; // fa-solid fa-up-right-from-square --pst-icon-search-minus: "\f010"; // fa-solid fa-magnifying-glass-minus + --pst-icon-github: "\f09b"; // fa-brands fa-github + --pst-icon-gitlab: "\f296"; // fa-brands fa-gitlab } diff --git a/tests/sites/base/page1.rst b/tests/sites/base/page1.rst index 01100f347..9318bceef 100644 --- a/tests/sites/base/page1.rst +++ b/tests/sites/base/page1.rst @@ -1,2 +1,6 @@ Page 1 ====== + +- here's a normal link: https://pydata-sphinx-theme.readthedocs.io/en/latest/ +- Here's a github link: https://github.com/2i2c-org/infrastructure/issues/1329 +- Here's a gitlab link: https://gitlab.com/gitlab-org/gitlab/-/issues/375583 diff --git a/tests/test_build.py b/tests/test_build.py index b420c78d1..369a61015 100644 --- a/tests/test_build.py +++ b/tests/test_build.py @@ -664,3 +664,15 @@ def test_theme_switcher(sphinx_build_factory, file_regression): file_regression.check( switcher.prettify(), basename="navbar_theme", extension=".html" ) + + +def test_shorten_link(sphinx_build_factory, file_regression): + """regression test the shorten links html""" + + sphinx_build = sphinx_build_factory("base").build() + + github = sphinx_build.html_tree("page1.html").select(".github")[0] + file_regression.check(github.prettify(), basename="github_link", extension=".html") + + gitlab = sphinx_build.html_tree("page1.html").select(".gitlab")[0] + file_regression.check(gitlab.prettify(), basename="gitlab_link", extension=".html") diff --git a/tests/test_build/github_link.html b/tests/test_build/github_link.html new file mode 100644 index 000000000..adfedcf19 --- /dev/null +++ b/tests/test_build/github_link.html @@ -0,0 +1,3 @@ + + 2i2c-org/infrastructure#1329 + diff --git a/tests/test_build/gitlab_link.html b/tests/test_build/gitlab_link.html new file mode 100644 index 000000000..5242c3127 --- /dev/null +++ b/tests/test_build/gitlab_link.html @@ -0,0 +1,3 @@ + + gitlab-org/gitlab#375583 +