zig

fork of https://codeberg.org/ziglang/zig
Log | Tree | Refs | README | LICENSE

commit 4dacaa1e129a3991cd805f5a602bcc329e5794d2 (tree)
parent 7166407d8f2e9e080f4f97926a2b543150261576
Author: Ian Johnson <ian@ianjohnson.dev>
Date:   Tue, 27 Jun 2023 00:19:40 -0400

Autodoc: add preference for `/` search

Closes #16081

Diffstat:
Mlib/docs/index.html | 54++++++++++++++++++++++++++++++++++++------------------
Mlib/docs/main.js | 147+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
2 files changed, 158 insertions(+), 43 deletions(-)

diff --git a/lib/docs/index.html b/lib/docs/index.html @@ -25,8 +25,8 @@ --search-bg-color-focus: #ffffff; --search-sh-color: rgba(0, 0, 0, 0.18); --search-other-results-color: rgb(100, 100, 100); - --help-sh-color: rgba(0, 0, 0, 0.75); - --help-bg-color: #aaa; + --modal-sh-color: rgba(0, 0, 0, 0.75); + --modal-bg-color: #aaa; } html, body { margin: 0; padding: 0; height: 100%; } @@ -99,7 +99,7 @@ flex-shrink: 1; } - .help-modal { + .modal-container { z-index: 400; } @@ -412,8 +412,8 @@ padding: 1px 1em; } - /* help modal */ - .help-modal { + /* modals */ + .modal-container { display: flex; width: 100%; height: 100%; @@ -426,29 +426,36 @@ backdrop-filter: blur(0.3em); } - .help-modal > .modal { + .modal-container > .modal { max-width: 97vw; max-height: 97vh; overflow: auto; font-size: 1rem; color: #fff; - background-color: var(--help-bg-color); + background-color: var(--modal-bg-color); border: 0.125rem solid #000; - box-shadow: 0 0.5rem 2.5rem 0.3rem var(--help-sh-color); + box-shadow: 0 0.5rem 2.5rem 0.3rem var(--modal-sh-color); } - .help-modal h1 { + .modal-container h1 { margin: 0.75em 2.5em 1em 2.5em; font-size: 1.5em; text-align: center; } - .help-modal dt, .help-modal dd { + .modal-container dt, .modal-container dd { display: inline; margin: 0 0.2em; } - .help-modal dl { + .modal-container dl { + margin-left: 0.5em; + margin-right: 0.5em; + } + + .prefs-list { + list-style: none; + padding: 0; margin-left: 0.5em; margin-right: 0.5em; } @@ -539,8 +546,8 @@ --search-bg-color-focus: #000; --search-sh-color: rgba(255, 255, 255, 0.28); --search-other-results-color: rgba(255, 255, 255, 0.28); - --help-sh-color: rgba(142, 142, 142, 0.5); - --help-bg-color: #333; + --modal-sh-color: rgba(142, 142, 142, 0.5); + --modal-bg-color: #333; } .docs pre { @@ -677,13 +684,13 @@ </style> </head> <body class="canvas"> - <div class="banner"> + <div id="banner" class="banner"> This is a beta autodoc build; expect bugs and missing information. <a href="https://github.com/ziglang/zig/wiki/How-to-contribute-to-Autodoc">Report an Issue</a>, <a href="https://github.com/ziglang/zig/wiki/How-to-contribute-to-Autodoc">Contribute</a>, <a href="https://github.com/ziglang/zig/wiki/How-to-read-the-standard-library-source-code">Learn more about stdlib source code</a>. </div> - <div class="flex-main"> + <div id="main" class="flex-main"> <div class="flex-filler"></div> <div class="flex-left sidebar"> <nav> @@ -758,7 +765,7 @@ <div class="wrap"> <section class="docs" style="padding-top: 1.5rem; padding-bottom:0;"> <div style="position: relative"> - <span id="searchPlaceholder"><kbd>/</kbd> or <kbd>s</kbd> to search, <kbd>?</kbd> for more options</span> + <span id="searchPlaceholder"><!-- populated by setPrefSlashSearch --></span> <input type="search" class="search" id="search" autocomplete="off" spellcheck="false" disabled> </div> </section> @@ -872,20 +879,31 @@ </div> </div> <div id="helpModal" class="hidden"> - <div class="help-modal"> + <div class="modal-container"> <div class="modal"> <h1>Keyboard Shortcuts</h1> <dl><dt><kbd>?</kbd></dt><dd>Toggle this help modal</dd></dl> - <dl><dt><kbd>s</kbd> or <kbd>/</kbd></dt><dd>Focus the search field</dd></dl> + <dl><dt id="searchKeys"><!-- populated by setPrefSlashSearch --></dt><dd>Focus the search field</dd></dl> <div style="margin-left: 1em"> <dl><dt><kbd>↑</kbd></dt><dd>Move up in search results</dd></dl> <dl><dt><kbd>↓</kbd></dt><dd>Move down in search results</dd></dl> <dl><dt><kbd>⏎</kbd></dt><dd>Go to active search result</dd></dl> </div> + <dl><dt><kbd>p</kbd></dt><dd>Open preferences</dd></dl> <dl><dt><kbd>Esc</kbd></dt><dd>Clear focus; close this modal</dd></dl> </div> </div> </div> + <div id="prefsModal" class="hidden"> + <div class="modal-container"> + <div class="modal"> + <h1>Preferences</h1> + <ul class="prefs-list"> + <li><input id="prefSlashSearch" type="checkbox"><label for="prefSlashSearch">Enable <kbd>/</kbd> for search</label></li> + </ul> + </div> + </div> + </div> <script src="data.js"></script> <script src="commonmark.js"></script> <script src="main.js"></script> diff --git a/lib/docs/main.js b/lib/docs/main.js @@ -8,6 +8,8 @@ const NAV_MODES = { }; (function () { + const domBanner = document.getElementById("banner"); + const domMain = document.getElementById("main"); const domStatus = document.getElementById("status"); const domSectNav = document.getElementById("sectNav"); const domListNav = document.getElementById("listNav"); @@ -65,10 +67,18 @@ const NAV_MODES = { const domTdZigVer = document.getElementById("tdZigVer"); const domHdrName = document.getElementById("hdrName"); const domHelpModal = document.getElementById("helpModal"); + const domSearchKeys = document.getElementById("searchKeys"); + const domPrefsModal = document.getElementById("prefsModal"); const domSearchPlaceholder = document.getElementById("searchPlaceholder"); const sourceFileUrlTemplate = "src/{{mod}}/{{file}}.html#L{{line}}" const domLangRefLink = document.getElementById("langRefLink"); + const domPrefSlashSearch = document.getElementById("prefSlashSearch"); + const prefs = getLocalStorage(); + loadPrefs(); + + domPrefSlashSearch.addEventListener("change", () => setPrefSlashSearch(domPrefSlashSearch.checked)); + let searchTimer = null; let searchTrimResults = true; @@ -127,21 +137,21 @@ const NAV_MODES = { window.guideSearch = guidesSearchIndex; parseGuides(); - // identifiers can contain '?' so we want to allow typing - // the question mark when the search is focused instead of toggling the help modal - let canToggleHelpModal = true; + // identifiers can contain modal trigger characters so we want to allow typing + // such characters when the search is focused instead of toggling the modal + let canToggleModal = true; domSearch.disabled = false; domSearch.addEventListener("keydown", onSearchKeyDown, false); domSearch.addEventListener("input", onSearchInput, false); domSearch.addEventListener("focus", ev => { domSearchPlaceholder.classList.add("hidden"); - canToggleHelpModal = false; + canToggleModal = false; }); domSearch.addEventListener("blur", ev => { if (domSearch.value.length == 0) domSearchPlaceholder.classList.remove("hidden"); - canToggleHelpModal = true; + canToggleModal = true; }); domSectSearchAllResultsLink.addEventListener('click', onClickSearchShowAllResults, false); function onClickSearchShowAllResults(ev) { @@ -156,10 +166,13 @@ const NAV_MODES = { } // make the modal disappear if you click outside it - domHelpModal.addEventListener("click", ev => { - if (ev.target.className == "help-modal") - domHelpModal.classList.add("hidden"); - }); + function handleModalClick(ev) { + if (ev.target.classList.contains("modal-container")) { + hideModal(this); + } + } + domHelpModal.addEventListener("click", handleModalClick); + domPrefsModal.addEventListener("click", handleModalClick); window.addEventListener("hashchange", onHashChange, false); window.addEventListener("keydown", onWindowKeyDown, false); @@ -3996,8 +4009,12 @@ function addDeclToSearchResults(decl, declIndex, modNames, item, list, stack) { // hide the modal if it's visible or return to the previous result page and unfocus the search function onEscape(ev) { - if (!domHelpModal.classList.contains("hidden")) { - domHelpModal.classList.add("hidden"); + if (isModalVisible(domHelpModal)) { + hideModal(domHelpModal); + ev.preventDefault(); + ev.stopPropagation(); + } else if (isModalVisible(domPrefsModal)) { + hideModal(domPrefsModal); ev.preventDefault(); ev.stopPropagation(); } else { @@ -4110,8 +4127,10 @@ function addDeclToSearchResults(decl, declIndex, modNames, item, list, stack) { onEscape(ev); break; case "/": + if (!getPrefSlashSearch()) break; + // fallthrough case "s": - if (domHelpModal.classList.contains("hidden")) { + if (!isModalVisible(domHelpModal) && !isModalVisible(domPrefsModal)) { if (ev.target == domSearch) break; domSearch.focus(); @@ -4123,28 +4142,65 @@ function addDeclToSearchResults(decl, declIndex, modNames, item, list, stack) { } break; case "?": - if (!canToggleHelpModal) break; + if (!canToggleModal) break; + + if (isModalVisible(domPrefsModal)) { + hideModal(domPrefsModal); + } // toggle the help modal - if (!domHelpModal.classList.contains("hidden")) { - onEscape(ev); + if (isModalVisible(domHelpModal)) { + hideModal(domHelpModal); } else { - ev.preventDefault(); - ev.stopPropagation(); - showHelpModal(); + showModal(domHelpModal); } + ev.preventDefault(); + ev.stopPropagation(); break; + case "p": + if (!canToggleModal) break; + + if (isModalVisible(domHelpModal)) { + hideModal(domHelpModal); + } + + // toggle the preferences modal + if (isModalVisible(domPrefsModal)) { + hideModal(domPrefsModal); + } else { + showModal(domPrefsModal); + } + ev.preventDefault(); + ev.stopPropagation(); } } - function showHelpModal() { - domHelpModal.classList.remove("hidden"); - domHelpModal.style.left = - window.innerWidth / 2 - domHelpModal.clientWidth / 2 + "px"; - domHelpModal.style.top = - window.innerHeight / 2 - domHelpModal.clientHeight / 2 + "px"; - domHelpModal.focus(); + function isModalVisible(modal) { + return !modal.classList.contains("hidden"); + } + + function showModal(modal) { + modal.classList.remove("hidden"); + modal.style.left = + window.innerWidth / 2 - modal.clientWidth / 2 + "px"; + modal.style.top = + window.innerHeight / 2 - modal.clientHeight / 2 + "px"; + const firstInput = modal.querySelector("input"); + if (firstInput) { + firstInput.focus(); + } else { + modal.focus(); + } domSearch.blur(); + domBanner.inert = true; + domMain.inert = true; + } + + function hideModal(modal) { + modal.classList.add("hidden"); + domBanner.inert = false; + domMain.inert = false; + modal.blur(); } function clearAsyncSearch() { @@ -4678,6 +4734,47 @@ function addDeclToSearchResults(decl, declIndex, modNames, item, list, stack) { } } + function getLocalStorage() { + if ("localStorage" in window) { + try { + return window.localStorage; + } catch (ignored) { + // localStorage may be disabled (SecurityError) + } + } + // If localStorage isn't available, persist preferences only for the current session + const sessionPrefs = {}; + return { + getItem(key) { + return key in sessionPrefs ? sessionPrefs[key] : null; + }, + setItem(key, value) { + sessionPrefs[key] = String(value); + }, + }; + } + + function loadPrefs() { + const storedPrefSlashSearch = prefs.getItem("slashSearch"); + if (storedPrefSlashSearch === null) { + // Slash search defaults to enabled for all browsers except Firefox + setPrefSlashSearch(navigator.userAgent.indexOf("Firefox") === -1); + } else { + setPrefSlashSearch(storedPrefSlashSearch === "true"); + } + } + + function getPrefSlashSearch() { + return prefs.getItem("slashSearch") === "true"; + } + + function setPrefSlashSearch(enabled) { + prefs.setItem("slashSearch", String(enabled)); + domPrefSlashSearch.checked = enabled; + const searchKeys = enabled ? "<kbd>/</kbd> or <kbd>s</kbd>" : "<kbd>s</kbd>"; + domSearchKeys.innerHTML = searchKeys; + domSearchPlaceholder.innerHTML = searchKeys + " to search, <kbd>?</kbd> for more options"; + } })(); function toggleExpand(event) {