Skip to content

Commit 6517f50

Browse files
committed
deploy: 44be720
1 parent 2ee0bf1 commit 6517f50

13 files changed

Lines changed: 585 additions & 1 deletion

File tree

.buildinfo

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# Sphinx build info version 1
22
# This file records the configuration used when building these files. When it is not found, a full rebuild will be done.
3-
config: e1ce356c4cc38ca6ad7632c195b8ee58
3+
config: 6961e4a502162834c7576592cfa717bb
44
tags: 645f666f9bcd5a90fca523b33c5a78b7

.doctrees/environment.pickle

441 Bytes
Binary file not shown.

_static/searchlite-index.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[{"u":"autoapi/index.html","t":"API Reference","x":"API Reference This page contains auto-generated API reference documentation 1. test_all python_template_js 1 Created with sphinx-autoapi"},{"u":"autoapi/python_template_js/index.html","t":"python_template_js","x":"python_template_js Attributes __version__ Package Contents python_template_js.__version__ = '0.1.0'"},{"u":"autoapi/python_template_js/index.html#attributes","t":"python_template_js","s":"Attributes","x":"__version__"},{"u":"autoapi/python_template_js/index.html#package-contents","t":"python_template_js","s":"Package Contents","x":"python_template_js.__version__ = '0.1.0'"},{"u":"autoapi/test_all/index.html","t":"test_all","x":"test_all Functions test_all() Module Contents test_all.test_all()"},{"u":"autoapi/test_all/index.html#functions","t":"test_all","s":"Functions","x":"test_all()"},{"u":"autoapi/test_all/index.html#module-contents","t":"test_all","s":"Module Contents","x":"test_all.test_all()"},{"u":"index.html","t":"python template js","x":"python template js A JavaScript-Python project template Build Status codecov License PyPI Overview Note This library was generated using copier from the Base Python Project Template repository."},{"u":"index.html#overview","t":"python template js","s":"Overview","x":"Note This library was generated using copier from the Base Python Project Template repository."}]

