mirror of https://github.com/logseq/logseq
feat(outliner): sync to file
parent
2f790d3a34
commit
3b8a825b24
|
@ -281,6 +281,12 @@
|
||||||
@conn)
|
@conn)
|
||||||
(flatten))))
|
(flatten))))
|
||||||
|
|
||||||
|
(defn get-file-by-path
|
||||||
|
[file-path]
|
||||||
|
(when-let [repo (state/get-current-repo)]
|
||||||
|
(when-let [conn (conn/get-files-conn repo)]
|
||||||
|
(d/pull @conn '[*] [:file/path file-path]))))
|
||||||
|
|
||||||
(defn get-custom-css
|
(defn get-custom-css
|
||||||
[]
|
[]
|
||||||
(when-let [repo (state/get-current-repo)]
|
(when-let [repo (state/get-current-repo)]
|
||||||
|
@ -638,6 +644,18 @@
|
||||||
block-uuid)
|
block-uuid)
|
||||||
sort-by-left)))
|
sort-by-left)))
|
||||||
|
|
||||||
|
(defn get-blocks-by-page
|
||||||
|
[id-or-lookup-ref]
|
||||||
|
(when-let [conn (conn/get-conn)]
|
||||||
|
(->
|
||||||
|
(d/q
|
||||||
|
'[:find (pull ?block [*])
|
||||||
|
:in $ ?page
|
||||||
|
:where
|
||||||
|
[?block :block/page ?page]]
|
||||||
|
conn id-or-lookup-ref)
|
||||||
|
flatten)))
|
||||||
|
|
||||||
(defn get-block-children
|
(defn get-block-children
|
||||||
"Including nested children."
|
"Including nested children."
|
||||||
[repo block-uuid]
|
[repo block-uuid]
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
(:require [datascript.core :as d]
|
(:require [datascript.core :as d]
|
||||||
[frontend.db.react :as react]
|
[frontend.db.react :as react]
|
||||||
[frontend.util :as util]
|
[frontend.util :as util]
|
||||||
[frontend.debug :as debug]))
|
[frontend.debug :as debug]
|
||||||
|
[frontend.db.utils :as db-utils]))
|
||||||
|
|
||||||
(defn get-by-id
|
(defn get-by-id
|
||||||
[conn id]
|
[conn id]
|
||||||
|
@ -29,8 +30,10 @@
|
||||||
(defn save-block
|
(defn save-block
|
||||||
[conn block-m]
|
[conn block-m]
|
||||||
(let [tx (-> (dissoc block-m :block/children)
|
(let [tx (-> (dissoc block-m :block/children)
|
||||||
(util/remove-nils))]
|
(util/remove-nils))
|
||||||
(d/transact! conn [tx])))
|
lookup-ref (:block/uuid block-m)]
|
||||||
|
(d/transact! conn [tx])
|
||||||
|
(db-utils/pull [:block/uuid lookup-ref])))
|
||||||
|
|
||||||
(defn del-block
|
(defn del-block
|
||||||
[conn id-or-look-ref]
|
[conn id-or-look-ref]
|
||||||
|
|
|
@ -12,7 +12,9 @@
|
||||||
[cljs-time.coerce :as tc]
|
[cljs-time.coerce :as tc]
|
||||||
[cljs-time.core :as t]
|
[cljs-time.core :as t]
|
||||||
[frontend.modules.outliner.core :as outliner-core]
|
[frontend.modules.outliner.core :as outliner-core]
|
||||||
[frontend.modules.outliner.tree :as tree]))
|
[frontend.modules.outliner.tree :as tree]
|
||||||
|
[lambdaisland.glogi :as log]
|
||||||
|
[frontend.debug :as debug]))
|
||||||
|
|
||||||
(defn- remove-block-child!
|
(defn- remove-block-child!
|
||||||
[target-block parent-block]
|
[target-block parent-block]
|
||||||
|
@ -367,22 +369,25 @@
|
||||||
2. Sometimes we might need to move a parent block to it's own child.
|
2. Sometimes we might need to move a parent block to it's own child.
|
||||||
"
|
"
|
||||||
[current-block target-block top? nested?]
|
[current-block target-block top? nested?]
|
||||||
(let [[current-node target-node]
|
(if-not (every? map? [current-block target-block])
|
||||||
(mapv outliner-core/block [current-block target-block])]
|
(log/error :dnd/move-block-argument-error
|
||||||
(cond
|
{:current-block current-block :target-block target-block})
|
||||||
top?
|
(let [[current-node target-node]
|
||||||
(let [first-child?
|
(mapv outliner-core/block [current-block target-block])]
|
||||||
(= (tree/-get-parent-id target-node)
|
(cond
|
||||||
(tree/-get-left-id target-node))]
|
top?
|
||||||
(if first-child?
|
(let [first-child?
|
||||||
(let [parent (tree/-get-parent target-node)]
|
(= (tree/-get-parent-id target-node)
|
||||||
(outliner-core/move-subtree current-node parent false))
|
(tree/-get-left-id target-node))]
|
||||||
(outliner-core/move-subtree current-node target-node true)))
|
(if first-child?
|
||||||
nested?
|
(let [parent (tree/-get-parent target-node)]
|
||||||
(outliner-core/move-subtree current-node target-node false)
|
(outliner-core/move-subtree current-node parent false))
|
||||||
|
(outliner-core/move-subtree current-node target-node true)))
|
||||||
|
nested?
|
||||||
|
(outliner-core/move-subtree current-node target-node false)
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(outliner-core/move-subtree current-node target-node true))
|
(outliner-core/move-subtree current-node target-node true))
|
||||||
(let [repo (state/get-current-repo)]
|
(let [repo (state/get-current-repo)]
|
||||||
(db/refresh repo {:key :block/change
|
(db/refresh repo {:key :block/change
|
||||||
:data [(:data current-node) (:data target-node)]}))))
|
:data [(:data current-node) (:data target-node)]})))))
|
||||||
|
|
|
@ -561,7 +561,7 @@
|
||||||
(->
|
(->
|
||||||
(wrap-parse-block block)
|
(wrap-parse-block block)
|
||||||
(outliner-core/block)
|
(outliner-core/block)
|
||||||
(tree/-save))
|
(outliner-core/save-node))
|
||||||
(let [opts {:key :block/change
|
(let [opts {:key :block/change
|
||||||
:data [block]}]
|
:data [block]}]
|
||||||
(db/refresh repo opts))))
|
(db/refresh repo opts))))
|
||||||
|
@ -768,7 +768,7 @@
|
||||||
(mapv outliner-core/block [current-block new-block])
|
(mapv outliner-core/block [current-block new-block])
|
||||||
has-children? (seq (tree/-get-children current-node))
|
has-children? (seq (tree/-get-children current-node))
|
||||||
new-is-sibling? (not has-children?)]
|
new-is-sibling? (not has-children?)]
|
||||||
(tree/-save current-node)
|
(outliner-core/save-node current-node)
|
||||||
(outliner-core/insert-node new-node current-node new-is-sibling?)))
|
(outliner-core/insert-node new-node current-node new-is-sibling?)))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
(ns frontend.modules.file.core
|
||||||
|
(:require [frontend.debug :as debug]
|
||||||
|
[clojure.string :as str]
|
||||||
|
[frontend.state :as state]
|
||||||
|
[cljs.core.async :as async]
|
||||||
|
[frontend.db.conn :as conn]
|
||||||
|
[frontend.db.utils :as db-utils]
|
||||||
|
[frontend.db.model :as model]
|
||||||
|
[frontend.modules.outliner.tree :as tree]))
|
||||||
|
|
||||||
|
(defn clip-content
|
||||||
|
[content]
|
||||||
|
(->
|
||||||
|
(str/replace content #"^\n+" "")
|
||||||
|
(str/replace #"^#+" "")
|
||||||
|
(str/replace #"\n+$" "")))
|
||||||
|
|
||||||
|
(defn transform-content
|
||||||
|
[pre-block? content level]
|
||||||
|
(if pre-block?
|
||||||
|
(clip-content content)
|
||||||
|
(let [prefix (->>
|
||||||
|
(repeat level "#")
|
||||||
|
(apply str))
|
||||||
|
new-content (clip-content content)]
|
||||||
|
(str prefix " " new-content))))
|
||||||
|
|
||||||
|
(defn tree->file-content
|
||||||
|
[tree init-level]
|
||||||
|
(loop [block-contents []
|
||||||
|
[f & r] tree
|
||||||
|
level init-level]
|
||||||
|
(if (nil? f)
|
||||||
|
(str/join "\n" block-contents)
|
||||||
|
(let [content (transform-content
|
||||||
|
(:block/pre-block? f) (:block/content f) level)
|
||||||
|
new-content
|
||||||
|
(if-let [children (seq (:block/children f))]
|
||||||
|
[content (tree->file-content children (inc level))]
|
||||||
|
[content])]
|
||||||
|
(recur (into block-contents new-content) r level)))))
|
||||||
|
|
||||||
|
(def markdown-init-level 2)
|
||||||
|
|
||||||
|
(defn push-to-write-chan
|
||||||
|
[files file->content & opts]
|
||||||
|
(let [repo (state/get-current-repo)]
|
||||||
|
(when-let [chan (state/get-file-write-chan)]
|
||||||
|
(let [chan-callback (:chan-callback opts)]
|
||||||
|
(async/put! chan [repo files opts file->content])
|
||||||
|
(when chan-callback
|
||||||
|
(chan-callback))))))
|
||||||
|
|
||||||
|
(defn save-tree
|
||||||
|
[page-block tree]
|
||||||
|
{:pre [(map? page-block)]}
|
||||||
|
(let [new-content (tree->file-content tree markdown-init-level)
|
||||||
|
file-db-id (-> page-block :block/file :db/id)
|
||||||
|
file-path (-> (db-utils/entity file-db-id) :file/path)
|
||||||
|
_ (assert (string? file-path) "File path should satisfy string?")
|
||||||
|
{old-content :file/content :as file} (model/get-file-by-path file-path)
|
||||||
|
files [[file-path new-content]]
|
||||||
|
file->content {file-path old-content}]
|
||||||
|
(push-to-write-chan files file->content)))
|
|
@ -7,12 +7,15 @@
|
||||||
[frontend.modules.outliner.ref :as outliner-ref]
|
[frontend.modules.outliner.ref :as outliner-ref]
|
||||||
[frontend.state :as state]
|
[frontend.state :as state]
|
||||||
[frontend.debug :as debug]
|
[frontend.debug :as debug]
|
||||||
[clojure.set :as set]))
|
[clojure.set :as set]
|
||||||
|
[frontend.modules.outliner.file :as outliner-file]
|
||||||
|
[frontend.util :as util]))
|
||||||
|
|
||||||
(defrecord Block [data])
|
(defrecord Block [data])
|
||||||
|
|
||||||
(defn block
|
(defn block
|
||||||
[m]
|
[m]
|
||||||
|
(assert (map? m) (util/format "block data must be map,got: %s %s" (type m) m))
|
||||||
(->Block m))
|
(->Block m))
|
||||||
|
|
||||||
(defn get-block-by-id
|
(defn get-block-by-id
|
||||||
|
@ -97,9 +100,9 @@
|
||||||
|
|
||||||
(-save [this]
|
(-save [this]
|
||||||
(let [conn (conn/get-conn false)
|
(let [conn (conn/get-conn false)
|
||||||
data (:data this)]
|
data (:data this)
|
||||||
(db-outliner/save-block conn data)
|
new-data (db-outliner/save-block conn data)]
|
||||||
this))
|
(assoc this :data new-data)))
|
||||||
|
|
||||||
(-del [this]
|
(-del [this]
|
||||||
(let [conn (conn/get-conn false)
|
(let [conn (conn/get-conn false)
|
||||||
|
@ -126,44 +129,51 @@
|
||||||
(throw (js/Error. "Number of children and sorted-children are not equal."))))
|
(throw (js/Error. "Number of children and sorted-children are not equal."))))
|
||||||
sorted-children)))))))))
|
sorted-children)))))))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn save-node
|
||||||
|
[node]
|
||||||
|
{:pre [(tree/satisfied-inode? node)]}
|
||||||
|
(let [saved-node (tree/-save node)]
|
||||||
|
(outliner-file/sync-to-file saved-node)))
|
||||||
|
|
||||||
(defn insert-node-as-first-child
|
(defn insert-node-as-first-child
|
||||||
"Insert a node as first child."
|
"Insert a node as first child."
|
||||||
[new-node parent-node]
|
[new-node parent-node]
|
||||||
(:pre [(every? tree/satisfied-inode? [new-node parent-node])])
|
{:pre [(every? tree/satisfied-inode? [new-node parent-node])]}
|
||||||
(let [parent-id (tree/-get-id parent-node)
|
(let [parent-id (tree/-get-id parent-node)
|
||||||
node (-> (tree/-set-left-id new-node parent-id)
|
node (-> (tree/-set-left-id new-node parent-id)
|
||||||
(tree/-set-parent-id parent-id))
|
(tree/-set-parent-id parent-id))
|
||||||
right-node (tree/-get-down parent-node)]
|
right-node (tree/-get-down parent-node)]
|
||||||
(do
|
(do
|
||||||
(if (tree/satisfied-inode? right-node)
|
(if (tree/satisfied-inode? right-node)
|
||||||
(let [new-right-node (tree/-set-left-id right-node (tree/-get-id new-node))]
|
(let [new-right-node (tree/-set-left-id right-node (tree/-get-id new-node))
|
||||||
(tree/-save node)
|
saved-new-node (tree/-save node)]
|
||||||
(tree/-save new-right-node))
|
(tree/-save new-right-node)
|
||||||
(tree/-save node))
|
saved-new-node)
|
||||||
(let [repo (state/get-current-repo)]
|
(tree/-save node)))))
|
||||||
(outliner-state/update-block-state repo node)))))
|
|
||||||
|
|
||||||
(defn insert-node-as-sibling
|
(defn insert-node-as-sibling
|
||||||
"Insert a node as sibling."
|
"Insert a node as sibling."
|
||||||
[new-node left-node]
|
[new-node left-node]
|
||||||
(:pre [(every? tree/satisfied-inode? [new-node left-node])])
|
{:pre [(every? tree/satisfied-inode? [new-node left-node])]}
|
||||||
(let [node (-> (tree/-set-left-id new-node (tree/-get-id left-node))
|
(let [node (-> (tree/-set-left-id new-node (tree/-get-id left-node))
|
||||||
(tree/-set-parent-id (tree/-get-parent-id left-node)))
|
(tree/-set-parent-id (tree/-get-parent-id left-node)))
|
||||||
right-node (tree/-get-right left-node)]
|
right-node (tree/-get-right left-node)]
|
||||||
(do
|
(do
|
||||||
(if (tree/satisfied-inode? right-node)
|
(if (tree/satisfied-inode? right-node)
|
||||||
(let [new-right-node (tree/-set-left-id right-node (tree/-get-id new-node))]
|
(let [new-right-node (tree/-set-left-id right-node (tree/-get-id new-node))
|
||||||
(tree/-save node)
|
saved-new-node (tree/-save node)]
|
||||||
(tree/-save new-right-node))
|
(tree/-save new-right-node)
|
||||||
(tree/-save node))
|
saved-new-node)
|
||||||
(let [repo (state/get-current-repo)]
|
(tree/-save node)))))
|
||||||
(outliner-state/update-block-state repo node)))))
|
|
||||||
|
|
||||||
(defn insert-node
|
(defn insert-node
|
||||||
[new-node target-node sibling?]
|
[new-node target-node sibling?]
|
||||||
(if sibling?
|
(let [saved-node
|
||||||
(insert-node-as-sibling new-node target-node)
|
(if sibling?
|
||||||
(insert-node-as-first-child new-node target-node)))
|
(insert-node-as-sibling new-node target-node)
|
||||||
|
(insert-node-as-first-child new-node target-node))]
|
||||||
|
(outliner-file/sync-to-file saved-node)))
|
||||||
|
|
||||||
(defn delete-node
|
(defn delete-node
|
||||||
"Delete node from the tree."
|
"Delete node from the tree."
|
||||||
|
@ -175,8 +185,7 @@
|
||||||
(let [left-node (tree/-get-left node)
|
(let [left-node (tree/-get-left node)
|
||||||
new-right-node (tree/-set-left-id right-node (tree/-get-id left-node))]
|
new-right-node (tree/-set-left-id right-node (tree/-get-id left-node))]
|
||||||
(tree/-save new-right-node)))
|
(tree/-save new-right-node)))
|
||||||
(let [repo (state/get-current-repo)]
|
(outliner-file/sync-to-file node)))
|
||||||
(outliner-state/update-block-state repo node))))
|
|
||||||
|
|
||||||
(defn move-subtree
|
(defn move-subtree
|
||||||
"Move subtree to a destination position in the relation tree.
|
"Move subtree to a destination position in the relation tree.
|
||||||
|
@ -194,4 +203,10 @@
|
||||||
(tree/-save new-right-node)))
|
(tree/-save new-right-node)))
|
||||||
(if sibling
|
(if sibling
|
||||||
(insert-node-as-sibling root target-node)
|
(insert-node-as-sibling root target-node)
|
||||||
(insert-node-as-first-child root target-node))))
|
(insert-node-as-first-child root target-node))
|
||||||
|
(do
|
||||||
|
|
||||||
|
(outliner-file/sync-to-file root)
|
||||||
|
;; TODO Should sync to file where the target-node located when the
|
||||||
|
;; target-node is in another file.
|
||||||
|
)))
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
(ns frontend.modules.outliner.file
|
||||||
|
(:require [frontend.state :as state]
|
||||||
|
[frontend.db.model :as model]
|
||||||
|
[frontend.modules.outliner.tree :as tree]
|
||||||
|
[frontend.modules.file.core :as file]
|
||||||
|
[frontend.debug :as debug]
|
||||||
|
[frontend.db.utils :as db-utils]))
|
||||||
|
|
||||||
|
(defn sync-to-file
|
||||||
|
[updated-block]
|
||||||
|
{:pre [(tree/satisfied-inode? updated-block)]}
|
||||||
|
(let [page-db-id (-> updated-block :data :block/page :db/id)
|
||||||
|
blocks (model/get-blocks-by-page page-db-id)
|
||||||
|
tree (tree/blocks->vec-tree blocks)
|
||||||
|
page-block (db-utils/pull page-db-id)]
|
||||||
|
(file/save-tree page-block tree)))
|
|
@ -1,7 +1,8 @@
|
||||||
(ns frontend.modules.outliner.tree
|
(ns frontend.modules.outliner.tree
|
||||||
(:require [frontend.modules.outliner.ref :as outliner-ref]
|
(:require [frontend.modules.outliner.ref :as outliner-ref]
|
||||||
[clojure.set :as set]
|
[clojure.set :as set]
|
||||||
[frontend.modules.outliner.utils :as outliner-u]))
|
[frontend.modules.outliner.utils :as outliner-u]
|
||||||
|
[frontend.debug :as debug]))
|
||||||
|
|
||||||
(defprotocol INode
|
(defprotocol INode
|
||||||
(-get-id [this])
|
(-get-id [this])
|
||||||
|
@ -54,16 +55,16 @@
|
||||||
(recur db-id (conj children child))
|
(recur db-id (conj children child))
|
||||||
children)))
|
children)))
|
||||||
|
|
||||||
(comment
|
(defn- clip-block
|
||||||
(defn- clip-block
|
"For debug. It's should be removed."
|
||||||
"For debug. It's should be removed."
|
[x]
|
||||||
[x]
|
(let [ks [:block/parent :block/left :block/pre-block? :block/uuid
|
||||||
(let [ks [:block/parent :block/left :block/pre-block? :block/uuid
|
:block/level :block/title :db/id :block/page]]
|
||||||
:block/level :block/title :db/id]]
|
(map #(select-keys % ks) x)))
|
||||||
(map #(select-keys % ks) x))))
|
|
||||||
|
|
||||||
(defn blocks->vec-tree
|
(defn blocks->vec-tree
|
||||||
[blocks]
|
[blocks]
|
||||||
|
;; (debug/pprint "blocks->vec-tree" blocks)
|
||||||
(let [{:keys [ids parents indexed-by-position]}
|
(let [{:keys [ids parents indexed-by-position]}
|
||||||
(prepare-blocks blocks)
|
(prepare-blocks blocks)
|
||||||
root-id (first (set/difference parents ids))]
|
root-id (first (set/difference parents ids))]
|
||||||
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
(ns frontend.modules.file.core-test
|
||||||
|
(:require [cljs.test :refer [deftest is are testing use-fixtures run-tests] :as test]
|
||||||
|
[cljs-run-test :refer [run-test]]
|
||||||
|
[frontend.modules.file.core :as file]
|
||||||
|
[clojure.string :as str]))
|
||||||
|
|
||||||
|
(deftest test-transform-content
|
||||||
|
(let [s "#### abc\n\n"
|
||||||
|
r "abc"]
|
||||||
|
(is (= r (file/clip-content s)))))
|
||||||
|
|
||||||
|
(def tree
|
||||||
|
'({:block/pre-block? true,
|
||||||
|
:block/uuid #uuid "60643869-3b5b-4e1b-a1f8-28ec965abb4c",
|
||||||
|
:block/left {:db/id 20},
|
||||||
|
:block/body
|
||||||
|
({:block/uuid #uuid "60643869-6feb-4b4a-87b0-7a8a76cf2746",
|
||||||
|
:block/refs (),
|
||||||
|
:block/anchor "level_1",
|
||||||
|
:block/children
|
||||||
|
#{[:block/uuid #uuid "60643869-c9dc-4a06-b1c3-e86bad631b3a"]},
|
||||||
|
:block/body [],
|
||||||
|
:block/meta
|
||||||
|
{:timestamps [], :properties [], :start-pos 30, :end-pos 41},
|
||||||
|
:block/level 2,
|
||||||
|
:block/tags [],
|
||||||
|
:block/title [["Plain" "level 1"]]}
|
||||||
|
{:block/uuid #uuid "60643869-c9dc-4a06-b1c3-e86bad631b3a",
|
||||||
|
:block/refs (),
|
||||||
|
:block/anchor "level_1_1",
|
||||||
|
:block/children
|
||||||
|
#{[:block/uuid #uuid "60643869-3d80-4926-8854-5de911fb2aca"]},
|
||||||
|
:block/body [],
|
||||||
|
:block/meta
|
||||||
|
{:timestamps [], :properties [], :start-pos 41, :end-pos 55},
|
||||||
|
:block/level 3,
|
||||||
|
:block/tags [],
|
||||||
|
:block/title [["Plain" "level 1-1"]]}
|
||||||
|
{:block/uuid #uuid "60643869-3d80-4926-8854-5de911fb2aca",
|
||||||
|
:block/refs (),
|
||||||
|
:block/anchor "level_1_1_1",
|
||||||
|
:block/children #{},
|
||||||
|
:block/body [],
|
||||||
|
:block/meta
|
||||||
|
{:timestamps [], :properties [], :start-pos 55, :end-pos 72},
|
||||||
|
:block/level 4,
|
||||||
|
:block/tags [],
|
||||||
|
:block/title [["Plain" "level 1-1-1"]]}
|
||||||
|
{:block/uuid #uuid "60643869-39d5-497e-b300-fa49993f6fda",
|
||||||
|
:block/refs (),
|
||||||
|
:block/anchor "level_2",
|
||||||
|
:block/children #{},
|
||||||
|
:block/body [],
|
||||||
|
:block/meta
|
||||||
|
{:timestamps [], :properties [], :start-pos 72, :end-pos 83},
|
||||||
|
:block/level 2,
|
||||||
|
:block/tags [],
|
||||||
|
:block/title [["Plain" "level 2"]]}),
|
||||||
|
:block/format :markdown,
|
||||||
|
:block/level 2,
|
||||||
|
:block/refs-with-children (),
|
||||||
|
:block/content "---\ntitle: Mar 31th, 2021\n---\n",
|
||||||
|
:db/id 24,
|
||||||
|
:block/parent {:db/id 20},
|
||||||
|
:block/page {:db/id 20},
|
||||||
|
:block/file {:db/id 16}}
|
||||||
|
{:block/uuid #uuid "60643869-6feb-4b4a-87b0-7a8a76cf2746",
|
||||||
|
:block/left {:db/id 24},
|
||||||
|
:block/anchor "level_1",
|
||||||
|
:block/children
|
||||||
|
({:block/uuid #uuid "60643869-c9dc-4a06-b1c3-e86bad631b3a",
|
||||||
|
:block/left {:db/id 25},
|
||||||
|
:block/anchor "level_1_1",
|
||||||
|
:block/children
|
||||||
|
({:block/uuid #uuid "60643869-3d80-4926-8854-5de911fb2aca",
|
||||||
|
:block/left {:db/id 26},
|
||||||
|
:block/anchor "level_1_1_1",
|
||||||
|
:block/body [],
|
||||||
|
:block/format :markdown,
|
||||||
|
:block/level 4,
|
||||||
|
:block/title [["Plain" "level 1-1-1"]],
|
||||||
|
:block/refs-with-children (),
|
||||||
|
:block/content "#### level 1-1-1\n",
|
||||||
|
:db/id 27,
|
||||||
|
:block/parent {:db/id 26},
|
||||||
|
:block/page {:db/id 20},
|
||||||
|
:block/file {:db/id 16}}),
|
||||||
|
:block/body [],
|
||||||
|
:block/format :markdown,
|
||||||
|
:block/level 3,
|
||||||
|
:block/title [["Plain" "level 1-1"]],
|
||||||
|
:block/refs-with-children (),
|
||||||
|
:block/content "### level 1-1",
|
||||||
|
:db/id 26,
|
||||||
|
:block/parent {:db/id 25},
|
||||||
|
:block/page {:db/id 20},
|
||||||
|
:block/file {:db/id 16}}),
|
||||||
|
:block/body [],
|
||||||
|
:block/format :markdown,
|
||||||
|
:block/level 2,
|
||||||
|
:block/title [["Plain" "level 1"]],
|
||||||
|
:block/refs-with-children (),
|
||||||
|
:block/content "## level 1\n",
|
||||||
|
:db/id 25,
|
||||||
|
:block/parent {:db/id 20},
|
||||||
|
:block/page {:db/id 20},
|
||||||
|
:block/file {:db/id 16}}
|
||||||
|
{:block/uuid #uuid "60643869-39d5-497e-b300-fa49993f6fda",
|
||||||
|
:block/left {:db/id 25},
|
||||||
|
:block/anchor "level_2",
|
||||||
|
:block/repo "logseq_local_test_navtive_fs",
|
||||||
|
:block/body [],
|
||||||
|
:block/format :markdown,
|
||||||
|
:block/level 2,
|
||||||
|
:block/title [["Plain" "level 2"]],
|
||||||
|
:block/refs-with-children (),
|
||||||
|
:block/content "## level 2",
|
||||||
|
:db/id 28,
|
||||||
|
:block/parent {:db/id 20},
|
||||||
|
:block/page {:db/id 20},
|
||||||
|
:block/file {:db/id 16}}))
|
||||||
|
|
||||||
|
(defn- clip-first-space [s]
|
||||||
|
(str/replace s #"\n\s+" "\n"))
|
||||||
|
|
||||||
|
(deftest test-tree->file-content
|
||||||
|
(let [r "---\ntitle: Mar 31th, 2021\n---\n## level 1\n### level 1-1\n#### level 1-1-1\n## level 2"
|
||||||
|
r (clip-first-space r)]
|
||||||
|
(is (= r (file/tree->file-content tree 2)))))
|
||||||
|
|
||||||
|
(comment
|
||||||
|
(run-test test-tree->file-content))
|
Loading…
Reference in New Issue