| | |
| | | import { Document, SimpleDocumentSearchResultSetUnit } from "flexsearch" |
| | | import FlexSearch from "flexsearch" |
| | | import { ContentDetails } from "../../plugins/emitters/contentIndex" |
| | | import { registerEscapeHandler, removeAllChildren } from "./util" |
| | | import { FullSlug, resolveRelative } from "../../util/path" |
| | |
| | | tags: string[] |
| | | } |
| | | |
| | | let index: Document<Item> | undefined = undefined |
| | | let index: FlexSearch.Document<Item> | undefined = undefined |
| | | |
| | | // Can be expanded with things like "term" in the future |
| | | type SearchType = "basic" | "tags" |
| | |
| | | const anchor = document.getElementsByClassName("result-card")[0] as HTMLInputElement | null |
| | | anchor?.click() |
| | | } |
| | | } else if (e.key === "ArrowDown") { |
| | | } else if (e.key === "ArrowUp" || (e.shiftKey && e.key === "Tab")) { |
| | | e.preventDefault() |
| | | if (results?.contains(document.activeElement)) { |
| | | // If an element in results-container already has focus, focus previous one |
| | | const prevResult = document.activeElement?.previousElementSibling as HTMLInputElement | null |
| | | prevResult?.focus() |
| | | } |
| | | } else if (e.key === "ArrowDown" || e.key === "Tab") { |
| | | e.preventDefault() |
| | | // When first pressing ArrowDown, results wont contain the active element, so focus first element |
| | | if (!results?.contains(document.activeElement)) { |
| | |
| | | const nextResult = document.activeElement?.nextElementSibling as HTMLInputElement | null |
| | | nextResult?.focus() |
| | | } |
| | | } else if (e.key === "ArrowUp") { |
| | | e.preventDefault() |
| | | if (results?.contains(document.activeElement)) { |
| | | // If an element in results-container already has focus, focus previous one |
| | | const prevResult = document.activeElement?.previousElementSibling as HTMLInputElement | null |
| | | prevResult?.focus() |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | removeAllChildren(results) |
| | | if (finalResults.length === 0) { |
| | | results.innerHTML = `<button class="result-card"> |
| | | results.innerHTML = `<a class="result-card"> |
| | | <h3>No results.</h3> |
| | | <p>Try another search term?</p> |
| | | </button>` |
| | | </a>` |
| | | } else { |
| | | results.append(...finalResults.map(resultToHTML)) |
| | | } |
| | |
| | | |
| | | async function onType(e: HTMLElementEventMap["input"]) { |
| | | let term = (e.target as HTMLInputElement).value |
| | | let searchResults: SimpleDocumentSearchResultSetUnit[] |
| | | let searchResults: FlexSearch.SimpleDocumentSearchResultSetUnit[] |
| | | |
| | | if (term.toLowerCase().startsWith("#")) { |
| | | searchType = "tags" |
| | |
| | | |
| | | // setup index if it hasn't been already |
| | | if (!index) { |
| | | index = new Document({ |
| | | index = new FlexSearch.Document({ |
| | | charset: "latin:extra", |
| | | optimize: true, |
| | | encode: encoder, |
| | | document: { |
| | | id: "id", |
| | | index: [ |
| | | { |
| | | field: "title", |
| | | tokenize: "reverse", |
| | | tokenize: "forward", |
| | | }, |
| | | { |
| | | field: "content", |
| | | tokenize: "reverse", |
| | | tokenize: "forward", |
| | | }, |
| | | { |
| | | field: "tags", |
| | | tokenize: "reverse", |
| | | tokenize: "forward", |
| | | }, |
| | | ], |
| | | }, |
| | |
| | | * @param index index to fill |
| | | * @param data data to fill index with |
| | | */ |
| | | async function fillDocument(index: Document<Item, false>, data: any) { |
| | | async function fillDocument(index: FlexSearch.Document<Item, false>, data: any) { |
| | | let id = 0 |
| | | for (const [slug, fileData] of Object.entries<ContentDetails>(data)) { |
| | | await index.addAsync(id, { |