_static/searchlite-ui.js

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
/*!
2+
* sphinx-searchlite — the bundled dialog.
3+
*
4+
* Optional: set `searchlite_ui = False` and drive `window.SearchLite` yourself
5+
* if your theme ships its own search UI. The markup is created at runtime so
6+
* this works with any theme without template overrides.
7+
*/
8+
9+
(function () {
10+
"use strict";
11+
12+
if (!window.SearchLite || !window.SearchLite.indexUrl) return;
13+
14+
// Captured while the script is executing; `currentScript` is null later on.
15+
var uiScript = document.currentScript || document.querySelector("script[data-searchlite-adopt]");
16+
var adoptThemeSearch = !uiScript || uiScript.getAttribute("data-searchlite-adopt") !== "false";
17+
18+
var engine = window.SearchLite.create({ url: window.SearchLite.indexUrl });
19+
var selected = 0;
20+
21+
var dialog = document.createElement("dialog");
22+
dialog.id = "searchlite-dialog";
23+
dialog.innerHTML =
24+
'<form class="searchlite-panel" method="dialog" role="search">' +
25+
'<div class="searchlite-field">' +
26+
'<input type="search" id="searchlite-input" autocomplete="off" spellcheck="false" placeholder="Search documentation…" aria-label="Search" />' +
27+
'<kbd class="searchlite-kbd">Esc</kbd>' +
28+
"</div>" +
29+
'<div id="searchlite-results" role="listbox" aria-label="Search results"></div>' +
30+
'<p id="searchlite-empty" class="searchlite-empty" hidden>No results found.</p>' +
31+
"</form>";
32+
document.body.appendChild(dialog);
33+
34+
var input = dialog.querySelector("#searchlite-input");
35+
var results = dialog.querySelector("#searchlite-results");
36+
var empty = dialog.querySelector("#searchlite-empty");
37+
38+
/* Colour adoption ------------------------------------------------------ */
39+
40+
// Themes signal dark mode with their own class or attribute, not
41+
// `prefers-color-scheme`, so read the page's actual colours instead. The
42+
// computed value is assigned verbatim: it may be `color(display-p3 ...)` or
43+
// any other modern syntax, and parsing it would lose that.
44+
function backdropColour() {
45+
var node = document.body;
46+
while (node) {
47+
var colour = getComputedStyle(node).backgroundColor;
48+
if (colour && colour !== "transparent" && colour.indexOf("rgba(0, 0, 0, 0") !== 0) return colour;
49+
node = node.parentElement;
50+
}
51+
return null;
52+
}
53+
54+
function adoptColours() {
55+
var background = backdropColour();
56+
var foreground = getComputedStyle(document.body).color;
57+
if (background) dialog.style.setProperty("--searchlite-background", background);
58+
if (foreground) dialog.style.setProperty("--searchlite-foreground", foreground);
59+
}
60+
61+
// Theme toggles mutate a class or attribute on <html> or <body>.
62+
var themeWatcher = new MutationObserver(adoptColours);
63+
[document.documentElement, document.body].forEach(function (node) {
64+
themeWatcher.observe(node, { attributes: true, attributeFilter: ["class", "data-theme", "data-mode", "style"] });
65+
});
66+
adoptColours();
67+
68+
function render(found) {
69+
results.replaceChildren();
70+
found.items.forEach(function (record, position) {
71+
var link = document.createElement("a");
72+
link.className = "searchlite-result";
73+
link.href = record.u;
74+
link.setAttribute("role", "option");
75+
link.setAttribute("aria-selected", String(position === selected));
76+
77+
var title = document.createElement("span");
78+
title.className = "searchlite-result-title";
79+
title.appendChild(window.SearchLite.highlight(record.s || record.t, found.terms));
80+
81+
var context = document.createElement("span");
82+
context.className = "searchlite-result-context";
83+
var summary = window.SearchLite.excerpt(record, found.terms);
84+
context.textContent = record.s ? record.t + " \u2014 " + summary : summary;
85+
86+
link.append(title, context);
87+
results.appendChild(link);
88+
});
89+
empty.hidden = found.items.length > 0;
90+
}
91+
92+
function update() {
93+
if (!input.value.trim()) {
94+
results.replaceChildren();
95+
empty.hidden = true;
96+
return;
97+
}
98+
selected = 0;
99+
render(engine.search(input.value));
100+
}
101+
102+
function move(delta) {
103+
var options = results.querySelectorAll(".searchlite-result");
104+
if (!options.length) return;
105+
selected = (selected + delta + options.length) % options.length;
106+
options.forEach(function (option, position) {
107+
option.setAttribute("aria-selected", String(position === selected));
108+
});
109+
options[selected].scrollIntoView({ block: "nearest" });
110+
}
111+
112+
function open() {
113+
if (dialog.open) return;
114+
adoptColours();
115+
dialog.showModal();
116+
engine.load().then(update);
117+
input.focus();
118+
input.select();
119+
}
120+
121+
document.querySelectorAll("[data-searchlite-open]").forEach(function (trigger) {
122+
trigger.addEventListener("click", open);
123+
});
124+
125+
/* Adopting the theme's own search box ---------------------------------- */
126+
127+
// Without this the dialog has no visible entry point on a theme that knows
128+
// nothing about it, and the theme's box still leads to Sphinx's separate
129+
// search page — two searches with different results.
130+
function adoptSearchFields() {
131+
if (!adoptThemeSearch) return;
132+
var selectors = [
133+
'input[name="q"]',
134+
'form[action$="search.html"] input',
135+
'form[role="search"] input',
136+
"input[type=search]",
137+
];
138+
var seen = new Set();
139+
selectors.forEach(function (selector) {
140+
document.querySelectorAll(selector).forEach(function (field) {
141+
if (field === input || seen.has(field)) return;
142+
seen.add(field);
143+
field.classList.add("searchlite-adopted");
144+
field.readOnly = true;
145+
field.addEventListener("focus", open);
146+
field.addEventListener("click", open);
147+
var form = field.closest("form");
148+
if (form) {
149+
form.addEventListener("submit", function (event) {
150+
event.preventDefault();
151+
open();
152+
});
153+
}
154+
});
155+
});
156+
}
157+
158+
adoptSearchFields();
159+
160+
input.addEventListener("input", function () {
161+
engine.load().then(update);
162+
});
163+
164+
dialog.addEventListener("keydown", function (event) {
165+
if (event.key === "ArrowDown") {
166+
event.preventDefault();
167+
move(1);
168+
} else if (event.key === "ArrowUp") {
169+
event.preventDefault();
170+
move(-1);
171+
} else if (event.key === "Enter") {
172+
var active = results.querySelector('.searchlite-result[aria-selected="true"]');
173+
if (active) {
174+
event.preventDefault();
175+
window.location.href = active.href;
176+
}
177+
}
178+
});
179+
180+
dialog.addEventListener("click", function (event) {
181+
if (event.target === dialog) dialog.close();
182+
});
183+
184+
document.addEventListener("keydown", function (event) {
185+
var target = event.target;
186+
if (target && (target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.isContentEditable)) return;
187+
if (event.key === "/" || ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "k")) {
188+
event.preventDefault();
189+
open();
190+
}
191+
});
192+
})();

