(ns outliner.model.core.annotations) (def type-precedence {:horizontal-line 0 :link 1 :markdown-link 1 :style 2}) (def style-precedence {:highlight 0 :code 1 :italic 2 :bold 3 :bold-italic 4}) (defn sort-annotations [annotations] (sort-by (fn [a] [(get type-precedence (:type a) 99) (get style-precedence (:style a) 99)]) annotations)) (defn get-top-annotations [annotations types] (let [filtered (->> annotations (filter #(contains? types (:type %))) (sort-by (juxt :range-start (comp - :range-end))))] (reduce (fn [acc next-ann] (if (some (fn [l] (and (<= (:range-start l) (:range-start next-ann)) (>= (:range-end l) (:range-end next-ann)))) acc) acc (conj acc next-ann))) [] filtered))) (defn get-boundaries [top-annotations text-length] (->> top-annotations (mapcat (fn [l] [(:range-start l) (:range-end l)])) (concat [0 text-length]) distinct sort)) (defn- annotation-merge-key [ann] (case (:type ann) :style [(:type ann) (:style ann)] :link [(:type ann) (:url ann)] :markdown-link [(:type ann) (:url ann)] [(:type ann)])) (defn merge-annotations [annotations] (if (empty? annotations) [] (->> (group-by annotation-merge-key annotations) vals (mapcat (fn [group] (let [sorted (sort-by (juxt :range-start :range-end) group)] (reduce (fn [acc next-ann] (let [last-ann (peek acc)] (if (and last-ann (<= (:range-start next-ann) (:range-end last-ann))) (conj (pop acc) (assoc last-ann :range-end (max (:range-end last-ann) (:range-end next-ann)))) (conj acc next-ann)))) [] sorted)))) vec)))