Skip to content

Commit 959042d

Browse files
12rambaucholdgraf
andauthored
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 <[email protected]> * Update docs/user_guide/theme-elements.md Co-authored-by: Chris Holdgraf <[email protected]> * Update src/pydata_sphinx_theme/__init__.py Co-authored-by: Chris Holdgraf <[email protected]> * Update src/pydata_sphinx_theme/__init__.py Co-authored-by: Chris Holdgraf <[email protected]> * refactor: new function names * maint: use fontawesome 6 Co-authored-by: Chris Holdgraf <[email protected]>
1 parent 494e5e9 commit 959042d

File tree

9 files changed

+124
-1
lines changed

9 files changed

+124
-1
lines changed

docs/user_guide/theme-elements.md

+6
Original file line numberDiff line numberDiff line change
@@ -143,3 +143,9 @@ For example, the admonition sidebar was created with the following markdown:
143143
Some sidebar content.
144144
```
145145
````
146+
147+
## Link shortening for git repository services
148+
149+
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).
150+
151+
Links provided with a text body won't be changed.

src/pydata_sphinx_theme/__init__.py

+78
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,16 @@
55
import warnings
66
from pathlib import Path
77
from functools import lru_cache
8+
from urllib.parse import urlparse
89

910
import jinja2
1011
from bs4 import BeautifulSoup as bs
12+
from docutils import nodes
1113
from sphinx import addnodes
1214
from sphinx.environment.adapters.toctree import TocTree
1315
from sphinx.addnodes import toctree as toctree_node
16+
from sphinx.transforms.post_transforms import SphinxPostTransform
17+
from sphinx.util.nodes import NodeMatcher
1418
from sphinx.errors import ExtensionError
1519
from sphinx.util import logging
1620
from pygments.formatters import HtmlFormatter
@@ -816,6 +820,78 @@ def _overwrite_pygments_css(app, exception=None):
816820
f.write(get_pygments_stylesheet(light_theme, dark_theme))
817821

818822

823+
# ------------------------------------------------------------------------------
824+
# customize rendering of the links
825+
# ------------------------------------------------------------------------------
826+
827+
828+
class ShortenLinkTransform(SphinxPostTransform):
829+
"""
830+
Shorten link when they are coming from github or gitlab and add an extra class to the tag
831+
for further styling.
832+
Before::
833+
<a class="reference external" href="https://github.com/2i2c-org/infrastructure/issues/1329">
834+
https://github.com/2i2c-org/infrastructure/issues/1329
835+
</a>
836+
After::
837+
<a class="reference external github" href="https://github.com/2i2c-org/infrastructure/issues/1329">
838+
2i2c-org/infrastructure#1329
839+
</a>
840+
""" # noqa
841+
842+
default_priority = 400
843+
formats = ("html",)
844+
supported_platform = {"github.com": "github", "gitlab.com": "gitlab"}
845+
platform = None
846+
847+
def run(self, **kwargs):
848+
matcher = NodeMatcher(nodes.reference)
849+
for node in self.document.findall(matcher):
850+
uri = node.attributes.get("refuri")
851+
text = next(iter(node.children), None)
852+
# only act if the uri and text are the same
853+
# if not the user has already customized the display of the link
854+
if uri is not None and text is not None and text == uri:
855+
uri = urlparse(uri)
856+
# only do something if the platform is identified
857+
self.platform = self.supported_platform.get(uri.netloc)
858+
if self.platform is not None:
859+
node.attributes["classes"].append(self.platform)
860+
node.children[0] = nodes.Text(self.parse_url(uri.path))
861+
862+
def parse_url(self, path):
863+
"""
864+
parse the content of the url with respect to the selected platform
865+
"""
866+
867+
# split the url content
868+
# be careful the first one is a "/"
869+
s = path.split("/")
870+
871+
# check the platform name and read the information accordingly
872+
if self.platform == "github":
873+
text = "github"
874+
if len(s) > 1:
875+
text = s[1]
876+
if len(s) > 2:
877+
text += f"/{s[2]}"
878+
if len(s) > 3:
879+
if s[3] in ["issues", "pull", "discussions"]:
880+
text += f"#{s[-1]}"
881+
882+
elif self.platform == "gitlab":
883+
text = "gitlab"
884+
if len(s) > 1:
885+
text = s[1]
886+
if len(s) > 2:
887+
text += f"/{s[2]}"
888+
if len(s) > 3:
889+
if s[4] in ["issues", "merge_requests"]:
890+
text += f"#{s[-1]}"
891+
892+
return text
893+
894+
819895
# -----------------------------------------------------------------------------
820896

821897

@@ -825,6 +901,8 @@ def setup(app):
825901

826902
app.add_html_theme("pydata_sphinx_theme", str(theme_path))
827903

904+
app.add_post_transform(ShortenLinkTransform)
905+
828906
app.set_translator("html", BootstrapHTML5Translator)
829907
# Read the Docs uses ``readthedocs`` as the name of the build, and also
830908
# uses a special "dirhtml" builder so we need to replace these both with

src/pydata_sphinx_theme/assets/styles/base/_base.scss

+15
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,21 @@ a {
5959
opacity: 1;
6060
}
6161
}
62+
63+
// set up a icon next to the shorten links from github and gitlab
64+
&::before {
65+
color: var(--pst-color-text-muted);
66+
font-family: "Font Awesome 6 Brands";
67+
margin-right: 0.25rem;
68+
}
69+
70+
&.github::before {
71+
content: var(--pst-icon-github);
72+
}
73+
74+
&.gitlab::before {
75+
content: var(--pst-icon-gitlab);
76+
}
6277
}
6378

6479
.heading-style {

src/pydata_sphinx_theme/assets/styles/content/_admonitions.scss

+1-1
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ div.topic,
242242
div.topic.contents,
243243
// Docutils >= 0.18
244244
nav.contents,
245-
aside.topic, {
245+
aside.topic {
246246
display: flex;
247247
flex-direction: column;
248248
background-color: var(--pst-color-surface);

src/pydata_sphinx_theme/assets/styles/variables/_icons.scss

+2
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,6 @@
1818
--pst-icon-angle-right: "\f105"; // fa-solid fa-angle-right
1919
--pst-icon-external-link: "\f35d"; // fa-solid fa-up-right-from-square
2020
--pst-icon-search-minus: "\f010"; // fa-solid fa-magnifying-glass-minus
21+
--pst-icon-github: "\f09b"; // fa-brands fa-github
22+
--pst-icon-gitlab: "\f296"; // fa-brands fa-gitlab
2123
}

tests/sites/base/page1.rst

+4
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
Page 1
22
======
3+
4+
- here's a normal link: https://pydata-sphinx-theme.readthedocs.io/en/latest/
5+
- Here's a github link: https://github.com/2i2c-org/infrastructure/issues/1329
6+
- Here's a gitlab link: https://gitlab.com/gitlab-org/gitlab/-/issues/375583

tests/test_build.py

+12
Original file line numberDiff line numberDiff line change
@@ -664,3 +664,15 @@ def test_theme_switcher(sphinx_build_factory, file_regression):
664664
file_regression.check(
665665
switcher.prettify(), basename="navbar_theme", extension=".html"
666666
)
667+
668+
669+
def test_shorten_link(sphinx_build_factory, file_regression):
670+
"""regression test the shorten links html"""
671+
672+
sphinx_build = sphinx_build_factory("base").build()
673+
674+
github = sphinx_build.html_tree("page1.html").select(".github")[0]
675+
file_regression.check(github.prettify(), basename="github_link", extension=".html")
676+
677+
gitlab = sphinx_build.html_tree("page1.html").select(".gitlab")[0]
678+
file_regression.check(gitlab.prettify(), basename="gitlab_link", extension=".html")

tests/test_build/github_link.html

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<a class="github reference external" href="https://github.com/2i2c-org/infrastructure/issues/1329">
2+
2i2c-org/infrastructure#1329
3+
</a>

tests/test_build/gitlab_link.html

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<a class="gitlab reference external" href="https://gitlab.com/gitlab-org/gitlab/-/issues/375583">
2+
gitlab-org/gitlab#375583
3+
</a>

0 commit comments

Comments
 (0)