From 44da82467ee7077a22f0054b7bc4d0f2a008e2e0 Mon Sep 17 00:00:00 2001
From: Jacky Zhao <j.zhao2k19@gmail.com>
Date: Fri, 02 Feb 2024 09:45:15 +0000
Subject: [PATCH] fix(style): remove redundant selector

---
 quartz/components/scripts/search.inline.ts |  119 +++++++++++++++++++++++++++++++----------------------------
 1 files changed, 63 insertions(+), 56 deletions(-)

diff --git a/quartz/components/scripts/search.inline.ts b/quartz/components/scripts/search.inline.ts
index c960f5e..ec55f96 100644
--- a/quartz/components/scripts/search.inline.ts
+++ b/quartz/components/scripts/search.inline.ts
@@ -15,10 +15,30 @@
 type SearchType = "basic" | "tags"
 let searchType: SearchType = "basic"
 let currentSearchTerm: string = ""
-let index: FlexSearch.Document<Item> | undefined = undefined
-const p = new DOMParser()
 const encoder = (str: string) => str.toLowerCase().split(/([^a-z]|[^\x00-\x7F])/)
+let index = new FlexSearch.Document<Item>({
+  charset: "latin:extra",
+  encode: encoder,
+  document: {
+    id: "id",
+    index: [
+      {
+        field: "title",
+        tokenize: "forward",
+      },
+      {
+        field: "content",
+        tokenize: "forward",
+      },
+      {
+        field: "tags",
+        tokenize: "forward",
+      },
+    ],
+  },
+})
 
+const p = new DOMParser()
 const fetchContentCache: Map<FullSlug, Element[]> = new Map()
 const contextWindowWords = 30
 const numSearchResults = 8
@@ -76,14 +96,15 @@
     })
     .join(" ")
 
-  return `${startIndex === 0 ? "" : "..."}${slice}${endIndex === tokenizedText.length - 1 ? "" : "..."
-    }`
+  return `${startIndex === 0 ? "" : "..."}${slice}${
+    endIndex === tokenizedText.length - 1 ? "" : "..."
+  }`
 }
 
-function highlightHTML(searchTerm: string, innerHTML: string) {
+function highlightHTML(searchTerm: string, el: HTMLElement) {
   const p = new DOMParser()
   const tokenizedTerms = tokenizeTerm(searchTerm)
-  const html = p.parseFromString(innerHTML, "text/html")
+  const html = p.parseFromString(el.innerHTML, "text/html")
 
   const createHighlightSpan = (text: string) => {
     const span = document.createElement("span")
@@ -167,7 +188,7 @@
       removeAllChildren(preview)
     }
     if (searchLayout) {
-      searchLayout.style.visibility = "hidden"
+      searchLayout.classList.remove("display-results")
     }
 
     searchType = "basic" // reset search type after closing
@@ -203,6 +224,7 @@
 
     if (currentHover) {
       currentHover.classList.remove("focus")
+      currentHover.blur()
     }
 
     // If search is active, then we will render the first result and display accordingly
@@ -229,9 +251,9 @@
           : (document.activeElement as HTMLInputElement | null)
         const prevResult = currentResult?.previousElementSibling as HTMLInputElement | null
         currentResult?.classList.remove("focus")
-        await displayPreview(prevResult)
         prevResult?.focus()
         currentHover = prevResult
+        await displayPreview(prevResult)
       }
     } else if (e.key === "ArrowDown" || e.key === "Tab") {
       e.preventDefault()
@@ -243,9 +265,9 @@
           : (document.getElementsByClassName("result-card")[0] as HTMLInputElement | null)
         const secondResult = firstResult?.nextElementSibling as HTMLInputElement | null
         firstResult?.classList.remove("focus")
-        await displayPreview(secondResult)
         secondResult?.focus()
         currentHover = secondResult
+        await displayPreview(secondResult)
       } else {
         // If an element in results-container already has focus, focus next one
         const active = currentHover
@@ -253,9 +275,9 @@
           : (document.activeElement as HTMLInputElement | null)
         active?.classList.remove("focus")
         const nextResult = active?.nextElementSibling as HTMLInputElement | null
-        await displayPreview(nextResult)
         nextResult?.focus()
         currentHover = nextResult
+        await displayPreview(nextResult)
       }
     }
   }
@@ -276,13 +298,15 @@
       return []
     }
 
