From 4bb2881dc592555958358d4416f043113d40d71a Mon Sep 17 00:00:00 2001 From: confused-Techie Date: Sat, 14 Feb 2026 18:15:20 -0800 Subject: [PATCH] Add base of search functionality --- docs/search-preview.11ty.js | 28 +++++++++ docs/search.js | 111 ++++++++++++++++++++++++++++++++++++ docs/search/index.md | 4 ++ layouts/page_header.ejs | 7 +++ layouts/search.ejs | 16 ++++++ less/page-header.less | 18 +++++- 6 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 docs/search-preview.11ty.js create mode 100644 docs/search.js create mode 100644 docs/search/index.md create mode 100644 layouts/search.ejs diff --git a/docs/search-preview.11ty.js b/docs/search-preview.11ty.js new file mode 100644 index 0000000..3ddf762 --- /dev/null +++ b/docs/search-preview.11ty.js @@ -0,0 +1,28 @@ +module.exports = +class SearchPreview { + constructor() {} + data() { + // Export Front Matter + return { + permalink: "/search-preview.json", + eleventyExcludeFromCollections: true + }; + } + render(data) { + let obj = { pages: {} }; + + for (const pageIdx in data.collections.all) { + const page = data.collections.all[pageIdx]; + if (page.page.outputFileExtension === "html") { + // Only include HTML content into our search preview file, since + // that's what we include in our search index file + obj.pages[page.url] = { + title: page.data.title, + summary: "A quick summary of the content of this page." + }; + } + } + + return JSON.stringify(obj); + } +} diff --git a/docs/search.js b/docs/search.js new file mode 100644 index 0000000..79eff57 --- /dev/null +++ b/docs/search.js @@ -0,0 +1,111 @@ +class SearchUtility { + constructor() { + this.api = "https://search.pulsar-edit.dev/search/docs"; + this.isSearchUrl = location.pathname.startsWith("/search"); + + this.searchTerm = ""; + this.searchResults = []; + this.searchPreviews = {}; + } + + async setup() { + if (!this.isSearchUrl) { return; } + // Get our search term + const paramsString = window.location.search; + const searchParams = new URLSearchParams(paramsString); + this.searchTerm = searchParams.get("q"); + + // Get our search preview + try { + const response = await fetch("/search-preview.json"); + + if (!response.ok) { + console.error(response); + return; + } + + const data = await response.json(); + this.searchPreviews = data.pages; + } catch(err) { + console.error(err); + } + } + + async search() { + if (!this.isSearchUrl || this.searchTerm?.length === 0 || typeof this.searchTerm !== "string") { + return; + } + + try { + const response = await fetch(`${this.api}?q=${this.searchTerm}`); + + if (!response.ok) { + console.error(response); + return; + } + + const data = await response.json(); + this.searchResults = data.results; + + } catch(err) { + console.error(err); + return; + } + } + + display() { + const resultsContainer = document.createElement("ul"); + resultsContainer.classList.add("list"); + + for (const result of this.searchResults) { + const resultPreview = this.searchPreviews[result.ref]; + + const node = document.createElement("li"); + node.classList.add("list-item"); + node.innerHTML = ` +
+
+

+ ${resultPreview.title} +

+
${resultPreview.summary}
+
+ `; + + resultsContainer.append(node); + } + + document.querySelector("main").append(resultsContainer); + } + + createSearchLink(searchResult) { + // Takes a search result item directly from the search API, and creates a link + // to the content indicated by the result. Will use Text Fragments if supported + // in the current browser. + let link = searchResult.ref; // Base link + + if (document.fragmentDirective !== undefined) { + // This browser supports text fragments + let fragment = "#:~:"; + + for (let term in searchResult.matchData.metadata) { + if (fragment.includes("text=")) { + // If we are appending additional fragments to a directive, add `&` + fragment = `${fragment}&`; + } + fragment = `${fragment}text=${term}`; + } + + link = `${link}${fragment}`; + } + + return link; + } +} + +(async () => { + const search = new SearchUtility(); + search.setup(); + await search.search(); + search.display(); +})(); diff --git a/docs/search/index.md b/docs/search/index.md new file mode 100644 index 0000000..8068b5c --- /dev/null +++ b/docs/search/index.md @@ -0,0 +1,4 @@ +--- +title: Search +layout: search.ejs +--- diff --git a/layouts/page_header.ejs b/layouts/page_header.ejs index 0832e71..971189b 100644 --- a/layouts/page_header.ejs +++ b/layouts/page_header.ejs @@ -17,6 +17,13 @@