diff --git a/src/main/frontend/components/search.cljs b/src/main/frontend/components/search.cljs index c0192f461f..ad91b2c617 100644 --- a/src/main/frontend/components/search.cljs +++ b/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))})]))) diff --git a/src/main/frontend/search.cljs b/src/main/frontend/search.cljs index d3e4dc2e6c..a3cdfed281 100644 --- a/src/main/frontend/search.cljs +++ b/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?)))))))))