-    return tags.map(tag => {
-      if (tag.toLowerCase().includes(term.toLowerCase())) {
-        return `<li><p class="match-tag">#${tag}</p></li>`
-      } else {
-        return `<li><p>#${tag}</p></li>`
-      }
-    }).slice(0, numTagResults)
+    return tags
+      .map((tag) => {
+        if (tag.toLowerCase().includes(term.toLowerCase())) {
+          return `<li><p class="match-tag">#${tag}</p></li>`
+        } else {
+          return `<li><p>#${tag}</p></li>`
+        }
+      })
+      .slice(0, numTagResults)
   }
 
   function resolveUrl(slug: FullSlug): URL {
@@ -299,12 +323,12 @@
 
     async function onMouseEnter(ev: MouseEvent) {
       if (!ev.target) return
-      currentHover?.classList.remove('focus')
+      currentHover?.classList.remove("focus")
       currentHover?.blur()
       const target = ev.target as HTMLInputElement
-      await displayPreview(target)
       currentHover = target
       currentHover.classList.add("focus")
+      await displayPreview(target)
     }
 
     async function onMouseLeave(ev: MouseEvent) {
@@ -382,24 +406,25 @@
   async function displayPreview(el: HTMLElement | null) {
     if (!searchLayout || !enablePreview || !el || !preview) return
     const slug = el.id as FullSlug
-    el.classList.add("focus")
+    const innerDiv = await fetchContent(slug).then((contents) =>
+      contents.flatMap((el) => [...highlightHTML(currentSearchTerm, el as HTMLElement).children]),
+    )
     previewInner = document.createElement("div")
     previewInner.classList.add("preview-inner")
-    const innerDiv = await fetchContent(slug).then((contents) =>
-      contents.map((el) => highlightHTML(currentSearchTerm, el.innerHTML)),
-    )
     previewInner.append(...innerDiv)
     preview.replaceChildren(previewInner)
 
     // scroll to longest
-    const highlights = [...preview.querySelectorAll(".highlight")].sort((a, b) => b.innerHTML.length - a.innerHTML.length)
-    highlights[0]?.scrollIntoView()
+    const highlights = [...preview.querySelectorAll(".highlight")].sort(
+      (a, b) => b.innerHTML.length - a.innerHTML.length,
+    )
+    highlights[0]?.scrollIntoView({ block: "start" })
   }
 
   async function onType(e: HTMLElementEventMap["input"]) {
     if (!searchLayout || !index) return
     currentSearchTerm = (e.target as HTMLInputElement).value
-    searchLayout.style.visibility = currentSearchTerm === "" ? "hidden" : "visible"
+    searchLayout.classList.toggle("display-results", currentSearchTerm !== "")
     searchType = currentSearchTerm.startsWith("#") ? "tags" : "basic"
 
     let searchResults: FlexSearch.SimpleDocumentSearchResultSetUnit[]
@@ -439,8 +464,8 @@
   searchBar?.addEventListener("input", onType)
   window.addCleanup(() => searchBar?.removeEventListener("input", onType))
 
-  index ??= await fillDocument(data)
   registerEscapeHandler(container, hideSearch)
+  await fillDocument(data)
 })
 
 /**
@@ -449,37 +474,19 @@
  * @param data data to fill index with
  */
 async function fillDocument(data: { [key: FullSlug]: ContentDetails }) {
-  const index = new FlexSearch.Document<Item>({
-    charset: "latin:extra",
-    encode: encoder,
-    document: {
-      id: "id",
-      index: [
-        {
-          field: "title",
-          tokenize: "forward",
-        },
-        {
-          field: "content",
-          tokenize: "forward",
-        },
-        {
-          field: "tags",
-          tokenize: "forward",
-        },
-      ],
-    },
-  })
   let id = 0
+  const promises: Array<Promise<unknown>> = []
   for (const [slug, fileData] of Object.entries<ContentDetails>(data)) {
-    await index.addAsync(id++, {
-      id,
-      slug: slug as FullSlug,
-      title: fileData.title,
-      content: fileData.content,
-      tags: fileData.tags,
-    })
+    promises.push(
+      index.addAsync(id++, {
+        id,
+        slug: slug as FullSlug,
+        title: fileData.title,
+        content: fileData.content,
+        tags: fileData.tags,
+      }),
+    )
   }
 
-  return index
+  return await Promise.all(promises)
 }

--
Gitblit v1.10.0