Skip to content

fix(pdf): use assets:// protocol for local PDFs/images on Electron - #12970

Open
e-zz wants to merge 3 commits into
logseq:masterfrom
e-zz:fix/12746-pdf-assets-url
Open

fix(pdf): use assets:// protocol for local PDFs/images on Electron#12970
e-zz wants to merge 3 commits into
logseq:masterfrom
e-zz:fix/12746-pdf-assets-url

Conversation

@e-zz

@e-zz e-zz commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #12746 — local PDFs and inline images fail to open in the Electron app because Chromium's security policy blocks file:// URLs in the renderer ("Not allowed to load local resource" / Unexpected server response (0)).

Note: this PR was generated with the assistance of AI agents. The key findings from our debugging trials are documented below so reviewers can verify the reasoning rather than just the diff.

Root cause

Three code paths assembled PDF/image URLs by raw string concatenation, bypassing Logseq's registered assets:// protocol on Electron:

  1. frontend.extensions.zotero/zotero-linked-file and zotero-full-path(str "file://" (node-path/join ...))
  2. frontend.extensions.pdf.assets/get-zotero-local-pdf-path(str "assets://" (node-path/join ...))
  3. frontend.handler.assets/normalize-asset-resource-url and <make-asset-url — returned file:// URLs unchanged

Key findings from our trials

Finding 1: naive file://assets:// replacement is NOT enough on Windows

The first fix attempt simply replaced the file:// prefix with assets://. This broke on Windows: assets://C:/Users/... is parsed by the URL parser as host=c, port=/Users/... — the drive letter is consumed as the authority, the path is lost, and the request fails. The error shown in the app was:

Unexpected server response (0) while retrieving PDF "assets://c/Users/zhang/biblio/library/qn/Cao et al....pdf"

Note the lowercase c — that's the host component, not the path.

Finding 2: the drive letter must be protected before URL assembly

Logseq already has protect-windows-drive-in-assets-path (C:C/logseq__colon/), used by the normal asset path. The Electron main process reverses it in decode-protected-assets-schema-path (src/electron/electron/utils.cljs). The fix routes every file:// URL and zotero path through normalize-asset-resource-url, which applies this protection:

file://C:/Users/...  →  assets:///C/logseq__colon/Users/...

The correct form has three slashes and the encoded drive — the host is empty, the path is preserved.

Finding 3: verify the transformation, not just the prefix

Verified end-to-end with the real file paths from a user graph: the produced URL decodes through the Electron handler to the exact filesystem path (C:/Users/zhang/biblio/library/qn/Cao et al....pdf) and the file exists. All three code paths produce the canonical assets:///C/logseq__colon/... form that Electron already serves correctly for Windows images.

Changes

  • src/main/frontend/handler/assets.cljs
    • normalize-asset-resource-url: on Electron, strip file:// then re-normalize (applies drive protection)
    • <make-asset-url: same conversion when the URL protocol is file:
  • src/main/frontend/extensions/pdf/assets.cljs
    • get-zotero-local-pdf-path: build the local path, then normalize on Electron
    • inflate-asset: strip file:// then normalize on Electron
  • src/main/frontend/extensions/zotero.cljs
    • zotero-linked-file / zotero-full-path: build the local path, normalize on Electron instead of raw file:// concat

Non-Electron (web browser) behavior is unchanged — file:// is still emitted there since it's the only way a browser can reference local files.

Test plan

  • bb dev:test -v frontend.handler.assets-test — 14 tests, 23 assertions, 0 failures
  • Manual: open a {{zotero-linked-file ...}} PDF and an asset-block PDF on Windows Electron — both load via assets://

e-zz added 3 commits August 4, 2026 00:24
On Electron, Chromium blocks file:// URLs from the renderer process.
The assets:// custom protocol is already registered to handle local
file access. This change ensures all code paths that generate PDF
or image URLs use assets:// instead of file:// on Electron.

Fixes logseq#12746
get-zotero-local-pdf-path concatenated assets:// directly with the
joined path, so 'assets://C:/Users/...' was parsed with C: as the URL
host (lowercased to c), losing the path. Route through
normalize-asset-resource-url which applies protect-windows-drive-in-assets-path
(C: -> C/logseq__colon/), producing assets:///C/logseq__colon/Users/...
…drives

The previous fix replaced file:// with assets:// but left the drive
letter as the URL host (assets://C:/Users -> host 'c', losing the path).
Now strip file:// and route through normalize-asset-resource-url, which
applies protect-windows-drive-in-assets-path (C: -> C/logseq__colon/).
Also fix zotero-linked-file/zotero-imported-file macros to build local
paths and let normalize handle them on Electron.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

pdf not opening

1 participant