Skip to content

Commit 1461734

Browse files
authored
Merge pull request #247 from altheaden/version-switcher
Remove `sphinx-multiversion` and supply custom version drop-down on docs
2 parents d1150a0 + c63974a commit 1461734

File tree

12 files changed

+210
-51
lines changed

12 files changed

+210
-51
lines changed

.github/workflows/build_workflow.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,6 @@ jobs:
125125
- if: ${{ steps.skip_check.outputs.should_skip != 'true' }}
126126
name: Build Sphinx Docs
127127
run: |
128-
# sphinx-multiversion expects at least a "main" branch
129-
git branch main || echo "branch main already exists."
130128
cd docs
131-
sphinx-multiversion . _build/html
129+
DOCS_VERSION=test make versioned-html
132130

.github/workflows/docs_workflow.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,15 @@ jobs:
5959
set -e
6060
pip check
6161
cd docs
62-
sphinx-multiversion . _build/html
62+
DOCS_VERSION=${{ github.ref_name }} make versioned-html
6363
- name: Copy Docs and Commit
6464
run: |
6565
set -e
6666
pip check
6767
cd docs
6868
# gh-pages branch must already exist
6969
git clone https://github.com/MPAS-Dev/geometric_features.git --branch gh-pages --single-branch gh-pages
70+
7071
# Make sure we're in the gh-pages directory.
7172
cd gh-pages
7273
# Create `.nojekyll` (if it doesn't already exist) for proper GH Pages configuration.

dev-spec.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,4 @@ setuptools>=60
2121
# Documentation
2222
sphinx
2323
sphinx_rtd_theme
24-
sphinx-multiversion
2524
m2r2

docs/Makefile

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,22 @@ SPHINXPROJ = geometric_features
88
SOURCEDIR = .
99
BUILDDIR = _build
1010

11+
# Build into a versioned subdirectory
12+
versioned-html:
13+
@echo "Building version: $(DOCS_VERSION)"
14+
$(SPHINXBUILD) -b html "$(SOURCEDIR)" "$(BUILDDIR)/html/$(DOCS_VERSION)"
15+
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html/$(DOCS_VERSION)."
16+
@echo "Setting up shared version switcher for local preview..."
17+
mkdir -p _build/html/shared
18+
cp shared/version-switcher.js _build/html/shared/version-switcher.js
19+
python generate_versions_json.py --local
20+
21+
# Override html target to include local setup
22+
html:
23+
$(SPHINXBUILD) -b html "$(SOURCEDIR)" "$(BUILDDIR)/html"
24+
@echo
25+
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
26+
1127
# Put it first so that "make" without argument is like "make help".
1228
help:
1329
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
@@ -22,3 +38,7 @@ clean:
2238
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
2339
%: Makefile
2440
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
41+
42+
clean-versioned-html:
43+
rm -rf $(BUILDDIR)/html/*
44+
@echo "Cleaned versioned HTML builds."

docs/_static/style.css

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,28 @@
22
max-width: 1200px !important;
33
}
44

5+
#version-switcher select {
6+
background-color: #2980b9;
7+
color: white;
8+
border: none;
9+
border-radius: 4px;
10+
padding: 4px 30px 4px 10px;
11+
font-size: 0.9em;
12+
appearance: none; /* Remove default dropdown arrow */
13+
background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg fill='white' height='10' viewBox='0 0 24 24' width='10' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M7 10l5 5 5-5z'/%3E%3C/svg%3E");
14+
background-repeat: no-repeat;
15+
background-position: right 10px center;
16+
background-size: 12px;
17+
}
18+
19+
#version-switcher select:focus {
20+
outline: none;
21+
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.4);
22+
background-color: #2c89c4; /* slightly lighter blue on focus */
23+
}
24+
25+
/* Selected item in the dropdown menu */
26+
#version-switcher option:checked {
27+
background-color: #dddddd; /* for selected */
28+
color: black;
29+
}

docs/_templates/layout.html

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,24 @@
33
<link href="{{ pathto("_static/style.css", True) }}" rel="stylesheet" type="text/css">
44
{% endblock %}
55

6+
{% block footer %}
7+
{{ super() }}
8+
9+
<!-- Meta tags for JS to use -->
10+
<meta name="doc-version" content="{{ current_version }}">
11+
<meta name="doc-site-root" content="{{ pathto('', 1) }}">
12+
13+
<!-- Create version switcher container -->
14+
<script>
15+
const sidebar = document.querySelector('.wy-side-nav-search');
16+
if (sidebar) {
17+
const versionDiv = document.createElement('div');
18+
versionDiv.id = 'version-switcher';
19+
versionDiv.style.marginTop = '1em';
20+
sidebar.appendChild(versionDiv);
21+
}
22+
</script>
23+
24+
<!-- Load version-switcher.js using the correct relative path -->
25+
<script src="{{ pathto('../shared/version-switcher.js', 1) }}"></script>
26+
{% endblock %}

docs/_templates/versions.html

