feat!: add pagefind for static search (#458)

Replace React with pagefind for static site search
This commit is contained in:
Sat Naing
2025-03-07 08:53:16 +07:00
parent 79c7df45e5
commit 9119125643
6 changed files with 191 additions and 4 deletions
+4
View File
@@ -22,3 +22,7 @@ pnpm-debug.log*
# jetbrains setting folder
.idea/
# pagefind
public/pagefind
+3 -1
View File
@@ -4,7 +4,7 @@
"version": "0.0.1",
"scripts": {
"dev": "astro dev",
"build": "astro check && astro build",
"build": "astro check && astro build && pagefind --site dist && cp -r dist/pagefind public/",
"preview": "astro preview",
"astro": "astro",
"format:check": "prettier --check .",
@@ -27,12 +27,14 @@
},
"devDependencies": {
"@astrojs/check": "^0.9.4",
"@pagefind/default-ui": "^1.3.0",
"@tailwindcss/typography": "^0.5.16",
"@types/lodash.kebabcase": "^4.1.9",
"@typescript-eslint/parser": "^8.25.0",
"eslint": "^9.21.0",
"eslint-plugin-astro": "^1.3.1",
"globals": "^16.0.0",
"pagefind": "^1.3.0",
"prettier": "^3.5.2",
"prettier-plugin-astro": "^0.14.1",
"prettier-plugin-tailwindcss": "^0.6.11",
+63
View File
@@ -48,6 +48,9 @@ importers:
'@astrojs/check':
specifier: ^0.9.4
version: 0.9.4(prettier-plugin-astro@0.14.1)(prettier@3.5.2)(typescript@5.7.3)
'@pagefind/default-ui':
specifier: ^1.3.0
version: 1.3.0
'@tailwindcss/typography':
specifier: ^0.5.16
version: 0.5.16(tailwindcss@4.0.8)
@@ -66,6 +69,9 @@ importers:
globals:
specifier: ^16.0.0
version: 16.0.0
pagefind:
specifier: ^1.3.0
version: 1.3.0
prettier:
specifier: ^3.5.2
version: 3.5.2
@@ -496,6 +502,34 @@ packages:
'@oslojs/encoding@1.1.0':
resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==}
'@pagefind/darwin-arm64@1.3.0':
resolution: {integrity: sha512-365BEGl6ChOsauRjyVpBjXybflXAOvoMROw3TucAROHIcdBvXk9/2AmEvGFU0r75+vdQI4LJdJdpH4Y6Yqaj4A==}
cpu: [arm64]
os: [darwin]
'@pagefind/darwin-x64@1.3.0':
resolution: {integrity: sha512-zlGHA23uuXmS8z3XxEGmbHpWDxXfPZ47QS06tGUq0HDcZjXjXHeLG+cboOy828QIV5FXsm9MjfkP5e4ZNbOkow==}
cpu: [x64]
os: [darwin]
'@pagefind/default-ui@1.3.0':
resolution: {integrity: sha512-CGKT9ccd3+oRK6STXGgfH+m0DbOKayX6QGlq38TfE1ZfUcPc5+ulTuzDbZUnMo+bubsEOIypm4Pl2iEyzZ1cNg==}
'@pagefind/linux-arm64@1.3.0':
resolution: {integrity: sha512-8lsxNAiBRUk72JvetSBXs4WRpYrQrVJXjlRRnOL6UCdBN9Nlsz0t7hWstRk36+JqHpGWOKYiuHLzGYqYAqoOnQ==}
cpu: [arm64]
os: [linux]
'@pagefind/linux-x64@1.3.0':
resolution: {integrity: sha512-hAvqdPJv7A20Ucb6FQGE6jhjqy+vZ6pf+s2tFMNtMBG+fzcdc91uTw7aP/1Vo5plD0dAOHwdxfkyw0ugal4kcQ==}
cpu: [x64]
os: [linux]
'@pagefind/windows-x64@1.3.0':
resolution: {integrity: sha512-BR1bIRWOMqkf8IoU576YDhij1Wd/Zf2kX/kCI0b2qzCKC8wcc2GQJaaRMCpzvCCrmliO4vtJ6RITp/AnoYUUmQ==}
cpu: [x64]
os: [win32]
'@pkgr/core@0.1.1':
resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==}
engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
@@ -1918,6 +1952,10 @@ packages:
resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
engines: {node: '>=6'}
pagefind@1.3.0:
resolution: {integrity: sha512-8KPLGT5g9s+olKMRTU9LFekLizkVIu9tes90O1/aigJ0T5LmyPqTzGJrETnSw3meSYg58YH7JTzhTTW/3z6VAw==}
hasBin: true
pako@0.2.9:
resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==}
@@ -3074,6 +3112,23 @@ snapshots:
'@oslojs/encoding@1.1.0': {}
'@pagefind/darwin-arm64@1.3.0':
optional: true
'@pagefind/darwin-x64@1.3.0':
optional: true
'@pagefind/default-ui@1.3.0': {}
'@pagefind/linux-arm64@1.3.0':
optional: true
'@pagefind/linux-x64@1.3.0':
optional: true
'@pagefind/windows-x64@1.3.0':
optional: true
'@pkgr/core@0.1.1': {}
'@resvg/resvg-js-android-arm-eabi@2.6.2':
@@ -4771,6 +4826,14 @@ snapshots:
p-try@2.2.0: {}
pagefind@1.3.0:
optionalDependencies:
'@pagefind/darwin-arm64': 1.3.0
'@pagefind/darwin-x64': 1.3.0
'@pagefind/linux-arm64': 1.3.0
'@pagefind/linux-x64': 1.3.0
'@pagefind/windows-x64': 1.3.0
pako@0.2.9: {}
parent-module@1.0.1:
+2 -1
View File
@@ -74,6 +74,7 @@ const nextPost =
"mx-auto w-full max-w-3xl px-4 pb-12",
{ "mt-8": !SITE.showBackButton },
]}
data-pagefind-body
>
<h1
transition:name={slugifyStr(title)}
@@ -119,7 +120,7 @@ const nextPost =
<hr class="my-6 border-dashed" />
<!-- Previous/Next Post Buttons -->
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2">
<div data-pagefind-ignore class="grid grid-cols-1 gap-6 sm:grid-cols-2">
{
prevPost && (
<a
+118 -1
View File
@@ -1,15 +1,132 @@
---
import "@pagefind/default-ui/css/ui.css";
import Main from "@/layouts/Main.astro";
import Layout from "@/layouts/Layout.astro";
import Header from "@/components/Header.astro";
import Footer from "@/components/Footer.astro";
import { SITE } from "@/config";
const backUrl = SITE.showBackButton ? `${Astro.url.pathname}` : "/";
---
<Layout title={`Search | ${SITE.title}`}>
<Header />
<Main pageTitle="Search" pageDesc="Search any article ...">
<!-- Search bar -->
<div id="pagefind-search" transition:persist data-backurl={backUrl}></div>
</Main>
<Footer />
</Layout>
<script>
function initSearch() {
const pageFindSearch: HTMLElement | null =
document.querySelector("#pagefind-search");
if (!pageFindSearch) return;
const params = new URLSearchParams(window.location.search);
const onIdle = window.requestIdleCallback || (cb => setTimeout(cb, 1));
onIdle(async () => {
// @ts-expect-error — Missing types for @pagefind/default-ui package.
const { PagefindUI } = await import("@pagefind/default-ui");
// Display warning inn dev mode
if (import.meta.env.DEV) {
pageFindSearch.innerHTML = `
<div class="bg-muted/75 rounded p-4 space-y-4 mb-4">
<p><strong>DEV mode Warning! </strong>You need to build the project at least once to see the search results during development.</p>
<code class="block bg-black text-white px-2 py-1 rounded">pnpm run build</code>
</div>
`;
}
// Init pagefind ui
const search = new PagefindUI({
element: "#pagefind-search",
showSubResults: true,
showImages: false,
processTerm: function (term: string) {
params.set("q", term); // Update the `q` parameter in the URL
history.replaceState(history.state, "", "?" + params.toString()); // Push the new URL without reloading
const backUrl = pageFindSearch?.dataset?.backurl;
sessionStorage.setItem("backUrl", backUrl + "?" + params.toString());
return term;
},
});
// If search param exists (eg: search?q=astro), trigger search
const query = params.get("q");
if (query) {
search.triggerSearch(query);
}
// Reset search param if search input is cleared
const searchInput = document.querySelector(".pagefind-ui__search-input");
const clearButton = document.querySelector(".pagefind-ui__search-clear");
searchInput?.addEventListener("input", resetSearchParam);
clearButton?.addEventListener("click", resetSearchParam);
function resetSearchParam(e: Event) {
if ((e.target as HTMLInputElement)?.value.trim() === "") {
history.replaceState(history.state, "", window.location.pathname);
}
}
});
}
document.addEventListener("astro:after-swap", initSearch);
initSearch();
</script>
<style is:global>
#pagefind-search {
--pagefind-ui-font: var(--font-mono);
--pagefind-ui-text: var(--foreground);
--pagefind-ui-background: var(--background);
--pagefind-ui-border: var(--border);
--pagefind-ui-primary: var(--accent);
--pagefind-ui-tag: var(--background);
--pagefind-ui-border-radius: 0.375rem;
--pagefind-ui-border-width: 1px;
--pagefind-ui-image-border-radius: 8px;
--pagefind-ui-image-box-ratio: 3 / 2;
form::before {
background-color: var(--foreground);
}
input {
font-weight: 400;
border: 1px solid var(--border);
}
input:focus-visible {
outline: 1px solid var(--accent);
}
.pagefind-ui__result-title a {
color: var(--accent);
outline-offset: 1px;
outline-color: var(--accent);
}
.pagefind-ui__result-title a:focus-visible,
.pagefind-ui__search-clear:focus-visible {
text-decoration-line: none;
outline-width: 2px;
outline-style: dashed;
}
.pagefind-ui__result:last-of-type {
border-bottom: 0;
}
.pagefind-ui__result-nested .pagefind-ui__result-link:before {
font-family: system-ui;
}
}
</style>
+1 -1
View File
@@ -1,7 +1,7 @@
{
"extends": "astro/tsconfigs/strict",
"include": [".astro/types.d.ts", "**/*"],
"exclude": ["dist"],
"exclude": ["dist", "public/pagefind"],
"compilerOptions": {
"baseUrl": ".",
"paths": {