Skip to content

Commit fc1218a

Browse files
#607: Pagefind Search (#615)
* Issue #607: proof of concept for site search with pagefind * Build pagefind search index in doc/Makefile * more gracefully handle missing doc/themes * fix unwanted interactions between pagefind ui css and theme styles * Make search controlled by a config switch * Restore original handling for missing themes in Makefile * update outer Makefile to build pagefind for doc site * fix whitespace in doc/Makefile * only show search affordance when search is enabled * set search affordance title on the button * disable search by default, only enable for doc site * use native dialog element to show search input in a modal popover dialog * remove now unnecessary Esc key handler for closing search dialog * use npx --yes flag instead of piping yes * remove unused js variable * move search css into a dedicated static css file * remove unused standalone search.js * restore search css to search partial as it was failing CI (but not dev) build * split search css into a separate css document * whitespace change in new css file to satisfy prettier precommit hook * split search js into a separate javascript file * change single to double quotes in search.js to satisfy prettier * unset pagefind color setting for dark mode without referring to internal pagefind svelte * Inform user when pagefind is being installed * ensure every page includes the search form when enabled --------- Co-authored-by: Stefan van der Walt <[email protected]>
1 parent b3892d9 commit fc1218a

File tree

12 files changed

+116
-6
lines changed

12 files changed

+116
-6
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,6 @@ resources
66
# Auto-generated
77
doc/content/shortcodes.md
88
public
9+
10+
# vim droppings
11+
.*.swp