Lines changed: 0 additions & 28 deletions
This file was deleted.

docs/build_docs.rst

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,17 @@ Then, run:
1313
.. code-block:: bash
1414
1515
cd docs
16-
make clean
17-
make html
16+
DOCS_VERSION=test make clean versioned-html
1817
19-
You can find the test build in ``_build/html/index.html``.
18+
Previewing the Documentation
19+
============================
20+
21+
To preview the documentation locally, open the ``index.html`` file in the
22+
``_build/html/test`` directory with your browser or try:
23+
24+
.. code-block:: bash
25+
26+
cd _build/html
27+
python -m http.server 8000
28+
29+
Then, open http://0.0.0.0:8000/test/ in your browser.

docs/conf.py

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# serve to show the default.
1414

1515
from datetime import date
16+
import os
1617

1718
from geometric_features.docs.parse_quick_start import build_quick_start
1819
from geometric_features.version import __version__
@@ -28,7 +29,6 @@
2829
# ones.
2930
extensions = [
3031
'sphinx_rtd_theme',
31-
'sphinx_multiversion',
3232
'sphinx.ext.autodoc',
3333
'sphinx.ext.autosummary',
3434
'sphinx.ext.intersphinx',
@@ -69,11 +69,14 @@
6969
# The version info for the project you're documenting, acts as replacement for
7070
# |version| and |release|, also used in various other places throughout the
7171
# built documents.
72-
#
73-
# The short X.Y version.
74-
version = __version__
75-
# The full version, including alpha/beta/rc tags.
76-
release = __version__
72+
if 'DOCS_VERSION' in os.environ:
73+
version = os.environ.get('DOCS_VERSION')
74+
release = version
75+
else:
76+
# The short X.Y.Z version.
77+
version = __version__
78+
# The full version, including alpha/beta/rc tags.
79+
release = __version__
7780

7881
# The language for content autogenerated by Sphinx. Refer to documentation
7982
# for a list of supported languages.
@@ -187,13 +190,7 @@
187190
# so a file named "default.css" will overwrite the builtin "default.css".
188191
html_static_path = ["_static"]
189192

190-
html_sidebars = {
191-
"**": [
192-
"versions.html",
193-
],
193+
html_context = {
194+
"current_version": os.getenv("DOCS_VERSION", "main"),
194195
}
195196

196-
# -- Options sphinx-multiversion -------------------------------------------
197-
smv_tag_whitelist = r'^\d+\.\d+.\d+$'
198-
smv_branch_whitelist = 'main'
199-
smv_remote_whitelist = 'origin'

docs/generate_versions_json.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#!/usr/bin/env python
2+
import argparse
3+
import json
4+
import os
5+
import re
6+
7+
8+
def version_key(name):
9+
"""Key function for sorting versions."""
10+
match = re.match(r'^(\d+)\.(\d+)\.(\d+)$', name)
11+
if match:
12+
# Sort by major, minor, patch
13+
return tuple(map(int, match.groups()))
14+
return ()
15+
16+
17+
# Mode: local or production
18+
parser = argparse.ArgumentParser(
19+
description='Generate versions.json for geometric features documentation.')
20+
parser.add_argument(
21+
'--local',
22+
action='store_true',
23+
help='Generate versions.json for local build.'
24+
)
25+
args = parser.parse_args()
26+
local = args.local
27+
base_dir = '_build/html' if local else 'gh-pages'
28+
shared_dir = os.path.join(base_dir, 'shared')
29+
30+
entries = []
31+
32+
if not os.path.exists(base_dir) or not os.listdir(base_dir):
33+
raise FileNotFoundError(
34+
f"Base directory '{base_dir}' does not exist or is empty.")
35+
36+
versions = os.listdir(base_dir)
37+
numeric_versions = []
38+
non_numeric_versions = []
39+
40+
for version in versions:
41+
# Check if it matches version pattern
42+
if re.match(r'^\d+\.\d+\.\d+$', version):
43+
numeric_versions.append(version)
44+
else:
45+
non_numeric_versions.append(version)
46+
47+
# Sort numeric versions by major, minor, patch in descending order
48+
numeric_versions.sort(key=version_key, reverse=True)
49+
# Sort non-numeric versions alphabetically
50+
non_numeric_versions.sort()
51+
52+
# Combine the sorted lists
53+
versions = non_numeric_versions + numeric_versions
54+
55+
if 'main' in versions:
56+
versions.insert(0, versions.pop(versions.index('main')))
57+
58+
for name in versions:
59+
path = os.path.join(base_dir, name)
60+
if os.path.isdir(path) and name not in ('shared', '.git'):
61+
entries.append({
62+
'version': name,
63+
'url': f'../{name}/' if local else f'/geometric_features/{name}/'
64+
})
65+
66+
os.makedirs(shared_dir, exist_ok=True)
67+
with open(os.path.join(shared_dir, 'versions.json'), 'w') as f:
68+
json.dump(entries, f, indent=2)
69+

0 commit comments

Comments
 (0)