|  | @@ -1006,47 +1006,99 @@
 | 
	
		
			
				|  |  |            block-title
 | 
	
		
			
				|  |  |            asset-name-to-uuids))
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -(defn- build-annotation-tx
 | 
	
		
			
				|  |  | -  "Creates annotations for a pdf asset given the asset's edn file"
 | 
	
		
			
				|  |  | -  [asset-edn-map parent-asset image-asset-name-to-uuids {:keys [log-fn] :or {log-fn prn}}]
 | 
	
		
			
				|  |  | +(defn find-annotation-children-blocks
 | 
	
		
			
				|  |  | +  "Given a list of blocks and a set of parent uuids, return all blocks that are
 | 
	
		
			
				|  |  | +   descendants via :block/parent of given parent uuids"
 | 
	
		
			
				|  |  | +  [blocks parent-uuids]
 | 
	
		
			
				|  |  | +  (let [get-descendant-uuids
 | 
	
		
			
				|  |  | +        (fn get-descendant-uuids [acc-uuids seen]
 | 
	
		
			
				|  |  | +          (let [new-blocks (filter #(contains? acc-uuids (second (:block/parent %))) blocks)
 | 
	
		
			
				|  |  | +                new-uuids  (set (map :block/uuid new-blocks))
 | 
	
		
			
				|  |  | +                unseen     (set/difference new-uuids seen)]
 | 
	
		
			
				|  |  | +            (if (empty? unseen)
 | 
	
		
			
				|  |  | +              seen
 | 
	
		
			
				|  |  | +              (recur unseen (set/union seen unseen)))))
 | 
	
		
			
				|  |  | +        parent-and-descendant-uuids (get-descendant-uuids parent-uuids parent-uuids)
 | 
	
		
			
				|  |  | +        only-descendants (set/difference parent-and-descendant-uuids parent-uuids)]
 | 
	
		
			
				|  |  | +    (filter #(contains? only-descendants (:block/uuid %)) blocks)))
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +(defn- build-annotation-block
 | 
	
		
			
				|  |  | +  [m color-text-idents parent-asset image-asset-name-to-uuids md-blocks {:keys [log-fn] :or {log-fn prn}}]
 | 
	
		
			
				|  |  | +  (let [user-attributes
 | 
	
		
			
				|  |  | +        {:logseq.property.pdf/hl-color (get color-text-idents (get-in m [:properties :color]))
 | 
	
		
			
				|  |  | +         :logseq.property.pdf/hl-page (:page m)
 | 
	
		
			
				|  |  | +         :block/title (get-in m [:content :text])}
 | 
	
		
			
				|  |  | +        _ (when (some (comp nil? val) user-attributes)
 | 
	
		
			
				|  |  | +            (log-fn :missing-annotation-attributes "Annotation is missing some attributes so set reasonable defaults for them"
 | 
	
		
			
				|  |  | +                    {:annotation user-attributes :asset (:block/title parent-asset)}))
 | 
	
		
			
				|  |  | +        asset-image-uuid (some (fn [[asset-name image-uuid]]
 | 
	
		
			
				|  |  | +                                 (when (string/includes? asset-name
 | 
	
		
			
				|  |  | +                                                         (str (:id m)
 | 
	
		
			
				|  |  | +                                                              (when (get-in m [:content :image])
 | 
	
		
			
				|  |  | +                                                                (str "_" (get-in m [:content :image])))))
 | 
	
		
			
				|  |  | +                                   image-uuid))
 | 
	
		
			
				|  |  | +                               image-asset-name-to-uuids)
 | 
	
		
			
				|  |  | +        md-block (get md-blocks (:id m))
 | 
	
		
			
				|  |  | +        annotation (merge
 | 
	
		
			
				|  |  | +                     ;; Reasonable defaults for user attributes
 | 
	
		
			
				|  |  | +                    {:logseq.property.pdf/hl-color :logseq.property/color.yellow
 | 
	
		
			
				|  |  | +                     :logseq.property.pdf/hl-page 1
 | 
	
		
			
				|  |  | +                     :block/title ""}
 | 
	
		
			
				|  |  | +                    user-attributes
 | 
	
		
			
				|  |  | +                    {:block/uuid (d/squuid)
 | 
	
		
			
				|  |  | +                     :block/order (db-order/gen-key)
 | 
	
		
			
				|  |  | +                     :logseq.property/ls-type :annotation
 | 
	
		
			
				|  |  | +                     :logseq.property.pdf/hl-value (dissoc m :id)
 | 
	
		
			
				|  |  | +                     :logseq.property/asset [:block/uuid (:block/uuid parent-asset)]
 | 
	
		
			
				|  |  | +                     :block/tags [:logseq.class/Pdf-annotation]
 | 
	
		
			
				|  |  | +                     :block/parent [:block/uuid (:block/uuid parent-asset)]
 | 
	
		
			
				|  |  | +                     :block/page :logseq.class/Asset}
 | 
	
		
			
				|  |  | +                    (when asset-image-uuid
 | 
	
		
			
				|  |  | +                      {:logseq.property.pdf/hl-image [:block/uuid asset-image-uuid]
 | 
	
		
			
				|  |  | +                       :logseq.property.pdf/hl-type :area})
 | 
	
		
			
				|  |  | +                    (when md-block
 | 
	
		
			
				|  |  | +                      (select-keys md-block [:block/title])))]
 | 
	
		
			
				|  |  | +    (sqlite-util/block-with-timestamps annotation)))
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +(defn- build-pdf-annotations-tx*
 | 
	
		
			
				|  |  | +  "Creates annotations for a pdf asset given the asset's edn map and parsed markdown file"
 | 
	
		
			
				|  |  | +  [asset-edn-map parsed-md parent-asset image-asset-name-to-uuids {:keys [log-fn] :or {log-fn prn} :as opts}]
 | 
	
		
			
				|  |  |    (let [color-text-idents
 | 
	
		
			
				|  |  |          (->> (get-in db-property/built-in-properties [:logseq.property.pdf/hl-color :closed-values])
 | 
	
		
			
				|  |  |               (map (juxt :value :db-ident))
 | 
	
		
			
				|  |  | -             (into {}))]
 | 
	
		
			
				|  |  | -    (mapv #(let [user-attributes
 | 
	
		
			
				|  |  | -                 {:logseq.property.pdf/hl-color (get color-text-idents (get-in % [:properties :color]))
 | 
	
		
			
				|  |  | -                  :logseq.property.pdf/hl-page (:page %)
 | 
	
		
			
				|  |  | -                  :block/title (get-in % [:content :text])}
 | 
	
		
			
				|  |  | -                 _ (when (some (comp nil? val) user-attributes)
 | 
	
		
			
				|  |  | -                     (log-fn :missing-annotation-attributes "Annotation is missing some attributes so set reasonable defaults for them"
 | 
	
		
			
				|  |  | -                             {:annotation user-attributes :asset (:block/title parent-asset)}))
 | 
	
		
			
				|  |  | -                 asset-image-uuid (some (fn [[asset-name image-uuid]]
 | 
	
		
			
				|  |  | -                                          (when (string/includes? asset-name
 | 
	
		
			
				|  |  | -                                                                  (str (:id %)
 | 
	
		
			
				|  |  | -                                                                       (when (get-in % [:content :image])
 | 
	
		
			
				|  |  | -                                                                         (str "_" (get-in % [:content :image])))))
 | 
	
		
			
				|  |  | -                                            image-uuid))
 | 
	
		
			
				|  |  | -                                        image-asset-name-to-uuids)
 | 
	
		
			
				|  |  | -                 annotation (merge
 | 
	
		
			
				|  |  | -                             ;; Reasonable defaults for user attributes
 | 
	
		
			
				|  |  | -                             {:logseq.property.pdf/hl-color :logseq.property/color.yellow
 | 
	
		
			
				|  |  | -                              :logseq.property.pdf/hl-page 1
 | 
	
		
			
				|  |  | -                              :block/title ""}
 | 
	
		
			
				|  |  | -                             user-attributes
 | 
	
		
			
				|  |  | -                             {:block/uuid (d/squuid)
 | 
	
		
			
				|  |  | -                              :block/order (db-order/gen-key)
 | 
	
		
			
				|  |  | -                              :logseq.property/ls-type :annotation
 | 
	
		
			
				|  |  | -                              :logseq.property.pdf/hl-value (dissoc % :id)
 | 
	
		
			
				|  |  | -                              :logseq.property/asset [:block/uuid (:block/uuid parent-asset)]
 | 
	
		
			
				|  |  | -                              :block/tags [:logseq.class/Pdf-annotation]
 | 
	
		
			
				|  |  | -                              :block/parent [:block/uuid (:block/uuid parent-asset)]
 | 
	
		
			
				|  |  | -                              :block/page :logseq.class/Asset}
 | 
	
		
			
				|  |  | -                             (when asset-image-uuid
 | 
	
		
			
				|  |  | -                               {:logseq.property.pdf/hl-image [:block/uuid asset-image-uuid]
 | 
	
		
			
				|  |  | -                                :logseq.property.pdf/hl-type :area}))]
 | 
	
		
			
				|  |  | -             (prn :annotation-added! user-attributes)
 | 
	
		
			
				|  |  | -             (sqlite-util/block-with-timestamps annotation))
 | 
	
		
			
				|  |  | -          (get-in asset-edn-map [:edn-content :highlights]))))
 | 
	
		
			
				|  |  | +             (into {}))
 | 
	
		
			
				|  |  | +        md-blocks
 | 
	
		
			
				|  |  | +        (->> parsed-md
 | 
	
		
			
				|  |  | +             :blocks
 | 
	
		
			
				|  |  | +             ;; Currently we can only import text of any md annotation blocks. No tags or properties
 | 
	
		
			
				|  |  | +             (map #(vector (:block/uuid %)
 | 
	
		
			
				|  |  | +                           (select-keys % [:block/title :block/order :block/parent :block/uuid])))
 | 
	
		
			
				|  |  | +             (into {}))
 | 
	
		
			
				|  |  | +        annotation-blocks
 | 
	
		
			
				|  |  | +        (mapv #(build-annotation-block % color-text-idents parent-asset image-asset-name-to-uuids md-blocks opts)
 | 
	
		
			
				|  |  | +              (get-in asset-edn-map [:edn-content :highlights]))
 | 
	
		
			
				|  |  | +        md-children-blocks*
 | 
	
		
			
				|  |  | +        (mapv #(assoc %
 | 
	
		
			
				|  |  | +                      :block/uuid (d/squuid)
 | 
	
		
			
				|  |  | +                      :old-uuid (:block/uuid %))
 | 
	
		
			
				|  |  | +              (find-annotation-children-blocks (vals md-blocks) (set (map :id (get-in asset-edn-map [:edn-content :highlights])))))
 | 
	
		
			
				|  |  | +        old-to-new-annotation-uuids
 | 
	
		
			
				|  |  | +        (->> (map (fn [old-annotation new-block]
 | 
	
		
			
				|  |  | +                    [(:id old-annotation) (:block/uuid new-block)])
 | 
	
		
			
				|  |  | +                  (get-in asset-edn-map [:edn-content :highlights]) annotation-blocks)
 | 
	
		
			
				|  |  | +             (into {})
 | 
	
		
			
				|  |  | +             (merge (into {} (map (juxt :old-uuid :block/uuid)) md-children-blocks*)))
 | 
	
		
			
				|  |  | +        md-children-blocks (keep #(if-let [parent-uuid (get old-to-new-annotation-uuids (second (:block/parent %)))]
 | 
	
		
			
				|  |  | +                                    (sqlite-util/block-with-timestamps
 | 
	
		
			
				|  |  | +                                     (merge (select-keys % [:block/uuid :block/title :block/order])
 | 
	
		
			
				|  |  | +                                            {:block/parent [:block/uuid parent-uuid]
 | 
	
		
			
				|  |  | +                                             :block/page :logseq.class/Asset}))
 | 
	
		
			
				|  |  | +                                    (do (log-fn :invalid-md-annotation-block "Ignore md annotation block because it has no valid :block/parent"
 | 
	
		
			
				|  |  | +                                                :block %)
 | 
	
		
			
				|  |  | +                                        nil))
 | 
	
		
			
				|  |  | +                                 md-children-blocks*)]
 | 
	
		
			
				|  |  | +    ;; (prn :descendants md-children-blocks)
 | 
	
		
			
				|  |  | +    (into annotation-blocks md-children-blocks)))
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  (defn- build-new-asset [asset-data]
 | 
	
		
			
				|  |  |    (merge (sqlite-util/block-with-timestamps
 | 
	
	
		
			
				|  | @@ -1077,9 +1129,21 @@
 | 
	
		
			
				|  |  |                   [(node-path/basename image-path) (:block/uuid tx)]) image-paths txs)
 | 
	
		
			
				|  |  |            (into {}))}))
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +(defn- build-pdf-annotations-tx
 | 
	
		
			
				|  |  | +  "Builds tx for pdf annotations when a pdf has an annotations EDN file under assets/"
 | 
	
		
			
				|  |  | +  [parent-asset-path assets parent-asset pdf-annotation-pages opts]
 | 
	
		
			
				|  |  | +  (let [asset-edn-path (string/replace-first parent-asset-path #"(?i)\.pdf$" ".edn")
 | 
	
		
			
				|  |  | +        asset-md-name (str "hls__" (node-path/basename (string/replace-first parent-asset-path #"(?i)\.pdf$" ".md")))]
 | 
	
		
			
				|  |  | +    (when-let [asset-edn-map (get @assets asset-edn-path)]
 | 
	
		
			
				|  |  | +      ;; Mark edn asset so it isn't treated like a normal asset later
 | 
	
		
			
				|  |  | +      (swap! assets assoc-in [asset-edn-path :pdf-annotation?] true)
 | 
	
		
			
				|  |  | +      (let [{:keys [txs image-asset-name-to-uuids]} (build-annotation-images parent-asset-path assets)]
 | 
	
		
			
				|  |  | +        (concat txs
 | 
	
		
			
				|  |  | +                (build-pdf-annotations-tx* asset-edn-map (get @pdf-annotation-pages asset-md-name) parent-asset image-asset-name-to-uuids opts))))))
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  (defn- handle-assets-in-block
 | 
	
		
			
				|  |  |    "If a block contains assets, creates them as #Asset nodes in the Asset page and references them in the block."
 | 
	
		
			
				|  |  | -  [block {:keys [asset-links]} {:keys [assets ignored-assets]} opts]
 | 
	
		
			
				|  |  | +  [block {:keys [asset-links]} {:keys [assets ignored-assets pdf-annotation-pages]} opts]
 | 
	
		
			
				|  |  |    (if (seq asset-links)
 | 
	
		
			
				|  |  |      (let [asset-maps
 | 
	
		
			
				|  |  |            (keep
 | 
	
	
		
			
				|  | @@ -1092,17 +1156,12 @@
 | 
	
		
			
				|  |  |                                            {:block/title (db-asset/asset-name->title (node-path/basename asset-name))}
 | 
	
		
			
				|  |  |                                            (when-let [metadata (not-empty (common-util/safe-read-map-string (:metadata (second asset-link))))]
 | 
	
		
			
				|  |  |                                              {:logseq.property.asset/resize-metadata metadata}))
 | 
	
		
			
				|  |  | -                         asset-edn-path (when (= "pdf" (path/file-ext asset-name)) (string/replace-first asset-name #"(?i)\.pdf$" ".edn"))
 | 
	
		
			
				|  |  | -                         ;; Mark edn asset so it isn't treated like a normal asset later
 | 
	
		
			
				|  |  | -                         _ (when (get @assets asset-edn-path)
 | 
	
		
			
				|  |  | -                             (swap! assets assoc-in [asset-edn-path :pdf-annotation?] true))
 | 
	
		
			
				|  |  | +                         pdf-annotations-tx (when (= "pdf" (path/file-ext asset-name))
 | 
	
		
			
				|  |  | +                                              (build-pdf-annotations-tx asset-name assets new-asset pdf-annotation-pages opts))
 | 
	
		
			
				|  |  |                           asset-tx (concat [new-asset]
 | 
	
		
			
				|  |  | -                                          (when-let [asset-edn-map (get @assets asset-edn-path)]
 | 
	
		
			
				|  |  | -                                            (let [{:keys [txs image-asset-name-to-uuids]} (build-annotation-images asset-name assets)]
 | 
	
		
			
				|  |  | -                                              (concat txs
 | 
	
		
			
				|  |  | -                                                      (build-annotation-tx asset-edn-map new-asset image-asset-name-to-uuids opts)))))]
 | 
	
		
			
				|  |  | -                     (prn :asset-added! (node-path/basename asset-name))
 | 
	
		
			
				|  |  | -                      ;;  (cljs.pprint/pprint asset-link)
 | 
	
		
			
				|  |  | +                                          (when pdf-annotations-tx pdf-annotations-tx))]
 | 
	
		
			
				|  |  | +                    ;;  (prn :asset-added! (node-path/basename asset-name))
 | 
	
		
			
				|  |  | +                    ;;  (cljs.pprint/pprint asset-link)
 | 
	
		
			
				|  |  |                       (swap! assets assoc-in [asset-name :block/uuid] (:block/uuid new-asset))
 | 
	
		
			
				|  |  |                       {:asset-name-uuid [asset-name (:block/uuid new-asset)]
 | 
	
		
			
				|  |  |                        :asset-tx asset-tx}))
 | 
	
	
		
			
				|  | @@ -1166,7 +1225,7 @@
 | 
	
		
			
				|  |  |          {block-after-built-in-props :block deadline-properties-tx :properties-tx}
 | 
	
		
			
				|  |  |          (update-block-deadline-and-scheduled block page-names-to-uuids options)
 | 
	
		
			
				|  |  |          {block-after-assets :block :keys [asset-blocks-tx]}
 | 
	
		
			
				|  |  | -        (handle-assets-in-block block-after-built-in-props walked-ast-blocks (select-keys import-state [:assets :ignored-assets]) (select-keys options [:log-fn]))
 | 
	
		
			
				|  |  | +        (handle-assets-in-block block-after-built-in-props walked-ast-blocks import-state (select-keys options [:log-fn]))
 | 
	
		
			
				|  |  |          ;; :block/page should be [:block/page NAME]
 | 
	
		
			
				|  |  |          journal-page-created-at (some-> (:block/page block*) second journal-created-ats)
 | 
	
		
			
				|  |  |          prepared-block (cond-> block-after-assets
 | 
	
	
		
			
				|  | @@ -1422,6 +1481,8 @@
 | 
	
		
			
				|  |  |     :ignored-files (atom [])
 | 
	
		
			
				|  |  |     ;; Vec of maps with keys :path, :reason and :location (optional).
 | 
	
		
			
				|  |  |     :ignored-assets (atom [])
 | 
	
		
			
				|  |  | +   ;; Map of annotation page paths and their parsed contents
 | 
	
		
			
				|  |  | +   :pdf-annotation-pages (atom {})
 | 
	
		
			
				|  |  |     ;; Map of property names (keyword) and their current schemas (map of qualified properties).
 | 
	
		
			
				|  |  |     ;; Used for adding schemas to properties and detecting changes across a property's usage
 | 
	
		
			
				|  |  |     :property-schemas (atom {})
 | 
	
	
		
			
				|  | @@ -1564,8 +1625,6 @@
 | 
	
		
			
				|  |  |    "Main fn which calls graph-parser to convert markdown into data"
 | 
	
		
			
				|  |  |    [db file content {:keys [extract-options import-state]}]
 | 
	
		
			
				|  |  |    (let [format (common-util/get-format file)
 | 
	
		
			
				|  |  | -        ;; TODO: Remove once pdf highlights are supported
 | 
	
		
			
				|  |  | -        ignored-highlight-file? (string/starts-with? (str (path/basename file)) "hls__")
 | 
	
		
			
				|  |  |          extract-options' (merge {:block-pattern (common-config/get-block-pattern format)
 | 
	
		
			
				|  |  |                                   :date-formatter "MMM do, yyyy"
 | 
	
		
			
				|  |  |                                   :uri-encoded? false
 | 
	
	
		
			
				|  | @@ -1573,30 +1632,34 @@
 | 
	
		
			
				|  |  |                                   :export-to-db-graph? true
 | 
	
		
			
				|  |  |                                   :filename-format :legacy}
 | 
	
		
			
				|  |  |                                  extract-options
 | 
	
		
			
				|  |  | -                                {:db db})]
 | 
	
		
			
				|  |  | -    (cond (and (contains? common-config/mldoc-support-formats format) (not ignored-highlight-file?))
 | 
	
		
			
				|  |  | -          (-> (extract/extract file content extract-options')
 | 
	
		
			
				|  |  | -              (update :pages (fn [pages]
 | 
	
		
			
				|  |  | -                               (map #(dissoc % :block.temp/original-page-name) pages)))
 | 
	
		
			
				|  |  | -              (update :blocks fix-extracted-block-tags-and-refs))
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -          (common-config/whiteboard? file)
 | 
	
		
			
				|  |  | -          (-> (extract/extract-whiteboard-edn file content extract-options')
 | 
	
		
			
				|  |  | -              (update :pages (fn [pages]
 | 
	
		
			
				|  |  | -                               (->> pages
 | 
	
		
			
				|  |  | -                                    ;; migrate previous attribute for :block/title
 | 
	
		
			
				|  |  | -                                    (map #(-> %
 | 
	
		
			
				|  |  | -                                              (assoc :block/title (or (:block/original-name %) (:block/title %))
 | 
	
		
			
				|  |  | -                                                     :block/tags #{:logseq.class/Whiteboard})
 | 
	
		
			
				|  |  | -                                              (dissoc :block/type :block/original-name))))))
 | 
	
		
			
				|  |  | -              (update :blocks update-whiteboard-blocks format))
 | 
	
		
			
				|  |  | +                                {:db db})
 | 
	
		
			
				|  |  | +        extracted
 | 
	
		
			
				|  |  | +        (cond (contains? common-config/mldoc-support-formats format)
 | 
	
		
			
				|  |  | +              (-> (extract/extract file content extract-options')
 | 
	
		
			
				|  |  | +                  (update :pages (fn [pages]
 | 
	
		
			
				|  |  | +                                   (map #(dissoc % :block.temp/original-page-name) pages)))
 | 
	
		
			
				|  |  | +                  (update :blocks fix-extracted-block-tags-and-refs))
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +              (common-config/whiteboard? file)
 | 
	
		
			
				|  |  | +              (-> (extract/extract-whiteboard-edn file content extract-options')
 | 
	
		
			
				|  |  | +                  (update :pages (fn [pages]
 | 
	
		
			
				|  |  | +                                   (->> pages
 | 
	
		
			
				|  |  | +                                        ;; migrate previous attribute for :block/title
 | 
	
		
			
				|  |  | +                                        (map #(-> %
 | 
	
		
			
				|  |  | +                                                  (assoc :block/title (or (:block/original-name %) (:block/title %))
 | 
	
		
			
				|  |  | +                                                         :block/tags #{:logseq.class/Whiteboard})
 | 
	
		
			
				|  |  | +                                                  (dissoc :block/type :block/original-name))))))
 | 
	
		
			
				|  |  | +                  (update :blocks update-whiteboard-blocks format))
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -          :else
 | 
	
		
			
				|  |  | -          (if ignored-highlight-file?
 | 
	
		
			
				|  |  | -            (swap! (:ignored-files import-state) conj
 | 
	
		
			
				|  |  | -                   {:path file :reason :pdf-highlight})
 | 
	
		
			
				|  |  | -            (swap! (:ignored-files import-state) conj
 | 
	
		
			
				|  |  | -                   {:path file :reason :unsupported-file-format})))))
 | 
	
		
			
				|  |  | +              :else
 | 
	
		
			
				|  |  | +              (swap! (:ignored-files import-state) conj
 | 
	
		
			
				|  |  | +                     {:path file :reason :unsupported-file-format}))]
 | 
	
		
			
				|  |  | +    ;; Annotation markdown pages are saved for later as they are dependant on the asset being annotated
 | 
	
		
			
				|  |  | +    (if (string/starts-with? (str (path/basename file)) "hls__")
 | 
	
		
			
				|  |  | +      (do
 | 
	
		
			
				|  |  | +        (swap! (:pdf-annotation-pages import-state) assoc (node-path/basename file) extracted)
 | 
	
		
			
				|  |  | +        nil)
 | 
	
		
			
				|  |  | +      extracted)))
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  (defn- build-journal-created-ats
 | 
	
		
			
				|  |  |    "Calculate created-at timestamps for journals"
 | 
	
	
		
			
				|  | @@ -1755,7 +1818,10 @@
 | 
	
		
			
				|  |  |    (set-ui-state [:graph/importing-state :total] (count *doc-files))
 | 
	
		
			
				|  |  |    (let [doc-files (mapv #(assoc %1 :idx %2)
 | 
	
		
			
				|  |  |                          ;; Sort files to ensure reproducible import behavior
 | 
	
		
			
				|  |  | -                        (sort-by :path *doc-files)
 | 
	
		
			
				|  |  | +                        ;; pdf annotation pages sort first because other pages depend on them
 | 
	
		
			
				|  |  | +                        (sort-by (fn [{:keys [path]}]
 | 
	
		
			
				|  |  | +                                   [(not (string/starts-with? (node-path/basename path) "hls__")) path])
 | 
	
		
			
				|  |  | +                                 *doc-files)
 | 
	
		
			
				|  |  |                          (range 0 (count *doc-files)))]
 | 
	
		
			
				|  |  |      (-> (p/loop [_file-map (export-doc-file (get doc-files 0) conn <read-file options)
 | 
	
		
			
				|  |  |                   i 0]
 |