Browse Source

fix: paste blocks

Tienson Qin 3 years ago
parent
commit
b59d98ada5

+ 1 - 1
deps.edn

@@ -18,7 +18,7 @@
   cljs-http/cljs-http                   {:mvn/version "0.1.46"}
   org.babashka/sci                      {:mvn/version "0.3.2"}
   hickory/hickory                       {:git/url "https://github.com/logseq/hickory"
-                                         :sha     "9c2c2f1fc2c45efaad906e0faabc3201278deeaa"}
+                                         :sha     "86baee0319a66b7921719a5d2345e09734b23650"}
   hiccups/hiccups                       {:mvn/version "0.3.0"}
   tongue/tongue                         {:mvn/version "0.4.4"}
   org.clojure/core.async                {:mvn/version "1.3.610"}

+ 2 - 1
src/main/frontend/components/editor.cljs

@@ -11,6 +11,7 @@
             [frontend.db.model :as db-model]
             [frontend.extensions.zotero :as zotero]
             [frontend.handler.editor :as editor-handler :refer [get-state]]
+            [frontend.handler.paste :as paste-handler]
             [frontend.handler.editor.lifecycle :as lifecycle]
             [frontend.handler.page :as page-handler]
             [frontend.mixins :as mixins]
@@ -530,7 +531,7 @@
        :minRows           (if (state/enable-grammarly?) 2 1)
        :on-click          (editor-handler/editor-on-click! id)
        :on-change         (editor-handler/editor-on-change! block id search-timeout)
-       :on-paste          (editor-handler/editor-on-paste! id)
+       :on-paste          (paste-handler/editor-on-paste! id)
        :auto-focus        false
        :class             heading-class})
 

+ 2 - 177
src/main/frontend/handler/editor.cljs

@@ -1,7 +1,5 @@
 (ns frontend.handler.editor
-  (:require ["/frontend/utils" :as utils]
-            ["path" :as path]
-            [cljs.core.match :refer [match]]
+  (:require ["path" :as path]
             [clojure.set :as set]
             [clojure.string :as string]
             [clojure.walk :as w]
@@ -56,8 +54,7 @@
             [promesa.core :as p]
             [logseq.graph-parser.util :as gp-util]
             [logseq.graph-parser.mldoc :as gp-mldoc]
-            [logseq.graph-parser.block :as gp-block]
-            [frontend.extensions.html-parser :as html-parser]))
+            [logseq.graph-parser.block :as gp-block]))
 
 ;; FIXME: should support multiple images concurrently uploading
 
@@ -2848,178 +2845,6 @@
         (edit-box-on-change! e block id)
         (util/scroll-editor-cursor input)))))
 
