|
@@ -282,8 +282,8 @@
|
|
|
(defn- remove-non-existed-refs!
|
|
(defn- remove-non-existed-refs!
|
|
|
[refs]
|
|
[refs]
|
|
|
(remove (fn [x] (and (vector? x)
|
|
(remove (fn [x] (and (vector? x)
|
|
|
- (= :block/uuid (first x))
|
|
|
|
|
- (nil? (db/entity x)))) refs))
|
|
|
|
|
|
|
+ (= :block/uuid (first x))
|
|
|
|
|
+ (nil? (db/entity x)))) refs))
|
|
|
|
|
|
|
|
(defn- wrap-parse-block
|
|
(defn- wrap-parse-block
|
|
|
[{:block/keys [content format parent left page uuid pre-block?] :as block}]
|
|
[{:block/keys [content format parent left page uuid pre-block?] :as block}]
|
|
@@ -581,7 +581,6 @@
|
|
|
value)]
|
|
value)]
|
|
|
[properties value]))
|
|
[properties value]))
|
|
|
|
|
|
|
|
-
|
|
|
|
|
(defn insert-new-block!
|
|
(defn insert-new-block!
|
|
|
([state]
|
|
([state]
|
|
|
(insert-new-block! state nil))
|
|
(insert-new-block! state nil))
|
|
@@ -725,8 +724,8 @@
|
|
|
format (or (db/get-page-format (state/get-current-page))
|
|
format (or (db/get-page-format (state/get-current-page))
|
|
|
(state/get-preferred-format))
|
|
(state/get-preferred-format))
|
|
|
cond-fn (fn [marker] (or (and (= :markdown format)
|
|
cond-fn (fn [marker] (or (and (= :markdown format)
|
|
|
- (util/safe-re-find (re-pattern (str "#*\\s*" marker)) content))
|
|
|
|
|
- (util/starts-with? content "TODO")))
|
|
|
|
|
|
|
+ (util/safe-re-find (re-pattern (str "#*\\s*" marker)) content))
|
|
|
|
|
+ (util/starts-with? content "TODO")))
|
|
|
[new-content marker] (cond
|
|
[new-content marker] (cond
|
|
|
(cond-fn "TODO")
|
|
(cond-fn "TODO")
|
|
|
[(string/replace-first content "TODO" "DOING") "DOING"]
|
|
[(string/replace-first content "TODO" "DOING") "DOING"]
|
|
@@ -749,7 +748,6 @@
|
|
|
(state/set-edit-content! edit-input-id new-content)
|
|
(state/set-edit-content! edit-input-id new-content)
|
|
|
(util/set-caret-pos! current-input new-pos)))))
|
|
(util/set-caret-pos! current-input new-pos)))))
|
|
|
|
|
|
|
|
-
|
|
|
|
|
(defn set-marker
|
|
(defn set-marker
|
|
|
[{:block/keys [uuid marker content format properties] :as block} new-marker]
|
|
[{:block/keys [uuid marker content format properties] :as block} new-marker]
|
|
|
(let [new-content (-> (string/replace-first content marker new-marker)
|
|
(let [new-content (-> (string/replace-first content marker new-marker)
|
|
@@ -1164,9 +1162,8 @@
|
|
|
(edit-block! {:block/uuid block-id} :max nil block-id))
|
|
(edit-block! {:block/uuid block-id} :max nil block-id))
|
|
|
(let [page-id (some-> (db/entity [:block/uuid block-id])
|
|
(let [page-id (some-> (db/entity [:block/uuid block-id])
|
|
|
:block/page
|
|
:block/page
|
|
|
- :db/id
|
|
|
|
|
|
|
+ :db/id)]
|
|
|
|
|
|
|
|
- )]
|
|
|
|
|
(when-let [page-name (:block/name (db/entity page-id))]
|
|
(when-let [page-name (:block/name (db/entity page-id))]
|
|
|
(route-handler/redirect! {:to :page
|
|
(route-handler/redirect! {:to :page
|
|
|
:path-params {:name page-name}})
|
|
:path-params {:name page-name}})
|
|
@@ -1908,6 +1905,14 @@
|
|
|
(state/set-editor-show-block-search! false)
|
|
(state/set-editor-show-block-search! false)
|
|
|
(util/cursor-move-forward input 2)))
|
|
(util/cursor-move-forward input 2)))
|
|
|
|
|
|
|
|
|
|
+(defn- get-block-tree-insert-pos-after-target
|
|
|
|
|
+ "return [target-block sibling? delete-editing-block? editing-block]"
|
|
|
|
|
+ ([target-block-id sibling?]
|
|
|
|
|
+ (get-block-tree-insert-pos-after-target target-block-id sibling? nil))
|
|
|
|
|
+ ([target-block-id sibling? editing-block]
|
|
|
|
|
+ (when-let [target-block (db/pull target-block-id)]
|
|
|
|
|
+ [target-block sibling? false (or editing-block target-block)])))
|
|
|
|
|
+
|
|
|
(defn- get-block-tree-insert-pos-at-point
|
|
(defn- get-block-tree-insert-pos-at-point
|
|
|
"return [target-block sibling? delete-editing-block? editing-block]"
|
|
"return [target-block sibling? delete-editing-block? editing-block]"
|
|
|
[]
|
|
[]
|
|
@@ -1988,8 +1993,8 @@
|
|
|
:block/page (select-keys page [:db/id])
|
|
:block/page (select-keys page [:db/id])
|
|
|
:block/format format
|
|
:block/format format
|
|
|
:block/properties (apply dissoc (:block/properties block)
|
|
:block/properties (apply dissoc (:block/properties block)
|
|
|
- (concat [:id :custom_id :custom-id]
|
|
|
|
|
- exclude-properties))
|
|
|
|
|
|
|
+ (concat [:id :custom_id :custom-id]
|
|
|
|
|
+ exclude-properties))
|
|
|
:block/meta (dissoc (:block/meta block) :start-pos :end-pos)
|
|
:block/meta (dissoc (:block/meta block) :start-pos :end-pos)
|
|
|
:block/content new-content
|
|
:block/content new-content
|
|
|
:block/title new-title
|
|
:block/title new-title
|
|
@@ -1999,14 +2004,17 @@
|
|
|
(assoc m :block/file (select-keys file [:db/id]))
|
|
(assoc m :block/file (select-keys file [:db/id]))
|
|
|
m)))))
|
|
m)))))
|
|
|
|
|
|
|
|
-(defn- paste-block-tree-at-point
|
|
|
|
|
- ([tree exclude-properties] (paste-block-tree-at-point tree exclude-properties nil))
|
|
|
|
|
|
|
+(defn- paste-block-vec-tree-at-target
|
|
|
|
|
+ ([tree exclude-properties]
|
|
|
|
|
+ (paste-block-vec-tree-at-target tree exclude-properties nil nil))
|
|
|
([tree exclude-properties content-update-fn]
|
|
([tree exclude-properties content-update-fn]
|
|
|
|
|
+ (paste-block-vec-tree-at-target tree exclude-properties content-update-fn nil))
|
|
|
|
|
+ ([tree exclude-properties content-update-fn get-pos-fn]
|
|
|
(let [repo (state/get-current-repo)
|
|
(let [repo (state/get-current-repo)
|
|
|
page (:block/page (db/entity (:db/id (state/get-edit-block))))
|
|
page (:block/page (db/entity (:db/id (state/get-edit-block))))
|
|
|
file (:block/file page)]
|
|
file (:block/file page)]
|
|
|
(when-let [[target-block sibling? delete-editing-block? editing-block]
|
|
(when-let [[target-block sibling? delete-editing-block? editing-block]
|
|
|
- (get-block-tree-insert-pos-at-point)]
|
|
|
|
|
|
|
+ ((or get-pos-fn get-block-tree-insert-pos-at-point))]
|
|
|
(let [target-block (outliner-core/block target-block)
|
|
(let [target-block (outliner-core/block target-block)
|
|
|
editing-block (outliner-core/block editing-block)
|
|
editing-block (outliner-core/block editing-block)
|
|
|
format (or (:block/format target-block) (state/get-preferred-format))
|
|
format (or (:block/format target-block) (state/get-preferred-format))
|
|
@@ -2033,6 +2041,57 @@
|
|
|
(db/refresh! repo {:key :block/insert :data new-blocks})
|
|
(db/refresh! repo {:key :block/insert :data new-blocks})
|
|
|
(last metadata-replaced-blocks))))))
|
|
(last metadata-replaced-blocks))))))
|
|
|
|
|
|
|
|
|
|
+(defn- tree->vec-tree
|
|
|
|
|
+ "tree:
|
|
|
|
|
+ [
|
|
|
|
|
+ {
|
|
|
|
|
+ :content 'this is a block',
|
|
|
|
|
+ :props {\"key\" \"value\" \"key2\" \"value2\"},
|
|
|
|
|
+ :children [
|
|
|
|
|
+ { :content 'this is child block' }
|
|
|
|
|
+ ]
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ :content 'this is sibling block'
|
|
|
|
|
+ }
|
|
|
|
|
+ ]"
|
|
|
|
|
+ [tree]
|
|
|
|
|
+ (into []
|
|
|
|
|
+ (mapcat
|
|
|
|
|
+ (fn [e]
|
|
|
|
|
+ (let [e* (select-keys e [:content :props])]
|
|
|
|
|
+ (if-let [children (:children e)]
|
|
|
|
|
+ [e* (tree->vec-tree (:children e))]
|
|
|
|
|
+ [e*])))
|
|
|
|
|
+ tree)))
|
|
|
|
|
+
|
|
|
|
|
+(defn- vec-tree->vec-block-tree
|
|
|
|
|
+ [tree format]
|
|
|
|
|
+ (let [loc (zip/vector-zip tree)]
|
|
|
|
|
+ (loop [loc loc]
|
|
|
|
|
+ (if (zip/end? loc)
|
|
|
|
|
+ (zip/root loc)
|
|
|
|
|
+ (let [node (zip/node loc)]
|
|
|
|
|
+ (if (vector? node)
|
|
|
|
|
+ (recur (zip/next loc))
|
|
|
|
|
+ (let [content (:content node)
|
|
|
|
|
+ props (into [] (:props node))
|
|
|
|
|
+ content* (str "- "
|
|
|
|
|
+ (property/insert-properties format content props))
|
|
|
|
|
+ ast (mldoc/->edn content* (mldoc/default-config format))
|
|
|
|
|
+ blocks (block/extract-blocks ast content* true format)
|
|
|
|
|
+ fst-block (first blocks)]
|
|
|
|
|
+ (assert fst-block "fst-block shouldn't be nil")
|
|
|
|
|
+ (recur (zip/next (zip/replace loc fst-block))))))))))
|
|
|
|
|
+
|
|
|
|
|
+(defn paste-block-tree-after-target
|
|
|
|
|
+ [target-block-id sibling? tree format]
|
|
|
|
|
+ (let [vec-tree (tree->vec-tree tree)
|
|
|
|
|
+ block-tree (vec-tree->vec-block-tree vec-tree format)]
|
|
|
|
|
+ (paste-block-vec-tree-at-target
|
|
|
|
|
+ block-tree [] nil
|
|
|
|
|
+ #(get-block-tree-insert-pos-after-target target-block-id sibling?))))
|
|
|
|
|
+
|
|
|
(defn template-on-chosen-handler
|
|
(defn template-on-chosen-handler
|
|
|
[_input id _q format _edit-block _edit-content]
|
|
[_input id _q format _edit-block _edit-content]
|
|
|
(fn [[_template db-id] _click?]
|
|
(fn [[_template db-id] _click?]
|
|
@@ -2145,8 +2204,8 @@
|
|
|
(defn- select-up-down [direction]
|
|
(defn- select-up-down [direction]
|
|
|
(let [selected (first (state/get-selection-blocks))
|
|
(let [selected (first (state/get-selection-blocks))
|
|
|
f (case direction
|
|
f (case direction
|
|
|
- :up get-prev-block-non-collapsed
|
|
|
|
|
- :down get-next-block-non-collapsed)
|
|
|
|
|
|
|
+ :up get-prev-block-non-collapsed
|
|
|
|
|
+ :down get-next-block-non-collapsed)
|
|
|
sibling-block (f selected)]
|
|
sibling-block (f selected)]
|
|
|
(when (and sibling-block (dom/attr sibling-block "blockid"))
|
|
(when (and sibling-block (dom/attr sibling-block "blockid"))
|
|
|
(clear-selection! nil)
|
|
(clear-selection! nil)
|
|
@@ -2159,8 +2218,8 @@
|
|
|
line-pos (util/get-first-or-last-line-pos input)
|
|
line-pos (util/get-first-or-last-line-pos input)
|
|
|
repo (state/get-current-repo)
|
|
repo (state/get-current-repo)
|
|
|
f (case direction
|
|
f (case direction
|
|
|
- :up get-prev-block-non-collapsed
|
|
|
|
|
- :down get-next-block-non-collapsed)
|
|
|
|
|
|
|
+ :up get-prev-block-non-collapsed
|
|
|
|
|
+ :down get-next-block-non-collapsed)
|
|
|
sibling-block (f (gdom/getElement (state/get-editing-block-dom-id)))
|
|
sibling-block (f (gdom/getElement (state/get-editing-block-dom-id)))
|
|
|
{:block/keys [uuid content format]} (state/get-edit-block)]
|
|
{:block/keys [uuid content format]} (state/get-edit-block)]
|
|
|
(when sibling-block
|
|
(when sibling-block
|
|
@@ -2385,7 +2444,7 @@
|
|
|
(let [repo (state/get-current-repo)]
|
|
(let [repo (state/get-current-repo)]
|
|
|
(db/refresh! repo
|
|
(db/refresh! repo
|
|
|
{:key :block/change :data [(:data current-node)]}))))
|
|
{:key :block/change :data [(:data current-node)]}))))
|
|
|
- (state/set-editor-op! :nil)))
|
|
|
|
|
|
|
+ (state/set-editor-op! :nil)))
|
|
|
|
|
|
|
|
(defn keydown-tab-handler
|
|
(defn keydown-tab-handler
|
|
|
[direction]
|
|
[direction]
|
|
@@ -2563,7 +2622,6 @@
|
|
|
timeout)))
|
|
timeout)))
|
|
|
(edit-box-on-change! e block id))))
|
|
(edit-box-on-change! e block id))))
|
|
|
|
|
|
|
|
-
|
|
|
|
|
(defn- get-current-page-format
|
|
(defn- get-current-page-format
|
|
|
[]
|
|
[]
|
|
|
(when-let [page (state/get-current-page)]
|
|
(when-let [page (state/get-current-page)]
|
|
@@ -2579,7 +2637,7 @@
|
|
|
tree* (->> tree
|
|
tree* (->> tree
|
|
|
(mapv #(assoc % :level (- (:block/level %) prefix-level)))
|
|
(mapv #(assoc % :level (- (:block/level %) prefix-level)))
|
|
|
(blocks-vec->tree))]
|
|
(blocks-vec->tree))]
|
|
|
- (paste-block-tree-at-point tree* [])))
|
|
|
|
|
|
|
+ (paste-block-vec-tree-at-target tree* [])))
|
|
|
|
|
|
|
|
(defn- paste-segmented-text
|
|
(defn- paste-segmented-text
|
|
|
[format text]
|
|
[format text]
|
|
@@ -2589,8 +2647,8 @@
|
|
|
(mapv (fn [p] (->> (string/trim p)
|
|
(mapv (fn [p] (->> (string/trim p)
|
|
|
((fn [p]
|
|
((fn [p]
|
|
|
(if (util/safe-re-find (if (= format :org)
|
|
(if (util/safe-re-find (if (= format :org)
|
|
|
- #"\s*\*+\s+"
|
|
|
|
|
- #"\s*-\s+") p)
|
|
|
|
|
|
|
+ #"\s*\*+\s+"
|
|
|
|
|
+ #"\s*-\s+") p)
|
|
|
p
|
|
p
|
|
|
(str (if (= format :org) "* " "- ") p))))))
|
|
(str (if (= format :org) "* " "- ") p))))))
|
|
|
paragraphs))]
|
|
paragraphs))]
|
|
@@ -2610,7 +2668,7 @@
|
|
|
(= (string/trim text) (string/trim (:copy/content copied-blocks))))
|
|
(= (string/trim text) (string/trim (:copy/content copied-blocks))))
|
|
|
(do
|
|
(do
|
|
|
;; copy from logseq internally
|
|
;; copy from logseq internally
|
|
|
- (paste-block-tree-at-point copied-block-tree [])
|
|
|
|
|
|
|
+ (paste-block-vec-tree-at-target copied-block-tree [])
|
|
|
(util/stop e))
|
|
(util/stop e))
|
|
|
|
|
|
|
|
(do
|
|
(do
|
|
@@ -2649,35 +2707,35 @@
|
|
|
[id]
|
|
[id]
|
|
|
(fn [e]
|
|
(fn [e]
|
|
|
(if-let [handled
|
|
(if-let [handled
|
|
|
- (let [pick-one-allowed-item
|
|
|
|
|
- (fn [items]
|
|
|
|
|
- (if (util/electron?)
|
|
|
|
|
- (let [existed-file-path (js/window.apis.getFilePathFromClipboard)
|
|
|
|
|
- existed-file-path (if (and
|
|
|
|
|
- (string? existed-file-path)
|
|
|
|
|
- (not util/mac?)
|
|
|
|
|
- (not util/win32?)) ; FIXME: linux
|
|
|
|
|
- (when (util/safe-re-find #"^(/[^/ ]*)+/?$" existed-file-path)
|
|
|
|
|
- existed-file-path)
|
|
|
|
|
|
|
+ (let [pick-one-allowed-item
|
|
|
|
|
+ (fn [items]
|
|
|
|
|
+ (if (util/electron?)
|
|
|
|
|
+ (let [existed-file-path (js/window.apis.getFilePathFromClipboard)
|
|
|
|
|
+ existed-file-path (if (and
|
|
|
|
|
+ (string? existed-file-path)
|
|
|
|
|
+ (not util/mac?)
|
|
|
|
|
+ (not util/win32?)) ; FIXME: linux
|
|
|
|
|
+ (when (util/safe-re-find #"^(/[^/ ]*)+/?$" existed-file-path)
|
|
|
existed-file-path)
|
|
existed-file-path)
|
|
|
- has-file-path? (not (string/blank? existed-file-path))
|
|
|
|
|
- has-image? (js/window.apis.isClipboardHasImage)]
|
|
|
|
|
- (if (or has-image? has-file-path?)
|
|
|
|
|
- [:asset (js/File. #js[] (if has-file-path? existed-file-path "image.png"))]))
|
|
|
|
|
-
|
|
|
|
|
- (when (and items (.-length items))
|
|
|
|
|
- (let [files (. (js/Array.from items) (filter #(= (.-kind %) "file")))
|
|
|
|
|
- it (gobj/get files 0) ;;; TODO: support multiple files
|
|
|
|
|
- mime (and it (.-type it))]
|
|
|
|
|
- (cond
|
|
|
|
|
- (contains? #{"image/jpeg" "image/png" "image/jpg" "image/gif"} mime) [:asset (. it getAsFile)])))))
|
|
|
|
|
- clipboard-data (gobj/get e "clipboardData")
|
|
|
|
|
- items (or (.-items clipboard-data)
|
|
|
|
|
- (.-files clipboard-data))
|
|
|
|
|
- picked (pick-one-allowed-item items)]
|
|
|
|
|
- (if (get picked 1)
|
|
|
|
|
- (match picked
|
|
|
|
|
- [:asset file] (set-asset-pending-file file))))]
|
|
|
|
|
|
|
+ existed-file-path)
|
|
|
|
|
+ has-file-path? (not (string/blank? existed-file-path))
|
|
|
|
|
+ has-image? (js/window.apis.isClipboardHasImage)]
|
|
|
|
|
+ (if (or has-image? has-file-path?)
|
|
|
|
|
+ [:asset (js/File. #js[] (if has-file-path? existed-file-path "image.png"))]))
|
|
|
|
|
+
|
|
|
|
|
+ (when (and items (.-length items))
|
|
|
|
|
+ (let [files (. (js/Array.from items) (filter #(= (.-kind %) "file")))
|
|
|
|
|
+ it (gobj/get files 0) ;;; TODO: support multiple files
|
|
|
|
|
+ mime (and it (.-type it))]
|
|
|
|
|
+ (cond
|
|
|
|
|
+ (contains? #{"image/jpeg" "image/png" "image/jpg" "image/gif"} mime) [:asset (. it getAsFile)])))))
|
|
|
|
|
+ clipboard-data (gobj/get e "clipboardData")
|
|
|
|
|
+ items (or (.-items clipboard-data)
|
|
|
|
|
+ (.-files clipboard-data))
|
|
|
|
|
+ picked (pick-one-allowed-item items)]
|
|
|
|
|
+ (if (get picked 1)
|
|
|
|
|
+ (match picked
|
|
|
|
|
+ [:asset file] (set-asset-pending-file file))))]
|
|
|
(util/stop e)
|
|
(util/stop e)
|
|
|
(paste-text (.getData (gobj/get e "clipboardData") "text") e))))
|
|
(paste-text (.getData (gobj/get e "clipboardData") "text") e))))
|
|
|
|
|
|
|
@@ -2736,7 +2794,6 @@
|
|
|
:else
|
|
:else
|
|
|
(js/document.execCommand "copy"))))
|
|
(js/document.execCommand "copy"))))
|
|
|
|
|
|
|
|
-
|
|
|
|
|
(defn shortcut-cut
|
|
(defn shortcut-cut
|
|
|
"shortcut cut action:
|
|
"shortcut cut action:
|
|
|
* when in selection mode, cut selected blocks
|
|
* when in selection mode, cut selected blocks
|
|
@@ -2907,15 +2964,14 @@
|
|
|
(if (> level max-level)
|
|
(if (> level max-level)
|
|
|
nil
|
|
nil
|
|
|
(let [blocks-to-expand (->> blocks-with-level
|
|
(let [blocks-to-expand (->> blocks-with-level
|
|
|
- (filter (fn [b] (= (:block/level b) level)))
|
|
|
|
|
- (filter (fn [{:block/keys [properties]}]
|
|
|
|
|
- (contains? properties :collapsed))))]
|
|
|
|
|
|
|
+ (filter (fn [b] (= (:block/level b) level)))
|
|
|
|
|
+ (filter (fn [{:block/keys [properties]}]
|
|
|
|
|
+ (contains? properties :collapsed))))]
|
|
|
(if (empty? blocks-to-expand)
|
|
(if (empty? blocks-to-expand)
|
|
|
(recur (inc level))
|
|
(recur (inc level))
|
|
|
(doseq [{:block/keys [uuid]} blocks-to-expand]
|
|
(doseq [{:block/keys [uuid]} blocks-to-expand]
|
|
|
(expand-block! uuid)))))))))
|
|
(expand-block! uuid)))))))))
|
|
|
|
|
|
|
|
-
|
|
|
|
|
(defn collapse!
|
|
(defn collapse!
|
|
|
[]
|
|
[]
|
|
|
(cond
|
|
(cond
|