ai-agent-book 精选快照(<2MB 代码与文档,来自 github.com/bojieli/ai-agent-book)
Build latest book artifacts / build (push) Canceled after 0s
dependency resolution / resolve (3.11) (push) Canceled after 0s
dependency resolution / resolve (3.13) (push) Canceled after 0s
deploy-pages / build (push) Canceled after 0s
deploy-pages / deploy (push) Canceled after 0s
i18n consistency check / check (push) Canceled after 0s
provider adoption tests / test (chapter2/context-compression) (push) Canceled after 0s
provider adoption tests / test (chapter2/prompt-injection) (push) Canceled after 0s
provider adoption tests / test (chapter2/system-hint) (push) Canceled after 0s
provider adoption tests / test (chapter3/log-sanitization) (push) Canceled after 0s
web-search-agent tests / test (push) Canceled after 0s
web-search-agent tests / agentbook (push) Canceled after 0s
Build latest book artifacts / build (push) Canceled after 0s
dependency resolution / resolve (3.11) (push) Canceled after 0s
dependency resolution / resolve (3.13) (push) Canceled after 0s
deploy-pages / build (push) Canceled after 0s
deploy-pages / deploy (push) Canceled after 0s
i18n consistency check / check (push) Canceled after 0s
provider adoption tests / test (chapter2/context-compression) (push) Canceled after 0s
provider adoption tests / test (chapter2/prompt-injection) (push) Canceled after 0s
provider adoption tests / test (chapter2/system-hint) (push) Canceled after 0s
provider adoption tests / test (chapter3/log-sanitization) (push) Canceled after 0s
web-search-agent tests / test (push) Canceled after 0s
web-search-agent tests / agentbook (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,176 @@
|
||||
/**
|
||||
* Desktop navigation controls for Material's primary sidebar.
|
||||
*
|
||||
* Background: with `navigation.sections` + `navigation.indexes`, each
|
||||
* chapter renders as
|
||||
*
|
||||
* <li class="md-nav__item--section md-nav__item--nested">
|
||||
* <input class="md-toggle" id="__nav_N">
|
||||
* <div class="md-nav__link md-nav__container">
|
||||
* <a href="…/chapterN/">chapter title</a> ← navigates
|
||||
* <label for="__nav_N">chevron</label> ← toggles
|
||||
* </div>
|
||||
* <nav class="md-nav">…配套实验…</nav>
|
||||
* </li>
|
||||
*
|
||||
* Material only honours the checkbox on mobile; on desktop the section
|
||||
* subtree is always visible and the chevron is hidden. We inject CSS so
|
||||
* that on desktop, too, the subtree follows the checkbox and the chevron
|
||||
* is visible/clickable. Material checks the active chapter's checkbox at
|
||||
* render time, so the default state (active chapter open, rest closed)
|
||||
* comes for free.
|
||||
*
|
||||
* One case needs JS: on pages Material doesn't consider "active" — the
|
||||
* translated editions (sidebar links are rewritten client-side by
|
||||
* lang-switcher.js) and the per-experiment pages, which aren't in the
|
||||
* nav — no checkbox is checked. There we match the current URL against
|
||||
* each section's chapter number and open the matching section.
|
||||
*
|
||||
* The header also contains a desktop-only button for hiding the entire
|
||||
* primary sidebar. Its state is persisted locally and restored across full
|
||||
* reloads as well as Material's instant page swaps.
|
||||
*
|
||||
* Re-runs on every Material page swap (navigation.instant) via document$.
|
||||
*/
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
var SIDEBAR_STORAGE_KEY = "ai-agent-book.primary-sidebar-collapsed";
|
||||
|
||||
function ensureStyle() {
|
||||
if (document.getElementById("nav-collapse-style")) return;
|
||||
var s = document.createElement("style");
|
||||
s.id = "nav-collapse-style";
|
||||
s.textContent = [
|
||||
"@media screen and (min-width: 76.25em) {",
|
||||
// Collapse the subtree when the checkbox is unchecked (Material
|
||||
// keeps section subtrees always-visible on desktop by default).
|
||||
" .md-sidebar--primary .md-nav__item--nested > .md-toggle:not(:checked) ~ .md-nav {",
|
||||
" display: none !important;",
|
||||
" }",
|
||||
// Material hides the section chevron on desktop; bring it back and
|
||||
// make it clickable.
|
||||
" .md-sidebar--primary .md-nav__item--nested > .md-nav__container > label.md-nav__link {",
|
||||
" display: flex;",
|
||||
" align-items: center;",
|
||||
" cursor: pointer;",
|
||||
" pointer-events: auto !important;",
|
||||
" margin: 0;",
|
||||
// 4px top padding centres the 1.2rem icon on the title's FIRST line
|
||||
// (6px link padding + ~1.3 line-height): the container aligns
|
||||
// flex-start (book-theme.css) so wrapped two-line titles don't pull
|
||||
// the chevron down between the lines.
|
||||
" padding: 4px 0.2rem 0 0.4rem;",
|
||||
" }",
|
||||
// Material's own stylesheet already rotates the chevron's ::after
|
||||
// by 90° when the checkbox is checked — no extra transform here.
|
||||
" .md-sidebar--primary .md-nav__item--nested > .md-nav__container > label.md-nav__link .md-nav__icon {",
|
||||
" display: block;",
|
||||
" }",
|
||||
"}",
|
||||
].join("\n");
|
||||
document.head.appendChild(s);
|
||||
}
|
||||
|
||||
function applyDefaultState() {
|
||||
var sidebar = document.querySelector(".md-sidebar--primary");
|
||||
if (!sidebar) return;
|
||||
|
||||
// Material already checked a section's checkbox? Then its render-time
|
||||
// active detection worked — nothing to fix up.
|
||||
if (sidebar.querySelector(".md-nav__item--nested > .md-toggle:checked")) return;
|
||||
|
||||
// Otherwise (translated edition or a page outside the nav), derive the
|
||||
// chapter from the URL and open the matching section.
|
||||
var m = location.pathname.match(/chapter(\d+)/);
|
||||
if (!m) return;
|
||||
var wanted = m[1];
|
||||
var sections = sidebar.querySelectorAll(".md-nav__item--nested");
|
||||
for (var i = 0; i < sections.length; i++) {
|
||||
var link = sections[i].querySelector(":scope > .md-nav__container > a.md-nav__link");
|
||||
var checkbox = sections[i].querySelector(":scope > .md-toggle");
|
||||
if (!link || !checkbox) continue;
|
||||
var lm = (link.getAttribute("href") || "").match(/chapter(\d+)/);
|
||||
if (lm && lm[1] === wanted) {
|
||||
checkbox.checked = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function readSidebarPreference() {
|
||||
try {
|
||||
var value = window.localStorage.getItem(SIDEBAR_STORAGE_KEY);
|
||||
return value === null ? null : value === "true";
|
||||
} catch (_) {
|
||||
// Storage may be disabled by the browser. The control still works for
|
||||
// the current page, and the root class survives Material page swaps.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function writeSidebarPreference(collapsed) {
|
||||
try {
|
||||
window.localStorage.setItem(SIDEBAR_STORAGE_KEY, String(collapsed));
|
||||
} catch (_) {
|
||||
// A blocked localStorage must not prevent readers from using the
|
||||
// collapse control for the current page.
|
||||
}
|
||||
}
|
||||
|
||||
function setSidebarCollapsed(collapsed, remember) {
|
||||
document.documentElement.classList.toggle("sidebar-nav-collapsed", collapsed);
|
||||
|
||||
var button = document.querySelector("[data-sidebar-toggle]");
|
||||
if (button) {
|
||||
var catalog = window.SITE_I18N;
|
||||
var code = window.siteCurrentLanguage || (catalog && catalog.default) || "zh";
|
||||
var strings = catalog && catalog.languages && catalog.languages[code];
|
||||
var label = strings && strings.sidebar
|
||||
? strings.sidebar[collapsed ? "show" : "hide"]
|
||||
: (collapsed ? "展开侧边栏" : "隐藏侧边栏");
|
||||
button.setAttribute("aria-expanded", String(!collapsed));
|
||||
button.setAttribute("aria-label", label);
|
||||
button.setAttribute("title", label);
|
||||
}
|
||||
|
||||
if (remember) writeSidebarPreference(collapsed);
|
||||
}
|
||||
|
||||
function initSidebarToggle() {
|
||||
var button = document.querySelector("[data-sidebar-toggle]");
|
||||
var sidebar = document.querySelector(".md-sidebar--primary");
|
||||
if (!button || !sidebar || sidebar.hidden) {
|
||||
if (button) button.hidden = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Connect aria-controls to the sidebar generated by Material. The id is
|
||||
// re-applied because navigation.instant replaces page content in place.
|
||||
sidebar.id = "primary-navigation";
|
||||
button.hidden = false;
|
||||
|
||||
var preference = readSidebarPreference();
|
||||
var collapsed = preference === null
|
||||
? document.documentElement.classList.contains("sidebar-nav-collapsed")
|
||||
: preference;
|
||||
setSidebarCollapsed(collapsed, false);
|
||||
|
||||
if (button.getAttribute("data-sidebar-toggle-bound") !== "true") {
|
||||
button.setAttribute("data-sidebar-toggle-bound", "true");
|
||||
button.addEventListener("click", function () {
|
||||
var next = !document.documentElement.classList.contains("sidebar-nav-collapsed");
|
||||
setSidebarCollapsed(next, true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
ensureStyle();
|
||||
applyDefaultState();
|
||||
initSidebarToggle();
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", init);
|
||||
if (window.document$) window.document$.subscribe(init);
|
||||
})();
|
||||
Reference in New Issue
Block a user