Forráskód Böngészése

Add tag and url support for follow-link-under-cursor cmd

Plain urls, markdown urls and org mode urls all work
Gabriel Horner 3 éve
szülő
commit
757ac40fdd

+ 59 - 29
src/main/frontend/handler/editor.cljs

@@ -1304,46 +1304,76 @@
         (let [repo (state/get-current-repo)]
           (delete-blocks! repo blocks))))))
 
+(def url-regex
+  "Didn't use link/plain-link as it is incorrectly detects words as urls."
+  #"[^\s\(\[]+://[^\s\)\]]+")
+
+(defn extract-nearest-link-from-text
+  [text pos & additional-patterns]
+  (let [page-pattern #"\[\[([^\]]+)]]"
+        block-pattern #"\(\(([^\)]+)\)\)"
+        tag-pattern #"#\S+"
+        page-matches (util/re-pos page-pattern text)
+        block-matches (util/re-pos block-pattern text)
+        tag-matches (util/re-pos tag-pattern text)
+        additional-matches (mapcat #(util/re-pos % text) additional-patterns)
+        matches (->> (concat page-matches block-matches tag-matches additional-matches)
+                     (remove nil?))
+        [_ match] (first (sort-by
+                          (fn [[start-pos content]]
+                            (let [end-pos (+ start-pos (count content))]
+                              (cond
+                                (< pos start-pos)
+                                (- pos start-pos)
+
+                                (> pos end-pos)
+                                (- end-pos pos)
+
+                                :else
+                                0)))
+                          >
+                          matches))]
+    (when match
+      (cond
+        (some #(re-find % match) additional-patterns)
+        match
+        (string/starts-with? match "#")
+        (subs match 1 (count match))
+        :else
+        (subs match 2 (- (count match) 2))))))
+
+(defn- get-nearest-page-or-link
+  "Return the nearest page-name (not dereferenced, may be an alias), block, tag or link"
+  []
+  (when-let [block (state/get-edit-block)]
+    (when (:block/uuid block)
+      (when-let [edit-id (state/get-edit-input-id)]
+        (when-let [input (gdom/getElement edit-id)]
+          (when-let [pos (cursor/pos input)]
+            (let [value (gobj/get input "value")]
+              (extract-nearest-link-from-text value pos url-regex))))))))
+
 (defn- get-nearest-page
-  "Return the nearset page-name (not dereferenced, may be an alias)"
+  "Return the nearest page-name (not dereferenced, may be an alias), block or tag"
   []
   (when-let [block (state/get-edit-block)]
     (when (:block/uuid block)
       (when-let [edit-id (state/get-edit-input-id)]
         (when-let [input (gdom/getElement edit-id)]
           (when-let [pos (cursor/pos input)]
-            (let [value (gobj/get input "value")
-                  page-pattern #"\[\[([^\]]+)]]"
-                  block-pattern #"\(\(([^\)]+)\)\)"
-                  page-matches (util/re-pos page-pattern value)
-                  block-matches (util/re-pos block-pattern value)
-                  matches (->> (concat page-matches block-matches)
-                               (remove nil?))
-                  [_ page] (first (sort-by
-                                   (fn [[start-pos content]]
-                                     (let [end-pos (+ start-pos (count content))]
-                                       (cond
-                                         (< pos start-pos)
-                                         (- pos start-pos)
-
-                                         (> pos end-pos)
-                                         (- end-pos pos)
-
-                                         :else
-                                         0)))
-                                   >
-                                   matches))]
-              (when page
-                (subs page 2 (- (count page) 2))))))))))
+            (let [value (gobj/get input "value")]
+              (extract-nearest-link-from-text value pos))))))))
 
 (defn follow-link-under-cursor!
   []
-  (when-let [page (get-nearest-page)]
+  (when-let [page (get-nearest-page-or-link)]
     (when-not (string/blank? page)
-      (let [page-name (db-model/get-redirect-page-name page)]
-        (state/clear-edit!)
-        (insert-first-page-block-if-not-exists! page-name)
-        (route-handler/redirect-to-page! page-name)))))
+      (if (re-find url-regex page)
+        (js/window.open page)
+        (let [page-name (db-model/get-redirect-page-name page)]
+          (state/clear-edit!)
+          (insert-first-page-block-if-not-exists! page-name)
+          (route-handler/redirect-to-page! page-name))))))
 
 (defn open-link-in-sidebar!
   []

+ 43 - 0
src/test/frontend/handler/editor_test.cljs

@@ -0,0 +1,43 @@
+(ns frontend.handler.editor-test
+  (:require [frontend.handler.editor :as editor]
+            [clojure.test :refer [deftest is testing]]))
+
+(deftest extract-nearest-link-from-text-test
+  (testing "Page, block and tag links"
+    (is (= "page1"
+          (editor/extract-nearest-link-from-text "[[page1]] [[page2]]" 0))
+        "Finds first page link correctly based on cursor position")
+
+    (is (= "page2"
+           (editor/extract-nearest-link-from-text "[[page1]] [[page2]]" 10))
+        "Finds second page link correctly based on cursor position")
+
+    (is (= "tag"
+           (editor/extract-nearest-link-from-text "#tag [[page1]]" 3))
+        "Finds tag correctly")
+
+    (is (= "61e057b9-f799-4532-9258-cfef6ce58370"
+           (editor/extract-nearest-link-from-text
+            "((61e057b9-f799-4532-9258-cfef6ce58370)) #todo" 5))
+        "Finds block correctly"))
+
+  (testing "Url links"
+    (is (= "https://github.com/logseq/logseq"
+          (editor/extract-nearest-link-from-text
+           "https://github.com/logseq/logseq is #awesome :)" 0 editor/url-regex))
+        "Finds url correctly")
+
+    (is (not= "https://github.com/logseq/logseq"
+           (editor/extract-nearest-link-from-text
+            "https://github.com/logseq/logseq is #awesome :)" 0))
+        "Doesn't find url if regex not passed")
+
+    (is (= "https://github.com/logseq/logseq"
+           (editor/extract-nearest-link-from-text
+            "[logseq](https://github.com/logseq/logseq) is #awesome :)" 0 editor/url-regex))
+        "Finds url in markdown link correctly"))
+
+  (is (= "https://github.com/logseq/logseq"
+         (editor/extract-nearest-link-from-text
+          "[[https://github.com/logseq/logseq][logseq]] is #awesome :)" 0 editor/url-regex))
+      "Finds url in org link correctly"))