// version-picker.js // // Renders a version dropdown in the mdBook menu bar for multi-version // deployments. Reads //versions.json at page load and lets the // reader switch to the same page in a different version. // // The deployed URL layout is //, where // is "latest" or a semver-like tag (e.g., "v0.1.0"). When the reader // chooses a different version, the picker navigates to the matching // page under the new version subtree; if that page doesn't exist in // the target version, the browser will show a 404, which is fine for // a v0.1 deployment. (function () { 'use strict'; // Match the version segment in a path. Accepts "latest" or "vX[.Y[.Z]][-pre]". var VERSION_RE = /\/(latest|v\d+(?:\.\d+){0,2}(?:-[A-Za-z0-9.]+)?)(\/|$)/; function parseLocation() { var path = window.location.pathname; var m = path.match(VERSION_RE); if (!m) return null; var version = m[1]; var versionStart = m.index; var basePath = path.substring(0, versionStart + 1); var pagePath = path.substring(versionStart + 1 + version.length); return { version: version, basePath: basePath, pagePath: pagePath }; } function buildPicker(versions, current, basePath, pagePath) { var wrap = document.createElement('div'); wrap.className = 'version-picker'; wrap.setAttribute('role', 'group'); wrap.setAttribute('aria-label', 'Spec version'); var label = document.createElement('span'); label.className = 'version-picker-label'; label.textContent = 'version:'; wrap.appendChild(label); var select = document.createElement('select'); select.className = 'version-picker-select'; select.setAttribute('aria-label', 'Choose spec version'); for (var i = 0; i < versions.length; i++) { var v = versions[i]; var opt = document.createElement('option'); opt.value = v; opt.textContent = (v === 'latest') ? 'latest (main)' : v; if (v === current) opt.selected = true; select.appendChild(opt); } select.addEventListener('change', function (e) { var next = e.target.value; if (!next || next === current) return; window.location.pathname = basePath + next + pagePath; }); wrap.appendChild(select); return wrap; } function install() { var loc = parseLocation(); if (!loc) return; fetch(loc.basePath + 'versions.json', { cache: 'no-cache' }) .then(function (r) { return r.ok ? r.json() : null; }) .then(function (data) { if (!data) return; // Accepted shapes: // ["latest", "v0.1.0"] // { "versions": ["latest", "v0.1.0"] } var versions = Array.isArray(data) ? data : (data && data.versions); if (!versions || !versions.length) return; var picker = buildPicker(versions, loc.version, loc.basePath, loc.pagePath); // Prefer slotting into mdBook's menu bar; fall back to floating. var slot = document.querySelector('.right-buttons'); if (slot) { slot.insertBefore(picker, slot.firstChild); } else { picker.classList.add('version-picker-floating'); document.body.appendChild(picker); } }) .catch(function (err) { // Non-fatal: dev / file:// / pre-deploy will all land here. if (window.console) console.warn('version-picker:', err); }); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', install); } else { install(); } })();