forked from cleveragents/cleveragents-core
docs(timeline): update schedule adherence Day 54 (2026-04-03)
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* ADR Page — timeline placement
|
||||
*
|
||||
* On ADR pages the build hook embeds a hidden `.adr-timeline` element in the
|
||||
* page content.
|
||||
*
|
||||
* Desktop (>= 76.25em) — move the timeline into the left sidebar, replacing
|
||||
* the integrated Table of Contents.
|
||||
* Mobile (< 76.25em) — leave the navigation drawer alone; instead show
|
||||
* the timeline at the end of the article body.
|
||||
*
|
||||
* Compatible with Material for MkDocs instant-loading (SPA navigation).
|
||||
*/
|
||||
|
||||
var _adrDesktopQuery = window.matchMedia("(min-width: 76.25em)");
|
||||
|
||||
document$.subscribe(function () {
|
||||
var timeline = document.querySelector(".md-content .adr-timeline");
|
||||
|
||||
if (!timeline) {
|
||||
// Not an ADR page — clean up any leftover state from a previous page.
|
||||
document.body.classList.remove("adr-page");
|
||||
return;
|
||||
}
|
||||
|
||||
document.body.classList.add("adr-page");
|
||||
|
||||
if (_adrDesktopQuery.matches) {
|
||||
_placeInSidebar(timeline);
|
||||
} else {
|
||||
_placeInContent(timeline);
|
||||
}
|
||||
});
|
||||
|
||||
/* ── Desktop: replace the sidebar TOC with the timeline ──────────────── */
|
||||
|
||||
function _placeInSidebar(timeline) {
|
||||
var sidebarInner = document.querySelector(
|
||||
".md-sidebar--primary .md-sidebar__inner"
|
||||
);
|
||||
if (!sidebarInner) return;
|
||||
|
||||
var nav = document.createElement("nav");
|
||||
nav.className = "md-nav md-nav--primary adr-sidebar-timeline";
|
||||
nav.setAttribute("data-md-level", "0");
|
||||
|
||||
var title = document.createElement("label");
|
||||
title.className = "md-nav__title adr-timeline-title";
|
||||
title.textContent = "Status History";
|
||||
|
||||
var clone = timeline.cloneNode(true);
|
||||
clone.style.display = "";
|
||||
|
||||
nav.appendChild(title);
|
||||
nav.appendChild(clone);
|
||||
|
||||
sidebarInner.innerHTML = "";
|
||||
sidebarInner.appendChild(nav);
|
||||
|
||||
// Remove the hidden source element from the content area.
|
||||
timeline.parentNode.removeChild(timeline);
|
||||
}
|
||||
|
||||
/* ── Mobile: append the timeline at the end of the article ───────────── */
|
||||
|
||||
function _placeInContent(timeline) {
|
||||
var article = document.querySelector(".md-content__inner");
|
||||
if (!article) return;
|
||||
|
||||
// Build a wrapper with a heading so it reads as a distinct section.
|
||||
var wrapper = document.createElement("div");
|
||||
wrapper.className = "adr-timeline-mobile";
|
||||
|
||||
var heading = document.createElement("h2");
|
||||
heading.textContent = "Status History";
|
||||
heading.id = "status-history";
|
||||
wrapper.appendChild(heading);
|
||||
|
||||
// Move (not clone) the timeline into the wrapper and make it visible.
|
||||
timeline.style.display = "";
|
||||
wrapper.appendChild(timeline);
|
||||
|
||||
article.appendChild(wrapper);
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
* Diagram Lightbox — fullscreen viewer for Kroki-rendered diagrams.
|
||||
*
|
||||
* Behaviour:
|
||||
* - Clicking any Kroki diagram (<img alt="Kroki">) opens a fullscreen
|
||||
* overlay showing the diagram at maximum viewport size.
|
||||
* - The overlay has an X close button in the top-right corner.
|
||||
* - Pressing Escape or clicking the backdrop closes the overlay.
|
||||
* - Works with mkdocs-material instant-loading / SPA navigation.
|
||||
*/
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
/** The overlay element (created once, reused). */
|
||||
var overlay = null;
|
||||
|
||||
/** The <img> inside the overlay. */
|
||||
var overlayImg = null;
|
||||
|
||||
/** The close button. */
|
||||
var closeBtn = null;
|
||||
|
||||
/**
|
||||
* Build the lightbox DOM elements and append to <body>.
|
||||
* Called once on first use.
|
||||
*/
|
||||
function ensureOverlay() {
|
||||
if (overlay) return;
|
||||
|
||||
overlay = document.createElement("div");
|
||||
overlay.className = "diagram-lightbox";
|
||||
overlay.setAttribute("role", "dialog");
|
||||
overlay.setAttribute("aria-modal", "true");
|
||||
overlay.setAttribute("aria-label", "Diagram fullscreen view");
|
||||
|
||||
overlayImg = document.createElement("img");
|
||||
overlayImg.alt = "Diagram fullscreen";
|
||||
|
||||
closeBtn = document.createElement("button");
|
||||
closeBtn.className = "diagram-lightbox-close";
|
||||
closeBtn.setAttribute("aria-label", "Close fullscreen diagram");
|
||||
closeBtn.innerHTML = "×"; // × character
|
||||
closeBtn.type = "button";
|
||||
|
||||
overlay.appendChild(overlayImg);
|
||||
overlay.appendChild(closeBtn);
|
||||
document.body.appendChild(overlay);
|
||||
|
||||
// Close on button click
|
||||
closeBtn.addEventListener("click", function (e) {
|
||||
e.stopPropagation();
|
||||
closeLightbox();
|
||||
});
|
||||
|
||||
// Close on backdrop click (but not on the image itself)
|
||||
overlay.addEventListener("click", function (e) {
|
||||
if (e.target === overlay) {
|
||||
closeLightbox();
|
||||
}
|
||||
});
|
||||
|
||||
// Close on Escape key
|
||||
document.addEventListener("keydown", function (e) {
|
||||
if (e.key === "Escape" && overlay.classList.contains("active")) {
|
||||
closeLightbox();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the lightbox with the given image source.
|
||||
*/
|
||||
function openLightbox(src) {
|
||||
ensureOverlay();
|
||||
overlayImg.src = src;
|
||||
overlay.classList.add("active");
|
||||
// Prevent background scrolling
|
||||
document.body.style.overflow = "hidden";
|
||||
// Move focus to close button for accessibility
|
||||
closeBtn.focus();
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the lightbox.
|
||||
*/
|
||||
function closeLightbox() {
|
||||
if (!overlay) return;
|
||||
overlay.classList.remove("active");
|
||||
document.body.style.overflow = "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach click handlers to all Kroki diagram images on the page.
|
||||
* Safe to call multiple times (skips already-bound images).
|
||||
*/
|
||||
function bindDiagrams() {
|
||||
var imgs = document.querySelectorAll('img[alt="Kroki"]');
|
||||
imgs.forEach(function (img) {
|
||||
if (img.dataset.lightboxBound) return;
|
||||
img.dataset.lightboxBound = "1";
|
||||
|
||||
img.addEventListener("click", function () {
|
||||
openLightbox(img.src);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// ── Bootstrap ─────────────────────────────────────────────────────────
|
||||
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", bindDiagrams);
|
||||
} else {
|
||||
bindDiagrams();
|
||||
}
|
||||
|
||||
// Re-bind after instant navigation (mkdocs-material SPA mode)
|
||||
if (typeof document$ !== "undefined") {
|
||||
document$.subscribe(function () {
|
||||
bindDiagrams();
|
||||
});
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,274 @@
|
||||
/**
|
||||
* Collapsible Table of Contents for mkdocs-material with toc.integrate.
|
||||
*
|
||||
* Behaviour:
|
||||
* - ALL nested TOC items start collapsed on page load.
|
||||
* - Clicking a parent item toggles it and marks it as "user-pinned" so it
|
||||
* stays in whatever state the user chose.
|
||||
* - As the reader scrolls, the ancestors of the currently-active TOC link
|
||||
* are automatically expanded so the highlighted item is always visible.
|
||||
* - When the reader scrolls past a section, any items that were only
|
||||
* auto-expanded (not user-pinned) collapse back down.
|
||||
* - Works with mkdocs-material instant-loading / SPA navigation.
|
||||
*
|
||||
* Page navigation is handled by the top navbar tabs + dropdowns.
|
||||
* This script only manages the TOC (md-nav--secondary) in the left sidebar.
|
||||
*/
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Set of TOC <li> elements the user has manually expanded.
|
||||
* These survive auto-collapse and are only cleared on page navigation.
|
||||
*/
|
||||
var userPinned = new Set();
|
||||
|
||||
/**
|
||||
* Set of TOC <li> elements that were auto-expanded by the scroll tracker.
|
||||
* Cleared and recalculated each time the active link changes.
|
||||
*/
|
||||
var autoExpanded = new Set();
|
||||
|
||||
/** Reference to the sidebar element (cached after first lookup). */
|
||||
var sidebar = null;
|
||||
|
||||
// ── Helpers ──────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Return all ancestor <li.md-nav__item--nested> elements between `el`
|
||||
* and the TOC root (the <ul data-md-component="toc"> list).
|
||||
*/
|
||||
function ancestorItems(el) {
|
||||
var ancestors = [];
|
||||
var node = el ? el.parentElement : null;
|
||||
while (node && node !== sidebar) {
|
||||
if (
|
||||
node.tagName === "LI" &&
|
||||
node.classList.contains("md-nav__item--nested")
|
||||
) {
|
||||
ancestors.push(node);
|
||||
}
|
||||
node = node.parentElement;
|
||||
}
|
||||
return ancestors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collapse a nested item (add the CSS class that hides children).
|
||||
*/
|
||||
function collapse(li) {
|
||||
li.classList.add("toc-collapsed");
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand a nested item (remove the CSS class so children are visible).
|
||||
*/
|
||||
function expand(li) {
|
||||
li.classList.remove("toc-collapsed");
|
||||
}
|
||||
|
||||
// ── Shared: make nested items collapsible ────────────────────────────
|
||||
//
|
||||
// Scans `containerEl` for <li> items with nested <nav> children and
|
||||
// turns them into collapsible items: adds the --nested class, collapses
|
||||
// them, and injects a toggle chevron.
|
||||
|
||||
function makeItemsCollapsible(containerEl) {
|
||||
containerEl.querySelectorAll("li.md-nav__item").forEach(function (li) {
|
||||
var nestedNav = li.querySelector(":scope > nav.md-nav, :scope > .md-nav");
|
||||
if (!nestedNav) return;
|
||||
|
||||
li.classList.add("md-nav__item--nested");
|
||||
|
||||
// Collapse everything on load
|
||||
collapse(li);
|
||||
|
||||
// Inject a dedicated toggle button (chevron) into the link row.
|
||||
// Clicking the chevron only toggles expand/collapse.
|
||||
// Clicking the link text still navigates to the heading.
|
||||
var link = li.querySelector(":scope > a.md-nav__link");
|
||||
if (link && !link.querySelector(".toc-toggle")) {
|
||||
var toggle = document.createElement("span");
|
||||
toggle.className = "toc-toggle";
|
||||
toggle.setAttribute("role", "button");
|
||||
toggle.setAttribute("aria-label", "Toggle section");
|
||||
link.appendChild(toggle);
|
||||
|
||||
toggle.addEventListener("click", function (e) {
|
||||
// Stop the click from propagating to the <a> and navigating
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
var isCollapsed = li.classList.contains("toc-collapsed");
|
||||
if (isCollapsed) {
|
||||
expand(li);
|
||||
userPinned.add(li);
|
||||
} else {
|
||||
collapse(li);
|
||||
userPinned.delete(li);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ── Initialisation ──────────────────────────────────────────────────
|
||||
|
||||
function initCollapsibleToc() {
|
||||
sidebar = document.querySelector(".md-sidebar--primary");
|
||||
if (!sidebar) return;
|
||||
|
||||
// Reset pinned / auto-expanded tracking on (re-)init
|
||||
userPinned.clear();
|
||||
autoExpanded.clear();
|
||||
|
||||
// Force the TOC visible. Material's base CSS hides the secondary
|
||||
// nav via a sibling-combinator rule keyed off the #__toc checkbox.
|
||||
// We force-check it and set inline display so the TOC is guaranteed
|
||||
// visible regardless of the CSS cascade.
|
||||
var tocCheckbox = sidebar.querySelector("#__toc");
|
||||
if (tocCheckbox) {
|
||||
tocCheckbox.checked = true;
|
||||
}
|
||||
|
||||
// Find the actual TOC (md-nav--secondary). We scope to the secondary
|
||||
// nav to avoid touching the page-level nav items that wrap sections.
|
||||
var tocNav = sidebar.querySelector("nav.md-nav--secondary");
|
||||
if (!tocNav) return;
|
||||
|
||||
tocNav.style.display = "block";
|
||||
tocNav.style.opacity = "1";
|
||||
tocNav.style.visibility = "visible";
|
||||
|
||||
// Make all nested TOC items collapsible, with pinning support for
|
||||
// the active-link watcher.
|
||||
makeItemsCollapsible(tocNav);
|
||||
|
||||
// Kick off the active-link watcher
|
||||
watchActiveLink();
|
||||
}
|
||||
|
||||
// ── Active-link watcher ─────────────────────────────────────────────
|
||||
//
|
||||
// mkdocs-material dynamically toggles `.md-nav__link--active` on the
|
||||
// TOC link that corresponds to the heading currently in view. We use
|
||||
// a MutationObserver on the TOC container to detect when that class
|
||||
// changes and react by expanding / collapsing as needed.
|
||||
|
||||
var observer = null;
|
||||
|
||||
function watchActiveLink() {
|
||||
// Disconnect any previous observer (e.g. after SPA navigation)
|
||||
if (observer) {
|
||||
observer.disconnect();
|
||||
observer = null;
|
||||
}
|
||||
|
||||
var tocRoot = sidebar
|
||||
? sidebar.querySelector("[data-md-component='toc']")
|
||||
: null;
|
||||
if (!tocRoot) return;
|
||||
|
||||
// Respond to the current active link immediately
|
||||
handleActiveChange(tocRoot);
|
||||
|
||||
// Observe subtree attribute changes — the theme adds / removes
|
||||
// the --active class on <a> elements as the user scrolls.
|
||||
observer = new MutationObserver(function () {
|
||||
handleActiveChange(tocRoot);
|
||||
});
|
||||
|
||||
observer.observe(tocRoot, {
|
||||
subtree: true,
|
||||
attributes: true,
|
||||
attributeFilter: ["class"],
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Called whenever the active TOC link may have changed.
|
||||
*
|
||||
* 1. Find the currently-active <a>.
|
||||
* 2. Determine which ancestor <li>s need to be expanded.
|
||||
* 3. Auto-expand those ancestors (unless already open).
|
||||
* 4. Auto-collapse any previously auto-expanded items that are no longer
|
||||
* ancestors of the active link (but leave user-pinned items alone).
|
||||
*/
|
||||
function handleActiveChange(tocRoot) {
|
||||
var activeLink = tocRoot.querySelector("a.md-nav__link--active");
|
||||
|
||||
// Determine which nested <li>s must be open for the active link
|
||||
var requiredOpen = activeLink ? ancestorItems(activeLink) : [];
|
||||
|
||||
// Also include the active link's own <li> if it is a nested item
|
||||
if (activeLink) {
|
||||
var parentLi = activeLink.closest("li.md-nav__item--nested");
|
||||
if (parentLi && requiredOpen.indexOf(parentLi) === -1) {
|
||||
requiredOpen.push(parentLi);
|
||||
}
|
||||
}
|
||||
|
||||
var requiredSet = new Set(requiredOpen);
|
||||
|
||||
// Collapse items that were auto-expanded last round but are no longer
|
||||
// needed — skip anything the user has pinned open.
|
||||
autoExpanded.forEach(function (li) {
|
||||
if (!requiredSet.has(li) && !userPinned.has(li)) {
|
||||
collapse(li);
|
||||
}
|
||||
});
|
||||
|
||||
// Build the new auto-expanded set
|
||||
autoExpanded = new Set();
|
||||
|
||||
requiredOpen.forEach(function (li) {
|
||||
if (li.classList.contains("toc-collapsed")) {
|
||||
expand(li);
|
||||
}
|
||||
// Track as auto-expanded only if not user-pinned
|
||||
if (!userPinned.has(li)) {
|
||||
autoExpanded.add(li);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ── Desktop detection ────────────────────────────────────────────────
|
||||
//
|
||||
// This entire script is designed for the desktop persistent sidebar
|
||||
// (≥76.25em). On mobile, Material uses a slide-out drawer with its
|
||||
// own drill-down navigation, scroll management, and back-button
|
||||
// behaviour. Running our DOM restructuring on mobile breaks the
|
||||
// drawer's scroll container and makes it impossible to scroll past
|
||||
// the visible items.
|
||||
//
|
||||
// We use matchMedia to detect the breakpoint and only bootstrap on
|
||||
// desktop. On resize/orientation changes that cross the breakpoint,
|
||||
// the page reloads via Material's SPA system anyway, so we don't need
|
||||
// a live resize listener.
|
||||
|
||||
var desktopQuery = window.matchMedia("(min-width: 76.25em)");
|
||||
|
||||
function isDesktop() {
|
||||
return desktopQuery.matches;
|
||||
}
|
||||
|
||||
// ── Bootstrap ───────────────────────────────────────────────────────
|
||||
|
||||
function bootstrap() {
|
||||
if (!isDesktop()) return; // skip all DOM manipulation on mobile
|
||||
initCollapsibleToc();
|
||||
}
|
||||
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", bootstrap);
|
||||
} else {
|
||||
bootstrap();
|
||||
}
|
||||
|
||||
// Re-init after instant navigation (mkdocs-material SPA mode)
|
||||
if (typeof document$ !== "undefined") {
|
||||
document$.subscribe(function () {
|
||||
bootstrap();
|
||||
});
|
||||
}
|
||||
})();
|
||||
Reference in New Issue
Block a user