|
@@ -6,11 +6,77 @@
|
|
|
[logseq.graph-parser.util :as gp-util]
|
|
|
[logseq.graph-parser.date-time-util :as date-time-util]
|
|
|
[logseq.graph-parser.config :as gp-config]
|
|
|
+ [logseq.db.schema :as db-schema]
|
|
|
[clojure.string :as string]
|
|
|
[clojure.set :as set]))
|
|
|
|
|
|
+(defn- retract-blocks-tx
|
|
|
+ [blocks retain-uuids]
|
|
|
+ (mapcat (fn [{uuid :block/uuid eid :db/id}]
|
|
|
+ (if (and uuid (contains? retain-uuids uuid))
|
|
|
+ (map (fn [attr] [:db.fn/retractAttribute eid attr]) db-schema/retract-attributes)
|
|
|
+ [[:db.fn/retractEntity eid]]))
|
|
|
+ blocks))
|
|
|
+
|
|
|
+(defn- get-file-page
|
|
|
+ "Copy of db/get-file-page. Too basic to couple to main app"
|
|
|
+ [db file-path]
|
|
|
+ (ffirst
|
|
|
+ (d/q
|
|
|
+ '[:find ?page-name
|
|
|
+ :in $ ?path
|
|
|
+ :where
|
|
|
+ [?file :file/path ?path]
|
|
|
+ [?page :block/file ?file]
|
|
|
+ [?page :block/original-name ?page-name]]
|
|
|
+ db
|
|
|
+ file-path)))
|
|
|
+
|
|
|
+(defn- get-page-blocks-no-cache
|
|
|
+ "Copy of db/get-page-blocks-no-cache. Too basic to couple to main app"
|
|
|
+ [db page {:keys [pull-keys]
|
|
|
+ :or {pull-keys '[*]}}]
|
|
|
+ (let [sanitized-page (gp-util/page-name-sanity-lc page)
|
|
|
+ page-id (:db/id (d/entity db [:block/name sanitized-page]))]
|
|
|
+ (when page-id
|
|
|
+ (let [datoms (d/datoms db :avet :block/page page-id)
|
|
|
+ block-eids (mapv :e datoms)]
|
|
|
+ (d/pull-many db pull-keys block-eids)))))
|
|
|
+
|
|
|
+(defn get-blocks-to-delete
|
|
|
+ "Returns the transactional operations to retract blocks belonging to the
|
|
|
+ given page name and file path. This function is required when a file is being
|
|
|
+ parsed from disk; before saving the parsed, blocks from the previous version
|
|
|
+ of that file need to be retracted.
|
|
|
+
|
|
|
+ The 'Page' parsed from the new file version is passed separately from the
|
|
|
+ file-path, as the page name can be set via properties in the file, and thus
|
|
|
+ can change between versions. If it has changed, existing blocks for both the
|
|
|
+ old and new page name will be retracted.
|
|
|
+
|
|
|
+ Blocks are by default fully cleared via retractEntity. However, a collection
|
|
|
+ of block UUIDs to retain can be passed, and any blocks with matching uuids
|
|
|
+ will instead have their attributes cleared individually via
|
|
|
+ 'retractAttribute'. This will preserve block references to the retained
|
|
|
+ UUIDs."
|
|
|
+ [db file-page file-path retain-uuid-blocks]
|
|
|
+ (let [existing-file-page (get-file-page db file-path)
|
|
|
+ pages-to-clear (distinct (filter some? [existing-file-page (:block/name file-page)]))
|
|
|
+ blocks (mapcat (fn [page]
|
|
|
+ (get-page-blocks-no-cache db page {:pull-keys [:db/id :block/uuid]}))
|
|
|
+ pages-to-clear)
|
|
|
+ retain-uuids (set (keep :block/uuid retain-uuid-blocks))]
|
|
|
+ (retract-blocks-tx (distinct blocks) retain-uuids)))
|
|
|
+
|
|
|
(defn parse-file
|
|
|
- "Parse file and save parsed data to the given db. Main parse fn used by logseq app"
|
|
|
+ "Parse file and save parsed data to the given db. Main parse fn used by logseq app.
|
|
|
+Options available:
|
|
|
+
|
|
|
+* :new? - Boolean which indicates if this file already exists. Default is true.
|
|
|
+* :delete-blocks-fn - Optional fn which is called with the new page, file and existing block uuids
|
|
|
+ which may be referenced elsewhere.
|
|
|
+* :skip-db-transact? - Boolean which skips transacting in order to batch transactions. Default is false
|
|
|
+* :extract-options - Options map to pass to extract/extract"
|
|
|
[conn file content {:keys [new? delete-blocks-fn extract-options skip-db-transact?]
|
|
|
:or {new? true
|
|
|
delete-blocks-fn (constantly [])
|
|
@@ -31,20 +97,20 @@
|
|
|
blocks []
|
|
|
ast []}}
|
|
|
(cond (contains? gp-config/mldoc-support-formats format)
|
|
|
- (extract/extract file content extract-options')
|
|
|
+ (extract/extract file content extract-options')
|
|
|
|
|
|
- (gp-config/whiteboard? file)
|
|
|
- (extract/extract-whiteboard-edn file content extract-options')
|
|
|
+ (gp-config/whiteboard? file)
|
|
|
+ (extract/extract-whiteboard-edn file content extract-options')
|
|
|
|
|
|
- :else nil)
|
|
|
+ :else nil)
|
|
|
block-ids (map (fn [block] {:block/uuid (:block/uuid block)}) blocks)
|
|
|
- delete-blocks (delete-blocks-fn (first pages) file block-ids)
|
|
|
+ delete-blocks (delete-blocks-fn @conn (first pages) file block-ids)
|
|
|
block-refs-ids (->> (mapcat :block/refs blocks)
|
|
|
(filter (fn [ref] (and (vector? ref)
|
|
|
(= :block/uuid (first ref)))))
|
|
|
(map (fn [ref] {:block/uuid (second ref)}))
|
|
|
(seq))
|
|
|
- ;; To prevent "unique constraint" on datascript
|
|
|
+ ;; To prevent "unique constraint" on datascript
|
|
|
block-ids (set/union (set block-ids) (set block-refs-ids))
|
|
|
pages (extract/with-ref-pages pages blocks)
|
|
|
pages-index (map #(select-keys % [:block/name]) pages)]
|