From 21cf5e1df725d34dda22322c8a7d8e9b3ff243cd Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 3 Jan 2026 20:29:54 +0200 Subject: [PATCH 01/12] chore(client/pdf): use custom spaced update hook --- apps/client/src/widgets/react/hooks.tsx | 65 +++++++++++++++++++ .../src/widgets/type_widgets/file/Pdf.tsx | 29 ++++++--- 2 files changed, 84 insertions(+), 10 deletions(-) diff --git a/apps/client/src/widgets/react/hooks.tsx b/apps/client/src/widgets/react/hooks.tsx index 7fade29b9..1063def55 100644 --- a/apps/client/src/widgets/react/hooks.tsx +++ b/apps/client/src/widgets/react/hooks.tsx @@ -170,6 +170,71 @@ export function useEditorSpacedUpdate({ note, noteType, noteContext, getData, on return spacedUpdate; } +export function useBlobEditorSpacedUpdate({ note, noteType, noteContext, getData, onContentChange, dataSaved, updateInterval }: { + noteType: NoteType; + note: FNote, + noteContext: NoteContext | null | undefined, + getData: () => Promise | Blob | undefined, + onContentChange: (newBlob: FBlob) => void, + dataSaved?: (savedData: Blob) => void, + updateInterval?: number; +}) { + const parentComponent = useContext(ParentComponent); + const blob = useNoteBlob(note, parentComponent?.componentId); + + const callback = useMemo(() => { + return async () => { + const data = await getData(); + + // for read only notes + if (data === undefined || note.type !== noteType) return; + + protected_session_holder.touchProtectedSessionIfNecessary(note); + await server.upload(`notes/${note.noteId}/file`, new File([ data ], note.title, { type: note.mime }), parentComponent?.componentId); + dataSaved?.(data); + }; + }, [ note, getData, dataSaved, noteType, parentComponent ]); + const stateCallback = useCallback((state) => { + noteContext?.setContextData("saveState", { + state + }); + }, [ noteContext ]); + const spacedUpdate = useSpacedUpdate(callback, updateInterval, stateCallback); + + // React to note/blob changes. + useEffect(() => { + if (!blob) return; + spacedUpdate.allowUpdateWithoutChange(() => onContentChange(blob)); + }, [ blob ]); + + // React to update interval changes. + useEffect(() => { + if (!updateInterval) return; + spacedUpdate.setUpdateInterval(updateInterval); + }, [ updateInterval ]); + + // Save if needed upon switching tabs. + useTriliumEvent("beforeNoteSwitch", async ({ noteContext: eventNoteContext }) => { + if (eventNoteContext.ntxId !== noteContext?.ntxId) return; + await spacedUpdate.updateNowIfNecessary(); + }); + + // Save if needed upon tab closing. + useTriliumEvent("beforeNoteContextRemove", async ({ ntxIds }) => { + if (!noteContext?.ntxId || !ntxIds.includes(noteContext.ntxId)) return; + await spacedUpdate.updateNowIfNecessary(); + }); + + // Save if needed upon window/browser closing. + useEffect(() => { + const listener = () => spacedUpdate.isAllSavedAndTriggerUpdate(); + appContext.addBeforeUnloadListener(listener); + return () => appContext.removeBeforeUnloadListener(listener); + }, []); + + return spacedUpdate; +} + export function useNoteSavedData(noteId: string | undefined) { return useSyncExternalStore( (cb) => noteId ? noteSavedDataStore.subscribe(noteId, cb) : () => {}, diff --git a/apps/client/src/widgets/type_widgets/file/Pdf.tsx b/apps/client/src/widgets/type_widgets/file/Pdf.tsx index ad4bb8f56..cbd34eef8 100644 --- a/apps/client/src/widgets/type_widgets/file/Pdf.tsx +++ b/apps/client/src/widgets/type_widgets/file/Pdf.tsx @@ -4,9 +4,8 @@ import appContext from "../../../components/app_context"; import type NoteContext from "../../../components/note_context"; import FBlob from "../../../entities/fblob"; import FNote from "../../../entities/fnote"; -import server from "../../../services/server"; import { useViewModeConfig } from "../../collections/NoteList"; -import { useTriliumEvent } from "../../react/hooks"; +import { useBlobEditorSpacedUpdate, useTriliumEvent } from "../../react/hooks"; import PdfViewer from "./PdfViewer"; export default function PdfPreview({ note, blob, componentId, noteContext }: { @@ -17,13 +16,30 @@ export default function PdfPreview({ note, blob, componentId, noteContext }: { }) { const iframeRef = useRef(null); const historyConfig = useViewModeConfig(note, "pdfHistory"); + const dataRef = useRef(new Blob()); + + const spacedUpdate = useBlobEditorSpacedUpdate({ + note, + noteType: "file", + noteContext, + getData() { + return dataRef.current; + }, + onContentChange() { + if (iframeRef.current?.contentWindow) { + iframeRef.current.contentWindow.location.reload(); + } + } + }); useEffect(() => { function handleMessage(event: PdfMessageEvent) { if (event.data?.type === "pdfjs-viewer-document-modified") { const blob = new Blob([event.data.data as Uint8Array], { type: note.mime }); if (event.data.noteId === note.noteId && event.data.ntxId === noteContext.ntxId) { - server.upload(`notes/${note.noteId}/file`, new File([blob], note.title, { type: note.mime }), componentId); + dataRef.current = blob; + spacedUpdate.resetUpdateTimer(); + spacedUpdate.scheduleUpdate(); } } @@ -138,13 +154,6 @@ export default function PdfPreview({ note, blob, componentId, noteContext }: { }; }, [ note, historyConfig, componentId, blob, noteContext ]); - // Refresh when blob changes. - useEffect(() => { - if (iframeRef.current?.contentWindow) { - iframeRef.current.contentWindow.location.reload(); - } - }, [ blob ]); - useTriliumEvent("customDownload", ({ ntxId }) => { if (ntxId !== noteContext.ntxId) return; iframeRef.current?.contentWindow?.postMessage({ From 69511134e5d975761df5c974a1d319aadd9859b2 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 3 Jan 2026 20:54:28 +0200 Subject: [PATCH 02/12] refactor(client/pdf): handle blob request on client side --- apps/client/src/types-pdfjs.d.ts | 5 +++ apps/client/src/widgets/react/hooks.tsx | 2 +- .../src/widgets/type_widgets/file/Pdf.tsx | 20 ++++++++-- packages/pdfjs-viewer/src/custom.ts | 40 +++++++++++-------- 4 files changed, 45 insertions(+), 22 deletions(-) diff --git a/apps/client/src/types-pdfjs.d.ts b/apps/client/src/types-pdfjs.d.ts index 12756778e..3a4b3f16d 100644 --- a/apps/client/src/types-pdfjs.d.ts +++ b/apps/client/src/types-pdfjs.d.ts @@ -45,6 +45,10 @@ interface WithContext { interface PdfDocumentModifiedMessage extends WithContext { type: "pdfjs-viewer-document-modified"; +} + +interface PdfDocumentBlobResultMessage extends WithContext { + type: "pdfjs-viewer-blob"; data: Uint8Array; } @@ -113,4 +117,5 @@ type PdfMessageEvent = MessageEvent< | PdfViewerThumbnailMessage | PdfViewerAttachmentsMessage | PdfViewerLayersMessage + | PdfDocumentBlobResultMessage >; diff --git a/apps/client/src/widgets/react/hooks.tsx b/apps/client/src/widgets/react/hooks.tsx index 1063def55..17efcc275 100644 --- a/apps/client/src/widgets/react/hooks.tsx +++ b/apps/client/src/widgets/react/hooks.tsx @@ -174,7 +174,7 @@ export function useBlobEditorSpacedUpdate({ note, noteType, noteContext, getData noteType: NoteType; note: FNote, noteContext: NoteContext | null | undefined, - getData: () => Promise | Blob | undefined, + getData: () => Promise | Blob | undefined, onContentChange: (newBlob: FBlob) => void, dataSaved?: (savedData: Blob) => void, updateInterval?: number; diff --git a/apps/client/src/widgets/type_widgets/file/Pdf.tsx b/apps/client/src/widgets/type_widgets/file/Pdf.tsx index cbd34eef8..60d6f2059 100644 --- a/apps/client/src/widgets/type_widgets/file/Pdf.tsx +++ b/apps/client/src/widgets/type_widgets/file/Pdf.tsx @@ -16,14 +16,28 @@ export default function PdfPreview({ note, blob, componentId, noteContext }: { }) { const iframeRef = useRef(null); const historyConfig = useViewModeConfig(note, "pdfHistory"); - const dataRef = useRef(new Blob()); const spacedUpdate = useBlobEditorSpacedUpdate({ note, noteType: "file", noteContext, getData() { - return dataRef.current; + if (!iframeRef.current?.contentWindow) return undefined; + + return new Promise((resolve) => { + const onMessageReceived = (event: PdfMessageEvent) => { + if (event.data.type !== "pdfjs-viewer-blob") return; + if (event.data.noteId !== note.noteId || event.data.ntxId !== noteContext.ntxId) return; + const blob = new Blob([event.data.data as Uint8Array], { type: note.mime }); + window.removeEventListener("message", onMessageReceived); + resolve(blob); + }; + + window.addEventListener("message", onMessageReceived); + iframeRef.current?.contentWindow?.postMessage({ + type: "trilium-request-blob", + }); + }); }, onContentChange() { if (iframeRef.current?.contentWindow) { @@ -35,9 +49,7 @@ export default function PdfPreview({ note, blob, componentId, noteContext }: { useEffect(() => { function handleMessage(event: PdfMessageEvent) { if (event.data?.type === "pdfjs-viewer-document-modified") { - const blob = new Blob([event.data.data as Uint8Array], { type: note.mime }); if (event.data.noteId === note.noteId && event.data.ntxId === noteContext.ntxId) { - dataRef.current = blob; spacedUpdate.resetUpdateTimer(); spacedUpdate.scheduleUpdate(); } diff --git a/packages/pdfjs-viewer/src/custom.ts b/packages/pdfjs-viewer/src/custom.ts index c58e4104b..d78560122 100644 --- a/packages/pdfjs-viewer/src/custom.ts +++ b/packages/pdfjs-viewer/src/custom.ts @@ -55,35 +55,41 @@ function getCustomAppOptions(urlParams: URLSearchParams) { function manageSave() { const app = window.PDFViewerApplication; const storage = app.pdfDocument.annotationStorage; - let timeout = null; - function debouncedSave() { - if (timeout) { - clearTimeout(timeout); - } - timeout = setTimeout(async () => { - if (!storage) return; + function onChange() { + if (!storage) return; + window.parent.postMessage({ + type: "pdfjs-viewer-document-modified", + ntxId: window.TRILIUM_NTX_ID, + noteId: window.TRILIUM_NOTE_ID + } satisfies PdfDocumentModifiedMessage, window.location.origin); + storage.resetModified(); + } + + window.addEventListener("message", async (event) => { + if (event.origin !== window.location.origin) return; + + if (event.data?.type === "trilium-request-blob") { + const app = window.PDFViewerApplication; const data = await app.pdfDocument.saveDocument(); window.parent.postMessage({ - type: "pdfjs-viewer-document-modified", + type: "pdfjs-viewer-blob", data, ntxId: window.TRILIUM_NTX_ID, noteId: window.TRILIUM_NOTE_ID - } satisfies PdfDocumentModifiedMessage, window.location.origin); - storage.resetModified(); - timeout = null; - }, 2_000); - } + } satisfies PdfDocumentBlobResultMessage, window.location.origin) + } + }); - app.pdfDocument.annotationStorage.onSetModified = debouncedSave; // works great for most cases, including forms. - app.eventBus.on("annotationeditorcommit", debouncedSave); - app.eventBus.on("annotationeditorparamschanged", debouncedSave); + app.pdfDocument.annotationStorage.onSetModified = onChange; // works great for most cases, including forms. + app.eventBus.on("annotationeditorcommit", onChange); + app.eventBus.on("annotationeditorparamschanged", onChange); app.eventBus.on("annotationeditorstateschanged", evt => { // needed for detecting when annotations are moved around. const { activeEditorId } = evt; // When activeEditorId becomes null, an editor was just committed if (activeEditorId === null) { - debouncedSave(); + onChange(); } }); } From e485b75a448ef2f1b064c74d33b4b140ee6bfaf5 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sun, 4 Jan 2026 17:06:41 +0200 Subject: [PATCH 03/12] fix(pdfjs): saves as soon as document is opened --- packages/pdfjs-viewer/src/custom.ts | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/packages/pdfjs-viewer/src/custom.ts b/packages/pdfjs-viewer/src/custom.ts index d78560122..8ec01752c 100644 --- a/packages/pdfjs-viewer/src/custom.ts +++ b/packages/pdfjs-viewer/src/custom.ts @@ -81,16 +81,11 @@ function manageSave() { } }); - app.pdfDocument.annotationStorage.onSetModified = onChange; // works great for most cases, including forms. - app.eventBus.on("annotationeditorcommit", onChange); - app.eventBus.on("annotationeditorparamschanged", onChange); - app.eventBus.on("annotationeditorstateschanged", evt => { // needed for detecting when annotations are moved around. - const { activeEditorId } = evt; - - // When activeEditorId becomes null, an editor was just committed - if (activeEditorId === null) { - onChange(); - } + app.pdfDocument.annotationStorage.onSetModified = () => { + onChange(); + }; // works great for most cases, including forms. + app.eventBus.on("switchannotationeditorparams", () => { + onChange(); }); } From 23f7dc63b88abd64724709844aaf7271136e1ce9 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sun, 4 Jan 2026 17:11:16 +0200 Subject: [PATCH 04/12] feat(pdfjs): enable editing features only if in main editor --- .../src/widgets/type_widgets/file/Pdf.tsx | 1 + .../widgets/type_widgets/file/PdfViewer.tsx | 8 ++++-- packages/pdfjs-viewer/src/custom.ts | 27 +++++++++++-------- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/apps/client/src/widgets/type_widgets/file/Pdf.tsx b/apps/client/src/widgets/type_widgets/file/Pdf.tsx index 60d6f2059..d7a09b35a 100644 --- a/apps/client/src/widgets/type_widgets/file/Pdf.tsx +++ b/apps/client/src/widgets/type_widgets/file/Pdf.tsx @@ -192,6 +192,7 @@ export default function PdfPreview({ note, blob, componentId, noteContext }: { }); } }} + editable /> ); } diff --git a/apps/client/src/widgets/type_widgets/file/PdfViewer.tsx b/apps/client/src/widgets/type_widgets/file/PdfViewer.tsx index 82bc4a2b9..7e6870dd4 100644 --- a/apps/client/src/widgets/type_widgets/file/PdfViewer.tsx +++ b/apps/client/src/widgets/type_widgets/file/PdfViewer.tsx @@ -15,12 +15,16 @@ interface PdfViewerProps extends Pick, "tabInd /** Note: URLs are relative to /pdfjs/web. */ pdfUrl: string; onLoad?(): void; + /** + * If set, enables editable mode which includes persistence of user settings, annotations as well as specific features such as sending table of contents data for the sidebar. + */ + editable?: boolean; } /** * Reusable component displaying a PDF. The PDF needs to be provided via a URL. */ -export default function PdfViewer({ iframeRef: externalIframeRef, pdfUrl, onLoad }: PdfViewerProps) { +export default function PdfViewer({ iframeRef: externalIframeRef, pdfUrl, onLoad, editable }: PdfViewerProps) { const iframeRef = useSyncedRef(externalIframeRef, null); const [ locale ] = useTriliumOption("locale"); const [ newLayout ] = useTriliumOptionBool("newLayout"); @@ -30,7 +34,7 @@ export default function PdfViewer({ iframeRef: externalIframeRef, pdfUrl, onLoad '); - $pdfPreview.attr("src", openService.getUrlForDownload(`api/${entityType}/${entityId}/open`)); + $pdfPreview.attr("src", openService.getUrlForDownload(`pdfjs/web/viewer.html?file=../../api/${entityType}/${entityId}/open`)); $content.append($pdfPreview); } else if (type === "audio") { From 757fc7a7fe823540e6b4ba2b4540a7b04fef186f Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sun, 4 Jan 2026 18:50:40 +0200 Subject: [PATCH 08/12] chore(pdfjs): embed sandbox file --- packages/pdfjs-viewer/scripts/build.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/pdfjs-viewer/scripts/build.ts b/packages/pdfjs-viewer/scripts/build.ts index 6f9d3a53d..9683b31cc 100644 --- a/packages/pdfjs-viewer/scripts/build.ts +++ b/packages/pdfjs-viewer/scripts/build.ts @@ -34,8 +34,9 @@ async function main() { build.writeJson("web/locale/locale.json", localeMappings); // Copy pdfjs-dist files. - build.copy("/node_modules/pdfjs-dist/build/pdf.mjs", "build/pdf.mjs"); - build.copy("/node_modules/pdfjs-dist/build/pdf.worker.mjs", "build/pdf.worker.mjs"); + for (const file of [ "pdf.mjs", "pdf.worker.mjs", "pdf.sandbox.mjs" ]) { + build.copy(join("/node_modules/pdfjs-dist/build", file), join("build", file)); + } if (watchMode) { watchForChanges(); From 971d6ad9e3c3254db73c621823f8311af7939077 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sun, 4 Jan 2026 20:06:11 +0200 Subject: [PATCH 09/12] chore(pdfjs): use version-based system for cache busting --- packages/pdfjs-viewer/scripts/build.ts | 18 ++++++++++++++++++ scripts/update-nightly-version.ts | 13 +++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/packages/pdfjs-viewer/scripts/build.ts b/packages/pdfjs-viewer/scripts/build.ts index 9683b31cc..ff0cd9805 100644 --- a/packages/pdfjs-viewer/scripts/build.ts +++ b/packages/pdfjs-viewer/scripts/build.ts @@ -3,6 +3,8 @@ import BuildHelper from "../../../scripts/build-utils"; import { build as esbuild } from "esbuild"; import { LOCALES } from "@triliumnext/commons"; import { watch } from "chokidar"; +import { readFileSync, writeFileSync } from "fs"; +import packageJson from "../package.json" with { type: "json "}; const build = new BuildHelper("packages/pdfjs-viewer"); const watchMode = process.argv.includes("--watch"); @@ -16,6 +18,7 @@ async function main() { for (const file of [ "viewer.css", "viewer.html", "viewer.mjs" ]) { build.copy(`viewer/${file}`, `web/${file}`); } + patchCacheBuster(`${build.outDir}/web/viewer.html`); build.copy(`viewer/images`, `web/images`); // Copy the custom files. @@ -60,6 +63,21 @@ async function rebuildCustomFiles() { build.copy("src/custom.css", "web/custom.css"); } +function patchCacheBuster(htmlFilePath: string) { + const version = packageJson.version; + console.log(`Versioned URLs: ${version}.`) + let html = readFileSync(htmlFilePath, "utf-8"); + html = html.replace( + ``, + ``); + html = html.replace( + `` , + `` + ); + + writeFileSync(htmlFilePath, html); +} + function watchForChanges() { console.log("Watching for changes in src directory..."); const watcher = watch(join(build.projectDir, "src"), { diff --git a/scripts/update-nightly-version.ts b/scripts/update-nightly-version.ts index 2c0179331..71f5a9684 100644 --- a/scripts/update-nightly-version.ts +++ b/scripts/update-nightly-version.ts @@ -11,9 +11,9 @@ * */ -import { fileURLToPath } from "url"; -import { dirname, join } from "path"; import fs from "fs"; +import { dirname, join } from "path"; +import { fileURLToPath } from "url"; function processVersion(version) { // Remove the beta suffix if any. @@ -42,14 +42,19 @@ function patchPackageJson(packageJsonPath) { function main() { const scriptDir = dirname(fileURLToPath(import.meta.url)); - + const rootPackageJson = join(scriptDir, "..", "package.json"); patchPackageJson(rootPackageJson); - + for (const app of ["server", "client"]) { const appPackageJsonPath = join(scriptDir, "..", "apps", app, "package.json"); patchPackageJson(appPackageJsonPath); } + + for (const packageName of [ "pdfjs-viewer" ]) { + const packageJsonPath = join(scriptDir, "..", "packages", packageName, "package.json"); + patchPackageJson(packageJsonPath); + } } main(); From 20c265201325ec306612504adfba377535d7d57a Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sun, 4 Jan 2026 20:33:54 +0200 Subject: [PATCH 10/12] chore(server): set up environment for starting Nginx proxy with subdir --- apps/server/docker/nginx.conf | 2 +- apps/server/package.json | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/server/docker/nginx.conf b/apps/server/docker/nginx.conf index 3c207c1ce..e4e744b18 100644 --- a/apps/server/docker/nginx.conf +++ b/apps/server/docker/nginx.conf @@ -9,7 +9,7 @@ server { proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; - proxy_pass http://host.docker.internal:8082; # change it to a different port if non-default is used + proxy_pass http://127.0.0.1:8082; proxy_cookie_path / /trilium/; proxy_read_timeout 90; } diff --git a/apps/server/package.json b/apps/server/package.json index 4dcd1c561..ecde42986 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -25,7 +25,8 @@ "docker-start-rootless-debian": "pnpm docker-build-rootless-debian && docker run -p 8081:8080 triliumnext-rootless-debian", "docker-start-rootless-alpine": "pnpm docker-build-rootless-alpine && docker run -p 8081:8080 triliumnext-rootless-alpine", "generate-document": "cross-env TRILIUM_ENV=dev TRILIUM_DATA_DIR=data TRILIUM_RESOURCE_DIR=src tsx ./scripts/generate_document.ts", - "proxy-traefik": "docker run --name trilium-traefik --rm --network=host -v ./docker/traefik/traefik.yml:/etc/traefik/traefik.yml -v ./docker/traefik/dynamic:/etc/traefik/dynamic traefik:latest" + "proxy-traefik": "docker run --name trilium-traefik --rm --network=host -v ./docker/traefik/traefik.yml:/etc/traefik/traefik.yml:ro -v ./docker/traefik/dynamic:/etc/traefik/dynamic traefik:latest", + "proxy-nginx-subdir": "docker run --name trilium-nginx-subdir --rm --network=host -v ./docker/nginx.conf:/etc/nginx/conf.d/default.conf:ro nginx:latest" }, "dependencies": { "better-sqlite3": "12.5.0", From fb4e912ed0cca7217927ef226e3e23f221b0de01 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sun, 4 Jan 2026 21:08:39 +0200 Subject: [PATCH 11/12] chore(pdfjs): address requested changes --- apps/client/src/widgets/type_widgets/file/Pdf.tsx | 10 ++++++++-- packages/pdfjs-viewer/scripts/build.ts | 4 ++-- packages/pdfjs-viewer/src/custom.ts | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/apps/client/src/widgets/type_widgets/file/Pdf.tsx b/apps/client/src/widgets/type_widgets/file/Pdf.tsx index 7acbc6d6c..ee731448a 100644 --- a/apps/client/src/widgets/type_widgets/file/Pdf.tsx +++ b/apps/client/src/widgets/type_widgets/file/Pdf.tsx @@ -24,11 +24,17 @@ export default function PdfPreview({ note, blob, componentId, noteContext }: { getData() { if (!iframeRef.current?.contentWindow) return undefined; - return new Promise((resolve) => { + return new Promise((resolve, reject) => { + const timeout = setTimeout(() => { + reject(new Error("Timeout while waiting for blob response")); + }, 10_000); + const onMessageReceived = (event: PdfMessageEvent) => { if (event.data.type !== "pdfjs-viewer-blob") return; if (event.data.noteId !== note.noteId || event.data.ntxId !== noteContext.ntxId) return; const blob = new Blob([event.data.data as Uint8Array], { type: note.mime }); + + clearTimeout(timeout); window.removeEventListener("message", onMessageReceived); resolve(blob); }; @@ -36,7 +42,7 @@ export default function PdfPreview({ note, blob, componentId, noteContext }: { window.addEventListener("message", onMessageReceived); iframeRef.current?.contentWindow?.postMessage({ type: "trilium-request-blob", - }); + }, window.location.origin); }); }, onContentChange() { diff --git a/packages/pdfjs-viewer/scripts/build.ts b/packages/pdfjs-viewer/scripts/build.ts index ff0cd9805..4a7e56880 100644 --- a/packages/pdfjs-viewer/scripts/build.ts +++ b/packages/pdfjs-viewer/scripts/build.ts @@ -4,7 +4,7 @@ import { build as esbuild } from "esbuild"; import { LOCALES } from "@triliumnext/commons"; import { watch } from "chokidar"; import { readFileSync, writeFileSync } from "fs"; -import packageJson from "../package.json" with { type: "json "}; +import packageJson from "../package.json" with { type: "json " }; const build = new BuildHelper("packages/pdfjs-viewer"); const watchMode = process.argv.includes("--watch"); @@ -71,7 +71,7 @@ function patchCacheBuster(htmlFilePath: string) { ``, ``); html = html.replace( - `` , + ``, `` ); diff --git a/packages/pdfjs-viewer/src/custom.ts b/packages/pdfjs-viewer/src/custom.ts index 2532c8d76..95b56a3c2 100644 --- a/packages/pdfjs-viewer/src/custom.ts +++ b/packages/pdfjs-viewer/src/custom.ts @@ -82,7 +82,7 @@ function manageSave() { data, ntxId: window.TRILIUM_NTX_ID, noteId: window.TRILIUM_NOTE_ID - } satisfies PdfDocumentBlobResultMessage, window.location.origin) + } satisfies PdfDocumentBlobResultMessage, window.location.origin); } }); From 51a19d054470a51b115ee6d78a1d7c9a1c333d99 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sun, 4 Jan 2026 21:11:13 +0200 Subject: [PATCH 12/12] docs(user): add missing slug --- docs/User Guide/!!!meta.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/User Guide/!!!meta.json b/docs/User Guide/!!!meta.json index 272c4dbfe..50b9abb02 100644 --- a/docs/User Guide/!!!meta.json +++ b/docs/User Guide/!!!meta.json @@ -10201,6 +10201,13 @@ "value": "bx bxs-file-pdf", "isInheritable": false, "position": 30 + }, + { + "type": "label", + "name": "shareAlias", + "value": "pdf", + "isInheritable": false, + "position": 60 } ], "format": "markdown",