diff options
Diffstat (limited to 'sphinx/ext/githubpages.py')
-rw-r--r-- | sphinx/ext/githubpages.py | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/sphinx/ext/githubpages.py b/sphinx/ext/githubpages.py new file mode 100644 index 0000000..c9be928 --- /dev/null +++ b/sphinx/ext/githubpages.py @@ -0,0 +1,57 @@ +"""To publish HTML docs at GitHub Pages, create .nojekyll file.""" + +from __future__ import annotations + +import contextlib +import os +import urllib.parse +from typing import TYPE_CHECKING, Any + +import sphinx + +if TYPE_CHECKING: + from sphinx.application import Sphinx + from sphinx.environment import BuildEnvironment + + +def _get_domain_from_url(url: str) -> str: + """Get the domain from a URL.""" + return url and urllib.parse.urlparse(url).hostname or '' + + +def create_nojekyll_and_cname(app: Sphinx, env: BuildEnvironment) -> None: + """Manage the ``.nojekyll`` and ``CNAME`` files for GitHub Pages. + + For HTML-format builders (e.g. 'html', 'dirhtml') we unconditionally create + the ``.nojekyll`` file to signal that GitHub Pages should not run Jekyll + processing. + + If the :confval:`html_baseurl` option is set, we also create a CNAME file + with the domain from ``html_baseurl``, so long as it is not a ``github.io`` + domain. + + If this extension is loaded and the domain in ``html_baseurl`` no longer + requires a CNAME file, we remove any existing ``CNAME`` files from the + output directory. + """ + if app.builder.format != 'html': + return + + app.builder.outdir.joinpath('.nojekyll').touch() + cname_path = os.path.join(app.builder.outdir, 'CNAME') + + domain = _get_domain_from_url(app.config.html_baseurl) + # Filter out GitHub Pages domains, as they do not require CNAME files. + if domain and not domain.endswith(".github.io"): + with open(cname_path, 'w', encoding="utf-8") as f: + # NOTE: don't write a trailing newline. The `CNAME` file that's + # auto-generated by the GitHub UI doesn't have one. + f.write(domain) + else: + with contextlib.suppress(FileNotFoundError): + os.unlink(cname_path) + + +def setup(app: Sphinx) -> dict[str, Any]: + app.connect('env-updated', create_nojekyll_and_cname) + return {'version': sphinx.__display_version__, 'parallel_read_safe': True} |