fix(asset): handle external-url paths and plugin binary writes (#12656)

This commit is contained in:
A. S.
2026-05-15 10:13:58 +01:00
committed by GitHub
parent 4eb012ac7e
commit a9778555c1
4 changed files with 40 additions and 6 deletions

View File

@@ -562,7 +562,13 @@
{:on-click (fn [e]
(util/stop e)
(let [repo-dir (config/get-repo-dir repo)
file-fpath (path/path-join repo-dir (str "assets/" (:block/uuid asset-block) "." (name ext)))]
ext-url (:logseq.property.asset/external-url asset-block)
local-ext-url? (and (not (string/blank? ext-url))
(common-config/local-relative-asset? ext-url))
file-fpath (if local-ext-url?
;; Plugin-sourced asset stored under assets/storages/<plugin-id>/...
(path/path-join repo-dir (string/replace ext-url #"^[./]+" ""))
(path/path-join repo-dir (str "assets/" (:block/uuid asset-block) "." (name ext))))]
(js/window.apis.openPath file-fpath)))}
file-name])
@@ -1113,13 +1119,19 @@
img-placeholder (when image?
[:div.img-placeholder.asset-container
{:style img-metadata}])
;; When external-url is set, use it as the render path so
;; plugin-sandboxed assets (./assets/storages/<plugin-id>/...)
;; resolve correctly; <make-asset-url handles both remote URLs
;; and graph-root-relative paths.
href (or (:logseq.property.asset/external-url block)
(path/path-join (str "../" common-config/local-assets-dir) file))
content (cond
file-ready?
(asset-link (assoc config
:asset-block block
:image-placeholder img-placeholder)
(:block/title block)
(path/path-join (str "../" common-config/local-assets-dir) file)
href
img-metadata
nil)
image?

View File

@@ -356,7 +356,10 @@
video? (contains? config/video-formats asset-type)
pdf? (= :pdf asset-type)
file-name (str (:block/uuid asset) "." asset-type-str)
rel-path (path/path-join (str "../" common-config/local-assets-dir) file-name)]
;; Prefer external-url so plugin-sandboxed assets resolve to their
;; real on-disk path; mirrors the asset-cp render-side fix.
rel-path (or (:logseq.property.asset/external-url asset)
(path/path-join (str "../" common-config/local-assets-dir) file-name))]
(cond
image?
(p/let [url (assets-handler/<make-asset-url rel-path)]

View File

@@ -122,7 +122,7 @@
(defn- schema-type-check!
[type]
(let [valid-types #{:default :number :date :datetime :checkbox :url :node :json :string}]
(let [valid-types #{:default :number :date :datetime :checkbox :url :node :asset :json :string}]
(when-not (contains? valid-types type)
(throw (ex-info (str "Invalid type, type should be one of: " valid-types) {:type type})))))
@@ -151,7 +151,7 @@
(defn upsert-property
"schema:
{:type :default | :number | :date | :datetime | :checkbox | :url | :node | :json | :string
{:type :default | :number | :date | :datetime | :checkbox | :url | :node | :asset | :json | :string
:cardinality :many | :one
:hide? true
:view-context :page

View File

@@ -6,6 +6,7 @@
[electron.ipc :as ipc]
[frontend.config :as config]
[frontend.fs :as fs]
[frontend.handler.assets :as assets-handler]
[frontend.handler.command-palette :as palette-handler]
[frontend.handler.common.plugin :as plugin-common-handler]
[frontend.handler.plugin :as plugin-handler]
@@ -88,6 +89,18 @@
[plugin-id]
(util/node-path.join "storages" (util/node-path.basename plugin-id)))
(defn- binary-content?
"Detect payload shapes that can't be transit-serialized through ipc/ipc.
Mirrors assets-handler/->uint8 — anything it accepts as binary, we route
through writeFileBytes instead of write-plain-text-file!."
[content]
(or (instance? js/ArrayBuffer content)
(instance? js/Uint8Array content)
(and (exists? js/ArrayBuffer) (.isView js/ArrayBuffer content))
(and (object? content)
(= "Buffer" (aget content "type"))
(array? (aget content "data")))))
(defn- write_rootdir_file
[file content sub-root root-dir]
(p/let [repo ""
@@ -98,7 +111,13 @@
user-path-root (util/node-path.dirname user-path)
exist? (fs/file-exists? user-path-root "")
_ (when-not exist? (fs/mkdir-recur! user-path-root))
_ (fs/write-plain-text-file! repo nil user-path content {:skip-compare? true})]
;; Binary content (ArrayBuffer/Uint8Array/...) can't survive
;; transit serialization through ipc/ipc inside write-plain-text-file!,
;; so on Electron we bypass to window.apis.writeFileBytes — same path
;; the native fs/write-asset-file! uses for the same reason.
_ (if (and (binary-content? content) (util/electron?))
(js/window.apis.writeFileBytes user-path (assets-handler/->uint8 content))
(fs/write-plain-text-file! repo nil user-path content {:skip-compare? true}))]
user-path))
(defn write_dotdir_file