Browse Source

fix: fix highlight for fuzzy search

Yukun Guo 4 years ago
parent
commit
536ce5dd87
2 changed files with 46 additions and 4 deletions
  1. 43 2
      src/main/frontend/components/search.cljs
  2. 3 2
      src/main/frontend/search.cljs

+ 43 - 2
src/main/frontend/components/search.cljs

@@ -13,6 +13,7 @@
             [frontend.search :as search]
             [clojure.string :as string]
             [goog.dom :as gdom]
+            [medley.core :as medley]
             [frontend.context.i18n :as i18n]))
 
 (rum/defc dropdown-content-wrapper [state content]
@@ -24,6 +25,46 @@
              "exited" "transition ease-in duration-75 transform opacity-0 scale-95")}
    content])
 
+(defn- partition-between
+  "Split `coll` at positions where `pred?` is true."
+  [pred? coll]
+  (let [switch (reductions not= true (map pred? coll (rest coll)))]
+    (map (partial map first) (partition-by second (map list coll switch)))))
+
+(rum/defc highlight-fuzzy
+  [content indexes]
+  (let [n (count content)
+        max-hightlighted-len 64
+        max-surrounding-len 32
+
+        first-index (first indexes)
+        last-index (nth indexes (dec (count indexes)))
+        last-index (min (+ first-index max-hightlighted-len -1) last-index)
+        last-index* (+ last-index max-surrounding-len)
+        indexes (take-while #(<= % last-index*) indexes)
+        content-begin (max 0 (- first-index max-surrounding-len))
+        content-end   (min n (+ last-index 1 max-surrounding-len)) ; exclusive
+
+        ; finds inconsecutive sections
+        sections (partition-between #(> (- %2 %) 1) indexes)
+        hl-ranges (for [sec sections
+                        :let [begin (first sec)
+                              end (-> sec last inc)]]
+                    [begin end]) ; `end` is exclusive
+        hl-ranges* (concat [[content-begin content-begin]]
+                           hl-ranges
+                           [[content-end content-end]])
+        normal-ranges (for [[[_ begin] [end _]] (partition 2 1 hl-ranges*)] [begin end])
+        normal-hl-pairs (partition-all 2 (medley/interleave-all normal-ranges hl-ranges))]
+    [:p
+     (mapcat
+      (fn [[normal highlighted]]
+        [(when-some [[begin end] normal]
+           [:span (subs content begin end)])
+         (when-some [[begin end] highlighted]
+           [:mark (subs content begin end)])])
+      normal-hl-pairs)]))
+
 (rum/defc highlight
   [content q]
   (let [q-pattern (->> q
@@ -135,11 +176,11 @@
                            data]
 
                           :block
-                          (let [{:block/keys [page content]} data]
+                          (let [{:block/keys [page content indexes]} data]
                             (let [page (:page/original-name page)]
                               [:div.flex-1
                                [:div.text-sm.font-medium page]
-                               (highlight content search-q)]))
+                               (highlight-fuzzy content indexes)]))
 
                           nil))})])))
 

+ 3 - 2
src/main/frontend/search.cljs

@@ -154,9 +154,10 @@
                          (bean/->clj))]
              (->>
               (map
-               (fn [{:keys [target uuid]}]
+               (fn [{:keys [target uuid indexes]}]
                  {:block/uuid uuid
-                  :block/content target})
+                  :block/content target
+                  :block/indexes indexes}) ; For result highlight
                result)
               (remove nil?)))))))))