(ns frontend.diff (:require [clojure.string :as string] ["diff" :as jsdiff] [goog.object :as gobj] [lambdaisland.glogi :as log] [cljs-bean.core :as bean] [frontend.util :as util] [logseq.graph-parser.util :as gp-util] [frontend.util.text :as text-util])) (defn diff [s1 s2] (-> ((gobj/get jsdiff "diffLines") s1 s2 (clj->js {"newlineIsToken" true})) bean/->clj)) (def inline-special-chars #{\* \_ \/ \` \+ \^ \~ \$}) (defn- markdown-link? [markup current-line pos] (and current-line (= (util/nth-safe markup pos) "]") (= (util/nth-safe markup (inc pos)) "(") (string/includes? (subs current-line 0 pos) "[") (string/includes? (subs current-line pos) ")"))) ;; (find-position "** hello _w_" "hello w") (defn find-position [markup text] (when (and (string? markup) (string? text)) (try (let [pos (loop [t1 (-> markup string/lower-case seq) t2 (-> text string/lower-case seq) i1 0 i2 0] (let [[h1 & r1] t1 [h2 & r2] t2] (cond (or (empty? t1) (empty? t2)) i1 (= h1 h2) (recur r1 r2 (inc i1) (inc i2)) (#{\[ \space \]} h2) (recur t1 r2 i1 (inc i2)) :else (recur r1 t2 (inc i1) i2)))) current-line (text-util/get-current-line-by-pos markup pos)] (cond (= (util/nth-safe markup pos) (util/nth-safe markup (inc pos)) "]") (+ pos 2) (contains? inline-special-chars (util/nth-safe markup pos)) (let [matched (->> (take-while inline-special-chars (gp-util/safe-subs markup pos)) (apply str)) matched? (and current-line (string/includes? current-line (string/reverse matched)))] (if matched? (+ pos (count matched)) pos)) (markdown-link? markup current-line pos) (let [idx (string/index-of (subs current-line pos) ")")] (+ pos (inc idx))) :else pos)) (catch js/Error e (log/error :diff/find-position {:error e}) (count markup)))))