Enhance/pdf improvements (#6475)

Full-text search, highlights and assets alias support 
It also exposes a plugin API for highlight context menu   
    ```ts
    /**
       * Current it's only available for pdf viewer
       * @param label - displayed name of command
       * @param action - callback for the clickable item
       * @param opts - clearSelection: clear highlight selection when callback invoked
       */
      registerHighlightContextMenuItem: (
        label: string,
        action: SimpleCommandCallback,
        opts?: {
          clearSelection: boolean
        }
      ) => unknown
    ```
This commit is contained in:
Charlie
2022-10-09 20:44:18 +08:00
committed by GitHub
parent ad4fec8ce7
commit d53ac94bfc
50 changed files with 3863 additions and 1359 deletions

View File

@@ -7,10 +7,11 @@
[frontend.fs :as fs]
[frontend.handler.editor :as editor-handler]
[frontend.handler.page :as page-handler]
[frontend.handler.assets :as assets-handler]
[frontend.util.page-property :as page-property]
[frontend.state :as state]
[frontend.util :as util]
[logseq.graph-parser.util :as gp-util]
[frontend.extensions.pdf.utils :as pdf-utils]
[logseq.graph-parser.config :as gp-config]
[logseq.graph-parser.util.block-ref :as block-ref]
[medley.core :as medley]
@@ -18,46 +19,16 @@
[reitit.frontend.easy :as rfe]
[rum.core :as rum]))
(def HLS-PREFIX "hls__")
(def HLS-PREFIX-DISPLAY "📒")
(def HLS-PREFIX-LEN (count HLS-PREFIX))
(def HLS-PREFIX-PATTERN (re-pattern (str "^" HLS-PREFIX)))
(defn make-hls
[name]
(str HLS-PREFIX name))
(defn hls-page?
[title]
(and title (string? title) (string/starts-with? title HLS-PREFIX)))
(defn hls-file?
[filename]
(and filename (string? filename) (string/starts-with? filename "hls__")))
(defn inflate-asset
[full-path]
(let [filename (util/node-path.basename full-path)
web-link? (string/starts-with? full-path "http")
[original-path]
(let [filename (util/node-path.basename original-path)
web-link? (string/starts-with? original-path "http")
ext-name (util/get-file-ext filename)
url (cond
web-link?
full-path
(util/absolute-path? full-path)
(str "file://" full-path)
(string/starts-with? full-path "file:/")
full-path
:else
(let [full-path (string/replace full-path #"^[.\/\\]+" "")
full-path (if-not (string/starts-with? full-path gp-config/local-assets-dir)
(util/node-path.join gp-config/local-assets-dir full-path)
full-path)]
(str "file://" ;; TODO: bfs
(util/node-path.join
(config/get-repo-dir (state/get-current-repo))
full-path))))]
url (assets-handler/normalize-asset-resource-url original-path)]
(when-let [key
(if web-link?
(str (hash url))
@@ -68,7 +39,14 @@
:identity (subs key (- (count key) 15))
:filename filename
:url url
:hls-file (str "assets/" key ".edn")})))
:hls-file (str "assets/" key ".edn")
:original-path original-path})))
(defn resolve-area-image-file
[img-stamp current {:keys [page id] :as _hl}]
(when-let [key (:key current)]
(-> (str gp-config/local-assets-dir "/" key "/")
(str (util/format "%s_%s_%s.png" page id img-stamp)))))
(defn load-hls-data$
[{:keys [hls-file]}]
@@ -144,12 +122,14 @@
(.toBlob canvas' callback))
))))
(defn update-hl-area-block!
(defn update-hl-block!
[highlight]
(when-let [block (and (area-highlight? highlight)
(db-model/get-block-by-uuid (:id highlight)))]
(editor-handler/set-block-property!
(:block/uuid block) :hl-stamp (get-in highlight [:content :image]))))
(when-let [block (db-model/get-block-by-uuid (:id highlight))]
(doseq [[k v] {:hl-stamp (if (area-highlight? highlight)
(get-in highlight [:content :image])
(js/Date.now))
:hl-color (get-in highlight [:properties :color])}]
(editor-handler/set-block-property! (:block/uuid block) k v))))
(defn unlink-hl-area-image$
[^js _viewer current hl]
@@ -167,15 +147,15 @@
[pdf-current]
(let [page-name (:key pdf-current)
page-name (string/trim page-name)
page-name (make-hls page-name)
page (db-model/get-page page-name)
url (:url pdf-current)
format (state/get-preferred-format)
repo-dir (config/get-repo-dir (state/get-current-repo))
page-name (str "hls__" page-name)
page (db-model/get-page page-name)
file-path (:original-path pdf-current)
format (state/get-preferred-format)
repo-dir (config/get-repo-dir (state/get-current-repo))
asset-dir (util/node-path.join repo-dir gp-config/local-assets-dir)
url (if (string/includes? url asset-dir)
(str ".." (last (string/split url repo-dir)))
url)]
url (if (string/includes? file-path asset-dir)
(str ".." (last (string/split file-path repo-dir)))
file-path)]
(if-not page
(let [label (:filename pdf-current)]
(page-handler/create! page-name {:redirect? false :create-first-block? false
@@ -196,26 +176,28 @@
(page-property/add-property! page-name :file-path url))
page))
(defn create-ref-block!
[{:keys [id content page]}]
(when-let [pdf-current (:pdf/current @state/state)]
(when-let [ref-page (resolve-ref-page pdf-current)]
(if-let [ref-block (db-model/get-block-by-uuid id)]
(do
(js/console.debug "[existed ref block]" ref-block)
ref-block)
(let [text (:text content)
wrap-props #(if-let [stamp (:image content)]
(assoc % :hl-type "area" :hl-stamp stamp) %)]
(defn ensure-ref-block!
([pdf hl] (ensure-ref-block! pdf hl nil))
([pdf-current {:keys [id content page properties]} insert-opts]
(when-let [ref-page (and pdf-current (resolve-ref-page pdf-current))]
(if-let [ref-block (db-model/query-block-by-uuid id)]
(do
(println "[existed ref block]" ref-block)
ref-block)
(let [text (:text content)
wrap-props #(if-let [stamp (:image content)]
(assoc % :hl-type "area" :hl-stamp stamp) %)]
(editor-handler/api-insert-new-block!
text {:page (:block/name ref-page)
:custom-uuid id
:properties (wrap-props
{:ls-type "annotation"
:hl-page page
;; force custom uuid
:id (str id)})}))))))
(editor-handler/api-insert-new-block!
text (merge {:page (:block/name ref-page)
:custom-uuid id
:properties (wrap-props
{:ls-type "annotation"
:hl-page page
:hl-color (:color properties)
;; force custom uuid
:id (str id)})}
insert-opts)))))))
(defn del-ref-block!
[{:keys [id]}]
@@ -226,7 +208,7 @@
(defn copy-hl-ref!
[highlight]
(when-let [ref-block (create-ref-block! highlight)]
(when-let [ref-block (ensure-ref-block! (state/get-current-pdf) highlight)]
(util/copy-to-clipboard! (block-ref/->block-ref (:block/uuid ref-block)))))
(defn open-block-ref!
@@ -235,10 +217,10 @@
page (db-utils/pull (:db/id (:block/page block)))
page-name (:block/original-name page)
file-path (:file-path (:block/properties page))]
(when-let [target-key (and page-name (subs page-name HLS-PREFIX-LEN))]
(when-let [target-key (and page-name (subs page-name 5))]
(p/let [hls (resolve-hls-data-by-key$ target-key)
hls (and hls (:highlights hls))]
(let [file-path (if file-path file-path (str target-key ".pdf"))]
(let [file-path (or file-path (str "../assets/" target-key ".pdf"))]
(if-let [matched (and hls (medley/find-first #(= id (:id %)) hls))]
(do
(state/set-state! :pdf/ref-highlight matched)
@@ -247,47 +229,44 @@
(js/console.debug "[Unmatched highlight ref]" block)))))))
(defn goto-block-ref!
[{:keys [id]}]
[{:keys [id] :as hl}]
(when id
(ensure-ref-block!
(state/get-current-pdf) hl {:edit-block? false})
(rfe/push-state :page {:name (str id)})))
(defn goto-annotations-page!
([current] (goto-annotations-page! current nil))
([current id]
(when-let [name (:key current)]
(rfe/push-state :page {:name (make-hls name)} (if id {:anchor (str "block-content-" + id)} nil)))))
(rfe/push-state :page {:name (str "hls__" name)} (if id {:anchor (str "block-content-" + id)} nil)))))
(rum/defc area-display
[block stamp]
(let [id (:block/uuid block)
props (:block/properties block)]
(when-let [page (db-utils/pull (:db/id (:block/page block)))]
(when-let [group-key (string/replace-first (:block/original-name page) HLS-PREFIX-PATTERN "")]
(when-let [hl-page (:hl-page props)]
(let [encoded-chars? (boolean (re-find gp-util/url-encoded-pattern group-key))
group-key (if encoded-chars? (js/encodeURI group-key) group-key)
asset-path (editor-handler/make-asset-url
(str "/" gp-config/local-assets-dir "/" group-key "/" (str hl-page "_" id "_" stamp ".png")))]
[:span.hl-area
[:img {:src asset-path}]]))))))
[block]
(when-let [asset-path' (and block (pdf-utils/get-area-block-asset-url
block (db-utils/pull (:db/id (:block/page block)))))]
(let [asset-path (editor-handler/make-asset-url asset-path')]
[:span.hl-area
[:img {:src asset-path}]])))
(defn fix-local-asset-pagename
[title]
(when-not (string/blank? title)
(let [local-asset? (re-find #"[0-9]{13}_\d$" title)]
(if local-asset?
(-> title
(subs 0 (- (count title) 15))
(string/replace HLS-PREFIX-PATTERN HLS-PREFIX-DISPLAY)
[filename]
(when-not (string/blank? filename)
(let [local-asset? (re-find #"[0-9]{13}_\d$" filename)
hls? (re-find #"^hls__" filename)
len (count filename)]
(if (or local-asset? hls?)
(-> filename
(subs 0 (if local-asset? (- len 15) len))
(string/replace #"^hls__" "")
(string/replace "_" " ")
(string/trimr))
(-> title
(string/replace HLS-PREFIX-PATTERN HLS-PREFIX-DISPLAY)
(gp-util/safe-url-decode)) ;; In case user import URI pdf resource like #6167
))))
filename))))
(rum/defc human-hls-pagename-display
"Ensure it's a hls page by `hls-page?` before hand"
[title]
[:a.asset-ref
(fix-local-asset-pagename title)])
(defn human-page-name
[page-name]
(cond
(string/starts-with? page-name "hls__")
(fix-local-asset-pagename page-name)
:else (util/trim-safe page-name)))