From c155dbd514ee68dd6a88bf7053cf61b09f5dfe19 Mon Sep 17 00:00:00 2001 From: Elijah Greenstein Date: Fri, 29 May 2026 15:28:49 -0700 Subject: [PATCH 1/3] doc: update conf.py and add js for URL migration These changes support migration of the documentation from documentation.ubuntu.com/microcloud to canonical.com/microcloud/docs: - Adds `doc/_static/js/overwrite_links.js` to properly handle links in the flyout menu (version selector). - Updates configuration settings in `doc/conf.py` - Reorganizes JavaScript files into `doc/_static/js` directory, and updates relevant paths Signed-off-by: Elijah Greenstein --- doc/_static/js/overwrite_links.js | 38 +++++++++++++++++++++ doc/_static/{ => js}/rtd-versions-flyout.js | 0 doc/conf.py | 19 ++++++----- 3 files changed, 48 insertions(+), 9 deletions(-) create mode 100644 doc/_static/js/overwrite_links.js rename doc/_static/{ => js}/rtd-versions-flyout.js (100%) diff --git a/doc/_static/js/overwrite_links.js b/doc/_static/js/overwrite_links.js new file mode 100644 index 000000000..c23cdb11a --- /dev/null +++ b/doc/_static/js/overwrite_links.js @@ -0,0 +1,38 @@ + // Replace oldDomain with newDomain + const oldDomain = 'canonical-microcloud-documentation.readthedocs-hosted.com'; + const newDomain = 'canonical.com/microcloud/docs'; + + function escapeRegExp(value) { + return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + } + + function overwriteMatchingAnchorUrls(container) { + if (!container) return; + + const anchors = container.querySelectorAll('a[href], link[href]'); + const oldDomainRegex = new RegExp(escapeRegExp(oldDomain), 'g'); + + anchors.forEach(anchor => { + anchor.href = anchor.href.replace(oldDomainRegex, newDomain); + }); + } + + overwriteMatchingAnchorUrls(document.querySelector('header')); + + // Use a MutationObserver to wait for the RTD flyout element to appear in the DOM + const observer = new MutationObserver(function(mutations, obs) { + + const rtdFlyout = document.querySelector('readthedocs-flyout'); + if (!rtdFlyout) return; + + obs.disconnect(); + + rtdFlyout.addEventListener('click', function() { + const shadowRoot = rtdFlyout.shadowRoot; + if (!shadowRoot) return; + + overwriteMatchingAnchorUrls(shadowRoot); + }); + }); + + observer.observe(document.body, { childList: true, subtree: true }); diff --git a/doc/_static/rtd-versions-flyout.js b/doc/_static/js/rtd-versions-flyout.js similarity index 100% rename from doc/_static/rtd-versions-flyout.js rename to doc/_static/js/rtd-versions-flyout.js diff --git a/doc/conf.py b/doc/conf.py index a06900f0d..d6e8ab833 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -32,14 +32,18 @@ # Copyright string; shown at the bottom of the page copyright = '2014-%s AGPL-3.0, %s' % (datetime.date.today().year, author) -# Use RTD canonical URL to ensure duplicate pages have a single canonical URL -# that includes the version (such as /latest/); helps SEO. -html_baseurl = os.environ.get('READTHEDOCS_CANONICAL_URL', '/') +# Documentation website URL + +version_slug = f'{os.environ.get("READTHEDOCS_VERSION", "local")}' + +slug = 'microcloud/docs' + +html_baseurl = f'https://canonical.com/microcloud/docs/{version_slug}/' # OpenGraph metadata used for social sharing previews ogp_site_url = html_baseurl ogp_site_name = html_title -ogp_image = 'https://documentation.ubuntu.com/microcloud/latest/_static/microcloud_tag.png' +ogp_image = f'https://canonical.com/microcloud/docs/{version_slug}/_static/microcloud_tag.png' html_favicon = '_static/favicon.png' @@ -77,10 +81,6 @@ 'source_edit_link': html_context['github_url'] } -# Project slug -# Required if your project is hosted on documentation.ubuntu.com -slug = 'microcloud' - ####################### # Sitemap configuration: https://sphinx-sitemap.readthedocs.io/ ####################### @@ -211,7 +211,8 @@ html_js_files = [ 'https://assets.ubuntu.com/v1/287a5e8f-bundle.js', - 'rtd-versions-flyout.js', + 'js/rtd-versions-flyout.js', + "js/overwrite_links.js", ] # Feedback button at the top; enabled by default From e599f5a182b22b2f97199596469d35bb952cb779 Mon Sep 17 00:00:00 2001 From: Elijah Greenstein Date: Thu, 4 Jun 2026 20:51:15 -0700 Subject: [PATCH 2/3] doc/conf.py: temporarily remove "edit page" button This commit removes the "Contribute to this page" button. This change is temporary, and the button will be restored after the docs have moved to canonical.com. Signed-off-by: Elijah Greenstein --- doc/conf.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index d6e8ab833..895ddec98 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -77,9 +77,9 @@ html_extra_path = ['_extra'] # Enables the pencil icon to edit pages on GitHub, shown at the top of each page -html_theme_options = { - 'source_edit_link': html_context['github_url'] -} +# html_theme_options = { +# 'source_edit_link': html_context['github_url'] +# } ####################### # Sitemap configuration: https://sphinx-sitemap.readthedocs.io/ From c19f7958e35a3ed7319e1ca5155554c5dc9b5209 Mon Sep 17 00:00:00 2001 From: Elijah Greenstein Date: Mon, 6 Jul 2026 15:28:35 -0700 Subject: [PATCH 3/3] doc: consistently overwrite MicroCloud links - Copies the MicroCloud `overwrite_links.js` file into the cloned LXD, MicroCeph, and MicroOVN repos as `overwrite_microcloud_links.js`, so that the JavaScript loads across the integrated docs - Prefixes functions and variables in the MicroCloud `overwrite_links.js` file with `microcloud_` in order to prevent conflicts with the equivalents in the LXD, MicroCeph, and MicroOVN `overwrite_links.js` files. - Reconfigures the Makefile to append `add_config.py` to the end of the MicroOVN `conf.py` so that the addition of `overwrite_microcloud_links.js` to `html_js_files` applies to MicroOVN. Signed-off-by: Elijah Greenstein --- doc/.sphinx/_integration/add_config.py | 9 +++++++-- doc/Makefile | 11 +++++++++-- doc/_static/js/overwrite_links.js | 20 ++++++++++---------- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/doc/.sphinx/_integration/add_config.py b/doc/.sphinx/_integration/add_config.py index a54c610f9..ca143b3eb 100644 --- a/doc/.sphinx/_integration/add_config.py +++ b/doc/.sphinx/_integration/add_config.py @@ -12,6 +12,7 @@ if project == "LXD": html_baseurl = "https://canonical.com/lxd/docs/latest/" html_css_files = globals().get('html_css_files', []) + ['override-header.css'] + html_js_files = globals().get('html_js_files', []) + ['js/overwrite_microcloud_links.js'] tags.add('integrated') elif project == "MicroCeph": html_baseurl = "https://documentation.ubuntu.com/canonical-microceph/latest/" @@ -20,9 +21,13 @@ # Override default header styles html_static_path = globals().get('html_static_path', []) + ["_static"] html_css_files = globals().get('html_css_files', []) + ['override-header.css'] + # Add js to overwrite MicroCloud links + html_js_files = globals().get('html_js_files', []) + ['overwrite_microcloud_links.js'] # Add "integrated" to the list of custom tags tags.add('integrated') elif project == "MicroOVN": html_baseurl = "https://ubuntu.com/docs/microovn/latest/" - custom_tags.append('integrated') - + tags.add('integrated') + html_static_path = globals().get('html_static_path', []) + ["_static"] + # Add js to overwrite MicroCloud links + html_js_files = globals().get('html_js_files', []) + ['overwrite_microcloud_links.js'] diff --git a/doc/Makefile b/doc/Makefile index f09e7fce8..46a38030d 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -109,11 +109,18 @@ integrate: # Add information about where to find the tags/docs to the doc sets cat .sphinx/_integration/add_config.py >> integration/lxd/doc/conf.py cat .sphinx/_integration/add_config.py >> integration/microceph/docs/conf.py - cat .sphinx/_integration/add_config.py >> integration/microovn/docs/custom_conf.py + cat .sphinx/_integration/add_config.py >> integration/microovn/docs/conf.py # Override the MicroOVN tag with the circle of friends one (for consistency) cp .sphinx/_integration/tag.png integration/microovn/docs/.sphinx/_static/microovn.png + # Copy MicroCloud `overwrite_links.js` to all repos + cp _static/js/overwrite_links.js integration/lxd/doc/_static/js/overwrite_microcloud_links.js + mkdir -p integration/microceph/docs/_static + cp _static/js/overwrite_links.js integration/microceph/docs/_static/overwrite_microcloud_links.js + mkdir -p integration/microovn/docs/_static + cp _static/js/overwrite_links.js integration/microovn/docs/_static/overwrite_microcloud_links.js + # `html` builds the integrated docs. html: integrate install mkdir -p $(current_dir)/_build @@ -230,4 +237,4 @@ spellcheck: spelling # "make mode" option. $(O) is meant as a shortcut for $(SPHINX_OPTS). %: $(MAKE) --no-print-directory install - . $(DOCS_VENV); $(SPHINX_BUILD) -M $@ "$(DOCS_SOURCEDIR)" "$(DOCS_BUILDDIR)" $(SPHINX_OPTS) $(O) \ No newline at end of file + . $(DOCS_VENV); $(SPHINX_BUILD) -M $@ "$(DOCS_SOURCEDIR)" "$(DOCS_BUILDDIR)" $(SPHINX_OPTS) $(O) diff --git a/doc/_static/js/overwrite_links.js b/doc/_static/js/overwrite_links.js index c23cdb11a..19a30a5e2 100644 --- a/doc/_static/js/overwrite_links.js +++ b/doc/_static/js/overwrite_links.js @@ -1,26 +1,26 @@ // Replace oldDomain with newDomain - const oldDomain = 'canonical-microcloud-documentation.readthedocs-hosted.com'; - const newDomain = 'canonical.com/microcloud/docs'; + const microcloud_oldDomain = 'canonical-microcloud-documentation.readthedocs-hosted.com'; + const microcloud_newDomain = 'canonical.com/microcloud/docs'; - function escapeRegExp(value) { + function microcloud_escapeRegExp(value) { return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } - function overwriteMatchingAnchorUrls(container) { + function microcloud_overwriteMatchingAnchorUrls(container) { if (!container) return; const anchors = container.querySelectorAll('a[href], link[href]'); - const oldDomainRegex = new RegExp(escapeRegExp(oldDomain), 'g'); + const oldDomainRegex = new RegExp(microcloud_escapeRegExp(microcloud_oldDomain), 'g'); anchors.forEach(anchor => { - anchor.href = anchor.href.replace(oldDomainRegex, newDomain); + anchor.href = anchor.href.replace(oldDomainRegex, microcloud_newDomain); }); } - overwriteMatchingAnchorUrls(document.querySelector('header')); + microcloud_overwriteMatchingAnchorUrls(document.querySelector('header')); // Use a MutationObserver to wait for the RTD flyout element to appear in the DOM - const observer = new MutationObserver(function(mutations, obs) { + const microcloud_observer = new MutationObserver(function(mutations, obs) { const rtdFlyout = document.querySelector('readthedocs-flyout'); if (!rtdFlyout) return; @@ -31,8 +31,8 @@ const shadowRoot = rtdFlyout.shadowRoot; if (!shadowRoot) return; - overwriteMatchingAnchorUrls(shadowRoot); + microcloud_overwriteMatchingAnchorUrls(shadowRoot); }); }); - observer.observe(document.body, { childList: true, subtree: true }); + microcloud_observer.observe(document.body, { childList: true, subtree: true });