|  | @@ -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)
 | 
	
		
			
				|  |  | -              delete-blocks (delete-blocks-fn (first pages) file)
 | 
	
		
			
				|  |  | +                :else nil)
 | 
	
		
			
				|  |  |                block-ids (map (fn [block] {:block/uuid (:block/uuid block)}) blocks)
 | 
	
		
			
				|  |  | +              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)]
 |