From 3cabb4b6611d7c793f2eeccf63e5dc04a9bf191d Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sun, 8 Mar 2026 09:30:27 +0200 Subject: [PATCH 1/8] fix(pdf): not accessible on Nginx Proxy Manager with block common exploits (closes #8877) --- apps/client/src/widgets/type_widgets/file/Pdf.tsx | 2 +- .../src/widgets/type_widgets/file/PdfViewer.tsx | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/apps/client/src/widgets/type_widgets/file/Pdf.tsx b/apps/client/src/widgets/type_widgets/file/Pdf.tsx index ee731448a9..cd010857a7 100644 --- a/apps/client/src/widgets/type_widgets/file/Pdf.tsx +++ b/apps/client/src/widgets/type_widgets/file/Pdf.tsx @@ -184,7 +184,7 @@ export default function PdfPreview({ note, blob, componentId, noteContext }: { { const win = iframeRef.current?.contentWindow; if (win) { diff --git a/apps/client/src/widgets/type_widgets/file/PdfViewer.tsx b/apps/client/src/widgets/type_widgets/file/PdfViewer.tsx index 6415b89dd6..e00d0e9079 100644 --- a/apps/client/src/widgets/type_widgets/file/PdfViewer.tsx +++ b/apps/client/src/widgets/type_widgets/file/PdfViewer.tsx @@ -1,7 +1,8 @@ import type { HTMLAttributes, RefObject } from "preact"; import { useCallback, useEffect, useRef } from "preact/hooks"; -import Inter from "./../../../fonts/Inter/Inter-VariableFont_opsz,wght.ttf"; + import { useSyncedRef, useTriliumOption, useTriliumOptionBool } from "../../react/hooks"; +import Inter from "./../../../fonts/Inter/Inter-VariableFont_opsz,wght.ttf"; interface FontDefinition { name: string; @@ -10,11 +11,11 @@ interface FontDefinition { const FONTS: FontDefinition[] = [ {name: "Inter", url: Inter}, -] +]; interface PdfViewerProps extends Pick, "tabIndex"> { iframeRef?: RefObject; - /** Note: URLs are relative to /pdfjs/web. */ + /** Note: URLs are relative to /pdfjs/web, ideally use absolute paths (but without domain name) to avoid issues with some proxies. */ pdfUrl: string; onLoad?(): void; /** @@ -63,7 +64,7 @@ function useStyleInjection(iframeRef: RefObject) { const fontStyles = doc.createElement("style"); fontStyles.textContent = FONTS.map(injectFont).join("\n"); doc.head.appendChild(fontStyles); - + }, [ iframeRef ]); // React to changes. @@ -107,4 +108,4 @@ function injectFont(font: FontDefinition) { src: url('${font.url}'); } `; -} \ No newline at end of file +} From f18a53192498db71826bc27e35b4045dce5e2b19 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Thu, 5 Mar 2026 19:25:07 +0200 Subject: [PATCH 2/8] fix(mindmap): crashing on auto-switch to dark theme (closes #8879) --- apps/client/src/widgets/type_widgets/MindMap.tsx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/apps/client/src/widgets/type_widgets/MindMap.tsx b/apps/client/src/widgets/type_widgets/MindMap.tsx index ac545b49fb..a728398560 100644 --- a/apps/client/src/widgets/type_widgets/MindMap.tsx +++ b/apps/client/src/widgets/type_widgets/MindMap.tsx @@ -6,7 +6,7 @@ import "./MindMap.css"; import nodeMenu from "@mind-elixir/node-menu"; import { DISPLAYABLE_LOCALE_IDS } from "@triliumnext/commons"; import { snapdom } from "@zumer/snapdom"; -import { default as VanillaMindElixir,MindElixirData, MindElixirInstance, Operation, Options, THEME as LIGHT_THEME, DARK_THEME } from "mind-elixir"; +import { DARK_THEME, default as VanillaMindElixir, MindElixirData, MindElixirInstance, Operation, Options, THEME as LIGHT_THEME } from "mind-elixir"; import { HTMLAttributes, RefObject } from "preact"; import { useCallback, useEffect, useRef } from "preact/hooks"; @@ -154,6 +154,7 @@ function MindElixir({ containerRef: externalContainerRef, containerProps, apiRef const apiRef = useRef(null); const [ locale ] = useTriliumOption("locale"); const colorScheme = useColorScheme(); + const defaultColorScheme = useRef(colorScheme); function reinitialize() { if (!containerRef.current) return; @@ -162,7 +163,7 @@ function MindElixir({ containerRef: externalContainerRef, containerProps, apiRef el: containerRef.current, locale: LOCALE_MAPPINGS[locale as DISPLAYABLE_LOCALE_IDS] ?? undefined, editable, - theme: LIGHT_THEME + theme: defaultColorScheme.current === "dark" ? DARK_THEME : LIGHT_THEME }); if (editable) { @@ -188,7 +189,11 @@ function MindElixir({ containerRef: externalContainerRef, containerProps, apiRef if (!apiRef.current) return; const newTheme = colorScheme === "dark" ? DARK_THEME : LIGHT_THEME; if (apiRef.current.theme === newTheme) return; // Avoid unnecessary theme changes, which can be expensive to render. - apiRef.current.changeTheme(newTheme); + try { + apiRef.current.changeTheme(newTheme); + } catch (e) { + console.warn("Failed to change mind map theme:", e); + } }, [ colorScheme ]); useEffect(() => { From b27fd31c1f818d5a1e3951404330091defac300d Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Mon, 2 Mar 2026 11:21:47 +0200 Subject: [PATCH 3/8] style/pdf viewer: fix some layout issues in toolbar --- packages/pdfjs-viewer/src/custom.css | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/packages/pdfjs-viewer/src/custom.css b/packages/pdfjs-viewer/src/custom.css index bee9cfcf26..8f7ff95343 100644 --- a/packages/pdfjs-viewer/src/custom.css +++ b/packages/pdfjs-viewer/src/custom.css @@ -91,7 +91,7 @@ input[type="number"] { --input-horizontal-padding: 8px; border-radius: 4px !important; - font-size: .85rem !important; + font-size: .85rem; &:hover { --field-bg-color: var(--tn-input-hover-background); @@ -135,12 +135,14 @@ input[type="color"] { /* #region Toolbar */ -#toolbarContainer select.scaleSelect, -#toolbarContainer input.pageNumber { +#toolbarContainer select#scaleSelect, +#toolbarContainer input#pageNumber { height: calc(var(--toolbar-height) - 8px); padding-block: 0; + font-size: 13px; } + #toolbarContainer { padding-inline: 12px; } @@ -230,14 +232,19 @@ input[type="color"] { } #toolbarContainer #toolbarViewer #pageNumber { - font-size: 12px; font-weight: 600; } +#numPages { + font-size: 13px; + line-height: unset; +} + #scaleSelectContainer { --dropdown-btn-bg-color: transparent; --button-hover-color: transparent; border-radius: 6px; + margin-top: 1px; &:hover, &:focus-within{ From 8c1a58e64f858d061a363a22a8f57a926f902ed2 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sun, 8 Mar 2026 10:29:57 +0200 Subject: [PATCH 4/8] fix(pdf): cache buster not working in all circumstances --- .../widgets/type_widgets/file/PdfViewer.tsx | 2 +- packages/pdfjs-viewer/scripts/build.ts | 18 +++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/apps/client/src/widgets/type_widgets/file/PdfViewer.tsx b/apps/client/src/widgets/type_widgets/file/PdfViewer.tsx index e00d0e9079..0780a75d72 100644 --- a/apps/client/src/widgets/type_widgets/file/PdfViewer.tsx +++ b/apps/client/src/widgets/type_widgets/file/PdfViewer.tsx @@ -38,7 +38,7 @@ export default function PdfViewer({ iframeRef: externalIframeRef, pdfUrl, onLoad ref={iframeRef} class="pdf-preview" style={{width: "100%", height: "100%"}} - src={`pdfjs/web/viewer.html?file=${pdfUrl}&lang=${locale}&sidebar=${newLayout ? "0" : "1"}&editable=${editable ? "1" : "0"}`} + src={`pdfjs/web/viewer.html?v=${glob.triliumVersion}&file=${pdfUrl}&lang=${locale}&sidebar=${newLayout ? "0" : "1"}&editable=${editable ? "1" : "0"}`} onLoad={() => { injectStyles(); onLoad?.(); diff --git a/packages/pdfjs-viewer/scripts/build.ts b/packages/pdfjs-viewer/scripts/build.ts index 2728013463..496258b0b2 100644 --- a/packages/pdfjs-viewer/scripts/build.ts +++ b/packages/pdfjs-viewer/scripts/build.ts @@ -71,13 +71,17 @@ 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( - ``, - `` - ); + for (const file of [ "viewer.css", "custom.css" ]) { + html = html.replace( + ``, + ``); + } + for (const file of [ "viewer.mjs", "custom.mjs" ]) { + html = html.replace( + ``, + `` + ); + } writeFileSync(htmlFilePath, html); } From 64418c7fec2bca6b414cd6c05eb8d527e9d6e4c8 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sun, 8 Mar 2026 10:36:06 +0200 Subject: [PATCH 5/8] docs(release): prepare for v0.102.1 --- docs/Release Notes/!!!meta.json | 130 +++++++++++-------- docs/Release Notes/Release Notes/v0.102.1.md | 18 +++ 2 files changed, 96 insertions(+), 52 deletions(-) create mode 100644 docs/Release Notes/Release Notes/v0.102.1.md diff --git a/docs/Release Notes/!!!meta.json b/docs/Release Notes/!!!meta.json index 581507ba06..60744e69d0 100644 --- a/docs/Release Notes/!!!meta.json +++ b/docs/Release Notes/!!!meta.json @@ -1,6 +1,6 @@ { "formatVersion": 2, - "appVersion": "0.101.3", + "appVersion": "0.102.0", "files": [ { "isClone": false, @@ -61,6 +61,32 @@ "attachments": [], "dirFileName": "Release Notes", "children": [ + { + "isClone": false, + "noteId": "4FTGCuCiG7s7", + "notePath": [ + "hD3V4hiu2VW4", + "4FTGCuCiG7s7" + ], + "title": "v0.102.1", + "notePosition": 10, + "prefix": null, + "isExpanded": false, + "type": "text", + "mime": "text/html", + "attributes": [ + { + "type": "relation", + "name": "template", + "value": "wyurrlcDl416", + "isInheritable": false, + "position": 60 + } + ], + "format": "markdown", + "dataFileName": "v0.102.1.md", + "attachments": [] + }, { "isClone": false, "noteId": "d582eD4RY4OM", @@ -69,7 +95,7 @@ "d582eD4RY4OM" ], "title": "v0.102.0", - "notePosition": 10, + "notePosition": 20, "prefix": null, "isExpanded": false, "type": "text", @@ -95,7 +121,7 @@ "IlBzLeN3MJhw" ], "title": "v0.101.3", - "notePosition": 20, + "notePosition": 30, "prefix": null, "isExpanded": false, "type": "text", @@ -121,7 +147,7 @@ "vcBthaXcwAm6" ], "title": "v0.101.2", - "notePosition": 30, + "notePosition": 40, "prefix": null, "isExpanded": false, "type": "text", @@ -147,7 +173,7 @@ "AgUcrU9nFXuW" ], "title": "v0.101.1", - "notePosition": 40, + "notePosition": 50, "prefix": null, "isExpanded": false, "type": "text", @@ -173,7 +199,7 @@ "uYwlZ594eyJu" ], "title": "v0.101.0", - "notePosition": 50, + "notePosition": 60, "prefix": null, "isExpanded": false, "type": "text", @@ -199,7 +225,7 @@ "iPGKEk7pwJXK" ], "title": "v0.100.0", - "notePosition": 60, + "notePosition": 70, "prefix": null, "isExpanded": false, "type": "text", @@ -225,7 +251,7 @@ "7HKMTjmopLcM" ], "title": "v0.99.5", - "notePosition": 70, + "notePosition": 80, "prefix": null, "isExpanded": false, "type": "text", @@ -251,7 +277,7 @@ "RMBaNYPsRpIr" ], "title": "v0.99.4", - "notePosition": 80, + "notePosition": 90, "prefix": null, "isExpanded": false, "type": "text", @@ -277,7 +303,7 @@ "yuroLztFfpu5" ], "title": "v0.99.3", - "notePosition": 90, + "notePosition": 100, "prefix": null, "isExpanded": false, "type": "text", @@ -303,7 +329,7 @@ "z207sehwMJ6C" ], "title": "v0.99.2", - "notePosition": 100, + "notePosition": 110, "prefix": null, "isExpanded": false, "type": "text", @@ -329,7 +355,7 @@ "WGQsXq2jNyTi" ], "title": "v0.99.1", - "notePosition": 110, + "notePosition": 120, "prefix": null, "isExpanded": false, "type": "text", @@ -355,7 +381,7 @@ "cyw2Yue9vXf3" ], "title": "v0.99.0", - "notePosition": 120, + "notePosition": 130, "prefix": null, "isExpanded": false, "type": "text", @@ -381,7 +407,7 @@ "QOJwjruOUr4k" ], "title": "v0.98.1", - "notePosition": 130, + "notePosition": 140, "prefix": null, "isExpanded": false, "type": "text", @@ -407,7 +433,7 @@ "PLUoryywi0BC" ], "title": "v0.98.0", - "notePosition": 140, + "notePosition": 150, "prefix": null, "isExpanded": false, "type": "text", @@ -433,7 +459,7 @@ "lvOuiWsLDv8F" ], "title": "v0.97.2", - "notePosition": 150, + "notePosition": 160, "prefix": null, "isExpanded": false, "type": "text", @@ -459,7 +485,7 @@ "OtFZ6Nd9vM3n" ], "title": "v0.97.1", - "notePosition": 160, + "notePosition": 170, "prefix": null, "isExpanded": false, "type": "text", @@ -485,7 +511,7 @@ "SJZ5PwfzHSQ1" ], "title": "v0.97.0", - "notePosition": 170, + "notePosition": 180, "prefix": null, "isExpanded": false, "type": "text", @@ -511,7 +537,7 @@ "mYXFde3LuNR7" ], "title": "v0.96.0", - "notePosition": 180, + "notePosition": 190, "prefix": null, "isExpanded": false, "type": "text", @@ -537,7 +563,7 @@ "jthwbL0FdaeU" ], "title": "v0.95.0", - "notePosition": 190, + "notePosition": 200, "prefix": null, "isExpanded": false, "type": "text", @@ -563,7 +589,7 @@ "7HGYsJbLuhnv" ], "title": "v0.94.1", - "notePosition": 200, + "notePosition": 210, "prefix": null, "isExpanded": false, "type": "text", @@ -589,7 +615,7 @@ "Neq53ujRGBqv" ], "title": "v0.94.0", - "notePosition": 210, + "notePosition": 220, "prefix": null, "isExpanded": false, "type": "text", @@ -615,7 +641,7 @@ "VN3xnce1vLkX" ], "title": "v0.93.0", - "notePosition": 220, + "notePosition": 230, "prefix": null, "isExpanded": false, "type": "text", @@ -633,7 +659,7 @@ "WRaBfQqPr6qo" ], "title": "v0.92.7", - "notePosition": 230, + "notePosition": 240, "prefix": null, "isExpanded": false, "type": "text", @@ -659,7 +685,7 @@ "a2rwfKNmUFU1" ], "title": "v0.92.6", - "notePosition": 240, + "notePosition": 250, "prefix": null, "isExpanded": false, "type": "text", @@ -677,7 +703,7 @@ "fEJ8qErr0BKL" ], "title": "v0.92.5-beta", - "notePosition": 250, + "notePosition": 260, "prefix": null, "isExpanded": false, "type": "text", @@ -695,7 +721,7 @@ "kkkZQQGSXjwy" ], "title": "v0.92.4", - "notePosition": 260, + "notePosition": 270, "prefix": null, "isExpanded": false, "type": "text", @@ -713,7 +739,7 @@ "vAroNixiezaH" ], "title": "v0.92.3-beta", - "notePosition": 270, + "notePosition": 280, "prefix": null, "isExpanded": false, "type": "text", @@ -731,7 +757,7 @@ "mHEq1wxAKNZd" ], "title": "v0.92.2-beta", - "notePosition": 280, + "notePosition": 290, "prefix": null, "isExpanded": false, "type": "text", @@ -749,7 +775,7 @@ "IykjoAmBpc61" ], "title": "v0.92.1-beta", - "notePosition": 290, + "notePosition": 300, "prefix": null, "isExpanded": false, "type": "text", @@ -767,7 +793,7 @@ "dq2AJ9vSBX4Y" ], "title": "v0.92.0-beta", - "notePosition": 300, + "notePosition": 310, "prefix": null, "isExpanded": false, "type": "text", @@ -785,7 +811,7 @@ "3a8aMe4jz4yM" ], "title": "v0.91.6", - "notePosition": 310, + "notePosition": 320, "prefix": null, "isExpanded": false, "type": "text", @@ -803,7 +829,7 @@ "8djQjkiDGESe" ], "title": "v0.91.5", - "notePosition": 320, + "notePosition": 330, "prefix": null, "isExpanded": false, "type": "text", @@ -821,7 +847,7 @@ "OylxVoVJqNmr" ], "title": "v0.91.4-beta", - "notePosition": 330, + "notePosition": 340, "prefix": null, "isExpanded": false, "type": "text", @@ -839,7 +865,7 @@ "tANGQDvnyhrj" ], "title": "v0.91.3-beta", - "notePosition": 340, + "notePosition": 350, "prefix": null, "isExpanded": false, "type": "text", @@ -857,7 +883,7 @@ "hMoBfwSoj1SC" ], "title": "v0.91.2-beta", - "notePosition": 350, + "notePosition": 360, "prefix": null, "isExpanded": false, "type": "text", @@ -875,7 +901,7 @@ "a2XMSKROCl9z" ], "title": "v0.91.1-beta", - "notePosition": 360, + "notePosition": 370, "prefix": null, "isExpanded": false, "type": "text", @@ -893,7 +919,7 @@ "yqXFvWbLkuMD" ], "title": "v0.90.12", - "notePosition": 370, + "notePosition": 380, "prefix": null, "isExpanded": false, "type": "text", @@ -911,7 +937,7 @@ "veS7pg311yJP" ], "title": "v0.90.11-beta", - "notePosition": 380, + "notePosition": 390, "prefix": null, "isExpanded": false, "type": "text", @@ -929,7 +955,7 @@ "sq5W9TQxRqMq" ], "title": "v0.90.10-beta", - "notePosition": 390, + "notePosition": 400, "prefix": null, "isExpanded": false, "type": "text", @@ -947,7 +973,7 @@ "yFEGVCUM9tPx" ], "title": "v0.90.9-beta", - "notePosition": 400, + "notePosition": 410, "prefix": null, "isExpanded": false, "type": "text", @@ -965,7 +991,7 @@ "o4wAGqOQuJtV" ], "title": "v0.90.8", - "notePosition": 410, + "notePosition": 420, "prefix": null, "isExpanded": false, "type": "text", @@ -998,7 +1024,7 @@ "i4A5g9iOg9I0" ], "title": "v0.90.7-beta", - "notePosition": 420, + "notePosition": 430, "prefix": null, "isExpanded": false, "type": "text", @@ -1016,7 +1042,7 @@ "ThNf2GaKgXUs" ], "title": "v0.90.6-beta", - "notePosition": 430, + "notePosition": 440, "prefix": null, "isExpanded": false, "type": "text", @@ -1034,7 +1060,7 @@ "G4PAi554kQUr" ], "title": "v0.90.5-beta", - "notePosition": 440, + "notePosition": 450, "prefix": null, "isExpanded": false, "type": "text", @@ -1061,7 +1087,7 @@ "zATRobGRCmBn" ], "title": "v0.90.4", - "notePosition": 450, + "notePosition": 460, "prefix": null, "isExpanded": false, "type": "text", @@ -1079,7 +1105,7 @@ "sCDLf8IKn3Iz" ], "title": "v0.90.3", - "notePosition": 460, + "notePosition": 470, "prefix": null, "isExpanded": false, "type": "text", @@ -1097,7 +1123,7 @@ "VqqyBu4AuTjC" ], "title": "v0.90.2-beta", - "notePosition": 470, + "notePosition": 480, "prefix": null, "isExpanded": false, "type": "text", @@ -1115,7 +1141,7 @@ "RX3Nl7wInLsA" ], "title": "v0.90.1-beta", - "notePosition": 480, + "notePosition": 490, "prefix": null, "isExpanded": false, "type": "text", @@ -1133,7 +1159,7 @@ "GyueACukPWjk" ], "title": "v0.90.0-beta", - "notePosition": 490, + "notePosition": 500, "prefix": null, "isExpanded": false, "type": "text", @@ -1151,7 +1177,7 @@ "kzjHexDTTeVB" ], "title": "v0.48", - "notePosition": 500, + "notePosition": 510, "prefix": null, "isExpanded": false, "type": "text", @@ -1218,7 +1244,7 @@ "wyurrlcDl416" ], "title": "Release Template", - "notePosition": 510, + "notePosition": 520, "prefix": null, "isExpanded": false, "type": "text", diff --git a/docs/Release Notes/Release Notes/v0.102.1.md b/docs/Release Notes/Release Notes/v0.102.1.md new file mode 100644 index 0000000000..dc69df1654 --- /dev/null +++ b/docs/Release Notes/Release Notes/v0.102.1.md @@ -0,0 +1,18 @@ +# v0.102.1 +> [!NOTE] +> If you enjoyed this release, consider showing a token of appreciation by: +> +> * Pressing the โ€œStarโ€ button on [GitHub](https://github.com/TriliumNext/Trilium) (top-right). +> * Considering a one-time or recurrent donation to the [lead developer](https://github.com/eliandoran) via [GitHub Sponsors](https://github.com/sponsors/eliandoran) or [PayPal](https://paypal.me/eliandoran). +> * If you are interested in an [official mobile application](https://oss.issuehunt.io/r/TriliumNext/Trilium/issues/7447) ย ([#7447](https://github.com/TriliumNext/Trilium/issues/7447)) or [multi-user support](https://oss.issuehunt.io/r/TriliumNext/Trilium/issues/4956) ([#4956](https://github.com/TriliumNext/Trilium/issues/4956)), consider offering financial support via IssueHunt (see links). + +> [!IMPORTANT] +> This is a hotfix of v0.102.0, addressing some blocking issues. For more information about the previous major version, see [v0.102.0 changelog](https://github.com/TriliumNext/Trilium/releases/tag/v0.102.0). + +## ๐Ÿž Bugfixes + +* [Mind Map feature breaks rendering in v0.102.0](https://github.com/TriliumNext/Trilium/issues/8879) +* Fixes for the PDF viewer: + * [PDF view is '403 Forbidden' on Nginx Proxy Manager](https://github.com/TriliumNext/Trilium/issues/8877) + * [PDF: address some layout issues](https://github.com/TriliumNext/Trilium/commit/8712e7dd160564f9a923a88bf5871e63c79d40f0) by @adoriandoran + * Cache not properly invalidated across versions. \ No newline at end of file From d2b62540ecb09709579aac817f68cecda21807db Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Tue, 3 Mar 2026 20:48:42 +0200 Subject: [PATCH 6/8] fix(ci): migrate all the jank docker ci to use crane instead (#8869) --- .github/workflows/main-docker.yml | 120 +++++++++---------- docs/Release Notes/Release Notes/v0.102.1.md | 6 +- 2 files changed, 65 insertions(+), 61 deletions(-) diff --git a/.github/workflows/main-docker.yml b/.github/workflows/main-docker.yml index c1e5a61341..4be76f37ed 100644 --- a/.github/workflows/main-docker.yml +++ b/.github/workflows/main-docker.yml @@ -166,9 +166,7 @@ jobs: id: meta uses: docker/metadata-action@v5 with: - images: | - ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }} - ${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }} + images: ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }} tags: | type=ref,event=branch type=ref,event=tag @@ -189,13 +187,6 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Login to DockerHub - uses: docker/login-action@v3 - with: - registry: ${{ env.DOCKERHUB_REGISTRY }} - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Build and push by digest id: build uses: docker/build-push-action@v6 @@ -204,9 +195,7 @@ jobs: file: apps/server/${{ matrix.dockerfile }} platforms: ${{ matrix.platform }} labels: ${{ steps.meta.outputs.labels }} - outputs: | - type=image,name=${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true - type=image,name=${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true + outputs: type=image,name=${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true - name: Export digest run: | @@ -239,18 +228,8 @@ jobs: - name: Set TEST_TAG to lowercase run: echo "TEST_TAG=${TEST_TAG,,}" >> $GITHUB_ENV - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Docker meta - id: meta - uses: docker/metadata-action@v5 - with: - images: | - ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }} - ${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }} - flavor: | - latest=false + - name: Set up crane + uses: imjasonh/setup-crane@v0.4 - name: Login to GHCR uses: docker/login-action@v3 @@ -266,48 +245,69 @@ jobs: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Create manifest list and push + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=ref,event=branch + type=ref,event=tag + type=sha + flavor: | + latest=false + + - name: Verify digests exist on GHCR working-directory: /tmp/digests run: | - # Extract the branch or tag name from the ref - REF_NAME=$(echo "${GITHUB_REF}" | sed 's/refs\/heads\///' | sed 's/refs\/tags\///') + echo "Verifying all digests are available on GHCR..." + for DIGEST_FILE in *; do + DIGEST="sha256:${DIGEST_FILE}" + echo -n " ${DIGEST}: " + crane manifest "${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}@${DIGEST}" > /dev/null + echo "OK" + done - # Create and push the manifest list with both the branch/tag name and the commit SHA - docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ - -t ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:${REF_NAME} \ - $(printf '${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *) + - name: Create and push multi-arch manifest + working-directory: /tmp/digests + run: | + GHCR_IMAGE="${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}" + DOCKERHUB_IMAGE="${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}" - docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ - -t ${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${REF_NAME} \ - $(printf '${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *) + # Build -m flags for crane index append from digest files + MANIFEST_ARGS="" + for d in *; do + MANIFEST_ARGS="${MANIFEST_ARGS} -m ${GHCR_IMAGE}@sha256:${d}" + done - # If the ref is a tag, also tag the image as stable as this is part of a 'release' - # and only go in the `if` if there is NOT a `-` in the tag's name, due to tagging of `-alpha`, `-beta`, etc... + # Create multi-arch manifest for each tag from metadata, plus copy to DockerHub + while IFS= read -r TAG; do + echo "Creating manifest: ${TAG}" + crane index append ${MANIFEST_ARGS} -t "${TAG}" + + SUFFIX="${TAG#*:}" + echo "Copying to DockerHub: ${DOCKERHUB_IMAGE}:${SUFFIX}" + crane copy "${TAG}" "${DOCKERHUB_IMAGE}:${SUFFIX}" + done <<< "${{ steps.meta.outputs.tags }}" + + # For stable releases (tags without hyphens), also create stable + latest + REF_NAME="${GITHUB_REF#refs/tags/}" if [[ "${GITHUB_REF}" == refs/tags/* && ! "${REF_NAME}" =~ - ]]; then - # First create stable tags - docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ - -t ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:stable \ - $(printf '${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *) - - docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ - -t ${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:stable \ - $(printf '${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *) - - # Small delay to ensure stable tag is fully propagated - sleep 5 - - # Now update latest tags - docker buildx imagetools create \ - -t ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:latest \ - ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:stable - - docker buildx imagetools create \ - -t ${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:latest \ - ${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:stable + echo "Creating stable tags..." + crane index append ${MANIFEST_ARGS} -t "${GHCR_IMAGE}:stable" + crane copy "${GHCR_IMAGE}:stable" "${DOCKERHUB_IMAGE}:stable" + echo "Creating latest tags..." + crane copy "${GHCR_IMAGE}:stable" "${GHCR_IMAGE}:latest" + crane copy "${GHCR_IMAGE}:latest" "${DOCKERHUB_IMAGE}:latest" fi - - name: Inspect image + - name: Inspect manifests run: | - docker buildx imagetools inspect ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }} - docker buildx imagetools inspect ${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }} + REF_NAME="${GITHUB_REF#refs/heads/}" + REF_NAME="${REF_NAME#refs/tags/}" + echo "=== GHCR ===" + crane manifest "${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:${REF_NAME}" + echo "" + echo "=== DockerHub ===" + crane manifest "${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${REF_NAME}" diff --git a/docs/Release Notes/Release Notes/v0.102.1.md b/docs/Release Notes/Release Notes/v0.102.1.md index dc69df1654..5552b54b37 100644 --- a/docs/Release Notes/Release Notes/v0.102.1.md +++ b/docs/Release Notes/Release Notes/v0.102.1.md @@ -15,4 +15,8 @@ * Fixes for the PDF viewer: * [PDF view is '403 Forbidden' on Nginx Proxy Manager](https://github.com/TriliumNext/Trilium/issues/8877) * [PDF: address some layout issues](https://github.com/TriliumNext/Trilium/commit/8712e7dd160564f9a923a88bf5871e63c79d40f0) by @adoriandoran - * Cache not properly invalidated across versions. \ No newline at end of file + * Cache not properly invalidated across versions. + +## ๐Ÿ› ๏ธ Technical updates + +* [Rework Docker infrastructure to use crane](https://github.com/TriliumNext/Trilium/pull/8869) by @perfectra1n \ No newline at end of file From 0b506c6327f9e4a705eda9785c2257614142edce Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sun, 8 Mar 2026 10:41:21 +0200 Subject: [PATCH 7/8] chore(pdfjs): bump pdfjs viewer version --- packages/pdfjs-viewer/package.json | 4 ++-- scripts/update-version.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/pdfjs-viewer/package.json b/packages/pdfjs-viewer/package.json index b0bcf658a4..dc6d213817 100644 --- a/packages/pdfjs-viewer/package.json +++ b/packages/pdfjs-viewer/package.json @@ -1,6 +1,6 @@ { "name": "@triliumnext/pdfjs-viewer", - "version": "1.0.0", + "version": "0.102.1", "private": true, "scripts": { "build": "tsx scripts/build.ts", @@ -12,4 +12,4 @@ "devDependencies": { "pdfjs-dist": "5.4.624" } -} +} \ No newline at end of file diff --git a/scripts/update-version.ts b/scripts/update-version.ts index d9e52abe45..78ccc28107 100644 --- a/scripts/update-version.ts +++ b/scripts/update-version.ts @@ -30,7 +30,7 @@ function main() { patchPackageJson(join(__dirname, "..", "apps", appName, "package.json"), version); } - for (const packageName of ["commons"]) { + for (const packageName of ["commons", "pdfjs-viewer"]) { patchPackageJson(join(__dirname, "..", "packages", packageName, "package.json"), version); } } From 8ac9daa5d384dc0db833d34d6788166e54443e51 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sun, 8 Mar 2026 10:43:59 +0200 Subject: [PATCH 8/8] chore(release): prepare for v0.102.1 --- apps/client/package.json | 2 +- apps/desktop/package.json | 2 +- apps/edit-docs/package.json | 2 +- apps/server/package.json | 2 +- package.json | 2 +- packages/commons/package.json | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/client/package.json b/apps/client/package.json index 09a27470aa..5e56c49a6c 100644 --- a/apps/client/package.json +++ b/apps/client/package.json @@ -1,6 +1,6 @@ { "name": "@triliumnext/client", - "version": "0.102.0", + "version": "0.102.1", "description": "JQuery-based client for TriliumNext, used for both web and desktop (via Electron)", "private": true, "license": "AGPL-3.0-only", diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 4d89f35d71..5d6d2b9f46 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -1,6 +1,6 @@ { "name": "@triliumnext/desktop", - "version": "0.102.0", + "version": "0.102.1", "description": "Build your personal knowledge base with Trilium Notes", "private": true, "main": "src/main.ts", diff --git a/apps/edit-docs/package.json b/apps/edit-docs/package.json index 9f955bcd52..1ed87a8276 100644 --- a/apps/edit-docs/package.json +++ b/apps/edit-docs/package.json @@ -1,6 +1,6 @@ { "name": "@triliumnext/edit-docs", - "version": "0.102.0", + "version": "0.102.1", "private": true, "description": "Desktop version of Trilium which imports the demo database (presented to new users at start-up) or the user guide and other documentation and saves the modifications for committing.", "dependencies": { diff --git a/apps/server/package.json b/apps/server/package.json index 5d3b210f86..bf2bf8f409 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -1,6 +1,6 @@ { "name": "@triliumnext/server", - "version": "0.102.0", + "version": "0.102.1", "description": "The server-side component of TriliumNext, which exposes the client via the web, allows for sync and provides a REST API for both internal and external use.", "private": true, "main": "./src/main.ts", diff --git a/package.json b/package.json index d1916b465d..dca3fee59b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@triliumnext/source", - "version": "0.102.0", + "version": "0.102.1", "description": "Build your personal knowledge base with Trilium Notes", "directories": { "doc": "docs" diff --git a/packages/commons/package.json b/packages/commons/package.json index 8d32ca4042..3a3d25e0e3 100644 --- a/packages/commons/package.json +++ b/packages/commons/package.json @@ -1,6 +1,6 @@ { "name": "@triliumnext/commons", - "version": "0.102.0", + "version": "0.102.1", "description": "Shared library between the clients (e.g. browser, Electron) and the server, mostly for type definitions and utility methods.", "private": true, "type": "module",