summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob L. Kreuze <zerodaysfordays@sdf.org>2026-02-15 08:36:30 -0500
committerJakob L. Kreuze <zerodaysfordays@sdf.org>2026-02-15 08:36:30 -0500
commit0e290794a649424c9853d1958be8674ac91353c0 (patch)
tree5a85f03b5b3c3c11c0a98a3329a8983a7051078c
parent0605db909c9edde1dcbdb6157f18f29ec1112e54 (diff)
Integrate pagefind
-rw-r--r--haunt.scm2
-rw-r--r--jakob/builder/blog.scm5
-rw-r--r--jakob/builder/search.scm39
-rw-r--r--jakob/theme.scm2
-rw-r--r--static/js/search.js58
5 files changed, 103 insertions, 3 deletions
diff --git a/haunt.scm b/haunt.scm
index c636a42..31d5596 100644
--- a/haunt.scm
+++ b/haunt.scm
@@ -27,6 +27,7 @@
(jakob builder index)
(jakob builder outbox)
(jakob builder projects)
+ (jakob builder search)
(jakob reader html-prime)
(jakob reader org-mode-prime)
(jakob theme)
@@ -53,6 +54,7 @@
#:builders
(list (atom-feed #:max-entries 1024)
(index)
+ (search)
(blog)
(blogroll)
(outbox)
diff --git a/jakob/builder/blog.scm b/jakob/builder/blog.scm
index 94b77d5..bb5567c 100644
--- a/jakob/builder/blog.scm
+++ b/jakob/builder/blog.scm
@@ -55,9 +55,10 @@
(define (render-article post)
"Return the SHTML for POST's contents."
- #<(article (@ (class "update-entry"))
+ #<(article (@ (class "update-entry")
+ (data-pagefind-body "1"))
(h1 (@ (class "section-header"))
- ,(format #f "Blog :: ~a" (post-ref post 'title)))
+ ,(format #f "Blog :: ~a" (post-ref post 'title)))
(div (@ (class "date-stamp"))
(time (@ (datetime ,(date->string (post-date post) "~Y-~m-~d")))
,(date->string (post-date post) "~B ~d, ~Y"))
diff --git a/jakob/builder/search.scm b/jakob/builder/search.scm
new file mode 100644
index 0000000..df8e94f
--- /dev/null
+++ b/jakob/builder/search.scm
@@ -0,0 +1,39 @@
+;;; Copyright © 2019 - 2026 Jakob L. Kreuze <zerodaysfordays@sdf.org>
+;;;
+;;; This program is free software; you can redistribute it and/or
+;;; modify it under the terms of the GNU General Public License as
+;;; published by the Free Software Foundation; either version 3 of the
+;;; License, or (at your option) any later version.
+;;;
+;;; This program is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;;; General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with this program. If not, see
+;;; <http://www.gnu.org/licenses/>.
+
+(define-module (jakob builder search)
+ #:use-module (haunt artifact)
+ #:use-module (haunt html)
+ #:use-module (jakob theme)
+ #:use-module (jakob utils sxml)
+ #:export (search))
+
+(define (search)
+ "Return a Haunt build procedure to create an index page."
+ (lambda (site posts)
+ `(,(serialized-artifact "search.html"
+ (theme #:title "Search Results"
+ ;; #:description (description-from-post post)
+ ;; #:keywords (post-ref post 'tags)
+ ;; #:meta (if (not (eof-object? meta-tags)) meta-tags '())
+ ;; #:scripts (if (not (eof-object? scripts)) scripts '())
+ #:content `((main (@ (class "main-content"))
+ (section (@ (id "search-results"))
+ (h2 (@ (class "section-header")) "Search Results")
+ (div (@ (id "search-output"))
+ (noscript "Javascript must be enabled for search."))))
+ ,(script "search.js")))
+ sxml->html))))
diff --git a/jakob/theme.scm b/jakob/theme.scm
index 0cfebd6..65aaf51 100644
--- a/jakob/theme.scm
+++ b/jakob/theme.scm
@@ -73,7 +73,7 @@
(class "module-title module-title-has-icon")
(style ,(fugue-icon-path "magnifier")))
"Search")
- (form (@ (action "/search")
+ (form (@ (action "/search.html")
(method "GET")
(role "search")
(style "display: flex; gap: 5px;"))
diff --git a/static/js/search.js b/static/js/search.js
new file mode 100644
index 0000000..7037386
--- /dev/null
+++ b/static/js/search.js
@@ -0,0 +1,58 @@
+/*
+ * search.js -- Alternative search results processor for pagefind.
+ * Copyright © 2022 - 2026 Jakob L. Kreuze <zerodaysfordays@sdf.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+window.addEventListener("load", async () => {
+ const pagefind = await import("/_pagefind/pagefind.js");
+ pagefind.init();
+
+ const params = new URLSearchParams(window.location.search);
+ const query = params.get('q');
+ const outputContainer = document.getElementById('search-output');
+
+ if (query) {
+ const search = await pagefind.search(query);
+
+ if (search.results.length === 0) {
+ outputContainer.innerHTML = `<p>No results found for "<strong>${query}</strong>".</p>`;
+ return;
+ }
+
+ outputContainer.innerHTML = `<p style="font-size: 9px; color: #999; margin-bottom: 20px;">
+ Found ${search.results.length} result(s) for "<strong>${query}</strong>":
+ </p>`;
+
+ for (let result of search.results) {
+ const data = await result.data();
+
+ const resultElement = document.createElement('article');
+ resultElement.className = 'update-entry';
+ console.log(data);
+ resultElement.innerHTML = `
+ <header>
+ <h3 class="title"><a href="${data.url}">${data.meta.title}</a></h3>
+ </header>
+ <p>${data.excerpt} ...</p>
+ <p><a href="${data.url}">view page →</a></p>
+ `;
+ outputContainer.appendChild(resultElement);
+ }
+ } else {
+ outputContainer.innerHTML = `<p>Searching for '${query}'...</p>`;
+ }
+});