_static/searchlite.css

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/*!
2+
* sphinx-searchlite — styling for the bundled dialog.
3+
*
4+
* The dialog adopts the host page's own colours at runtime (see searchlite-ui.js),
5+
* so it follows whatever light/dark mechanism the theme uses rather than relying
6+
* on `prefers-color-scheme`, which themes with their own toggle do not track.
7+
* The values below are only the fallback for when that lookup fails.
8+
*
9+
* Every colour derives from `--searchlite-background` and
10+
* `--searchlite-foreground`, so overriding those two restyles the whole dialog.
11+
*/
12+
13+
:root {
14+
--searchlite-background: #fff;
15+
--searchlite-foreground: #18181b;
16+
--searchlite-radius: 0.75rem;
17+
}
18+
19+
#searchlite-dialog {
20+
--searchlite-muted: color-mix(in srgb, var(--searchlite-foreground) 60%, transparent);
21+
--searchlite-border: color-mix(in srgb, var(--searchlite-foreground) 20%, transparent);
22+
--searchlite-accent: color-mix(in srgb, var(--searchlite-foreground) 10%, transparent);
23+
}
24+
25+
#searchlite-dialog {
26+
width: min(40rem, calc(100vw - 2rem));
27+
max-height: min(28rem, calc(100vh - 6rem));
28+
/* Stated rather than left to the user-agent default, which resets in themes
29+
that zero out `dialog` margins and would pin the dialog to the left edge. */
30+
margin-top: 4rem;
31+
margin-inline: auto;
32+
padding: 0;
33+
border: 1px solid var(--searchlite-border);
34+
border-radius: var(--searchlite-radius);
35+
background: var(--searchlite-background);
36+
color: var(--searchlite-foreground);
37+
overflow: hidden;
38+
box-shadow: 0 16px 48px rgb(0 0 0 / 0.18);
39+
}
40+
41+
#searchlite-dialog::backdrop {
42+
background: rgb(0 0 0 / 0.5);
43+
}
44+
45+
/* Sits above the theme's own search field once that field has been adopted. */
46+
.searchlite-adopted {
47+
cursor: pointer;
48+
}
49+
50+
.searchlite-panel {
51+
display: flex;
52+
flex-direction: column;
53+
max-height: inherit;
54+
}
55+
56+
.searchlite-field {
57+
display: flex;
58+
align-items: center;
59+
gap: 0.625rem;
60+
padding: 0.875rem 1rem;
61+
border-bottom: 1px solid var(--searchlite-border);
62+
}
63+
64+
#searchlite-input {
65+
flex: 1;
66+
min-width: 0;
67+
border: 0;
68+
outline: 0;
69+
background: transparent;
70+
font: inherit;
71+
font-size: 0.9375rem;
72+
color: inherit;
73+
}
74+
75+
#searchlite-input::-webkit-search-cancel-button {
76+
display: none;
77+
}
78+
79+
.searchlite-kbd {
80+
padding: 0.1875rem 0.375rem;
81+
border: 1px solid var(--searchlite-border);
82+
border-radius: 0.25rem;
83+
font-family: inherit;
84+
font-size: 0.6875rem;
85+
color: var(--searchlite-muted);
86+
}
87+
88+
#searchlite-results {
89+
overflow-y: auto;
90+
padding: 0.5rem;
91+
}
92+
93+
.searchlite-result {
94+
display: block;
95+
padding: 0.5rem 0.75rem;
96+
border-radius: 0.375rem;
97+
color: inherit;
98+
text-decoration: none;
99+
cursor: pointer;
100+
}
101+
102+
.searchlite-result[aria-selected="true"],
103+
.searchlite-result:hover {
104+
background: var(--searchlite-accent);
105+
}
106+
107+
.searchlite-result-title {
108+
display: block;
109+
font-size: 0.875rem;
110+
font-weight: 500;
111+
}
112+
113+
.searchlite-result-context {
114+
display: block;
115+
font-size: 0.75rem;
116+
color: var(--searchlite-muted);
117+
overflow: hidden;
118+
text-overflow: ellipsis;
119+
white-space: nowrap;
120+
}
121+
122+
.searchlite-result mark {
123+
background: transparent;
124+
color: inherit;
125+
font-weight: 700;
126+
}
127+
128+
.searchlite-empty {
129+
margin: 0;
130+
padding: 1.5rem 1rem;
131+
text-align: center;
132+
font-size: 0.875rem;
133+
color: var(--searchlite-muted);
134+
}

0 commit comments

Comments
 (0)