Makefile

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ GH_ORG = scientific-python
55
TEAMS_DIR = doc/content/about
66
TEAMS = theme-team
77
TEAMS_QUERY = python tools/team_query.py
8+
SEARCH = (echo "Installing \`pagefind\` and generating search index..." && npx --yes pagefind --site public)
89
910
$(TEAMS_DIR):
1011
mkdir -p $(TEAMS_DIR)
@@ -26,7 +27,10 @@ doc/content/shortcodes.md: $(wildcard layouts/shortcodes/*.html)
2627
# Serve for development purposes.
2728
serve-dev: doc-serve
2829
doc-serve: doc/content/shortcodes.md
29-
(cd doc && hugo --printI18nWarnings serve --themesDir="../.." --disableFastRender --poll 1000ms)
30+
(cd doc; \
31+
hugo --themesDir="../.."; \
32+
$(SEARCH); \
33+
hugo --printI18nWarnings serve --themesDir="../.." --disableFastRender --poll 1000ms)
3034
3135
# -----------------------------------
3236
# The following is for use on netlify
@@ -44,7 +48,7 @@ preview-theme:
4448
python tools/add_preview_links.py
4549
4650
theme: doc/content/shortcodes.md
47-
(cd doc ; hugo --themesDir="../..")
51+
(cd doc ; hugo --themesDir="../.."; $(SEARCH))
4852
4953
scipy:
5054
rm -rf $@

assets/js/search.js

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
"use strict";
2+
3+
window.addEventListener("DOMContentLoaded", () => {
4+
let searchDialog = document.querySelector(".search-dialog");
5+
6+
// Do nothing here if search is not enabled.
7+
if (!searchDialog) return;
8+
9+
new PagefindUI({
10+
element: ".search-dialog",
11+
autofocus: true,
12+
resetStyles: false,
13+
showSubResults: true,
14+
});
15+
16+
let showSearch = () => searchDialog.showModal();
17+
let hideSearch = () => searchDialog.close();
18+
19+
let toggleSearch = () => {
20+
if (!searchDialog.open) {
21+
showSearch();
22+
} else {
23+
hideSearch();
24+
}
25+
};
26+
27+
let isClickOutside = (elem, clickEvt) => {
28+
const elemDims = elem.getBoundingClientRect();
29+
return (
30+
clickEvt.clientX < elemDims.left ||
31+
clickEvt.clientX > elemDims.right ||
32+
clickEvt.clientY < elemDims.top ||
33+
clickEvt.clientY > elemDims.bottom
34+
);
35+
};
36+
37+
// Close the search dialog if user clicks outside of it when it is open.
38+
// This feels like functionality that should really be natively supported
39+
// by the dialog element already.
40+
// https://blog.webdevsimplified.com/2023-04/html-dialog/
41+
searchDialog.addEventListener("click", (evt) => {
42+
if (searchDialog.open && isClickOutside(searchDialog, evt)) {
43+
hideSearch();
44+
}
45+
});
46+
47+
window.addEventListener("keydown", (evt) => {
48+
if (evt.key === "k" && evt.ctrlKey) {
49+
toggleSearch();
50+
}
51+
});
52+
53+
document
54+
.querySelector(".search-button")
55+
.addEventListener("click", showSearch);
56+
});

assets/theme-css/search.css

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
.search-button {
2+
border-radius: 20px;
3+
padding: 8px;
4+
margin-right: 15px;
5+
cursor: pointer;
6+
}
7+
.search-dialog {
8+
padding: 15px;
9+
width: 80%;
10+
border-radius: 1rem;
11+
}
12+
.search-dialog::backdrop {
13+
background-color: rgb(0, 0, 0, 0.5);
14+
backdrop-filter: blur(3px);
15+
}
16+
.search-dialog input {
17+
padding: 10px 15px;
18+
color: #333;
19+
}
20+
.pagefind-ui button {
21+
border: none;
22+
}
23+
/* unset a pagefind color setting to make results more legible in dark mode */
24+
.pagefind-ui__result-title > .pagefind-ui__result-link {
25+
color: unset !important;
26+
}

config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ params:
77
images:
88
- /images/logo.svg
99
navColor: blue
10+
search: false
1011
plausible:
1112
dataDomain: null
1213
javaScript: "https://views.scientific-python.org/js/script.js"

doc/Makefile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,11 @@ themes: themes/scientific-python-hugo-theme
2424
html: ## Build site in `./public`
2525
html: themes content/shortcodes.md
2626
hugo
27+
npx --yes pagefind --site public
2728

2829
serve: ## Serve site, typically on http://localhost:1313
29-
serve: themes content/shortcodes.md
30-
@hugo --printI18nWarnings server
30+
serve: html
31+
@hugo --printI18nWarnings serve
3132

3233
clean: ## Remove built files
3334
clean:

doc/config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ params:
2121
description: "Documentation & template site for the Scientific Python Hugo Theme."
2222
images:
2323
- /images/logo.svg
24+
search: true
2425
navbarlogo:
2526
image: logo.svg
2627
text: Scientific Python Hugo Theme

layouts/_default/baseof.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@
3232
{{ partial "navbar.html" . -}}
3333
{{ end }}
3434

35+
{{ if .Site.Params.search }}
36+
{{ partial "search.html" . }}
37+
{{ end }}
38+
3539
{{ block "main" . }}
3640
{{ end }}
3741

layouts/partials/css.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@
3030
(resources.Get "theme-css/pst/pydata-sphinx-theme.scss")
3131
(resources.Get "theme-css/spht/index.scss")
3232
(resources.Match "theme-css/*.scss")
33-
| append (resources.Match "css/*.scss") -}}
33+
| append (resources.Match "css/*.scss")
34+
-}}
3435

3536
{{- range $sass -}}
3637
{{ with . }} <!-- Skips nil elements from appending empty resources.Match slices. -->

layouts/partials/javascript.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" />
66

77
<!-- Custom JS -->
8-
<!-- All JS files under static/js are included -->
8+
<!-- All JS files under assets/js are included -->
99
{{- $jsFiles := collections.Sort (resources.Match "js/*.js") "Name" -}}
1010
{{- if $inServerMode -}}
1111
{{- $js := $jsFiles | resources.Concat "js/bundle.js" }}

0 commit comments

Comments
 (0)