فهرست منبع

enhance: paste from clipboard (#8642)

replace the selected part from the clipboard
instead of formatting it to a link if it's within the link
megayu 2 سال پیش
والد
کامیت
a4a5758afc
3فایلهای تغییر یافته به همراه77 افزوده شده و 16 حذف شده
  1. 6 3
      src/main/frontend/handler/editor.cljs
  2. 32 12
      src/main/frontend/handler/paste.cljs
  3. 39 1
      src/test/frontend/handler/paste_test.cljs

+ 6 - 3
src/main/frontend/handler/editor.cljs

@@ -127,7 +127,7 @@
 (defn html-link-format!
   ([]
    (html-link-format! nil))
-  ([link]
+  ([text]
    (when-let [m (get-selection-and-format)]
      (let [{:keys [selection-start selection-end format selection value edit-id input]} m
            cur-pos (cursor/pos input)
@@ -137,8 +137,11 @@
                                    empty-selection?
                                    (config/get-empty-link-and-forward-pos format)
 
-                                   link
-                                   (config/with-label-link format selection link)
+                                   (and text selection-link?)
+                                   (config/with-label-link format text selection)
+
+                                   text
+                                   (config/with-label-link format selection text)
 
                                    selection-link?
                                    (config/with-default-link format selection)

+ 32 - 12
src/main/frontend/handler/paste.cljs

@@ -74,6 +74,19 @@
                                              (gp-util/safe-decode-uri-component text))]
     (try-parse-as-json (second matched-text))))
 
+(defn- selection-within-link?
+  [selection-and-format]
+  (let [{:keys [format selection-start selection-end selection value]} selection-and-format]
+    (and (not= selection-start selection-end)
+         (->> (case format
+                :markdown (util/re-pos #"\[.*?\]\(.*?\)" value)
+                :org (util/re-pos #"\[\[.*?\]\[.*?\]\]" value))
+              (some (fn [[start-index matched-text]]
+                      (and (<= start-index selection-start)
+                           (>= (+ start-index (count matched-text)) selection-end)
+                           (clojure.string/includes? matched-text selection))))
+              some?))))
+
 (defn- paste-copied-blocks-or-text
   ;; todo: logseq/whiteboard-shapes is now text/html
   [text e html]
@@ -82,10 +95,9 @@
         input (state/get-input)
         input-id (state/get-edit-input-id)
         text (string/replace text "\r\n" "\n") ;; Fix for Windows platform
-        shape-refs-text (when (and (not (string/blank? html))
-                                   (get-whiteboard-tldr-from-text html))
-                          ;; text should alway be prepared block-ref generated in tldr
-                          text)
+        replace-text-f (fn [text]
+                         (commands/delete-selection! input-id)
+                         (commands/simple-insert! input-id text nil))
         internal-paste? (and
                          (seq (:copy/blocks copied-blocks))
                          ;; not copied from the external clipboard
@@ -95,12 +107,23 @@
       (let [blocks (:copy/blocks copied-blocks)]
         (when (seq blocks)
           (editor-handler/paste-blocks blocks {})))
-      (let [{:keys [value]} (editor-handler/get-selection-and-format)]
+      (let [shape-refs-text (when (and (not (string/blank? html))
+                                       (get-whiteboard-tldr-from-text html))
+                              ;; text should alway be prepared block-ref generated in tldr
+                              text)
+            {:keys [value selection] :as selection-and-format} (editor-handler/get-selection-and-format)
+            text-url? (gp-util/url? text)
+            selection-url? (gp-util/url? selection)]
         (cond
           (not (string/blank? shape-refs-text))
           (commands/simple-insert! input-id shape-refs-text nil)
 
-          (and (or (gp-util/url? text)
+          (or (and (or text-url? selection-url?)
+                   (selection-within-link? selection-and-format))
+              (and text-url? selection-url?))
+          (replace-text-f text)
+
+          (and (or text-url?
                    (and value (gp-util/url? (string/trim value))))
                (not (string/blank? (util/get-selected-text))))
           (editor-handler/html-link-format! text)
@@ -119,10 +142,7 @@
                                              (log/error :exception e)
                                              nil)))]
                             (if (string/blank? result) nil result))
-                text (or html-text text)
-                replace-text-f (fn []
-                                 (commands/delete-selection! input-id)
-                                 (commands/simple-insert! input-id text nil))]
+                text (or html-text text)]
             (match [format
                     (nil? (util/safe-re-find #"(?m)^\s*(?:[-+*]|#+)\s+" text))
                     (nil? (util/safe-re-find #"(?m)^\s*\*+\s+" text))
@@ -137,13 +157,13 @@
               (paste-segmented-text format text)
 
               [:markdown true _ true]
-              (replace-text-f)
+              (replace-text-f text)
 
               [:org _ true false]
               (paste-segmented-text format text)
 
               [:org _ true true]
-              (replace-text-f))))))))
+              (replace-text-f text))))))))
 
 (defn paste-text-in-one-block-at-point
   []

+ 39 - 1
src/test/frontend/handler/paste_test.cljs

@@ -29,4 +29,42 @@
     "true" nil nil
     "[{\"number\": 1234}]" nil nil
     ;; invalid JSON
-    "{number: 1234}" nil nil))
+    "{number: 1234}" nil nil))
+  
+(deftest selection-within-link-test
+  (are [x y] (= (#'paste-handler/selection-within-link? x) y)
+    {:format :markdown
+     :value "[logseq](https://logseq.com)"
+     :selection-start 0
+     :selection-end 28
+     :selection "[logseq](https://logseq.com)"} true
+    {:format :markdown
+     :value "[logseq](https://logseq.com)"
+     :selection-start 1
+     :selection-end 27
+     :selection "logseq](https://logseq.com"} true
+    {:format :markdown
+     :value "[logseq](https://logseq.com)"
+     :selection-start 1
+     :selection-end 7
+     :selection "logseq"} true
+    {:format :markdown
+     :value "[logseq](https://logseq.com)"
+     :selection-start 9
+     :selection-end 27
+     :selection "https://logseq.com"} true
+    {:format :markdown
+     :value "[logseq](https://logseq.com) is awesome"
+     :selection-start 32
+     :selection-end 39
+     :selection "awesome"} false
+    {:format :markdown
+     :value "[logseq](https://logseq.com) is awesome"
+     :selection-start 9
+     :selection-end 39
+     :selection "https://logseq.com) is awesome"} false
+    {:format :markdown
+     :value "[logseq](https://logseq.com) is developed with [Clojure](https://clojure.org)"
+     :selection-start 9
+     :selection-end 76
+     :selection "https://logseq.com) is developed with [Clojure](https://clojure.org"} false))