Skip to content

Commit 2e66cd4

Browse files
authored
Merge pull request #308 from xylar/switch-to-version-dropdown
Switch to a custom version dropdown
2 parents 9398c67 + 3467e5b commit 2e66cd4

File tree

12 files changed

+215
-51
lines changed

12 files changed

+215
-51
lines changed

.github/workflows/build_workflow.yml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ jobs:
9191
init-shell: bash
9292
condarc: |
9393
channel_priority: strict
94-
channels:
94+
channels:
9595
- conda-forge
9696
- e3sm/label/polaris
9797
create-args: >-
@@ -111,8 +111,5 @@ jobs:
111111
name: Build Sphinx Docs
112112
run: |
113113
source load_polaris_test_mpich.sh
114-
# sphinx-multiversion expects at least a "main" branch
115-
git branch main || echo "branch main already exists."
116114
cd docs
117-
sphinx-multiversion . _build/html
118-
115+
DOCS_VERSION=test make versioned-html

.github/workflows/docs_workflow.yml

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,23 +62,33 @@ jobs:
6262
run: |
6363
source load_polaris_test.sh
6464
cd docs
65-
sphinx-multiversion . _build/html
65+
DOCS_VERSION=${{ github.ref_name }} make versioned-html
6666
- name: Copy Docs and Commit
6767
run: |
6868
source load_polaris_test.sh
6969
cd docs
7070
# gh-pages branch must already exist
7171
git clone https://github.com/E3SM-Project/polaris.git --branch gh-pages --single-branch gh-pages
72+
73+
# Only replace docs in a directory with the destination branch name with latest changes. Docs for
74+
# releases should be untouched.
75+
rm -rf gh-pages/${{ github.ref_name }}
76+
77+
# don't clobber existing release versions (in case we retroactively fixed them)
78+
cp -r _build/html/${{ github.ref_name }} gh-pages/
79+
80+
mkdir -p gh-pages/shared
81+
cp shared/version-switcher.js gh-pages/shared/version-switcher.js
82+
83+
# Update the list of versions with all versions in the gh-pages directory.
84+
python generate_versions_json.py
85+
7286
# Make sure we're in the gh-pages directory.
7387
cd gh-pages
7488
# Create `.nojekyll` (if it doesn't already exist) for proper GH Pages configuration.
7589
touch .nojekyll
7690
# Add `index.html` to point to the `main` branch automatically.
7791
printf '<meta http-equiv="refresh" content="0; url=./main/index.html" />' > index.html
78-
# Only replace `main` docs with latest changes. Docs for releases should be untouched.
79-
rm -rf main
80-
# don't clobber existing release versions (in case we retroactively fixed them)
81-
cp -r -n ../_build/html/* .
8292
# Configure git using GitHub Actions credentials.
8393
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
8494
git config --local user.name "github-actions[bot]"

deploy/conda-dev-spec.template

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ udunits2
7272
sphinx >=7.0.0
7373
sphinx_rtd_theme
7474
myst-parser
75-
sphinx-multiversion
7675

7776
# Visualization
7877
ncview

docs/Makefile

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,35 @@ SPHINXBUILD ?= sphinx-build
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)
1430

31+
32+
clean:
33+
rm -rf generated
34+
@$(SPHINXBUILD) -M clean "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
35+
36+
clean-versioned-html:
37+
rm -rf $(BUILDDIR)/html/*
38+
@echo "Cleaned versioned HTML builds."
39+
1540
.PHONY: help Makefile
1641

1742
# Catch-all target: route all unknown targets to Sphinx using the new

docs/_static/style.css

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,29 @@
11
.wy-nav-content {
22
max-width: 1200px !important;
33
}
4+
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: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,27 @@
11
{% extends "!layout.html" %}
2+
23
{% block extrahead %}
34
<link href="{{ pathto("_static/style.css", True) }}" rel="stylesheet" type="text/css">
45
{% endblock %}
6+
7+
{% block footer %}
8+
{{ super() }}
9+
10+
<!-- Meta tags for JS to use -->
11+
<meta name="doc-version" content="{{ current_version }}">
12+
<meta name="doc-site-root" content="{{ pathto('', 1) }}">
13+
14+
<!-- Create version switcher container -->
15+
<script>
16+
const sidebar = document.querySelector('.wy-side-nav-search');
17+
if (sidebar) {
18+
const versionDiv = document.createElement('div');
19+
versionDiv.id = 'version-switcher';
20+
versionDiv.style.marginTop = '1em';
21+
sidebar.appendChild(versionDiv);
22+
}
23+
</script>
24+
25+
<!-- Load version-switcher.js using the correct relative path -->
26+
<script src="{{ pathto('../shared/version-switcher.js', 1) }}"></script>
27+
{% endblock %}

docs/_templates/versions.html

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

docs/conf.py

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
extensions = [
3939
"myst_parser",
4040
"sphinx_rtd_theme",
41-
"sphinx_multiversion",
4241
"sphinx.ext.autodoc",
4342
"sphinx.ext.autosummary",
4443
"sphinx.ext.intersphinx",
@@ -102,13 +101,6 @@
102101
# so a file named "default.css" will overwrite the builtin "default.css".
103102
html_static_path = ["_static"]
104103

105-
html_sidebars = {
106-
"**": [
107-
"versions.html",
108-
],
104+
html_context = {
105+
"current_version": os.getenv("DOCS_VERSION", "main"),
109106
}
110-
111-
# Include tags like "tags/1.0.0" -- 0.1.0-0.4.0 don't build
112-
smv_tag_whitelist = r'^(?!(0.1.0|0.2.0|0.3.0|0.4.0))\d+\.\d+.\d+$'
113-
smv_branch_whitelist = "main"
114-
smv_remote_whitelist = "origin"

docs/developers_guide/building_docs.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,17 @@ Then, run the following script to build the docs:
1010

1111
```bash
1212
cd docs
13-
make clean && make html
13+
DOCS_VERSION=test make clean versioned-html
1414
```
1515

16-
You can view the documentation by opening `_build/html/index.html`.
16+
# Previewing the Documentation
17+
18+
To preview the documentation locally, open the `index.html` file in the
19+
`_build/html/test` directory with your browser or try:
20+
21+
```bash
22+
cd _build/html
23+
python -m http.server 8000
24+
```
25+
26+
Then, open http://0.0.0.0:8000/test/ in your browser.

docs/generate_versions_json.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
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 polaris 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'/polaris/{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)

0 commit comments

Comments
 (0)