From 0fab87c2623327147aee18c74d233dd72adf06ac 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 743672bc1..86a5c3d63 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 bcb0d2d2dd57111ad7fb33a86f6d30500a1a1550 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 86a5c3d63..cc5892b30 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 fde8f1a086a2de38c4bcd88e0c6ca461cbce9cf3 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 | 9 ++++++++- doc/_static/js/overwrite_links.js | 20 ++++++++++---------- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/doc/.sphinx/_integration/add_config.py b/doc/.sphinx/_integration/add_config.py index 7626ef140..da39aa2b2 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/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 2eed4487f..7ec7516c1 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -116,11 +116,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 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 });