Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions .github/workflows/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,22 @@ jobs:
with:
python-version: '3.12'
- run: pip install mkdocs-material mkdocs-static-i18n
# --strict fails the build on broken internal links. The docs use
# relative .md cross-links, so this is the gate that keeps them honest.
- run: mkdocs build --strict
# Build without --strict so the known i18n + navigation.instant warning
Comment thread
Jotatavo marked this conversation as resolved.
# does not abort. Still fail on any other WARNING (link/config issues).
# Language alternates are rewritten at runtime (language-selector-label.js).
- name: Build docs
run: |
set -o pipefail
mkdocs build 2>&1 | tee /tmp/mkdocs-build.log
# Allow only the known i18n ↔ navigation.instant incompatibility warning
# (exact message from mkdocs-static-i18n). Any other WARNING fails CI.
allowed='mkdocs_static_i18n: mkdocs-material language switcher contextual link is not compatible with theme.features = navigation.instant'
unexpected=$(grep -E '^WARNING' /tmp/mkdocs-build.log | grep -vF "$allowed" || true)
if [ -n "$unexpected" ]; then
echo "::error::Unexpected mkdocs WARNING(s):"
echo "$unexpected"
exit 1
fi
# tar --dereference is what preserves the hidden .well-known directory.
# Both deploy jobs consume this one artifact, so the two origins cannot drift.
- name: Package site
Expand Down
Binary file removed docs/dz-icon.png
Binary file not shown.
Binary file modified docs/favicon.ico
Binary file not shown.
Binary file added docs/fonts/RecklessStandardM-Bold.woff2
Binary file not shown.
Binary file added docs/fonts/RecklessStandardM-Medium.woff2
Binary file not shown.
Binary file added docs/fonts/RecklessStandardM-Regular.woff2
Binary file not shown.
Binary file added docs/fonts/RecklessStandardM-SemiBold.woff2
Binary file not shown.
Binary file added docs/fonts/SuisseIntl-Bold.ttf
Binary file not shown.
Binary file added docs/fonts/SuisseIntl-Light.ttf
Binary file not shown.
Binary file added docs/fonts/SuisseIntl-Medium.ttf
Binary file not shown.
Binary file added docs/fonts/SuisseIntl-Mono.ttf
Binary file not shown.
Binary file added docs/fonts/SuisseIntl-Regular.ttf
Binary file not shown.
Binary file added docs/fonts/SuisseIntl-SemiBold.ttf
Binary file not shown.
147 changes: 147 additions & 0 deletions docs/javascripts/header-controls-order.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
// Keep theme palette in the header (instant nav replaces the drawer container).
// On mobile, a drawer button clicks the header toggle instead of relocating the form.
(function () {
'use strict';

var MOBILE_MQ = '(max-width: 40em)';

function syncPaletteIcon(form) {
if (!form) {
form = document.querySelector('[data-md-component="palette"]');
}
if (!form) return;

// Compact theme button owns the visible UI — keep Material labels hidden.
if (form.querySelector('.dz2-theme-btn') || form.querySelector('.dz2-mode-switch')) {
var allLabels = form.querySelectorAll('label.md-header__button');
for (var k = 0; k < allLabels.length; k++) {
allLabels[k].setAttribute('hidden', '');
}
return;
}

var inputs = form.querySelectorAll('.md-option');
if (!inputs.length) return;

var checked = form.querySelector('.md-option:checked');
if (!checked) {
var scheme = document.body.getAttribute('data-md-color-scheme') || 'slate';
for (var i = 0; i < inputs.length; i++) {
if (inputs[i].getAttribute('data-md-color-scheme') === scheme) {
checked = inputs[i];
inputs[i].checked = true;
break;
}
}
if (!checked) {
checked = inputs[0];
checked.checked = true;
}
}

for (var j = 0; j < inputs.length; j++) {
var input = inputs[j];
var label = input.nextElementSibling;
while (label && label.tagName !== 'LABEL') {
label = label.nextElementSibling;
}
if (!label) continue;
var shouldHide = input !== checked;
var isHidden = label.hasAttribute('hidden');
if (shouldHide && !isHidden) {
label.setAttribute('hidden', '');
} else if (!shouldHide && isHidden) {
label.removeAttribute('hidden');
}
}
}

function placePalette() {
var palette = document.querySelector('[data-md-component="palette"]');
var header = document.querySelector('.md-header__inner');
if (!palette || !header) return;
// Always keep the form in the header so instant navigation cannot destroy it.
if (palette.parentElement !== header || header.lastElementChild !== palette) {
header.appendChild(palette);
}
}

function syncDrawerThemeBtn() {
var drawerBtn = document.getElementById('drawer-theme-btn');
var real = document.querySelector('.dz2-theme-btn');
if (!drawerBtn || !real) return;
drawerBtn.setAttribute('aria-label', real.getAttribute('aria-label') || 'Toggle theme');
drawerBtn.setAttribute('data-next-mode', real.getAttribute('data-next-mode') || '');
var icon = real.querySelector('svg');
if (icon) {
drawerBtn.innerHTML = icon.outerHTML;
}
}

function refresh() {
placePalette();
syncPaletteIcon();
syncDrawerThemeBtn();
}

function boot() {
refresh();
var form = document.querySelector('[data-md-component="palette"]');
if (form && !form.dataset.paletteSyncBound) {
form.dataset.paletteSyncBound = '1';
form.addEventListener('change', function () {
syncPaletteIcon(form);
syncDrawerThemeBtn();
});
}

if (!window.__dzPaletteMqBound) {
window.__dzPaletteMqBound = true;
window.matchMedia(MOBILE_MQ).addEventListener('change', refresh);

// Opening search from the drawer should close the drawer first
document.addEventListener('click', function (event) {
var trigger = event.target.closest && event.target.closest('label[for="__search"]');
if (!trigger || !trigger.closest('.mobile-drawer-controls')) return;
var drawer = document.getElementById('__drawer');
if (drawer) drawer.checked = false;
});

// Drawer theme control proxies the header toggle (form stays in header).
document.addEventListener('click', function (event) {
var drawerBtn = event.target.closest && event.target.closest('#drawer-theme-btn');
if (!drawerBtn) return;
event.preventDefault();
var real = document.querySelector('.dz2-theme-btn');
if (real) real.click();
});
}

var header = document.querySelector('.md-header');
if (header && !header.dataset.paletteOrderBound) {
header.dataset.paletteOrderBound = '1';
new MutationObserver(function () {
refresh();
}).observe(header, { childList: true, subtree: true });
}

new MutationObserver(syncDrawerThemeBtn).observe(document.body, {
attributes: true,
attributeFilter: ['data-md-color-scheme', 'data-md-color-primary']
});
}

function onReady(fn) {
if (typeof document$ !== 'undefined' && document$.subscribe) {
document$.subscribe(fn);
return;
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', fn);
} else {
fn();
}
}

onReady(boot);
})();
115 changes: 90 additions & 25 deletions docs/javascripts/language-selector-label.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
// Display the currently selected language name next to the language selector icon
(function() {
// Language control: label + path-aware alternate links for navigation.instant.
//
// mkdocs-static-i18n warns that Material's contextual language hrefs go stale
// under instant navigation. We rewrite every alternate link from the current
// pathname so locale switches always target the page you are on.
(function () {
'use strict';

var LOCALE_SEGMENTS = ['zh', 'ja', 'ko', 'pt', 'es', 'fr', 'it'];
Comment thread
Jotatavo marked this conversation as resolved.
Expand All @@ -14,39 +18,100 @@
return 'en';
}

function getCurrentLanguageName() {
var locale = getCurrentLocale();
var selector = document.querySelector('.md-select .md-select__list');
if (!selector) return null;
var links = selector.querySelectorAll('.md-select__link');
function stripLocale(pathname) {
var segments = (pathname || '/').split('/').filter(Boolean);
if (segments.length && LOCALE_SEGMENTS.indexOf(segments[0]) !== -1) {
segments.shift();
}
return segments;
}

// Build a same-page URL in targetLocale (en has no prefix).
// Preserve query + hash so deep links like /architecture/#topology survive.
function localizePath(pathname, targetLocale) {
var segments = stripLocale(pathname);
var tail = segments.length ? segments.join('/') + '/' : '';
var base;
if (!targetLocale || targetLocale === 'en') {
base = '/' + tail;
} else {
base = '/' + targetLocale + '/' + tail;
}
return base + window.location.search + window.location.hash;
}

function markActive(links, locale) {
var activeName = null;
for (var i = 0; i < links.length; i++) {
var link = links[i];
var hreflang = link.getAttribute('hreflang') || '';
link.setAttribute('href', localizePath(window.location.pathname, hreflang));
if (hreflang === locale) {
return link.textContent.trim();
link.classList.add('is-active');
link.setAttribute('aria-current', 'page');
activeName = link.textContent.trim();
} else {
link.classList.remove('is-active');
link.removeAttribute('aria-current');
}
}
return null;
return activeName;
}

function bindLocaleClicks(root) {
if (!root || root.dataset.langNavBound === '1') return;
root.dataset.langNavBound = '1';
root.addEventListener('click', function (event) {
var link = event.target.closest && event.target.closest('a[hreflang]');
if (!link || !root.contains(link)) return;
var hreflang = link.getAttribute('hreflang') || 'en';
// Full navigation on locale change (search index / chrome differ per language).
event.preventDefault();
window.location.assign(localizePath(window.location.pathname, hreflang));
});
}

function init() {
// Find the language selector button via its parent .md-select container
// rather than aria-label, which gets translated on non-English pages
var selector = document.querySelector('.md-select');
if (!selector) return;
var btn = selector.querySelector('button');
if (!btn) return;
var name = getCurrentLanguageName();
if (!name) return;
var label = document.createElement('span');
label.className = 'md-header__language-label';
label.textContent = name;
btn.appendChild(label);
var locale = getCurrentLocale();

var selector = document.querySelector('.md-header .md-select');
if (selector) {
var btn = selector.querySelector('button');
var label = selector.querySelector('.md-header__language-label');
var activeName = markActive(selector.querySelectorAll('.md-select__link'), locale);

if (label && activeName) {
label.textContent = activeName;
}
if (btn && activeName) {
btn.setAttribute('title', activeName);
btn.setAttribute('aria-label', 'Language: ' + activeName);
}
bindLocaleClicks(selector);
}

var drawerLang = document.querySelector('.mobile-drawer-lang');
if (drawerLang) {
var drawerLabel = drawerLang.querySelector('.mobile-drawer-lang__label');
var drawerActive = markActive(drawerLang.querySelectorAll('.mobile-drawer-lang__list a'), locale);
if (drawerLabel && drawerActive) {
drawerLabel.textContent = drawerActive;
}
bindLocaleClicks(drawerLang);
}
}

if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
function onReady(fn) {
if (typeof document$ !== 'undefined' && document$.subscribe) {
document$.subscribe(fn);
return;
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', fn);
} else {
fn();
}
}

onReady(init);
})();
67 changes: 67 additions & 0 deletions docs/javascripts/nav-accordion.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Accordion primary nav: opening a nested section closes sibling sections
// at the same level (so Solana + Other tenants can't both stay expanded).
(function() {
'use strict';

function siblingToggles(toggle) {
var item = toggle.closest('.md-nav__item--nested');
if (!item) return [];
var list = item.parentElement;
if (!list || !list.classList.contains('md-nav__list')) return [];
var result = [];
var children = list.children;
for (var i = 0; i < children.length; i++) {
var child = children[i];
if (!child.classList || !child.classList.contains('md-nav__item--nested')) continue;
var kids = child.children;
for (var j = 0; j < kids.length; j++) {
if (kids[j].classList && kids[j].classList.contains('md-nav__toggle') && kids[j] !== toggle) {
result.push(kids[j]);
break;
}
}
}
return result;
}

function closeSiblings(toggle) {
siblingToggles(toggle).forEach(function(other) {
other.checked = false;
other.classList.remove('md-toggle--indeterminate');
// Material uses indeterminate for "contains active page"; clear it so
// the section visually collapses when another section is opened.
try { other.indeterminate = false; } catch (e) {}
});
}

function onToggleChange(e) {
var toggle = e.target;
if (!toggle || !toggle.classList || !toggle.classList.contains('md-nav__toggle')) return;
if (!toggle.checked) return;
closeSiblings(toggle);
}

function bind(root) {
if (!root || root.getAttribute('data-nav-accordion') === '1') return;
root.setAttribute('data-nav-accordion', '1');
root.addEventListener('change', onToggleChange);
}

function init() {
document.querySelectorAll('.md-sidebar--primary').forEach(bind);
}

function onReady(fn) {
Comment thread
Jotatavo marked this conversation as resolved.
if (typeof document$ !== 'undefined' && document$.subscribe) {
document$.subscribe(fn);
return;
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', fn);
} else {
fn();
}
}

onReady(init);
})();
Loading