-(defn- paste-text-parseable
-  [format text]
-  (when-let [editing-block (state/get-edit-block)]
-    (let [page-id (:db/id (:block/page editing-block))
-          blocks (block/extract-blocks
-                  (mldoc/->edn text (gp-mldoc/default-config format)) text true format)
-          blocks' (gp-block/with-parent-and-left page-id blocks)]
-      (paste-blocks blocks' {}))))
-
-(defn- paste-segmented-text
-  [format text]
-  (let [paragraphs (string/split text #"(?:\r?\n){2,}")
-        updated-paragraphs
-        (string/join "\n"
-                     (mapv (fn [p] (->> (string/trim p)
-                                        ((fn [p]
-                                           (if (util/safe-re-find (if (= format :org)
-                                                                    #"\s*\*+\s+"
-                                                                    #"\s*-\s+") p)
-                                             p
-                                             (str (if (= format :org) "* " "- ") p))))))
-                           paragraphs))]
-    (paste-text-parseable format updated-paragraphs)))
-
-(defn- get-all-blocks-by-ids
-  [repo ids]
-  (loop [ids ids
-         result []]
-    (if (seq ids)
-      (let [blocks (db/get-block-and-children repo (first ids))
-            result (vec (concat result blocks))]
-        (recur (remove (set (map :block/uuid result)) (rest ids)) result))
-      result)))
-
-(defn wrap-macro-url
-  [url]
-  (cond
-    (boolean (text-util/get-matched-video url))
-    (util/format "{{video %s}}" url)
-
-    (string/includes? url "twitter.com")
-    (util/format "{{twitter %s}}" url)
-
-    :else
-    (do
-      (notification/show! (util/format "No macro is available for %s" url) :warning)
-      nil)))
-
-(defn- paste-copied-blocks-or-text
-  [text e html]
-  (let [copied-blocks (state/get-copied-blocks)
-        copied-block-ids (:copy/block-ids copied-blocks)
-        copied-graph (:copy/graph copied-blocks)
-        input (state/get-input)]
-    (if
-        ;; Internal blocks by either copy or cut blocks
-        (and
-         (= copied-graph (state/get-current-repo))
-         (or (seq copied-block-ids)
-             (seq (:copy/full-blocks copied-blocks)))
-         text
-         ;; not copied from the external clipboard
-         (= (string/replace (string/trim text) "\r" "")
-            (string/replace (string/trim (or (:copy/content copied-blocks) "")) "\r" "")))
-      (do
-        (util/stop e)
-        (let [blocks (or
-                      (:copy/full-blocks copied-blocks)
-                      (get-all-blocks-by-ids (state/get-current-repo) copied-block-ids))]
-          (when (seq blocks)
-            (state/set-copied-full-blocks! blocks)
-            (paste-blocks blocks {}))))
-
-      (cond
-        (and (gp-util/url? text)
-             (not (string/blank? (util/get-selected-text))))
-        (do
-          (util/stop e)
-          (html-link-format! text))
-
-        (and (text/block-ref? text)
-             (wrapped-by? input "((" "))"))
-        (do
-          (util/stop e)
-          (commands/simple-insert! (state/get-edit-input-id) (text/get-block-ref text) nil))
-
-        :else
-        ;; from external
-        (let [format (or (db/get-page-format (state/get-current-page)) :markdown)
-              text (or (when-not (string/blank? html)
-                         (html-parser/convert format html))
-                       text)]
-          (util/stop e)
-          (match [format
-                  (nil? (util/safe-re-find #"(?m)^\s*(?:[-+*]|#+)\s+" text))
-                  (nil? (util/safe-re-find #"(?m)^\s*\*+\s+" text))
-                  (nil? (util/safe-re-find #"(?:\r?\n){2,}" text))]
-            [:markdown false _ _]
-            (paste-text-parseable format text)
-
-            [:org _ false _]
-            (paste-text-parseable format text)
-
-            [:markdown true _ false]
-            (paste-segmented-text format text)
-
-            [:markdown true _ true]
-            (commands/simple-insert! (state/get-edit-input-id) text nil)
-
-            [:org _ true false]
-            (paste-segmented-text format text)
-
-            [:org _ true true]
-            (commands/simple-insert! (state/get-edit-input-id) text nil)))))))
-
-(defn paste-text-in-one-block-at-point
-  []
-  (utils/getClipText
-   (fn [clipboard-data]
-     (when-let [_ (state/get-input)]
-       (let [data (or (when (gp-util/url? clipboard-data)
-                        (wrap-macro-url clipboard-data))
-                      clipboard-data)]
-         (insert data true))))
-   (fn [error]
-     (js/console.error error))))
-
-(defn- paste-text-or-blocks-aux
-  [input e text html]
-  (if (or (thingatpt/markdown-src-at-point input)
-          (thingatpt/org-admonition&src-at-point input))
-    (when-not (mobile-util/native-ios?)
-      (util/stop e)
-      (paste-text-in-one-block-at-point))
-    (paste-copied-blocks-or-text text e html)))
-
-(defn editor-on-paste!
-  ([id]
-   (editor-on-paste! id false))
-  ([id raw-paste?]
-   (fn [e]
-     (state/set-state! :editor/on-paste? true)
-     (let [input (state/get-input)]
-       (if raw-paste?
-        (utils/getClipText
-         (fn [clipboard-data]
-           (when-let [_ (state/get-input)]
-             (let [text (or (when (gp-util/url? clipboard-data)
-                              (wrap-macro-url clipboard-data))
-                            clipboard-data)]
-               (paste-text-or-blocks-aux input e text nil))))
-         (fn [error]
-           (js/console.error error)))
-        (let [clipboard-data (gobj/get e "clipboardData")
-              html (when-not raw-paste? (.getData clipboard-data "text/html"))
-              edit-block (state/get-edit-block)
-              format (or (:block/format edit-block) :markdown)
-              text (.getData clipboard-data "text")
-              text (or (when-not (string/blank? html)
-                         (html-parser/convert format html))
-                       text)]
-          (if-not (string/blank? text)
-            (paste-text-or-blocks-aux input e text html)
-            (when id
-              (let [_handled
-                    (let [clipboard-data (gobj/get e "clipboardData")
-                          files (.-files clipboard-data)]
-                      (when-let [file (first files)]
-                        (when-let [block (state/get-edit-block)]
-                          (upload-asset id #js[file] (:block/format block) *asset-uploading? true))))]
-                (util/stop e))))))))))
-
 (defn- cut-blocks-and-clear-selections!
   [copy?]
   (cut-selection-blocks copy?)

+ 194 - 0
src/main/frontend/handler/paste.cljs

@@ -0,0 +1,194 @@
+(ns frontend.handler.paste
+  (:require [frontend.state :as state]
+            [frontend.db :as db]
+            [frontend.format.block :as block]
+            [logseq.graph-parser.util :as gp-util]
+            [logseq.graph-parser.mldoc :as gp-mldoc]
+            [logseq.graph-parser.block :as gp-block]
+            [clojure.string :as string]
+            [frontend.util :as util]
+            [frontend.handler.editor :as editor-handler]
+            [frontend.extensions.html-parser :as html-parser]
+            [goog.object :as gobj]
+            [frontend.mobile.util :as mobile-util]
+            [frontend.util.thingatpt :as thingatpt]
+            ["/frontend/utils" :as utils]
+            [frontend.commands :as commands]
+            [cljs.core.match :refer [match]]
+            [logseq.graph-parser.text :as text]
+            [frontend.handler.notification :as notification]
+            [frontend.util.text :as text-util]
+            [frontend.format.mldoc :as mldoc]))
+
+(defn- paste-text-parseable
+  [format text]
+  (when-let [editing-block (state/get-edit-block)]
+    (let [page-id (:db/id (:block/page editing-block))
+          blocks (block/extract-blocks
+                  (mldoc/->edn text (gp-mldoc/default-config format)) text true format)
+          blocks' (gp-block/with-parent-and-left page-id blocks)]
+      (editor-handler/paste-blocks blocks' {}))))
+
+(defn- paste-segmented-text
+  [format text]
+  (let [paragraphs (string/split text #"(?:\r?\n){2,}")
+        updated-paragraphs
+        (string/join "\n"
+                     (mapv (fn [p] (->> (string/trim p)
+                                        ((fn [p]
+                                           (if (util/safe-re-find (if (= format :org)
+                                                                    #"\s*\*+\s+"
+                                                                    #"\s*-\s+") p)
+                                             p
+                                             (str (if (= format :org) "* " "- ") p))))))
+                           paragraphs))]
+    (paste-text-parseable format updated-paragraphs)))
+
+(defn- get-all-blocks-by-ids
+  [repo ids]
+  (loop [ids ids
+         result []]
+    (if (seq ids)
+      (let [blocks (db/get-block-and-children repo (first ids))
+            result (vec (concat result blocks))]
+        (recur (remove (set (map :block/uuid result)) (rest ids)) result))
+      result)))
+
+(defn- wrap-macro-url
+  [url]
+  (cond
+    (boolean (text-util/get-matched-video url))
+    (util/format "{{video %s}}" url)
+
+    (string/includes? url "twitter.com")
+    (util/format "{{twitter %s}}" url)
+
+    :else
+    (do
+      (notification/show! (util/format "No macro is available for %s" url) :warning)
+      nil)))
+
+(defn- paste-copied-blocks-or-text
+  [text e html]
+  (let [copied-blocks (state/get-copied-blocks)
+        copied-block-ids (:copy/block-ids copied-blocks)
+        copied-graph (:copy/graph copied-blocks)
+        input (state/get-input)]
+    (if
+        ;; Internal blocks by either copy or cut blocks
+        (and
+         (= copied-graph (state/get-current-repo))
+         (or (seq copied-block-ids)
+             (seq (:copy/full-blocks copied-blocks)))
+         text
+         ;; not copied from the external clipboard
+         (= (string/replace (string/trim text) "\r" "")
+            (string/replace (string/trim (or (:copy/content copied-blocks) "")) "\r" "")))
+      (do
+        (util/stop e)
+        (let [blocks (or
+                      (:copy/full-blocks copied-blocks)
+                      (get-all-blocks-by-ids (state/get-current-repo) copied-block-ids))]
+          (when (seq blocks)
+            (state/set-copied-full-blocks! blocks)
+            (editor-handler/paste-blocks blocks {}))))
+
+      (cond
+        (and (gp-util/url? text)
+             (not (string/blank? (util/get-selected-text))))
+        (do
+          (util/stop e)
+          (editor-handler/html-link-format! text))
+
+        (and (text/block-ref? text)
+             (editor-handler/wrapped-by? input "((" "))"))
+        (do
+          (util/stop e)
+          (commands/simple-insert! (state/get-edit-input-id) (text/get-block-ref text) nil))
+
+        :else
+        ;; from external
+        (let [format (or (db/get-page-format (state/get-current-page)) :markdown)
+              text (or (when-not (string/blank? html)
+                         (html-parser/convert format html))
+                       text)]
+          (util/stop e)
+          (match [format
+                  (nil? (util/safe-re-find #"(?m)^\s*(?:[-+*]|#+)\s+" text))
+                  (nil? (util/safe-re-find #"(?m)^\s*\*+\s+" text))
+                  (nil? (util/safe-re-find #"(?:\r?\n){2,}" text))]
+            [:markdown false _ _]
+            (paste-text-parseable format text)
+
+            [:org _ false _]
+            (paste-text-parseable format text)
+
+            [:markdown true _ false]
+            (paste-segmented-text format text)
+
+            [:markdown true _ true]
+            (commands/simple-insert! (state/get-edit-input-id) text nil)
+
+            [:org _ true false]
+            (paste-segmented-text format text)
+
+            [:org _ true true]
+            (commands/simple-insert! (state/get-edit-input-id) text nil)))))))
+
+(defn paste-text-in-one-block-at-point
+  []
+  (utils/getClipText
+   (fn [clipboard-data]
+     (when-let [_ (state/get-input)]
+       (let [data (or (when (gp-util/url? clipboard-data)
+                        (wrap-macro-url clipboard-data))
+                      clipboard-data)]
+         (editor-handler/insert data true))))
+   (fn [error]
+     (js/console.error error))))
+
+(defn- paste-text-or-blocks-aux
+  [input e text html]
+  (if (or (thingatpt/markdown-src-at-point input)
+          (thingatpt/org-admonition&src-at-point input))
+    (when-not (mobile-util/native-ios?)
+      (util/stop e)
+      (paste-text-in-one-block-at-point))
+    (paste-copied-blocks-or-text text e html)))
+
+(defn editor-on-paste!
+  ([id]
+   (editor-on-paste! id false))
+  ([id raw-paste?]
+   (fn [e]
+     (state/set-state! :editor/on-paste? true)
+     (let [input (state/get-input)]
+       (if raw-paste?
+        (utils/getClipText
+         (fn [clipboard-data]
+           (when-let [_ (state/get-input)]
+             (let [text (or (when (gp-util/url? clipboard-data)
+                              (wrap-macro-url clipboard-data))
+                            clipboard-data)]
+               (paste-text-or-blocks-aux input e text nil))))
+         (fn [error]
+           (js/console.error error)))
+        (let [clipboard-data (gobj/get e "clipboardData")
+              html (when-not raw-paste? (.getData clipboard-data "text/html"))
+              edit-block (state/get-edit-block)
+              format (or (:block/format edit-block) :markdown)
+              text (.getData clipboard-data "text")
+              text (or (when-not (string/blank? html)
+                         (html-parser/convert format html))
+                       text)]
+          (if-not (string/blank? text)
+            (paste-text-or-blocks-aux input e text html)
+            (when id
+              (let [_handled
+                    (let [clipboard-data (gobj/get e "clipboardData")
+                          files (.-files clipboard-data)]
+                      (when-let [file (first files)]
+                        (when-let [block (state/get-edit-block)]
+                          (editor-handler/upload-asset id #js[file] (:block/format block)
+                                                       editor-handler/*asset-uploading? true))))]
+                (util/stop e))))))))))

+ 2 - 1
src/main/frontend/modules/shortcut/config.cljs

@@ -4,6 +4,7 @@
             [frontend.extensions.pdf.utils :as pdf-utils]
             [frontend.handler.config :as config-handler]
             [frontend.handler.editor :as editor-handler]
+            [frontend.handler.paste :as paste-handler]
             [frontend.handler.history :as history]
             [frontend.handler.page :as page-handler]
             [frontend.handler.route :as route-handler]
@@ -149,7 +150,7 @@
                        :fn      editor-handler/copy-current-block-embed}
 
    :editor/paste-text-in-one-block-at-point {:binding "mod+shift+v"
-                                             :fn      (fn [_state e] ((editor-handler/editor-on-paste! nil true) e))}
+                                             :fn      (fn [_state e] ((paste-handler/editor-on-paste! nil true) e))}
 
    :editor/insert-youtube-timestamp         {:binding "mod+shift+y"
                                              :fn      commands/insert-youtube-timestamp}