From 210dcfb98969a9bdda26073c89b7bac352404e3d Mon Sep 17 00:00:00 2001 From: SiriusXT <1160925501@qq.com> Date: Fri, 28 Nov 2025 19:38:52 +0800 Subject: [PATCH 01/80] fix(empty): open note in the correct split pane --- apps/client/src/widgets/type_widgets/Empty.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/client/src/widgets/type_widgets/Empty.tsx b/apps/client/src/widgets/type_widgets/Empty.tsx index eb0f0c5eeb..013f931fc2 100644 --- a/apps/client/src/widgets/type_widgets/Empty.tsx +++ b/apps/client/src/widgets/type_widgets/Empty.tsx @@ -45,10 +45,10 @@ function NoteSearch() { if (!suggestion?.notePath) { return false; } - - const activeContext = appContext.tabManager.getActiveContext(); - if (activeContext) { - activeContext.setNote(suggestion.notePath); + const ntxId = autocompleteRef.current?.closest(".note-split")?.getAttribute("data-ntx-id") ?? null; + const activeNoteContext = appContext.tabManager.getNoteContextById(ntxId) ?? appContext.tabManager.getActiveContext(); + if (activeNoteContext) { + activeNoteContext.setNote(suggestion.notePath); } }} /> From 407cac588a3e60bb185d249c5f9dd2859e7247ac Mon Sep 17 00:00:00 2001 From: SiriusXT <1160925501@qq.com> Date: Fri, 28 Nov 2025 19:42:04 +0800 Subject: [PATCH 02/80] fix(split): only trigger focusOnDetail when necessary --- apps/client/src/components/app_context.ts | 2 +- apps/client/src/components/tab_manager.ts | 2 +- apps/client/src/widgets/NoteDetail.tsx | 8 +++++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/apps/client/src/components/app_context.ts b/apps/client/src/components/app_context.ts index bda3536da8..c44ca01aa7 100644 --- a/apps/client/src/components/app_context.ts +++ b/apps/client/src/components/app_context.ts @@ -487,7 +487,7 @@ type EventMappings = { relationMapResetPanZoom: { ntxId: string | null | undefined }; relationMapResetZoomIn: { ntxId: string | null | undefined }; relationMapResetZoomOut: { ntxId: string | null | undefined }; - activeNoteChanged: {}; + activeNoteChanged: {ntxId: string | null | undefined}; showAddLinkDialog: AddLinkOpts; showIncludeDialog: IncludeNoteOpts; openBulkActionsDialog: { diff --git a/apps/client/src/components/tab_manager.ts b/apps/client/src/components/tab_manager.ts index 127ec30b7d..3cf06a7793 100644 --- a/apps/client/src/components/tab_manager.ts +++ b/apps/client/src/components/tab_manager.ts @@ -165,7 +165,7 @@ export default class TabManager extends Component { const activeNoteContext = this.getActiveContext(); this.updateDocumentTitle(activeNoteContext); - this.triggerEvent("activeNoteChanged", {}); // trigger this even in on popstate event + this.triggerEvent("activeNoteChanged", {ntxId:activeNoteContext?.ntxId}); // trigger this even in on popstate event } calculateHash(): string { diff --git a/apps/client/src/widgets/NoteDetail.tsx b/apps/client/src/widgets/NoteDetail.tsx index 5b5838584c..1ee5c58c60 100644 --- a/apps/client/src/widgets/NoteDetail.tsx +++ b/apps/client/src/widgets/NoteDetail.tsx @@ -95,9 +95,11 @@ export default function NoteDetail() { }); // Automatically focus the editor. - useTriliumEvent("activeNoteChanged", () => { - // Restore focus to the editor when switching tabs, but only if the note tree is not already focused. - if (!document.activeElement?.classList.contains("fancytree-title")) { + useTriliumEvent("activeNoteChanged", ({ ntxId: eventNtxId }) => { + if (eventNtxId != ntxId) return; + // Restore focus to the editor when switching tabs, + // but only if the note tree and the note panel (e.g., note title or note detail) are not focused. + if (!document.activeElement?.classList.contains("fancytree-title") && !parentComponent.$widget[0].closest(".note-split")?.contains(document.activeElement)) { parentComponent.triggerCommand("focusOnDetail", { ntxId }); } }); From 648ab4d736061b49c5033c0392070971f2f22986 Mon Sep 17 00:00:00 2001 From: SiriusXT <1160925501@qq.com> Date: Fri, 28 Nov 2025 19:45:19 +0800 Subject: [PATCH 03/80] fix(left-pane): only focus the note when toggling left pane visibility if necessary --- apps/client/src/widgets/containers/left_pane_container.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/client/src/widgets/containers/left_pane_container.ts b/apps/client/src/widgets/containers/left_pane_container.ts index e6bc78e232..cd832560bc 100644 --- a/apps/client/src/widgets/containers/left_pane_container.ts +++ b/apps/client/src/widgets/containers/left_pane_container.ts @@ -29,7 +29,11 @@ export default class LeftPaneContainer extends FlexContainer { if (visible) { this.triggerEvent("focusTree", {}); } else { - this.triggerEvent("focusOnDetail", { ntxId: appContext.tabManager.getActiveContext()?.ntxId }); + const ntxId = appContext.tabManager.getActiveContext()?.ntxId; + const noteContainer = document.querySelector(`.note-split[data-ntx-id="${ntxId}"]`); + if (!noteContainer?.contains(document.activeElement)) { + this.triggerEvent("focusOnDetail", { ntxId }); + } } options.save("leftPaneVisible", this.currentLeftPaneVisible.toString()); From 1898efa2829c404ce49f045156140c09ca3004b6 Mon Sep 17 00:00:00 2001 From: SiriusXT <1160925501@qq.com> Date: Fri, 28 Nov 2025 19:48:37 +0800 Subject: [PATCH 04/80] chore(e2e): add Playwright tests for split pane --- apps/server-e2e/src/layout/split_pane.spec.ts | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 apps/server-e2e/src/layout/split_pane.spec.ts diff --git a/apps/server-e2e/src/layout/split_pane.spec.ts b/apps/server-e2e/src/layout/split_pane.spec.ts new file mode 100644 index 0000000000..82a97b54e4 --- /dev/null +++ b/apps/server-e2e/src/layout/split_pane.spec.ts @@ -0,0 +1,72 @@ +import { test, expect } from "@playwright/test"; +import App from "../support/app"; + +const TEXT_NOTE_TITLE = "Text notes"; +const CODE_NOTE_TITLE = "Code notes"; + +test("Open the note in the correct split pane", async ({ page, context }) => { + const app = new App(page, context); + await app.goto(); + await app.closeAllTabs(); + + // Open the first split. + await app.goToNoteInNewTab(TEXT_NOTE_TITLE); + const split1 = app.currentNoteSplit; + + // Create a new split. + const splitButton = split1.locator("button.bx-dock-right"); + await expect(splitButton).toBeVisible(); + await splitButton.click(); + + // Search for "Code notes" in the empty area of the second split. + const split2 = app.currentNoteSplit.nth(1);; + await expect(split2).toBeVisible(); + const autocomplete = split2.locator(".note-autocomplete"); + await autocomplete.fill(CODE_NOTE_TITLE); + const resultsSelector = split2.locator(".note-detail-empty-results"); + await expect(resultsSelector).toContainText(CODE_NOTE_TITLE); + + //Focus on the first split. + const noteContent = split1.locator(".note-detail-editable-text-editor"); + await expect(noteContent.locator("p")).toBeVisible(); + await noteContent.focus(); + + // Click the search result in the second split. + await resultsSelector.locator(".aa-suggestion", { hasText: CODE_NOTE_TITLE }) + .nth(1).click(); + + await expect(split2).toContainText(CODE_NOTE_TITLE); +}); + +test("Can directly focus the autocomplete input within the split", async ({ page, context }) => { + const app = new App(page, context); + await app.goto(); + await app.closeAllTabs(); + + // Open the first split. + await app.goToNoteInNewTab(TEXT_NOTE_TITLE); + const split1 = app.currentNoteSplit; + + // Create a new split. + const splitButton = split1.locator("button.bx-dock-right"); + await expect(splitButton).toBeVisible(); + await splitButton.click(); + + // Search for "Code notes" in the empty area of the second split. + const split2 = app.currentNoteSplit.nth(1);; + await expect(split2).toBeVisible(); + + // Focus the first split. + const noteContent = split1.locator(".note-detail-editable-text-editor"); + await expect(noteContent.locator("p")).toBeVisible(); + await noteContent.focus(); + await noteContent.click(); + + // click the autocomplete input box of the second split + const autocomplete = split2.locator(".note-autocomplete"); + await autocomplete.focus(); + await autocomplete.click(); + + await page.waitForTimeout(100); + await expect(autocomplete).toBeFocused(); +}); \ No newline at end of file From 5847ce5c1419c971e47f8373926ffb9f4efda053 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 28 Nov 2025 23:21:14 +0200 Subject: [PATCH 05/80] feat(dev): enable CSS source maps --- apps/server/src/routes/assets.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/server/src/routes/assets.ts b/apps/server/src/routes/assets.ts index d8854d31a9..7fc3f1a271 100644 --- a/apps/server/src/routes/assets.ts +++ b/apps/server/src/routes/assets.ts @@ -27,7 +27,8 @@ async function register(app: express.Application) { appType: "custom", cacheDir: path.join(srcRoot, "../../.cache/vite"), base: `/${assetUrlFragment}/`, - root: clientDir + root: clientDir, + css: { devSourcemap: true } }); app.use(`/${assetUrlFragment}/`, (req, res, next) => { req.url = `/${assetUrlFragment}` + req.url; From 19cf07564f3d17d77ac30a2cc40d98b5f0c141f5 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 28 Nov 2025 23:21:31 +0200 Subject: [PATCH 06/80] style(mobile/context_menu): taller height + small animation when expanding items --- apps/client/src/stylesheets/style.css | 2 +- .../src/stylesheets/theme-next/base.css | 27 ++++++++++++------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/apps/client/src/stylesheets/style.css b/apps/client/src/stylesheets/style.css index 342cd671a3..62afc2012f 100644 --- a/apps/client/src/stylesheets/style.css +++ b/apps/client/src/stylesheets/style.css @@ -1316,7 +1316,7 @@ body.mobile #context-menu-container.mobile-bottom-menu { inset-inline-end: 0 !important; bottom: 0 !important; top: unset !important; - max-height: 70vh; + max-height: 90vh; overflow: auto !important; user-select: none; -webkit-user-select: none; diff --git a/apps/client/src/stylesheets/theme-next/base.css b/apps/client/src/stylesheets/theme-next/base.css index c2bb97c00b..5e62b80116 100644 --- a/apps/client/src/stylesheets/theme-next/base.css +++ b/apps/client/src/stylesheets/theme-next/base.css @@ -367,19 +367,26 @@ body.mobile .dropdown-menu { padding: var(--dropdown-menu-padding-vertical) var(--dropdown-menu-padding-horizontal); } + .dropdown-menu { + --menu-background-color: rgba(0, 0, 0, 0.15); + border-radius: 0; + max-height: 0; + transition: max-height 100ms ease-in; + display: block !important; + + &.show { + max-height: 1000px; + } + + .dropdown-item { + background: transparent; + } + } + &.submenu-open { .dropdown-toggle { padding-bottom: var(--dropdown-menu-padding-vertical); - } - - .dropdown-menu { - --menu-background-color: rgba(0, 0, 0, 0.15); - border-radius: 0; - - .dropdown-item { - background: transparent; - } - } + } } } } From 3cc64b576429b050ea356c3c76b8bf72f4a5b9b7 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 28 Nov 2025 23:43:16 +0200 Subject: [PATCH 07/80] fix(mobile/context_menu): note color picker not working --- .../menus/custom-items/NoteColorPicker.tsx | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/apps/client/src/menus/custom-items/NoteColorPicker.tsx b/apps/client/src/menus/custom-items/NoteColorPicker.tsx index 08bc7c84ae..847ae484e6 100644 --- a/apps/client/src/menus/custom-items/NoteColorPicker.tsx +++ b/apps/client/src/menus/custom-items/NoteColorPicker.tsx @@ -8,6 +8,7 @@ import Color, { ColorInstance } from "color"; import Debouncer from "../../utils/debouncer"; import FNote from "../../entities/fnote"; import froca from "../../services/froca"; +import { isMobile } from "../../services/utils"; const COLOR_PALETTE = [ "#e64d4d", "#e6994d", "#e5e64d", "#99e64d", "#4de64d", "#4de699", @@ -62,13 +63,13 @@ export default function NoteColorPicker(props: NoteColorPickerProps) { } else { attributes.removeOwnedLabelByName(note, "color"); } - + setCurrentColor(color); } }, [note, currentColor]); return
- + - - + + {COLOR_PALETTE.map((color) => ( (null); const colorInputDebouncer = useRef | null>(null); const callbackRef = useRef(props.onSelect); - const isSafari = useRef(/^((?!chrome|android).)*safari/i.test(navigator.userAgent)); useEffect(() => { colorInputDebouncer.current = new Debouncer(250, (color) => { @@ -160,13 +160,13 @@ function CustomColorCell(props: ColorCellProps) { }, [pickedColor]); return
{ - // The color picker dropdown will close on Safari if the parent context menu is + onClick={isMobile() ? (e) => { + // The color picker dropdown will close on some browser if the parent context menu is // dismissed, so stop the click propagation to prevent dismissing the menu. - isSafari.current && e.stopPropagation(); - }}> + e.stopPropagation(); + } : undefined}> Date: Sat, 29 Nov 2025 02:49:04 +0000 Subject: [PATCH 08/80] chore(deps): update dependency stylelint to v16.26.1 --- packages/ckeditor5-admonition/package.json | 2 +- packages/ckeditor5-footnotes/package.json | 2 +- .../ckeditor5-keyboard-marker/package.json | 2 +- packages/ckeditor5-math/package.json | 2 +- packages/ckeditor5-mermaid/package.json | 2 +- pnpm-lock.yaml | 84 +++++++++++-------- 6 files changed, 52 insertions(+), 42 deletions(-) diff --git a/packages/ckeditor5-admonition/package.json b/packages/ckeditor5-admonition/package.json index f0e3b8e233..6b8f361ebe 100644 --- a/packages/ckeditor5-admonition/package.json +++ b/packages/ckeditor5-admonition/package.json @@ -33,7 +33,7 @@ "eslint-config-ckeditor5": ">=9.1.0", "http-server": "14.1.1", "lint-staged": "16.2.7", - "stylelint": "16.26.0", + "stylelint": "16.26.1", "stylelint-config-ckeditor5": ">=9.1.0", "ts-node": "10.9.2", "typescript": "5.9.3", diff --git a/packages/ckeditor5-footnotes/package.json b/packages/ckeditor5-footnotes/package.json index 2344af52b9..c9d96cc205 100644 --- a/packages/ckeditor5-footnotes/package.json +++ b/packages/ckeditor5-footnotes/package.json @@ -34,7 +34,7 @@ "eslint-config-ckeditor5": ">=9.1.0", "http-server": "14.1.1", "lint-staged": "16.2.7", - "stylelint": "16.26.0", + "stylelint": "16.26.1", "stylelint-config-ckeditor5": ">=9.1.0", "ts-node": "10.9.2", "typescript": "5.9.3", diff --git a/packages/ckeditor5-keyboard-marker/package.json b/packages/ckeditor5-keyboard-marker/package.json index 75a9be8603..23fc474d94 100644 --- a/packages/ckeditor5-keyboard-marker/package.json +++ b/packages/ckeditor5-keyboard-marker/package.json @@ -36,7 +36,7 @@ "eslint-config-ckeditor5": ">=9.1.0", "http-server": "14.1.1", "lint-staged": "16.2.7", - "stylelint": "16.26.0", + "stylelint": "16.26.1", "stylelint-config-ckeditor5": ">=9.1.0", "ts-node": "10.9.2", "typescript": "5.9.3", diff --git a/packages/ckeditor5-math/package.json b/packages/ckeditor5-math/package.json index 00623f9918..ab00a473e2 100644 --- a/packages/ckeditor5-math/package.json +++ b/packages/ckeditor5-math/package.json @@ -37,7 +37,7 @@ "eslint-config-ckeditor5": ">=9.1.0", "http-server": "14.1.1", "lint-staged": "16.2.7", - "stylelint": "16.26.0", + "stylelint": "16.26.1", "stylelint-config-ckeditor5": ">=9.1.0", "ts-node": "10.9.2", "typescript": "5.9.3", diff --git a/packages/ckeditor5-mermaid/package.json b/packages/ckeditor5-mermaid/package.json index b7d7276b10..8cad9319ce 100644 --- a/packages/ckeditor5-mermaid/package.json +++ b/packages/ckeditor5-mermaid/package.json @@ -36,7 +36,7 @@ "eslint-config-ckeditor5": ">=9.1.0", "http-server": "14.1.1", "lint-staged": "16.2.7", - "stylelint": "16.26.0", + "stylelint": "16.26.1", "stylelint-config-ckeditor5": ">=9.1.0", "ts-node": "10.9.2", "typescript": "5.9.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e7bf70a306..b033882eba 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -915,11 +915,11 @@ importers: specifier: 16.2.7 version: 16.2.7 stylelint: - specifier: 16.26.0 - version: 16.26.0(typescript@5.9.3) + specifier: 16.26.1 + version: 16.26.1(typescript@5.9.3) stylelint-config-ckeditor5: specifier: '>=9.1.0' - version: 13.0.0(stylelint@16.26.0(typescript@5.9.3)) + version: 13.0.0(stylelint@16.26.1(typescript@5.9.3)) ts-node: specifier: 10.9.2 version: 10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@24.10.1)(typescript@5.9.3) @@ -975,11 +975,11 @@ importers: specifier: 16.2.7 version: 16.2.7 stylelint: - specifier: 16.26.0 - version: 16.26.0(typescript@5.9.3) + specifier: 16.26.1 + version: 16.26.1(typescript@5.9.3) stylelint-config-ckeditor5: specifier: '>=9.1.0' - version: 13.0.0(stylelint@16.26.0(typescript@5.9.3)) + version: 13.0.0(stylelint@16.26.1(typescript@5.9.3)) ts-node: specifier: 10.9.2 version: 10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@24.10.1)(typescript@5.9.3) @@ -1035,11 +1035,11 @@ importers: specifier: 16.2.7 version: 16.2.7 stylelint: - specifier: 16.26.0 - version: 16.26.0(typescript@5.9.3) + specifier: 16.26.1 + version: 16.26.1(typescript@5.9.3) stylelint-config-ckeditor5: specifier: '>=9.1.0' - version: 13.0.0(stylelint@16.26.0(typescript@5.9.3)) + version: 13.0.0(stylelint@16.26.1(typescript@5.9.3)) ts-node: specifier: 10.9.2 version: 10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@24.10.1)(typescript@5.9.3) @@ -1102,11 +1102,11 @@ importers: specifier: 16.2.7 version: 16.2.7 stylelint: - specifier: 16.26.0 - version: 16.26.0(typescript@5.9.3) + specifier: 16.26.1 + version: 16.26.1(typescript@5.9.3) stylelint-config-ckeditor5: specifier: '>=9.1.0' - version: 13.0.0(stylelint@16.26.0(typescript@5.9.3)) + version: 13.0.0(stylelint@16.26.1(typescript@5.9.3)) ts-node: specifier: 10.9.2 version: 10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@24.10.1)(typescript@5.9.3) @@ -1169,11 +1169,11 @@ importers: specifier: 16.2.7 version: 16.2.7 stylelint: - specifier: 16.26.0 - version: 16.26.0(typescript@5.9.3) + specifier: 16.26.1 + version: 16.26.1(typescript@5.9.3) stylelint-config-ckeditor5: specifier: '>=9.1.0' - version: 13.0.0(stylelint@16.26.0(typescript@5.9.3)) + version: 13.0.0(stylelint@16.26.1(typescript@5.9.3)) ts-node: specifier: 10.9.2 version: 10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@24.10.1)(typescript@5.9.3) @@ -2151,6 +2151,10 @@ packages: peerDependencies: '@csstools/css-tokenizer': ^3.0.4 + '@csstools/css-syntax-patches-for-csstree@1.0.19': + resolution: {integrity: sha512-QW5/SM2ARltEhoKcmRI1LoLf3/C7dHGswwCnfLcoMgqurBT4f8GvwXMgAbK/FwcxthmJRK5MGTtddj0yQn0J9g==} + engines: {node: '>=18'} + '@csstools/css-tokenizer@3.0.4': resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} engines: {node: '>=18'} @@ -13615,8 +13619,8 @@ packages: peerDependencies: stylelint: '>=16.0.0' - stylelint@16.26.0: - resolution: {integrity: sha512-Y/3AVBefrkqqapVYH3LBF5TSDZ1kw+0XpdKN2KchfuhMK6lQ85S4XOG4lIZLcrcS4PWBmvcY6eS2kCQFz0jukQ==} + stylelint@16.26.1: + resolution: {integrity: sha512-v20V59/crfc8sVTAtge0mdafI3AdnzQ2KsWe6v523L4OA1bJO02S7MO2oyXDCS6iWb9ckIPnqAFVItqSBQr7jw==} engines: {node: '>=18.12.0'} hasBin: true @@ -16454,8 +16458,8 @@ snapshots: process: 0.11.10 raw-loader: 4.0.2(webpack@5.101.3(@swc/core@1.11.29(@swc/helpers@0.5.17))(esbuild@0.27.0)) style-loader: 2.0.0(webpack@5.101.3(@swc/core@1.11.29(@swc/helpers@0.5.17))(esbuild@0.27.0)) - stylelint: 16.26.0(typescript@5.0.4) - stylelint-config-ckeditor5: 2.0.1(stylelint@16.26.0(typescript@5.9.3)) + stylelint: 16.26.1(typescript@5.0.4) + stylelint-config-ckeditor5: 2.0.1(stylelint@16.26.1(typescript@5.9.3)) terser-webpack-plugin: 5.3.14(@swc/core@1.11.29(@swc/helpers@0.5.17))(esbuild@0.27.0)(webpack@5.101.3(@swc/core@1.11.29(@swc/helpers@0.5.17))(esbuild@0.27.0)) ts-loader: 9.5.4(typescript@5.0.4)(webpack@5.101.3(@swc/core@1.11.29(@swc/helpers@0.5.17))(esbuild@0.27.0)) ts-node: 10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@24.10.1)(typescript@5.0.4) @@ -16749,6 +16753,8 @@ snapshots: '@ckeditor/ckeditor5-icons': 47.2.0 '@ckeditor/ckeditor5-ui': 47.2.0 '@ckeditor/ckeditor5-utils': 47.2.0 + transitivePeerDependencies: + - supports-color '@ckeditor/ckeditor5-upload@47.2.0': dependencies: @@ -16981,6 +16987,8 @@ snapshots: dependencies: '@csstools/css-tokenizer': 3.0.4 + '@csstools/css-syntax-patches-for-csstree@1.0.19': {} + '@csstools/css-tokenizer@3.0.4': {} '@csstools/media-query-list-parser@3.0.1(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': @@ -20241,7 +20249,7 @@ snapshots: - supports-color - typescript - '@stylistic/stylelint-plugin@3.1.3(stylelint@16.26.0(typescript@5.9.3))': + '@stylistic/stylelint-plugin@3.1.3(stylelint@16.26.1(typescript@5.9.3))': dependencies: '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 @@ -20251,7 +20259,7 @@ snapshots: postcss-selector-parser: 6.1.2 postcss-value-parser: 4.2.0 style-search: 0.1.0 - stylelint: 16.26.0(typescript@5.9.3) + stylelint: 16.26.1(typescript@5.9.3) '@swc/core-darwin-arm64@1.11.29': optional: true @@ -30767,33 +30775,34 @@ snapshots: postcss: 8.5.6 postcss-selector-parser: 7.1.0 - stylelint-config-ckeditor5@13.0.0(stylelint@16.26.0(typescript@5.9.3)): + stylelint-config-ckeditor5@13.0.0(stylelint@16.26.1(typescript@5.9.3)): dependencies: - '@stylistic/stylelint-plugin': 3.1.3(stylelint@16.26.0(typescript@5.9.3)) - stylelint: 16.26.0(typescript@5.9.3) - stylelint-config-recommended: 16.0.0(stylelint@16.26.0(typescript@5.9.3)) - stylelint-plugin-ckeditor5-rules: 13.0.0(stylelint@16.26.0(typescript@5.9.3)) + '@stylistic/stylelint-plugin': 3.1.3(stylelint@16.26.1(typescript@5.9.3)) + stylelint: 16.26.1(typescript@5.9.3) + stylelint-config-recommended: 16.0.0(stylelint@16.26.1(typescript@5.9.3)) + stylelint-plugin-ckeditor5-rules: 13.0.0(stylelint@16.26.1(typescript@5.9.3)) - stylelint-config-ckeditor5@2.0.1(stylelint@16.26.0(typescript@5.9.3)): + stylelint-config-ckeditor5@2.0.1(stylelint@16.26.1(typescript@5.9.3)): dependencies: - stylelint: 16.26.0(typescript@5.9.3) - stylelint-config-recommended: 3.0.0(stylelint@16.26.0(typescript@5.9.3)) + stylelint: 16.26.1(typescript@5.9.3) + stylelint-config-recommended: 3.0.0(stylelint@16.26.1(typescript@5.9.3)) - stylelint-config-recommended@16.0.0(stylelint@16.26.0(typescript@5.9.3)): + stylelint-config-recommended@16.0.0(stylelint@16.26.1(typescript@5.9.3)): dependencies: - stylelint: 16.26.0(typescript@5.9.3) + stylelint: 16.26.1(typescript@5.9.3) - stylelint-config-recommended@3.0.0(stylelint@16.26.0(typescript@5.9.3)): + stylelint-config-recommended@3.0.0(stylelint@16.26.1(typescript@5.9.3)): dependencies: - stylelint: 16.26.0(typescript@5.9.3) + stylelint: 16.26.1(typescript@5.9.3) - stylelint-plugin-ckeditor5-rules@13.0.0(stylelint@16.26.0(typescript@5.9.3)): + stylelint-plugin-ckeditor5-rules@13.0.0(stylelint@16.26.1(typescript@5.9.3)): dependencies: - stylelint: 16.26.0(typescript@5.9.3) + stylelint: 16.26.1(typescript@5.9.3) - stylelint@16.26.0(typescript@5.0.4): + stylelint@16.26.1(typescript@5.0.4): dependencies: '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-syntax-patches-for-csstree': 1.0.19 '@csstools/css-tokenizer': 3.0.4 '@csstools/media-query-list-parser': 4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.0) @@ -30835,9 +30844,10 @@ snapshots: - supports-color - typescript - stylelint@16.26.0(typescript@5.9.3): + stylelint@16.26.1(typescript@5.9.3): dependencies: '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-syntax-patches-for-csstree': 1.0.19 '@csstools/css-tokenizer': 3.0.4 '@csstools/media-query-list-parser': 4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.0) From 5ecafe214f873a5117f59a4d956441024c04bbb6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 29 Nov 2025 02:49:33 +0000 Subject: [PATCH 09/80] fix(deps): update dependency better-sqlite3 to v12.5.0 --- apps/desktop/package.json | 2 +- apps/dump-db/package.json | 2 +- apps/edit-docs/package.json | 2 +- apps/server/docker/package.json | 2 +- apps/server/package.json | 2 +- pnpm-lock.yaml | 26 +++++++++++--------------- 6 files changed, 16 insertions(+), 20 deletions(-) diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 755e48032c..769328ea06 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -23,7 +23,7 @@ }, "dependencies": { "@electron/remote": "2.1.3", - "better-sqlite3": "12.4.6", + "better-sqlite3": "12.5.0", "electron-debug": "4.1.0", "electron-dl": "4.0.0", "electron-squirrel-startup": "1.0.1", diff --git a/apps/dump-db/package.json b/apps/dump-db/package.json index ccbd400977..9a3f005540 100644 --- a/apps/dump-db/package.json +++ b/apps/dump-db/package.json @@ -4,7 +4,7 @@ "description": "Standalone tool to dump contents of Trilium document.db file into a directory tree of notes", "private": true, "dependencies": { - "better-sqlite3": "12.4.6", + "better-sqlite3": "12.5.0", "mime-types": "3.0.2", "sanitize-filename": "1.6.3", "tsx": "4.20.6", diff --git a/apps/edit-docs/package.json b/apps/edit-docs/package.json index 54723b27c4..e39cad3793 100644 --- a/apps/edit-docs/package.json +++ b/apps/edit-docs/package.json @@ -5,7 +5,7 @@ "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": { "archiver": "7.0.1", - "better-sqlite3": "12.4.6" + "better-sqlite3": "12.5.0" }, "devDependencies": { "@triliumnext/client": "workspace:*", diff --git a/apps/server/docker/package.json b/apps/server/docker/package.json index 6ed152f94e..52ce37103e 100644 --- a/apps/server/docker/package.json +++ b/apps/server/docker/package.json @@ -1,5 +1,5 @@ { "dependencies": { - "better-sqlite3": "12.4.6" + "better-sqlite3": "12.5.0" } } \ No newline at end of file diff --git a/apps/server/package.json b/apps/server/package.json index 5cf4c18092..33d720c7e3 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -25,7 +25,7 @@ "docker-start-rootless-alpine": "pnpm docker-build-rootless-alpine && docker run -p 8081:8080 triliumnext-rootless-alpine" }, "dependencies": { - "better-sqlite3": "12.4.6", + "better-sqlite3": "12.5.0", "html-to-text": "9.0.5", "node-html-parser": "7.0.1" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e7bf70a306..fb1e2fc4a1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -369,8 +369,8 @@ importers: specifier: 2.1.3 version: 2.1.3(electron@38.7.2) better-sqlite3: - specifier: 12.4.6 - version: 12.4.6 + specifier: 12.5.0 + version: 12.5.0 electron-debug: specifier: 4.1.0 version: 4.1.0 @@ -433,8 +433,8 @@ importers: apps/dump-db: dependencies: better-sqlite3: - specifier: 12.4.6 - version: 12.4.6 + specifier: 12.5.0 + version: 12.5.0 mime-types: specifier: 3.0.2 version: 3.0.2 @@ -464,8 +464,8 @@ importers: specifier: 7.0.1 version: 7.0.1 better-sqlite3: - specifier: 12.4.6 - version: 12.4.6 + specifier: 12.5.0 + version: 12.5.0 devDependencies: '@triliumnext/client': specifier: workspace:* @@ -489,8 +489,8 @@ importers: apps/server: dependencies: better-sqlite3: - specifier: 12.4.6 - version: 12.4.6 + specifier: 12.5.0 + version: 12.5.0 html-to-text: specifier: 9.0.5 version: 9.0.5 @@ -6367,8 +6367,8 @@ packages: peerDependencies: ajv: 4.11.8 - 8 - better-sqlite3@12.4.6: - resolution: {integrity: sha512-gaYt9yqTbQ1iOxLpJA8FPR5PiaHP+jlg8I5EX0Rs2KFwNzhBsF40KzMZS5FwelY7RG0wzaucWdqSAJM3uNCPCg==} + better-sqlite3@12.5.0: + resolution: {integrity: sha512-WwCZ/5Diz7rsF29o27o0Gcc1Du+l7Zsv7SYtVPG0X3G/uUI1LqdxrQI7c9Hs2FWpqXXERjW9hp6g3/tH7DlVKg==} engines: {node: 20.x || 22.x || 23.x || 24.x || 25.x} bezier-easing@2.1.0: @@ -15778,8 +15778,6 @@ snapshots: '@ckeditor/ckeditor5-core': 47.2.0 '@ckeditor/ckeditor5-utils': 47.2.0 ckeditor5: 47.2.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41) - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-code-block@47.2.0(patch_hash=2361d8caad7d6b5bddacc3a3b4aa37dbfba260b1c1b22a450413a79c1bb1ce95)': dependencies: @@ -16550,8 +16548,6 @@ snapshots: '@ckeditor/ckeditor5-ui': 47.2.0 '@ckeditor/ckeditor5-utils': 47.2.0 ckeditor5: 47.2.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41) - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-restricted-editing@47.2.0': dependencies: @@ -21874,7 +21870,7 @@ snapshots: jsonpointer: 5.0.1 leven: 3.1.0 - better-sqlite3@12.4.6: + better-sqlite3@12.5.0: dependencies: bindings: 1.5.0 prebuild-install: 7.1.3 From 9ae1a5589666b32439c49d43dcf2d990f1c18114 Mon Sep 17 00:00:00 2001 From: SiriusXT <1160925501@qq.com> Date: Sat, 29 Nov 2025 11:38:45 +0800 Subject: [PATCH 10/80] chore(react/empty): obtain ntxId via React props instead of DOM query --- apps/client/src/widgets/type_widgets/Empty.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/apps/client/src/widgets/type_widgets/Empty.tsx b/apps/client/src/widgets/type_widgets/Empty.tsx index 013f931fc2..83a4074937 100644 --- a/apps/client/src/widgets/type_widgets/Empty.tsx +++ b/apps/client/src/widgets/type_widgets/Empty.tsx @@ -10,16 +10,16 @@ import FNote from "../../entities/fnote"; import search from "../../services/search"; import { TypeWidgetProps } from "./type_widget"; -export default function Empty({ }: TypeWidgetProps) { +export default function Empty({ ntxId }: TypeWidgetProps) { return ( <> - + ) } -function NoteSearch() { +function NoteSearch({ ntxId }: { ntxId: string | null }) { const resultsContainerRef = useRef(null); const autocompleteRef = useRef(null); @@ -45,7 +45,6 @@ function NoteSearch() { if (!suggestion?.notePath) { return false; } - const ntxId = autocompleteRef.current?.closest(".note-split")?.getAttribute("data-ntx-id") ?? null; const activeNoteContext = appContext.tabManager.getNoteContextById(ntxId) ?? appContext.tabManager.getActiveContext(); if (activeNoteContext) { activeNoteContext.setNote(suggestion.notePath); From 8ced689432acd89475f5ec65d4768359570e41ef Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 29 Nov 2025 09:15:28 +0200 Subject: [PATCH 11/80] style(mobile/context_menu): make color picker easier to press --- apps/client/src/stylesheets/theme-next/base.css | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/apps/client/src/stylesheets/theme-next/base.css b/apps/client/src/stylesheets/theme-next/base.css index 5e62b80116..b0027bd9d0 100644 --- a/apps/client/src/stylesheets/theme-next/base.css +++ b/apps/client/src/stylesheets/theme-next/base.css @@ -389,6 +389,20 @@ body.mobile .dropdown-menu { } } } + + .dropdown-custom-item:has(.note-color-picker) { + overflow-x: auto; + } + + .note-color-picker { + padding: 0; + width: fit-content; + + .color-cell { + --color-picker-cell-size: 26px; + flex-shrink: 0; + } + } } /* #endregion */ From 2e6bdc225f3464f760f85962fdbecbd67d72db56 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 29 Nov 2025 09:22:51 +0200 Subject: [PATCH 12/80] style(mobile/context_menu): missing backdrop for global menu --- apps/client/src/stylesheets/theme-next/base.css | 4 ++++ apps/client/src/widgets/buttons/global_menu.tsx | 3 +++ apps/client/src/widgets/react/Dropdown.tsx | 6 +++++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/apps/client/src/stylesheets/theme-next/base.css b/apps/client/src/stylesheets/theme-next/base.css index b0027bd9d0..45ea5a3eb8 100644 --- a/apps/client/src/stylesheets/theme-next/base.css +++ b/apps/client/src/stylesheets/theme-next/base.css @@ -308,6 +308,10 @@ body.mobile #context-menu-cover { &.show { background: rgba(0, 0, 0, 0.7); } + + &.global-menu-cover { + bottom: 54px; + } } body.mobile .dropdown-menu { diff --git a/apps/client/src/widgets/buttons/global_menu.tsx b/apps/client/src/widgets/buttons/global_menu.tsx index c8c353b9cf..12cd870eba 100644 --- a/apps/client/src/widgets/buttons/global_menu.tsx +++ b/apps/client/src/widgets/buttons/global_menu.tsx @@ -26,6 +26,7 @@ export default function GlobalMenu({ isHorizontalLayout }: { isHorizontalLayout: const isVerticalLayout = !isHorizontalLayout; const parentComponent = useContext(ParentComponent); const { isUpdateAvailable, latestVersion } = useTriliumUpdateStatus(); + const isMobileLocal = isMobile(); return ( } } noDropdownListStyle + onShown={isMobileLocal ? () => document.getElementById("context-menu-cover")?.classList.add("show", "global-menu-cover") : undefined} + onHidden={isMobileLocal ? () => document.getElementById("context-menu-cover")?.classList.remove("show", "global-menu-cover") : undefined} > diff --git a/apps/client/src/widgets/react/Dropdown.tsx b/apps/client/src/widgets/react/Dropdown.tsx index 866a138b81..3ea79bc6c4 100644 --- a/apps/client/src/widgets/react/Dropdown.tsx +++ b/apps/client/src/widgets/react/Dropdown.tsx @@ -19,9 +19,11 @@ export interface DropdownProps extends Pick, "id" | "c disabled?: boolean; text?: ComponentChildren; forceShown?: boolean; + onShown?: () => void; + onHidden?: () => void; } -export default function Dropdown({ id, className, buttonClassName, isStatic, children, title, text, dropdownContainerStyle, dropdownContainerClassName, hideToggleArrow, iconAction, disabled, noSelectButtonStyle, noDropdownListStyle, forceShown }: DropdownProps) { +export default function Dropdown({ id, className, buttonClassName, isStatic, children, title, text, dropdownContainerStyle, dropdownContainerClassName, hideToggleArrow, iconAction, disabled, noSelectButtonStyle, noDropdownListStyle, forceShown, onShown: externalOnShown, onHidden: externalOnHidden }: DropdownProps) { const dropdownRef = useRef(null); const triggerRef = useRef(null); @@ -40,10 +42,12 @@ export default function Dropdown({ id, className, buttonClassName, isStatic, chi const onShown = useCallback(() => { setShown(true); + externalOnShown?.(); }, []) const onHidden = useCallback(() => { setShown(false); + externalOnHidden?.(); }, []); useEffect(() => { From 57b694162d031c785fda44a3b1c8569427645732 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 29 Nov 2025 09:29:00 +0200 Subject: [PATCH 13/80] style(mobile/context_menu): rounded corners for anchored positioning --- apps/client/src/stylesheets/theme-next/base.css | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/client/src/stylesheets/theme-next/base.css b/apps/client/src/stylesheets/theme-next/base.css index 45ea5a3eb8..7a1eacf67e 100644 --- a/apps/client/src/stylesheets/theme-next/base.css +++ b/apps/client/src/stylesheets/theme-next/base.css @@ -314,15 +314,19 @@ body.mobile #context-menu-cover { } } +body.mobile .dropdown-menu.mobile-bottom-menu, +body.mobile .dropdown.global-menu .dropdown-menu { + border-radius: var(--dropdown-border-radius) var(--dropdown-border-radius) 0 0; +} + body.mobile .dropdown-menu { --dropdown-menu-padding-vertical: 0.7em; --dropdown-menu-padding-horizontal: 1em; --hover-item-background-color: var(--card-background-color); font-size: 1em !important; backdrop-filter: var(--dropdown-backdrop-filter); - border-radius: var(--dropdown-border-radius) var(--dropdown-border-radius) 0 0; position: relative; - + .dropdown-toggle::after { top: 0.5em; right: var(--dropdown-menu-padding-horizontal); From 59ebfa6cc7ac01d7b44017e0cc7e55a1fc7cbeae Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 29 Nov 2025 09:33:11 +0200 Subject: [PATCH 14/80] style(mobile/context_menu): alter submenu separator style --- apps/client/src/stylesheets/theme-next/base.css | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/apps/client/src/stylesheets/theme-next/base.css b/apps/client/src/stylesheets/theme-next/base.css index 7a1eacf67e..d9a43c54fc 100644 --- a/apps/client/src/stylesheets/theme-next/base.css +++ b/apps/client/src/stylesheets/theme-next/base.css @@ -391,6 +391,18 @@ body.mobile .dropdown-menu { } } + .dropdown-divider { + visibility: visible; + margin: 0; + height: 3px; + border-top: unset; + background-color: rgba(0, 0, 0, 0.2); + + &:after { + content: unset; + } + } + &.submenu-open { .dropdown-toggle { padding-bottom: var(--dropdown-menu-padding-vertical); From 8200c0b0ab21248556e25d55985678e4c05a7579 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 29 Nov 2025 09:36:46 +0200 Subject: [PATCH 15/80] style(mobile/context_menu): improve delimiter color in light theme --- apps/client/src/stylesheets/theme-next/base.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/client/src/stylesheets/theme-next/base.css b/apps/client/src/stylesheets/theme-next/base.css index d9a43c54fc..1b3cb796ef 100644 --- a/apps/client/src/stylesheets/theme-next/base.css +++ b/apps/client/src/stylesheets/theme-next/base.css @@ -342,8 +342,8 @@ body.mobile .dropdown-menu { margin-bottom: 0; padding: var(--dropdown-menu-padding-vertical) var(--dropdown-menu-padding-horizontal) !important; background: var(--card-background-color); - border-bottom: 1px solid var(--main-border-color) !important; - border-radius: 0; + border-bottom: 1px solid var(--menu-item-delimiter-color) !important; + border-radius: 0; } .dropdown-item:first-of-type, From 70b39ddadf10accbe368a9895f6bddd38e3e14a1 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 29 Nov 2025 09:40:51 +0200 Subject: [PATCH 16/80] fix(mobile/context_menu): global menu not scrollable --- apps/client/src/stylesheets/style.css | 5 ++++- apps/client/src/stylesheets/theme-next/base.css | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/client/src/stylesheets/style.css b/apps/client/src/stylesheets/style.css index 62afc2012f..b0a963595e 100644 --- a/apps/client/src/stylesheets/style.css +++ b/apps/client/src/stylesheets/style.css @@ -1554,12 +1554,15 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu { @media (max-width: 991px) { body.mobile #launcher-pane .dropdown.global-menu > .dropdown-menu.show, body.mobile #launcher-container .dropdown > .dropdown-menu.show { + --dropdown-bottom: calc(var(--mobile-bottom-offset) + var(--launcher-pane-size)); position: fixed !important; - bottom: calc(var(--mobile-bottom-offset) + var(--launcher-pane-size)) !important; + bottom: var(--dropdown-bottom) !important; top: unset !important; inset-inline-start: 0 !important; inset-inline-end: 0 !important; transform: unset !important; + overflow-y: auto; + max-height: calc(90vh - var(--dropdown-bottom)); } #mobile-sidebar-container { diff --git a/apps/client/src/stylesheets/theme-next/base.css b/apps/client/src/stylesheets/theme-next/base.css index 1b3cb796ef..f9f88c3951 100644 --- a/apps/client/src/stylesheets/theme-next/base.css +++ b/apps/client/src/stylesheets/theme-next/base.css @@ -310,7 +310,7 @@ body.mobile #context-menu-cover { } &.global-menu-cover { - bottom: 54px; + bottom: calc(var(--mobile-bottom-offset) + var(--launcher-pane-size)); } } From ba5a72fdad4cef7cbca2b395d1153319b4346bfa Mon Sep 17 00:00:00 2001 From: "Andreas H." Date: Fri, 28 Nov 2025 10:52:33 +0100 Subject: [PATCH 17/80] Translated using Weblate (German) Currently translated at 100.0% (152 of 152 strings) Translation: Trilium Notes/Website Translate-URL: https://hosted.weblate.org/projects/trilium/website/de/ --- .../src/translations/de/translation.json | 125 +++++++++++++++++- 1 file changed, 119 insertions(+), 6 deletions(-) diff --git a/apps/website/src/translations/de/translation.json b/apps/website/src/translations/de/translation.json index 749a1a2371..620eefd52f 100644 --- a/apps/website/src/translations/de/translation.json +++ b/apps/website/src/translations/de/translation.json @@ -19,7 +19,9 @@ "note_structure_title": "Notizstruktur", "attributes_title": "Notiz Labels und Beziehungen", "note_structure_description": "Notizen lassen sich hierarchisch anordnen. Ordner sind nicht nötig, da jede Notiz Unternotizen enthalten kann. Eine einzelne Notiz kann an mehreren Stellen in der Hierarchie hinzugefügt werden.", - "hoisting_description": "Trennen Sie Ihre persönlichen und beruflichen Notizen ganz einfach, indem Sie sie in einem Arbeitsbereich gruppieren. Dadurch wird Ihre Notizstruktur so fokussiert, dass nur ein bestimmter Satz von Notizen angezeigt wird." + "hoisting_description": "Trennen Sie Ihre persönlichen und beruflichen Notizen ganz einfach, indem Sie sie in einem Arbeitsbereich gruppieren. Dadurch wird Ihre Notizstruktur so fokussiert, dass nur ein bestimmter Satz von Notizen angezeigt wird.", + "hoisting_title": "Arbeitsbereiche und Fokusansicht", + "attributes_description": "Nutzen Sie Verbindungen zwischen Notizen oder fügen Sie Labels hinzu, um die Kategorisierung zu erleichtern. Mit hervorgehobenen („promoted“) Attributen können Sie strukturierte Informationen erfassen, die sich direkt in Tabellen und Boards verwenden lassen." }, "productivity_benefits": { "revisions_title": "Notizrevisionen", @@ -29,7 +31,12 @@ "jump_to_title": "Schnellsuche und Kommandos", "search_title": "Leistungsstarke Suche", "web_clipper_title": "Web clipper", - "revisions_content": "Notizen werden regelmäßig im Hintergrund gespeichert und Revisionen können zur Überprüfung oder zum Rückgängigmachen versehentlicher Änderungen verwendet werden. Revisionen können auch bei Bedarf erstellt werden." + "revisions_content": "Notizen werden regelmäßig im Hintergrund gespeichert und Revisionen können zur Überprüfung oder zum Rückgängigmachen versehentlicher Änderungen verwendet werden. Revisionen können auch bei Bedarf erstellt werden.", + "sync_content": "Verwenden Sie eine selbst gehostete oder Cloud-Instanz, um Ihre Notizen ganz einfach auf mehreren Geräten zu synchronisieren und über eine WebApp von Ihrem mobilen Gerät aus darauf zuzugreifen.", + "protected_notes_content": "Halten Sie vertrauliche Informationen sicher, indem Sie Notizen verschlüsseln und mit einem Passwort schützen.", + "jump_to_content": "Springen Sie schnell zu Notizen oder UI-Befehlen in der gesamten Hierarchie, indem Sie nach ihrem Titel suchen. Dank Fuzzy-Matching finden Sie auch Treffer bei Tippfehlern oder leicht abweichenden Schreibweisen.", + "search_content": "Oder durchsuchen Sie den Inhalt von Notizen und grenzen Sie die Suche ein, indem Sie nach übergeordneten Notizen oder der Hierarchieebene filtern.", + "web_clipper_content": "Webseiten oder Screenshots direkt in Trilium speichern – mit der Web Clipper Browser-Erweiterung." }, "note_types": { "text_title": "Text Notizen", @@ -38,15 +45,38 @@ "mermaid_title": "Mermaid Diagramm", "mindmap_title": "Mind Map", "text_description": "Die Notizen werden mit einem visuellen Editor (WYSIWYG) bearbeitet, der Tabellen, Bilder, mathematische Ausdrücke und Code-Blöcke mit Syntaxhervorhebung unterstützt. Formatieren Sie den Text schnell mit einer Markdown-ähnlichen Syntax oder mit Slash-Befehlen.", - "code_description": "Große Quellcode- oder Skriptdateien werden mit einem speziellen Editor bearbeitet, der Syntaxhervorhebung für viele Programmiersprachen und diverse Farbschemata bietet." + "code_description": "Große Quellcode- oder Skriptdateien werden mit einem speziellen Editor bearbeitet, der Syntaxhervorhebung für viele Programmiersprachen und diverse Farbschemata bietet.", + "title": "Verschiedene Darstellungsformen für Ihre Informationen", + "file_title": "Datei Notizen", + "file_description": "Betten Sie Multimedia-Dateien wie PDFs, Bilder und Videos mit einer Vorschau innerhalb der Anwendung ein.", + "canvas_description": "Ordnen Sie Formen, Bilder und Text auf einer unendlichen Leinwand an, indem Sie dieselbe Technologie verwenden, die auch hinter excalidraw.com steckt. Ideal für Diagramme, Skizzen und visuelle Planung.", + "mermaid_description": "Erstellen Sie Fluss-, Klassen-, Sequenz- sowie Gantt-Diagramme und vieles mehr mit der Mermaid-Syntax.", + "mindmap_description": "Strukturieren Sie Ihre Gedanken visuell oder nutzen Sie eine Brainstorming-Sitzung.", + "others_list": "und andere: <0>note map, <1>relation map, <2>saved searches, <3>render note, and <4>web views." }, "extensibility_benefits": { "import_export_title": "Import/Export", "scripting_title": "Erweitertes Scripting", - "api_title": "REST API" + "api_title": "REST API", + "title": "Freigabe & Erweiterung", + "import_export_description": "Einfache Interaktion mit anderen Anwendungen mithilfe von Markdown, ENEX und OML Formaten.", + "share_title": "Notizen im Web teilen", + "share_description": "Wenn Sie über einen Server verfügen, können Sie diesen nutzen, um einen Teil Ihrer Notizen mit anderen zu teilen.", + "scripting_description": "Erstellen Sie Ihre eigenen Integrationen innerhalb von Trilium mit benutzerdefinierten Widgets oder serverseitiger Logik.", + "api_description": "Nutzen Sie die integrierte REST-API, um flexibel und automatisiert mit Trilium zu interagieren." }, "collections": { - "calendar_title": "Kalender" + "calendar_title": "Kalender", + "title": "Sammlungen", + "calendar_description": "Organisieren Sie Ihre privaten oder beruflichen Termine mithilfe eines Kalenders, der ganztägige und mehrtägige Termine unterstützt. Verschaffen Sie sich mit der Wochen-, Monats- und Jahresansicht einen Überblick über Ihre Termine. Einfaches Hinzufügen oder Verschieben von Terminen.", + "table_title": "Tabelle", + "table_description": "Zeigen Sie Informationen zu Notizen in einer tabellarischen Ansicht an und bearbeiten Sie diese. Dabei stehen verschiedene Spaltentypen wie Text, Zahlen, Kontrollkästchen, Datum sowie Uhrzeit, Links und Farben zur Verfügung, auch Beziehungen werden unterstützt. Optional können Sie die Notizen innerhalb einer Baumhierarchie in der Tabelle anzeigen.", + "board_title": "Kanban-Board", + "board_description": "Organisieren Sie Aufgaben und Projektstatus in einem Kanban-Board und ändern Sie den Status ganz einfach per Drag & Drop.", + "geomap_title": "Geokarte", + "geomap_description": "Planen Sie Ihren Urlaub oder markieren Sie Ihre Sehenswürdigkeiten direkt auf einer geografischen Karte mit individuellen Markierungen. Zeigen Sie aufgezeichnete GPX-Tracks an, um Reiserouten zu verfolgen.", + "presentation_title": "Präsentation", + "presentation_description": "Organisieren Sie Informationen in Folien und präsentieren Sie diese im Vollbildmodus mit flüssigen Übergängen. Die Folien können als PDF gespeichert und einfach geteilt werden." }, "download_helper_desktop_macos": { "quick_start": "Installieren mit Homebrew:", @@ -69,7 +99,13 @@ "download_nixpkgs": "nixpkgs", "download_zip": "Portable (.zip)", "download_flatpak": ".flatpak", - "download_rpm": ".rpm" + "download_rpm": ".rpm", + "title_x64": "Linux 64-bit", + "title_arm64": "Linux on ARM", + "description_x64": "Für die meisten Linux-Distributionen, kompatibel mit der x86_64-Architektur.", + "description_arm64": "Für ARM-basierte Linux-Distributionen, kompatibel mit der aarch64-Architektur.", + "quick_start": "Wählen Sie je nach Ihrer Distribution ein geeignetes Paketformat aus:", + "download_deb": ".deb" }, "download_helper_server_linux": { "title": "Self-hosted auf Linux", @@ -83,5 +119,82 @@ "description": "Trilium Notes wird auf PikaPods gehostet, einem kostenpflichtigen Dienst für einfachen Zugriff und Verwaltung. Es besteht keine direkte Verbindung zum Trilium-Team.", "download_pikapod": "Auf PikaPods installieren", "download_triliumcc": "Alternativ siehe trilium.cc" + }, + "faq": { + "title": "Häufig gestellte Fragen", + "mobile_question": "Gibt es eine mobile Applikation?", + "mobile_answer": "Derzeit gibt es keine offizielle mobile Anwendung. Wenn Sie jedoch über eine Serverinstanz verfügen, können Sie über einen Webbrowser darauf zugreifen und sie sogar als PWA installieren. Für Android gibt es eine inoffizielle Anwendung namens TriliumDroid, die sogar offline funktioniert (genau wie ein Desktop-Client).", + "database_question": "Wo werden die Daten gespeichert?", + "database_answer": "Alle Ihre Notizen werden in einer SQLite-Datenbank in einem Anwendungsordner gespeichert. Der Grund, warum Trilium eine Datenbank anstelle von einfachen Textdateien verwendet, liegt sowohl in der Leistung als auch darin, dass einige Funktionen, wie z. B. Klone (gleiche Notiz an mehreren Stellen im Baum), viel schwieriger zu implementieren wären. Um den Anwendungsordner zu finden, gehen Sie einfach zum Fenster „Über“.", + "server_question": "Benötige ich einen Server um Trilium zu nutzen?", + "server_answer": "Nein, der Server ermöglicht den Zugriff über einen Webbrowser und verwaltet die Synchronisierung, wenn Sie mehrere Geräte haben. Um loszulegen, reicht es aus, die Desktop-Anwendung herunterzuladen und zu verwenden.", + "scaling_question": "Wie gut skaliert die Anwendung bei einer großen Anzahl von Notizen?", + "scaling_answer": "Je nach Nutzung sollte die Anwendung min. 100.000 Notizen problemlos verarbeiten können. Beachten Sie, dass der Synchronisierungsvorgang manchmal fehlschlagen kann, wenn viele große Dateien (1 GB pro Datei) hochgeladen werden, da Trilium eher als Wissensdatenbank-Anwendung und nicht als Dateispeicher (wie beispielsweise NextCloud) konzipiert ist.", + "network_share_question": "Kann ich meine Datenbank über ein Netzlaufwerk freigeben?", + "network_share_answer": "Nein, es ist im Allgemeinen keine gute Idee, eine SQLite-Datenbank über ein Netzlaufwerk freizugeben. Auch wenn dies manchmal funktionieren mag, besteht die Gefahr, dass die Datenbank aufgrund unvollständiger Dateisperren über ein Netzwerk beschädigt wird.", + "security_question": "Wie werden meine Daten geschützt?", + "security_answer": "Standardmäßig sind Notizen nicht verschlüsselt und können direkt aus der Datenbank gelesen werden. Sobald eine Notiz als verschlüsselt markiert ist, wird diese mit AES-128-CBC verschlüsselt." + }, + "final_cta": { + "title": "Sind Sie bereit, um mit Trilium Notes zu starten?", + "description": "Baue dein persönliches Wissensarchiv mit leistungsstarken Funktionen und vollständigem Datenschutz auf.", + "get_started": "Loslegen" + }, + "components": { + "link_learn_more": "Mehr erfahren..." + }, + "download_now": { + "text": "Herunterladen ", + "platform_big": "v{{version}} für {{platform}}", + "platform_small": "für {{platform}}", + "linux_big": "v{{version}} für Linux", + "linux_small": "für Linux", + "more_platforms": "Weitere Plattformen & Server-Einrichtung" + }, + "header": { + "get-started": "Loslegen", + "documentation": "Dokumentation", + "support-us": "Unterstützt uns" + }, + "footer": { + "copyright_and_the": " und die ", + "copyright_community": "Community" + }, + "social_buttons": { + "github": "GitHub", + "github_discussions": "GitHub Discussions", + "matrix": "Matrix", + "reddit": "Reddit" + }, + "support_us": { + "title": "Unterstütze uns", + "financial_donations_title": "Geldspenden", + "financial_donations_description": "Trilium wurde mit Hunderten von Arbeitsstunden entwickelt und wird mit diesem Aufwand auch gewartet. Ihre Unterstützung sorgt dafür, dass es Open Source bleibt, verbessert die Funktionen und deckt Kosten wie das Hosting.", + "financial_donations_cta": "Bitte unterstützen Sie den Hauptentwickler (eliandoran) der Anwendung über:", + "github_sponsors": "GitHub Sponsoren", + "paypal": "PayPal", + "buy_me_a_coffee": "Buy Me A Coffee" + }, + "contribute": { + "title": "Weitere Möglichkeiten zum Mitwirken", + "way_translate": "Übersetzen Sie die Anwendung über Weblate in Ihre Muttersprache.", + "way_community": "Interagieren Sie mit der Community auf GitHub Discussions oder auf Matrix.", + "way_reports": "Fehlfunktionen über GitHub-Issues melden.", + "way_document": "Verbessern Sie die Dokumentation, indem Sie uns auf Lücken hinweisen oder durch eigene Beiträge wie Anleitungen, FAQs oder Tutorials unterstützen.", + "way_market": "Weitersagen: Teilen Sie Trilium Notes mit Freunden, in Blogs und sozialen Medien." + }, + "404": { + "title": "404: Not Found", + "description": "Die gesuchte Seite konnte nicht gefunden werden. Möglicherweise wurde sie gelöscht oder die URL ist falsch." + }, + "download_helper_desktop_windows": { + "title_x64": "Windows 64-bit", + "title_arm64": "Windows on ARM", + "description_x64": "Kompatibel mit Intel- oder AMD-Geräten unter Windows 10 und 11.", + "description_arm64": "Kompatibel mit ARM-Geräten (z. B. mit Qualcomm Snapdragon).", + "quick_start": "Installation über Winget:", + "download_exe": "Download Installer (.exe)", + "download_zip": "Portable (.zip)", + "download_scoop": "Scoop" } } From 8ba30135a13f2c9f7f7579387d4162638c02d6a0 Mon Sep 17 00:00:00 2001 From: green Date: Fri, 28 Nov 2025 02:43:20 +0100 Subject: [PATCH 18/80] Translated using Weblate (Japanese) Currently translated at 100.0% (1637 of 1637 strings) Translation: Trilium Notes/Client Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/ --- apps/client/src/translations/ja/translation.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/client/src/translations/ja/translation.json b/apps/client/src/translations/ja/translation.json index d8677c3050..9896920d06 100644 --- a/apps/client/src/translations/ja/translation.json +++ b/apps/client/src/translations/ja/translation.json @@ -1212,7 +1212,8 @@ "unhoist": "ホイスト解除", "saved-search-note-refreshed": "保存した検索ノートが更新されました。", "refresh-saved-search-results": "保存した検索結果を更新", - "toggle-sidebar": "サイドバーを切り替え" + "toggle-sidebar": "サイドバーを切り替え", + "dropping-not-allowed": "この場所にノートをドロップすることはできません。" }, "bulk_actions": { "bulk_actions": "一括操作", @@ -1266,7 +1267,8 @@ "reset_launcher_confirm": "本当に「{{title}}」をリセットしますか? このノート(およびその子ノート)のすべてのデータと設定が失われ、ランチャーは元の場所に戻ります。" }, "editable-text": { - "auto-detect-language": "自動検出" + "auto-detect-language": "自動検出", + "keeps-crashing": "編集コンポーネントがクラッシュし続けます。Trilium を再起動してください。問題が解決しない場合は、バグレポートの作成をご検討ください。" }, "highlighting": { "title": "コードブロック", From 484fbc6b9d859290d1bdf6b9d5a98b15b7ce0ed6 Mon Sep 17 00:00:00 2001 From: Tomas Adamek Date: Fri, 28 Nov 2025 21:32:55 +0100 Subject: [PATCH 19/80] Translated using Weblate (Czech) Currently translated at 69.0% (105 of 152 strings) Translation: Trilium Notes/Website Translate-URL: https://hosted.weblate.org/projects/trilium/website/cs/ --- apps/website/src/translations/cs/translation.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/website/src/translations/cs/translation.json b/apps/website/src/translations/cs/translation.json index ed8241175a..86b34534d2 100644 --- a/apps/website/src/translations/cs/translation.json +++ b/apps/website/src/translations/cs/translation.json @@ -18,8 +18,8 @@ "title": "Organizace", "note_structure_title": "Struktura poznámek", "note_structure_description": "Poznámky lze uspořádat hierarchicky. Není třeba používat složky, protože každá poznámka může obsahovat podpoznámky. Jednu poznámku lze přidat na více míst v hierarchii.", - "attributes_title": "Poznámky k štítkům a vztahům", - "attributes_description": "Využijte vztahy mezi poznámkami nebo přidejte štítky pro snadnou kategorizaci. Pomocí propagovaných atributů zadejte strukturované informace, které lze použít v tabulkách.", + "attributes_title": "Poznámky k štítkům a vazbám", + "attributes_description": "Využijte vazby mezi poznámkami nebo přidejte štítky pro snadnou kategorizaci. Pomocí propagovaných atributů zadejte strukturované informace, které lze použít v různých tabulkách.", "hoisting_title": "Pracovní prostředí a hoisting", "hoisting_description": "Snadno oddělte své osobní a pracovní poznámky tím, že je seskupíte do pracovního prostoru, který zaměří strom poznámek tak, aby zobrazoval pouze konkrétní sadu poznámek." }, From f81dbde15e2927c0003dfb40435743b0aecb61c1 Mon Sep 17 00:00:00 2001 From: "Sam.Lee" Date: Fri, 28 Nov 2025 09:05:21 +0100 Subject: [PATCH 20/80] Translated using Weblate (Korean) Currently translated at 21.0% (82 of 389 strings) Translation: Trilium Notes/Server Translate-URL: https://hosted.weblate.org/projects/trilium/server/ko/ --- .../src/assets/translations/ko/server.json | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/apps/server/src/assets/translations/ko/server.json b/apps/server/src/assets/translations/ko/server.json index d4129bd8ca..8223802509 100644 --- a/apps/server/src/assets/translations/ko/server.json +++ b/apps/server/src/assets/translations/ko/server.json @@ -39,7 +39,28 @@ "activate-previous-tab": "좌측 탭 활성화", "open-new-window": "새 비어있는 창 열기", "toggle-tray": "시스템 트레이에서 애플리케이션 보여주기/숨기기", - "tabs-and-windows": "탭 & 창" + "tabs-and-windows": "탭 & 창", + "first-tab": "목록의 첫 번째 탭 활성화", + "second-tab": "목록의 두 번째 탭 활성화", + "third-tab": "목록의 세 번째 탭 활성화", + "fourth-tab": "목록의 네 번째 탭 활성화", + "fifth-tab": "목록의 다섯 번째 탭 활성화", + "sixth-tab": "목록의 여섯 번째 탭 활성화", + "seventh-tab": "목록의 일곱 번째 탭 활성화", + "eight-tab": "목록의 여덟 번째 탭 활성화", + "ninth-tab": "목록의 아홉 번째 탭 활성화", + "last-tab": "목록의 마지막 탭 활성화", + "dialogs": "대화 상자", + "show-note-source": "\"노트 소스\" 대화 상자 표시", + "show-options": "\"옵션\" 페이지 열기", + "show-revisions": "\"노트 리비젼\" 대화 상자 표시", + "show-recent-changes": "\"최근 변경 사항\" 대화 상자 표시", + "show-sql-console": "\"SQL 콘솔\" 페이지 열기", + "show-backend-log": "\"백엔드 로그\" 페이지 열기", + "show-help": "내장 사용자 설명서 열기", + "show-cheatsheet": "일반적인 키보드 형식의 팝업 표시", + "text-note-operations": "텍스트 노트 작업", + "add-link-to-text": "텍스트에 링크 추가를 위한 대화 상자 열기" }, "hidden-subtree": { "zen-mode": "젠 모드", From 6fa88123f1d2f1dc4313eaf20c9fc7372db3071e Mon Sep 17 00:00:00 2001 From: Tomas Adamek Date: Fri, 28 Nov 2025 21:32:50 +0100 Subject: [PATCH 21/80] Translated using Weblate (Czech) Currently translated at 5.4% (89 of 1637 strings) Translation: Trilium Notes/Client Translate-URL: https://hosted.weblate.org/projects/trilium/client/cs/ --- apps/client/src/translations/cs/translation.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/client/src/translations/cs/translation.json b/apps/client/src/translations/cs/translation.json index 3c758f16b3..63fc797377 100644 --- a/apps/client/src/translations/cs/translation.json +++ b/apps/client/src/translations/cs/translation.json @@ -70,7 +70,7 @@ "cancel": "Zrušit", "ok": "OK", "confirmation": "Potvrzení", - "are_you_sure_remove_note": "Opravdu chcete odstranit poznámku „{{title}}“ z mapy vztahů?", + "are_you_sure_remove_note": "Opravdu chcete odstranit poznámku „{{title}}“ z mapy vztahů? ", "if_you_dont_check": "Pokud tuto možnost nezaškrtnete, poznámka bude odstraněna pouze z mapy vztahů.", "also_delete_note": "Odstraňte také poznámku" }, From 4de2182b40d2c9b7615f5d29ee25f96b41be4f33 Mon Sep 17 00:00:00 2001 From: "Sam.Lee" Date: Fri, 28 Nov 2025 08:53:36 +0100 Subject: [PATCH 22/80] Translated using Weblate (Korean) Currently translated at 42.7% (65 of 152 strings) Translation: Trilium Notes/Website Translate-URL: https://hosted.weblate.org/projects/trilium/website/ko/ --- apps/website/src/translations/ko/translation.json | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/website/src/translations/ko/translation.json b/apps/website/src/translations/ko/translation.json index b662d26e86..f399f0f4dc 100644 --- a/apps/website/src/translations/ko/translation.json +++ b/apps/website/src/translations/ko/translation.json @@ -38,7 +38,13 @@ "sync_title": "동기화", "sync_content": "자체 호스팅 또는 클라우드 인스턴스를 이용하여 여러 기기 사이에서 노트를 쉽게 동기화하고 PWA를 통해 모바일 폰에서 접근할 수 있습니다.", "protected_notes_title": "보호된 노트", - "protected_notes_content": "노트를 암호화하고 비밀번호로 보호되는 세션 뒤에 잠궈 민감한 개인 정보를 보호하세요." + "protected_notes_content": "노트를 암호화하고 비밀번호로 보호되는 세션 뒤에 잠궈 민감한 개인 정보를 보호하세요.", + "jump_to_title": "빠른 검색 및 명령어", + "jump_to_content": "제목을 검색하고 오타나 약간의 차이를 설명하기 위해 퍼지 매칭을 통해 계층 전반에 걸쳐 노트나 UI 명령으로 빠르게 이동하세요.", + "search_title": "상세 검색", + "search_content": "또는 노트 내부에서 문자를 검색하거나 부모 노트 또는 단계별로 필터링 하는 등 검색 범위를 조정하세요.", + "web_clipper_title": "웹 클리퍼", + "web_clipper_content": "웹 클리퍼 확장 프로그램을 사용하여 웹 페이지(또는 스크린샷)를 Trilium으로 가져와 문서에 사용하세요." }, "header": { "get-started": "시작하기", From a1df0751941ad0365615f28ad33921636001e5b0 Mon Sep 17 00:00:00 2001 From: "Sam.Lee" Date: Fri, 28 Nov 2025 08:52:24 +0100 Subject: [PATCH 23/80] Translated using Weblate (Korean) Currently translated at 2.4% (40 of 1637 strings) Translation: Trilium Notes/Client Translate-URL: https://hosted.weblate.org/projects/trilium/client/ko/ --- apps/client/src/translations/ko/translation.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/client/src/translations/ko/translation.json b/apps/client/src/translations/ko/translation.json index 6cfda19246..2f81cbe413 100644 --- a/apps/client/src/translations/ko/translation.json +++ b/apps/client/src/translations/ko/translation.json @@ -39,7 +39,9 @@ "edit_branch_prefix": "브랜치 접두사 편집", "help_on_tree_prefix": "트리 접두사에 대한 도움말", "prefix": "접두사: ", - "branch_prefix_saved": "브랜치 접두사가 저장되었습니다." + "branch_prefix_saved": "브랜치 접두사가 저장되었습니다.", + "edit_branch_prefix_multiple": "{{count}}개의 지점 접두사 편집", + "branch_prefix_saved_multiple": "{{count}}개의 지점에 대해 지점 접두사가 저장되었습니다." }, "bulk_actions": { "bulk_actions": "대량 작업", From a54d2a5f2209406b5a1e0ff717c0a8e059b8c183 Mon Sep 17 00:00:00 2001 From: "Andreas H." Date: Fri, 28 Nov 2025 10:32:37 +0100 Subject: [PATCH 24/80] Translated using Weblate (German) Currently translated at 100.0% (1637 of 1637 strings) Translation: Trilium Notes/Client Translate-URL: https://hosted.weblate.org/projects/trilium/client/de/ --- .../src/translations/de/translation.json | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/apps/client/src/translations/de/translation.json b/apps/client/src/translations/de/translation.json index 20b776e74d..49e4ad6356 100644 --- a/apps/client/src/translations/de/translation.json +++ b/apps/client/src/translations/de/translation.json @@ -21,7 +21,7 @@ }, "bundle-error": { "title": "Benutzerdefiniertes Skript konnte nicht geladen werden", - "message": "Skript von der Notiz mit der ID \"{{id}}\", und dem Titel \"{{title}}\" konnte nicht ausgeführt werden wegen:\n\n{{message}}" + "message": "Skript aus der Notiz \"{{title}}\" mit der ID \"{{id}}\", konnte nicht ausgeführt werden wegen:\n\n{{message}}" } }, "add_link": { @@ -41,7 +41,8 @@ "save": "Speichern", "branch_prefix_saved": "Zweigpräfix wurde gespeichert.", "branch_prefix_saved_multiple": "Der Zweigpräfix wurde für {{count}} Zweige gespeichert.", - "edit_branch_prefix_multiple": "Präfix für {{count}} Zweige bearbeiten" + "edit_branch_prefix_multiple": "Branch-Präfix für {{count}} Zweige bearbeiten", + "affected_branches": "Betroffene Zweige ({{count}}):" }, "bulk_actions": { "bulk_actions": "Massenaktionen", @@ -770,7 +771,10 @@ "board": "Tafel", "include_archived_notes": "Zeige archivierte Notizen", "presentation": "Präsentation", - "expand_all_levels": "Alle Ebenen erweitern" + "expand_all_levels": "Alle Ebenen erweitern", + "expand_tooltip": "Erweitert die direkten Unterelemente dieser Sammlung (eine Ebene tiefer). Für weitere Optionen auf den Pfeil rechts klicken.", + "expand_first_level": "Direkte Unterelemente erweitern", + "expand_nth_level": "{{depth}} Ebenen erweitern" }, "edited_notes": { "no_edited_notes_found": "An diesem Tag wurden noch keine Notizen bearbeitet...", @@ -1517,7 +1521,8 @@ "refresh-saved-search-results": "Gespeicherte Suchergebnisse aktualisieren", "create-child-note": "Unternotiz anlegen", "unhoist": "Fokus verlassen", - "toggle-sidebar": "Seitenleiste ein-/ausblenden" + "toggle-sidebar": "Seitenleiste ein-/ausblenden", + "dropping-not-allowed": "Ablegen von Notizen an dieser Stelle ist nicht zulässig." }, "title_bar_buttons": { "window-on-top": "Dieses Fenster immer oben halten" @@ -1620,7 +1625,8 @@ "duplicate-launcher": "Launcher duplizieren " }, "editable-text": { - "auto-detect-language": "Automatisch erkannt" + "auto-detect-language": "Automatisch erkannt", + "keeps-crashing": "Die Bearbeitungskomponente stürzt immer wieder ab. Bitte starten Sie Trilium neu. Wenn das Problem weiterhin besteht, erstellen Sie einen Fehlerbericht." }, "highlighting": { "description": "Steuert die Syntaxhervorhebung für Codeblöcke in Textnotizen, Code-Notizen sind nicht betroffen.", @@ -2089,7 +2095,7 @@ "slide-overview": "Übersicht der Folien ein-/ausblenden" }, "read-only-info": { - "read-only-note": "Aktuell wird eine Notiz nur im Lese-Modus angezeigt.", + "read-only-note": "Aktuelle Notiz wird im Lese-Modus angezeigt.", "auto-read-only-note": "Diese Notiz wird im Nur-Lesen-Modus angezeigt, um ein schnelleres Laden zu ermöglichen.", "auto-read-only-learn-more": "Mehr erfahren", "edit-note": "Notiz bearbeiten" From 76af488d351573696ed0eabfeab5441fea0f20d1 Mon Sep 17 00:00:00 2001 From: "Francis C." Date: Sat, 29 Nov 2025 07:17:48 +0100 Subject: [PATCH 25/80] Translated using Weblate (Chinese (Traditional Han script)) Currently translated at 100.0% (1637 of 1637 strings) Translation: Trilium Notes/Client Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/ --- apps/client/src/translations/tw/translation.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/client/src/translations/tw/translation.json b/apps/client/src/translations/tw/translation.json index 5b4fb2295a..01f8198e33 100644 --- a/apps/client/src/translations/tw/translation.json +++ b/apps/client/src/translations/tw/translation.json @@ -1516,7 +1516,8 @@ "refresh-saved-search-results": "重新整理儲存的搜尋結果", "create-child-note": "建立子筆記", "unhoist": "取消聚焦", - "toggle-sidebar": "切換側邊欄" + "toggle-sidebar": "切換側邊欄", + "dropping-not-allowed": "不允許移動筆記至此處。" }, "title_bar_buttons": { "window-on-top": "保持此視窗置頂" @@ -1619,7 +1620,8 @@ "duplicate-launcher": "複製啟動器 " }, "editable-text": { - "auto-detect-language": "自動檢測" + "auto-detect-language": "自動檢測", + "keeps-crashing": "編輯元件持續發生崩潰。請嘗試重新啟動 Trilium。若問題仍存在,請考慮提交錯誤報告。" }, "highlighting": { "description": "控制文字筆記程式碼區塊中的語法高亮,程式碼筆記不會受到影響。", From fbbe9998068a44067e8e5b6ee59b30c787585f58 Mon Sep 17 00:00:00 2001 From: noobhjy Date: Sat, 29 Nov 2025 03:01:55 +0100 Subject: [PATCH 26/80] Translated using Weblate (Chinese (Simplified Han script)) Currently translated at 100.0% (1637 of 1637 strings) Translation: Trilium Notes/Client Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/ --- apps/client/src/translations/cn/translation.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/client/src/translations/cn/translation.json b/apps/client/src/translations/cn/translation.json index 75efb4b7c5..e1f086e85d 100644 --- a/apps/client/src/translations/cn/translation.json +++ b/apps/client/src/translations/cn/translation.json @@ -1557,7 +1557,8 @@ "refresh-saved-search-results": "刷新保存的搜索结果", "create-child-note": "创建子笔记", "unhoist": "取消聚焦", - "toggle-sidebar": "切换侧边栏" + "toggle-sidebar": "切换侧边栏", + "dropping-not-allowed": "不允许移动笔记到此处。" }, "title_bar_buttons": { "window-on-top": "保持此窗口置顶" @@ -1660,7 +1661,8 @@ "duplicate-launcher": "复制启动器 " }, "editable-text": { - "auto-detect-language": "自动检测" + "auto-detect-language": "自动检测", + "keeps-crashing": "编辑组件时崩溃。请尝试重启 Trilium。如果问题仍然存在,请考虑提交错误报告。" }, "highlighting": { "title": "代码块", From 12abdcaf6c45aca4843518b901514d76cd2ba19d Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 29 Nov 2025 10:31:56 +0200 Subject: [PATCH 27/80] fix(ribbon): formatting toolbar disappearing after viewing attachments --- apps/client/src/widgets/ribbon/Ribbon.tsx | 110 +++++++++--------- .../type_widgets/text/ReadOnlyText.tsx | 1 - 2 files changed, 55 insertions(+), 56 deletions(-) diff --git a/apps/client/src/widgets/ribbon/Ribbon.tsx b/apps/client/src/widgets/ribbon/Ribbon.tsx index 78cec9aca3..60b2e2667f 100644 --- a/apps/client/src/widgets/ribbon/Ribbon.tsx +++ b/apps/client/src/widgets/ribbon/Ribbon.tsx @@ -8,6 +8,7 @@ import NoteActions from "./NoteActions"; import { KeyboardActionNames } from "@triliumnext/commons"; import { RIBBON_TAB_DEFINITIONS } from "./RibbonDefinition"; import { TabConfiguration, TitleContext } from "./ribbon-interface"; +import clsx from "clsx"; const TAB_CONFIGURATION = numberObjectsInPlace(RIBBON_TAB_DEFINITIONS); @@ -63,62 +64,61 @@ export default function Ribbon() { }, [ computedTabs, activeTabIndex ])); return ( -
- {noteContext?.viewScope?.viewMode === "default" && ( - <> -
-
- {computedTabs && computedTabs.map(({ title, icon, index, toggleCommand, shouldShow }) => ( - shouldShow && { - if (activeTabIndex !== index) { - setActiveTabIndex(index); - } else { - // Collapse - setActiveTabIndex(undefined); - } - }} - /> - ))} +
+
+
+ {computedTabs && computedTabs.map(({ title, icon, index, toggleCommand, shouldShow }) => ( + shouldShow && { + if (activeTabIndex !== index) { + setActiveTabIndex(index); + } else { + // Collapse + setActiveTabIndex(undefined); + } + }} + /> + ))} +
+
+ { note && } +
+
+ +
+ {computedTabs && computedTabs.map(tab => { + const isActive = tab.index === activeTabIndex; + if (!isActive && !tab.stayInDom) { + return; + } + + const TabContent = tab.content; + + return ( +
+
-
- { note && } -
-
- -
- {computedTabs && computedTabs.map(tab => { - const isActive = tab.index === activeTabIndex; - if (!isActive && !tab.stayInDom) { - return; - } - - const TabContent = tab.content; - - return ( -
-
- ); - })} -
- - )} + ); + })} +
) } diff --git a/apps/client/src/widgets/type_widgets/text/ReadOnlyText.tsx b/apps/client/src/widgets/type_widgets/text/ReadOnlyText.tsx index 5e2883201c..13b56bd5b5 100644 --- a/apps/client/src/widgets/type_widgets/text/ReadOnlyText.tsx +++ b/apps/client/src/widgets/type_widgets/text/ReadOnlyText.tsx @@ -41,7 +41,6 @@ export default function ReadOnlyText({ note, noteContext, ntxId }: TypeWidgetPro // React to included note changes. useTriliumEvent("refreshIncludedNote", ({ noteId }) => { - console.log("Refresh ", noteId); if (!contentRef.current) return; refreshIncludedNote(contentRef.current, noteId); }); From 80627997d1d10a6f5d4fd960383024f59d7f08ac Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 29 Nov 2025 10:56:31 +0200 Subject: [PATCH 28/80] fix(type_widgets): read-only text sometimes rendering wrong blob --- apps/client/src/widgets/react/hooks.tsx | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/apps/client/src/widgets/react/hooks.tsx b/apps/client/src/widgets/react/hooks.tsx index 34a7c9ed8a..f9e5d073d6 100644 --- a/apps/client/src/widgets/react/hooks.tsx +++ b/apps/client/src/widgets/react/hooks.tsx @@ -461,27 +461,31 @@ export function useNoteLabelInt(note: FNote | undefined | null, labelName: Filte export function useNoteBlob(note: FNote | null | undefined, componentId?: string): FBlob | null | undefined { const [ blob, setBlob ] = useState(); + const requestIdRef = useRef(0); - function refresh() { - note?.getBlob().then(setBlob); + async function refresh() { + const requestId = ++requestIdRef.current; + const newBlob = await note?.getBlob(); + + // Only update if this is the latest request. + if (requestId === requestIdRef.current) { + setBlob(newBlob); + } } - useEffect(refresh, [ note?.noteId ]); + useEffect(() => { refresh() }, [ note?.noteId ]); useTriliumEvent("entitiesReloaded", ({ loadResults }) => { if (!note) return; // Check if the note was deleted. if (loadResults.getEntityRow("notes", note.noteId)?.isDeleted) { + requestIdRef.current++; // invalidate pending results setBlob(null); return; } - // Check if a revision occurred. - if (loadResults.hasRevisionForNote(note.noteId)) { - refresh(); - } - - if (loadResults.isNoteContentReloaded(note.noteId, componentId)) { + if (loadResults.hasRevisionForNote(note.noteId) || + loadResults.isNoteContentReloaded(note.noteId, componentId)) { refresh(); } }); From 1fe8079fd5860f35d7efb261d28578ce8ad6210c Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 29 Nov 2025 11:08:50 +0200 Subject: [PATCH 29/80] fix(type_widgets): empty type widget when hot-reloading NoteDetail --- apps/client/src/widgets/NoteDetail.tsx | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/apps/client/src/widgets/NoteDetail.tsx b/apps/client/src/widgets/NoteDetail.tsx index 5b5838584c..e5d249b361 100644 --- a/apps/client/src/widgets/NoteDetail.tsx +++ b/apps/client/src/widgets/NoteDetail.tsx @@ -28,7 +28,7 @@ export default function NoteDetail() { const { note, type, mime, noteContext, parentComponent } = useNoteInfo(); const { ntxId, viewScope } = noteContext ?? {}; const isFullHeight = checkFullHeight(noteContext, type); - const noteTypesToRender = useRef<{ [ key in ExtendedNoteType ]?: (props: TypeWidgetProps) => VNode }>({}); + const [ noteTypesToRender, setNoteTypesToRender ] = useState<{ [ key in ExtendedNoteType ]?: (props: TypeWidgetProps) => VNode }>({}); const [ activeNoteType, setActiveNoteType ] = useState(); const props: TypeWidgetProps = { @@ -38,19 +38,23 @@ export default function NoteDetail() { parentComponent, noteContext }; + useEffect(() => { if (!type) return; - if (!noteTypesToRender.current[type]) { + if (!noteTypesToRender[type]) { getCorrespondingWidget(type).then((el) => { if (!el) return; - noteTypesToRender.current[type] = el; + setNoteTypesToRender(prev => ({ + ...prev, + [type]: el + })); setActiveNoteType(type); }); } else { setActiveNoteType(type); } - }, [ note, viewScope, type ]); + }, [ note, viewScope, type, noteTypesToRender ]); // Detect note type changes. useTriliumEvent("entitiesReloaded", async ({ loadResults }) => { @@ -192,7 +196,7 @@ export default function NoteDetail() { ref={containerRef} class={`note-detail ${isFullHeight ? "full-height" : ""}`} > - {Object.entries(noteTypesToRender.current).map(([ itemType, Element ]) => { + {Object.entries(noteTypesToRender).map(([ itemType, Element ]) => { return Date: Sat, 29 Nov 2025 11:47:36 +0200 Subject: [PATCH 30/80] fix(quick_edit): block popup not working --- apps/client/src/widgets/dialogs/PopupEditor.tsx | 1 + apps/client/src/widgets/react/Modal.tsx | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/apps/client/src/widgets/dialogs/PopupEditor.tsx b/apps/client/src/widgets/dialogs/PopupEditor.tsx index 38a9e86f0f..8d566a404b 100644 --- a/apps/client/src/widgets/dialogs/PopupEditor.tsx +++ b/apps/client/src/widgets/dialogs/PopupEditor.tsx @@ -67,6 +67,7 @@ export default function PopupEditor() { }} onHidden={() => setShown(false)} keepInDom // needed for faster loading + noFocus // automatic focus breaks block popup > diff --git a/apps/client/src/widgets/react/Modal.tsx b/apps/client/src/widgets/react/Modal.tsx index 695de67937..9c1e4a230f 100644 --- a/apps/client/src/widgets/react/Modal.tsx +++ b/apps/client/src/widgets/react/Modal.tsx @@ -66,9 +66,13 @@ interface ModalProps { * If true, the modal will remain in the DOM even when not shown. This can be useful for certain CSS transitions or when you want to avoid re-mounting the modal content. */ keepInDom?: boolean; + /** + * If true, the modal will not focus itself after becoming visible. + */ + noFocus?: boolean; } -export default function Modal({ children, className, size, title, header, footer, footerStyle, footerAlignment, onShown, onSubmit, helpPageId, minWidth, maxWidth, zIndex, scrollable, onHidden: onHidden, modalRef: externalModalRef, formRef, bodyStyle, show, stackable, keepInDom }: ModalProps) { +export default function Modal({ children, className, size, title, header, footer, footerStyle, footerAlignment, onShown, onSubmit, helpPageId, minWidth, maxWidth, zIndex, scrollable, onHidden: onHidden, modalRef: externalModalRef, formRef, bodyStyle, show, stackable, keepInDom, noFocus }: ModalProps) { const modalRef = useSyncedRef(externalModalRef); const modalInstanceRef = useRef(); const elementToFocus = useRef(); @@ -100,13 +104,15 @@ export default function Modal({ children, className, size, title, header, footer useEffect(() => { if (show && modalRef.current) { elementToFocus.current = document.activeElement; - openDialog($(modalRef.current), !stackable).then(($widget) => { + openDialog($(modalRef.current), !stackable, { + focus: !noFocus + }).then(($widget) => { modalInstanceRef.current = BootstrapModal.getOrCreateInstance($widget[0]); }) } else { modalInstanceRef.current?.hide(); } - }, [ show, modalRef.current ]); + }, [ show, modalRef.current, noFocus ]); // Memoize styles to prevent recreation on every render const dialogStyle = useMemo(() => { From ab97068a1dfc2ca1a7478bbb5b93c37b4ee49310 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 29 Nov 2025 12:16:42 +0200 Subject: [PATCH 31/80] fix(quick_edit): classic toolbar dropdowns not working --- .../src/widgets/dialogs/PopupEditor.css | 1 + .../src/widgets/dialogs/PopupEditor.tsx | 7 +- .../text/mobile_editor_toolbar.css | 104 +++++++++--------- .../text/mobile_editor_toolbar.tsx | 19 +++- 4 files changed, 73 insertions(+), 58 deletions(-) diff --git a/apps/client/src/widgets/dialogs/PopupEditor.css b/apps/client/src/widgets/dialogs/PopupEditor.css index c39545293d..c545a13ebb 100644 --- a/apps/client/src/widgets/dialogs/PopupEditor.css +++ b/apps/client/src/widgets/dialogs/PopupEditor.css @@ -59,6 +59,7 @@ body.desktop .modal.popup-editor-dialog .modal-dialog { inset-inline-end: 0; background: var(--modal-background-color); z-index: 998; + align-items: flex-start; } .modal.popup-editor-dialog .note-detail.full-height { diff --git a/apps/client/src/widgets/dialogs/PopupEditor.tsx b/apps/client/src/widgets/dialogs/PopupEditor.tsx index 8d566a404b..a6c641d8d1 100644 --- a/apps/client/src/widgets/dialogs/PopupEditor.tsx +++ b/apps/client/src/widgets/dialogs/PopupEditor.tsx @@ -18,6 +18,7 @@ import utils from "../../services/utils"; import tree from "../../services/tree"; import froca from "../../services/froca"; import ReadOnlyNoteInfoBar from "../ReadOnlyNoteInfoBar"; +import MobileEditorToolbar from "../type_widgets/text/mobile_editor_toolbar"; export default function PopupEditor() { const [ shown, setShown ] = useState(false); @@ -71,7 +72,11 @@ export default function PopupEditor() { > - + + {isMobile + ? + : } + diff --git a/apps/client/src/widgets/type_widgets/text/mobile_editor_toolbar.css b/apps/client/src/widgets/type_widgets/text/mobile_editor_toolbar.css index db469fcbdd..2286cc013d 100644 --- a/apps/client/src/widgets/type_widgets/text/mobile_editor_toolbar.css +++ b/apps/client/src/widgets/type_widgets/text/mobile_editor_toolbar.css @@ -1,52 +1,54 @@ -.classic-toolbar-outer-container { - contain: none !important; -} - -.classic-toolbar-outer-container.visible { - height: 38px; - background-color: var(--main-background-color); - position: relative; - overflow: visible; - flex-shrink: 0; -} - -#root-widget.virtual-keyboard-opened .classic-toolbar-outer-container.ios { - position: absolute; - inset-inline-start: 0; - inset-inline-end: 0; - bottom: 0; -} - -.classic-toolbar-widget { - position: absolute; - bottom: 0; - inset-inline-start: 0; - inset-inline-end: 0; - height: 38px; - overflow: scroll; - display: flex; - align-items: flex-end; - user-select: none; - scrollbar-width: 0 !important; -} - -.classic-toolbar-widget::-webkit-scrollbar:horizontal { - height: 0 !important; -} - -.classic-toolbar-widget.dropdown-active { - height: 50vh; -} - -.classic-toolbar-widget .ck.ck-toolbar { - --ck-color-toolbar-background: transparent; - --ck-color-button-default-background: transparent; - --ck-color-button-default-disabled-background: transparent; - position: absolute; - background-color: transparent; - border: none; -} - -.classic-toolbar-widget .ck.ck-button.ck-disabled { - opacity: 0.3; +body.mobile { + .classic-toolbar-outer-container { + contain: none !important; + } + + .classic-toolbar-outer-container.visible { + height: 38px; + background-color: var(--main-background-color); + position: relative; + overflow: visible; + flex-shrink: 0; + } + + #root-widget.virtual-keyboard-opened .classic-toolbar-outer-container.ios { + position: absolute; + inset-inline-start: 0; + inset-inline-end: 0; + bottom: 0; + } + + .classic-toolbar-widget { + position: absolute; + bottom: 0; + inset-inline-start: 0; + inset-inline-end: 0; + height: 38px; + overflow: scroll; + display: flex; + align-items: flex-end; + user-select: none; + scrollbar-width: 0 !important; + } + + .classic-toolbar-widget::-webkit-scrollbar:horizontal { + height: 0 !important; + } + + .classic-toolbar-widget.dropdown-active { + height: 50vh; + } + + .classic-toolbar-widget .ck.ck-toolbar { + --ck-color-toolbar-background: transparent; + --ck-color-button-default-background: transparent; + --ck-color-button-default-disabled-background: transparent; + position: absolute; + background-color: transparent; + border: none; + } + + .classic-toolbar-widget .ck.ck-button.ck-disabled { + opacity: 0.3; + } } \ No newline at end of file diff --git a/apps/client/src/widgets/type_widgets/text/mobile_editor_toolbar.tsx b/apps/client/src/widgets/type_widgets/text/mobile_editor_toolbar.tsx index 4b2ac7e1cd..86e7129ef6 100644 --- a/apps/client/src/widgets/type_widgets/text/mobile_editor_toolbar.tsx +++ b/apps/client/src/widgets/type_widgets/text/mobile_editor_toolbar.tsx @@ -4,19 +4,23 @@ import "./mobile_editor_toolbar.css"; import { isIOS } from "../../../services/utils"; import { CKTextEditor, ClassicEditor } from "@triliumnext/ckeditor5"; +interface MobileEditorToolbarProps { + inPopupEditor?: boolean; +} + /** * Handles the editing toolbar for CKEditor in mobile mode. The toolbar acts as a floating bar, with two different mechanism: * * - On iOS, because it does not respect the viewport meta value `interactive-widget=resizes-content`, we need to listen to window resizes and scroll and reposition the toolbar using absolute positioning. * - On Android, the viewport change makes the keyboard resize the content area, all we have to do is to hide the tab bar and global menu (handled in the global style). */ -export default function MobileEditorToolbar() { +export default function MobileEditorToolbar({ inPopupEditor }: MobileEditorToolbarProps) { const containerRef = useRef(null); const { note, noteContext, ntxId } = useNoteContext(); const [ shouldDisplay, setShouldDisplay ] = useState(false); const [ dropdownActive, setDropdownActive ] = useState(false); - usePositioningOniOS(containerRef); + usePositioningOniOS(!inPopupEditor, containerRef); useEffect(() => { noteContext?.isReadOnly().then(isReadOnly => { @@ -29,7 +33,10 @@ export default function MobileEditorToolbar() { if (eventNtxId !== ntxId || !containerRef.current) return; const toolbar = editor.ui.view.toolbar?.element; - repositionDropdowns(editor); + if (!inPopupEditor) { + repositionDropdowns(editor); + } + if (toolbar) { containerRef.current.replaceChildren(toolbar); } else { @@ -60,7 +67,7 @@ export default function MobileEditorToolbar() { ) } -function usePositioningOniOS(wrapperRef: MutableRef) { +function usePositioningOniOS(enabled: boolean, wrapperRef: MutableRef) { const adjustPosition = useCallback(() => { if (!wrapperRef.current) return; let bottom = window.innerHeight - (window.visualViewport?.height || 0); @@ -68,7 +75,7 @@ function usePositioningOniOS(wrapperRef: MutableRef) { }, []); useEffect(() => { - if (!isIOS()) return; + if (!isIOS() || !enabled) return; window.visualViewport?.addEventListener("resize", adjustPosition); window.addEventListener("scroll", adjustPosition); @@ -77,7 +84,7 @@ function usePositioningOniOS(wrapperRef: MutableRef) { window.visualViewport?.removeEventListener("resize", adjustPosition); window.removeEventListener("scroll", adjustPosition); }; - }, []); + }, [ enabled ]); } /** From fd6ad6dce338d663475bd71baa3cb5b7876af257 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 29 Nov 2025 12:25:15 +0200 Subject: [PATCH 32/80] fix(type_widgets): partially prevent wrong note type rendering due to async race condition --- apps/client/src/widgets/NoteDetail.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/apps/client/src/widgets/NoteDetail.tsx b/apps/client/src/widgets/NoteDetail.tsx index e5d249b361..852bb0238e 100644 --- a/apps/client/src/widgets/NoteDetail.tsx +++ b/apps/client/src/widgets/NoteDetail.tsx @@ -30,6 +30,7 @@ export default function NoteDetail() { const isFullHeight = checkFullHeight(noteContext, type); const [ noteTypesToRender, setNoteTypesToRender ] = useState<{ [ key in ExtendedNoteType ]?: (props: TypeWidgetProps) => VNode }>({}); const [ activeNoteType, setActiveNoteType ] = useState(); + const widgetRequestId = useRef(0); const props: TypeWidgetProps = { note: note!, @@ -41,10 +42,15 @@ export default function NoteDetail() { useEffect(() => { if (!type) return; + const requestId = ++widgetRequestId.current; if (!noteTypesToRender[type]) { getCorrespondingWidget(type).then((el) => { if (!el) return; + + // Ignore stale requests + if (requestId !== widgetRequestId.current) return; + setNoteTypesToRender(prev => ({ ...prev, [type]: el From b4ab07bd78871f3886cf0291279d2f2715a73c24 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 29 Nov 2025 12:33:54 +0200 Subject: [PATCH 33/80] feat(board): add keyboard navigation for "Add column" button --- apps/client/src/widgets/collections/board/index.tsx | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/apps/client/src/widgets/collections/board/index.tsx b/apps/client/src/widgets/collections/board/index.tsx index 2f8c0b6de5..a50213a317 100644 --- a/apps/client/src/widgets/collections/board/index.tsx +++ b/apps/client/src/widgets/collections/board/index.tsx @@ -204,8 +204,19 @@ function AddNewColumn({ api, isInRelationMode }: { api: BoardApi, isInRelationMo setIsCreatingNewColumn(true); }, []); + const keydownCallback = useCallback((e: KeyboardEvent) => { + if (e.key === "Enter") { + setIsCreatingNewColumn(true); + } + }, []); + return ( -
+
{!isCreatingNewColumn ? <> {" "} From 88b5e9db8721efabf0b63c1dbe93fe3280b82768 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 29 Nov 2025 13:03:08 +0200 Subject: [PATCH 34/80] fix(server): uploading new attachments doesn't report size --- apps/server/src/services/ws.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/server/src/services/ws.ts b/apps/server/src/services/ws.ts index 9dfcbc0198..132d71928d 100644 --- a/apps/server/src/services/ws.ts +++ b/apps/server/src/services/ws.ts @@ -150,7 +150,7 @@ function fillInAdditionalProperties(entityChange: EntityChange) { entityChange.entity = sql.getRow(/*sql*/`SELECT * FROM options WHERE name = ?`, [entityChange.entityId]); } } else if (entityChange.entityName === "attachments") { - entityChange.entity = becca.getAttachment(entityChange.entityId); + entityChange.entity = becca.getAttachment(entityChange.entityId, { includeContentLength: true }); if (!entityChange.entity) { entityChange.entity = sql.getRow( From 7094f71e325c804d0021a020f2a6d02c402dd613 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 29 Nov 2025 13:08:05 +0200 Subject: [PATCH 35/80] refactor(server): remove now unnecessary attachment without size --- apps/server/src/becca/becca-interface.ts | 23 +++++--------- apps/server/src/becca/entities/bnote.ts | 38 ++++++++--------------- apps/server/src/etapi/etapi_utils.ts | 2 +- apps/server/src/etapi/notes.ts | 2 +- apps/server/src/routes/api/attachments.ts | 6 ++-- apps/server/src/services/notes.ts | 2 +- apps/server/src/services/ws.ts | 2 +- 7 files changed, 28 insertions(+), 47 deletions(-) diff --git a/apps/server/src/becca/becca-interface.ts b/apps/server/src/becca/becca-interface.ts index 005a5cc520..1a8203f436 100644 --- a/apps/server/src/becca/becca-interface.ts +++ b/apps/server/src/becca/becca-interface.ts @@ -13,10 +13,6 @@ import BBlob from "./entities/bblob.js"; import BRecentNote from "./entities/brecent_note.js"; import type AbstractBeccaEntity from "./entities/abstract_becca_entity.js"; -interface AttachmentOpts { - includeContentLength?: boolean; -} - /** * Becca is a backend cache of all notes, branches, and attributes. * There's a similar frontend cache Froca, and share cache Shaca. @@ -167,21 +163,18 @@ export default class Becca { return revision; } - getAttachment(attachmentId: string, opts: AttachmentOpts = {}): BAttachment | null { - opts.includeContentLength = !!opts.includeContentLength; - - const query = opts.includeContentLength - ? /*sql*/`SELECT attachments.*, LENGTH(blobs.content) AS contentLength - FROM attachments - JOIN blobs USING (blobId) - WHERE attachmentId = ? AND isDeleted = 0` - : /*sql*/`SELECT * FROM attachments WHERE attachmentId = ? AND isDeleted = 0`; + getAttachment(attachmentId: string): BAttachment | null { + const query = /*sql*/`\ + SELECT attachments.*, LENGTH(blobs.content) AS contentLength + FROM attachments + JOIN blobs USING (blobId) + WHERE attachmentId = ? AND isDeleted = 0`; return sql.getRows(query, [attachmentId]).map((row) => new BAttachment(row))[0]; } - getAttachmentOrThrow(attachmentId: string, opts: AttachmentOpts = {}): BAttachment { - const attachment = this.getAttachment(attachmentId, opts); + getAttachmentOrThrow(attachmentId: string): BAttachment { + const attachment = this.getAttachment(attachmentId); if (!attachment) { throw new NotFoundError(`Attachment '${attachmentId}' has not been found.`); } diff --git a/apps/server/src/becca/entities/bnote.ts b/apps/server/src/becca/entities/bnote.ts index dd05fd9746..a2ff4c2821 100644 --- a/apps/server/src/becca/entities/bnote.ts +++ b/apps/server/src/becca/entities/bnote.ts @@ -61,10 +61,6 @@ interface ContentOpts { forceFrontendReload?: boolean; } -interface AttachmentOpts { - includeContentLength?: boolean; -} - interface Relationship { parentNoteId: string; childNoteId: string; @@ -1102,31 +1098,23 @@ class BNote extends AbstractBeccaEntity { return sql.getRows("SELECT * FROM revisions WHERE noteId = ? ORDER BY revisions.utcDateCreated ASC", [this.noteId]).map((row) => new BRevision(row)); } - getAttachments(opts: AttachmentOpts = {}) { - opts.includeContentLength = !!opts.includeContentLength; - // from testing, it looks like calculating length does not make a difference in performance even on large-ish DB - // given that we're always fetching attachments only for a specific note, we might just do it always - - const query = opts.includeContentLength - ? /*sql*/`SELECT attachments.*, LENGTH(blobs.content) AS contentLength - FROM attachments - JOIN blobs USING (blobId) - WHERE ownerId = ? AND isDeleted = 0 - ORDER BY position` - : /*sql*/`SELECT * FROM attachments WHERE ownerId = ? AND isDeleted = 0 ORDER BY position`; + getAttachments() { + const query = /*sql*/`\ + SELECT attachments.*, LENGTH(blobs.content) AS contentLength + FROM attachments + JOIN blobs USING (blobId) + WHERE ownerId = ? AND isDeleted = 0 + ORDER BY position`; return sql.getRows(query, [this.noteId]).map((row) => new BAttachment(row)); } - getAttachmentById(attachmentId: string, opts: AttachmentOpts = {}) { - opts.includeContentLength = !!opts.includeContentLength; - - const query = opts.includeContentLength - ? /*sql*/`SELECT attachments.*, LENGTH(blobs.content) AS contentLength - FROM attachments - JOIN blobs USING (blobId) - WHERE ownerId = ? AND attachmentId = ? AND isDeleted = 0` - : /*sql*/`SELECT * FROM attachments WHERE ownerId = ? AND attachmentId = ? AND isDeleted = 0`; + getAttachmentById(attachmentId: string) { + const query = /*sql*/`\ + SELECT attachments.*, LENGTH(blobs.content) AS contentLength + FROM attachments + JOIN blobs USING (blobId) + WHERE ownerId = ? AND attachmentId = ? AND isDeleted = 0`; return sql.getRows(query, [this.noteId, attachmentId]).map((row) => new BAttachment(row))[0]; } diff --git a/apps/server/src/etapi/etapi_utils.ts b/apps/server/src/etapi/etapi_utils.ts index a50434f708..1319162575 100644 --- a/apps/server/src/etapi/etapi_utils.ts +++ b/apps/server/src/etapi/etapi_utils.ts @@ -92,7 +92,7 @@ function getAndCheckNote(noteId: string) { } function getAndCheckAttachment(attachmentId: string) { - const attachment = becca.getAttachment(attachmentId, { includeContentLength: true }); + const attachment = becca.getAttachment(attachmentId); if (attachment) { return attachment; diff --git a/apps/server/src/etapi/notes.ts b/apps/server/src/etapi/notes.ts index 2a556dd402..9fae830704 100644 --- a/apps/server/src/etapi/notes.ts +++ b/apps/server/src/etapi/notes.ts @@ -185,7 +185,7 @@ function register(router: Router) { eu.route(router, "get", "/etapi/notes/:noteId/attachments", (req, res, next) => { const note = eu.getAndCheckNote(req.params.noteId); - const attachments = note.getAttachments({ includeContentLength: true }); + const attachments = note.getAttachments(); res.json(attachments.map((attachment) => mappers.mapAttachmentToPojo(attachment))); }); diff --git a/apps/server/src/routes/api/attachments.ts b/apps/server/src/routes/api/attachments.ts index 0da59b721e..b2c877fcb3 100644 --- a/apps/server/src/routes/api/attachments.ts +++ b/apps/server/src/routes/api/attachments.ts @@ -14,13 +14,13 @@ function getAttachmentBlob(req: Request) { function getAttachments(req: Request) { const note = becca.getNoteOrThrow(req.params.noteId); - return note.getAttachments({ includeContentLength: true }); + return note.getAttachments(); } function getAttachment(req: Request) { const { attachmentId } = req.params; - return becca.getAttachmentOrThrow(attachmentId, { includeContentLength: true }); + return becca.getAttachmentOrThrow(attachmentId); } function getAllAttachments(req: Request) { @@ -28,7 +28,7 @@ function getAllAttachments(req: Request) { // one particular attachment is requested, but return all note's attachments const attachment = becca.getAttachmentOrThrow(attachmentId); - return attachment.getNote()?.getAttachments({ includeContentLength: true }) || []; + return attachment.getNote()?.getAttachments() || []; } function saveAttachment(req: Request) { diff --git a/apps/server/src/services/notes.ts b/apps/server/src/services/notes.ts index 3de73bc217..ae8b24c0b2 100644 --- a/apps/server/src/services/notes.ts +++ b/apps/server/src/services/notes.ts @@ -764,7 +764,7 @@ function updateNoteData(noteId: string, content: string, attachments: Attachment note.setContent(newContent, { forceFrontendReload }); if (attachments?.length > 0) { - const existingAttachmentsByTitle = toMap(note.getAttachments({ includeContentLength: false }), "title"); + const existingAttachmentsByTitle = toMap(note.getAttachments(), "title"); for (const { attachmentId, role, mime, title, position, content } of attachments) { const existingAttachment = existingAttachmentsByTitle.get(title); diff --git a/apps/server/src/services/ws.ts b/apps/server/src/services/ws.ts index 132d71928d..9dfcbc0198 100644 --- a/apps/server/src/services/ws.ts +++ b/apps/server/src/services/ws.ts @@ -150,7 +150,7 @@ function fillInAdditionalProperties(entityChange: EntityChange) { entityChange.entity = sql.getRow(/*sql*/`SELECT * FROM options WHERE name = ?`, [entityChange.entityId]); } } else if (entityChange.entityName === "attachments") { - entityChange.entity = becca.getAttachment(entityChange.entityId, { includeContentLength: true }); + entityChange.entity = becca.getAttachment(entityChange.entityId); if (!entityChange.entity) { entityChange.entity = sql.getRow( From ca7bbefbdc0cc8012cc35962c5bfad756e0a9cf1 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 29 Nov 2025 13:19:49 +0200 Subject: [PATCH 36/80] fix(launch_bar/calendar): dropdown remains open when switching years --- apps/client/src/widgets/buttons/calendar.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/client/src/widgets/buttons/calendar.ts b/apps/client/src/widgets/buttons/calendar.ts index 27a4344c8a..548e9fd116 100644 --- a/apps/client/src/widgets/buttons/calendar.ts +++ b/apps/client/src/widgets/buttons/calendar.ts @@ -211,8 +211,7 @@ export default class CalendarWidget extends RightDropdownButtonWidget { const $target = $(e.target); // Keep dropdown open when clicking on month select button or year selector area - if ($target.closest('.btn.dropdown-toggle.select-button').length || - $target.closest('.calendar-year-selector').length) { + if ($target.closest('.btn.dropdown-toggle.select-button').length) { e.stopPropagation(); return; } From 351fe5848f0982455e87b4ab5637335a7af31878 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 29 Nov 2025 13:26:48 +0200 Subject: [PATCH 37/80] fix(launch_bar/calendar): clicking on the edges would dismiss modal --- apps/client/src/stylesheets/calendar.css | 4 ++++ apps/client/src/stylesheets/theme-next/shell.css | 2 +- apps/client/src/widgets/buttons/calendar.ts | 2 +- apps/client/src/widgets/buttons/right_dropdown_button.ts | 7 ++++++- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/apps/client/src/stylesheets/calendar.css b/apps/client/src/stylesheets/calendar.css index 48f01a9b83..314439846c 100644 --- a/apps/client/src/stylesheets/calendar.css +++ b/apps/client/src/stylesheets/calendar.css @@ -4,6 +4,10 @@ box-sizing: border-box; } +.dropdown-menu:not(.static).calendar-dropdown-menu { + padding: 0 !important; +} + .calendar-dropdown-widget { margin: 0 auto; overflow: hidden; diff --git a/apps/client/src/stylesheets/theme-next/shell.css b/apps/client/src/stylesheets/theme-next/shell.css index 19ac274778..83517e9ad8 100644 --- a/apps/client/src/stylesheets/theme-next/shell.css +++ b/apps/client/src/stylesheets/theme-next/shell.css @@ -345,7 +345,7 @@ body[dir=ltr] #launcher-container { */ .calendar-dropdown-widget { - padding: 12px; + padding: 18px; color: var(--calendar-color); user-select: none; } diff --git a/apps/client/src/widgets/buttons/calendar.ts b/apps/client/src/widgets/buttons/calendar.ts index 548e9fd116..f03a4da3aa 100644 --- a/apps/client/src/widgets/buttons/calendar.ts +++ b/apps/client/src/widgets/buttons/calendar.ts @@ -110,7 +110,7 @@ export default class CalendarWidget extends RightDropdownButtonWidget { private weekNotes: string[] = []; constructor(title: string = "", icon: string = "") { - super(title, icon, DROPDOWN_TPL); + super(title, icon, DROPDOWN_TPL, "calendar-dropdown-menu"); } doRender() { diff --git a/apps/client/src/widgets/buttons/right_dropdown_button.ts b/apps/client/src/widgets/buttons/right_dropdown_button.ts index 7c43f14af3..4b3505bc97 100644 --- a/apps/client/src/widgets/buttons/right_dropdown_button.ts +++ b/apps/client/src/widgets/buttons/right_dropdown_button.ts @@ -24,14 +24,16 @@ export default class RightDropdownButtonWidget extends BasicWidget { protected dropdown!: Dropdown; protected $tooltip!: JQuery; protected tooltip!: Tooltip; + private dropdownClass?: string; public $dropdownContent!: JQuery; - constructor(title: string, iconClass: string, dropdownTpl: string) { + constructor(title: string, iconClass: string, dropdownTpl: string, dropdownClass?: string) { super(); this.iconClass = iconClass; this.title = title; this.dropdownTpl = dropdownTpl; + this.dropdownClass = dropdownClass; this.settings = { titlePlacement: "right" @@ -41,6 +43,9 @@ export default class RightDropdownButtonWidget extends BasicWidget { doRender() { this.$widget = $(TPL); this.$dropdownMenu = this.$widget.find(".dropdown-menu"); + if (this.dropdownClass) { + this.$dropdownMenu.addClass(this.dropdownClass); + } this.dropdown = Dropdown.getOrCreateInstance(this.$widget.find("[data-bs-toggle='dropdown']")[0], { popperConfig: { placement: this.settings.titlePlacement, From 3c61626370c8361d9b57b133efcb16a13e4826e2 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 29 Nov 2025 15:16:43 +0200 Subject: [PATCH 38/80] fix(launch_bar/calendar): tooltip showing over the calendar dropdown --- apps/client/src/stylesheets/style.css | 19 ++++++++++++++----- .../widgets/buttons/right_dropdown_button.ts | 15 ++++++++------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/apps/client/src/stylesheets/style.css b/apps/client/src/stylesheets/style.css index b0a963595e..24d74a98d1 100644 --- a/apps/client/src/stylesheets/style.css +++ b/apps/client/src/stylesheets/style.css @@ -706,11 +706,6 @@ table.promoted-attributes-in-tooltip th { z-index: 32767 !important; } -.tooltip-trigger { - background: transparent; - pointer-events: none; -} - .bs-tooltip-bottom .tooltip-arrow::before { border-bottom-color: var(--main-border-color) !important; } @@ -1379,6 +1374,20 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu { flex-shrink: 0; } +.right-dropdown-widget .right-dropdown-button { + position: relative; +} + +.tooltip-trigger { + background: transparent; + pointer-events: none; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; +} + #launcher-pane.horizontal .right-dropdown-widget { width: 53px; } diff --git a/apps/client/src/widgets/buttons/right_dropdown_button.ts b/apps/client/src/widgets/buttons/right_dropdown_button.ts index 4b3505bc97..45915c2549 100644 --- a/apps/client/src/widgets/buttons/right_dropdown_button.ts +++ b/apps/client/src/widgets/buttons/right_dropdown_button.ts @@ -7,9 +7,9 @@ const TPL = /*html*/` @@ -52,9 +52,8 @@ export default class RightDropdownButtonWidget extends BasicWidget { } }); - this.$widget.attr("title", this.title); - this.tooltip = Tooltip.getOrCreateInstance(this.$widget[0], { - trigger: "hover", + this.$tooltip = this.$widget.find(".tooltip-trigger").attr("title", this.title); + this.tooltip = new Tooltip(this.$tooltip[0], { placement: handleRightToLeftPlacement(this.settings.titlePlacement), fallbackPlacements: [ handleRightToLeftPlacement(this.settings.titlePlacement) ] }); @@ -62,7 +61,9 @@ export default class RightDropdownButtonWidget extends BasicWidget { this.$widget .find(".right-dropdown-button") .addClass(this.iconClass) - .on("click", () => this.tooltip.hide()); + .on("click", () => this.tooltip.hide()) + .on("mouseenter", () => this.tooltip.show()) + .on("mouseleave", () => this.tooltip.hide()); this.$widget.on("show.bs.dropdown", async () => { await this.dropdownShown(); From cd2a085d005130bf3d9ae54fa38ba1487bce11d5 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 29 Nov 2025 15:30:17 +0200 Subject: [PATCH 39/80] fix(type_widgets/notemap): bottom part not visible --- apps/client/src/widgets/type_widgets/NoteMap.css | 10 ++++++++++ apps/client/src/widgets/type_widgets/NoteMap.tsx | 1 + 2 files changed, 11 insertions(+) create mode 100644 apps/client/src/widgets/type_widgets/NoteMap.css diff --git a/apps/client/src/widgets/type_widgets/NoteMap.css b/apps/client/src/widgets/type_widgets/NoteMap.css new file mode 100644 index 0000000000..0afa0f4d24 --- /dev/null +++ b/apps/client/src/widgets/type_widgets/NoteMap.css @@ -0,0 +1,10 @@ +.note-detail-note-map { + &>div { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + overflow: hidden; + } +} \ No newline at end of file diff --git a/apps/client/src/widgets/type_widgets/NoteMap.tsx b/apps/client/src/widgets/type_widgets/NoteMap.tsx index 7a308151c5..aca9f68d18 100644 --- a/apps/client/src/widgets/type_widgets/NoteMap.tsx +++ b/apps/client/src/widgets/type_widgets/NoteMap.tsx @@ -1,6 +1,7 @@ import { TypeWidgetProps } from "./type_widget"; import NoteMapEl from "../note_map/NoteMap"; import { useRef } from "preact/hooks"; +import "./NoteMap.css"; export default function NoteMap({ note }: TypeWidgetProps) { const containerRef = useRef(null); From fe10c9f8c8e09218ef046f459ea42bff68026247 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 29 Nov 2025 15:34:43 +0200 Subject: [PATCH 40/80] fix(text): strikethrough icon appears disabled --- apps/client/src/stylesheets/style.css | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/apps/client/src/stylesheets/style.css b/apps/client/src/stylesheets/style.css index 24d74a98d1..dc95206cb9 100644 --- a/apps/client/src/stylesheets/style.css +++ b/apps/client/src/stylesheets/style.css @@ -1001,9 +1001,17 @@ div[data-notify="container"] { font-family: var(--monospace-font-family); } -svg.ck-icon .note-icon { - color: var(--main-text-color); - font-size: 20px; +svg.ck-icon { + &.ck-icon_inherit-color { + * { + fill: currentColor; + } + } + + &.note-icon { + color: var(--main-text-color); + font-size: 20px; + } } .ck-content { From 5af7425cae2cd1700f44cc438e8b80fd0c651b51 Mon Sep 17 00:00:00 2001 From: noobhjy Date: Sat, 29 Nov 2025 10:00:15 +0100 Subject: [PATCH 41/80] Translated using Weblate (Chinese (Simplified Han script)) Currently translated at 100.0% (1637 of 1637 strings) Translation: Trilium Notes/Client Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/ --- apps/client/src/translations/cn/translation.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/client/src/translations/cn/translation.json b/apps/client/src/translations/cn/translation.json index e1f086e85d..6c82a00af7 100644 --- a/apps/client/src/translations/cn/translation.json +++ b/apps/client/src/translations/cn/translation.json @@ -1662,7 +1662,7 @@ }, "editable-text": { "auto-detect-language": "自动检测", - "keeps-crashing": "编辑组件时崩溃。请尝试重启 Trilium。如果问题仍然存在,请考虑提交错误报告。" + "keeps-crashing": "编辑组件时持续崩溃。请尝试重启 Trilium。如果问题仍然存在,请考虑提交错误报告。" }, "highlighting": { "title": "代码块", From d3f3ff4eab21942455fe9fe7808e2109b4d0edea Mon Sep 17 00:00:00 2001 From: pythaac Date: Sat, 29 Nov 2025 14:01:05 +0100 Subject: [PATCH 42/80] Translated using Weblate (Korean) Currently translated at 43.4% (66 of 152 strings) Translation: Trilium Notes/Website Translate-URL: https://hosted.weblate.org/projects/trilium/website/ko/ --- apps/website/src/translations/ko/translation.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/website/src/translations/ko/translation.json b/apps/website/src/translations/ko/translation.json index f399f0f4dc..75fa485e75 100644 --- a/apps/website/src/translations/ko/translation.json +++ b/apps/website/src/translations/ko/translation.json @@ -85,5 +85,8 @@ "title_arm64": "ARM 기반 리눅스", "description_x64": "대부분의 리눅스 배포판에서 x86_64 아키텍처와 호환됩니다.", "description_arm64": "ARM 기반 리눅스 배포판에서 aarch64 아키텍처와 호환됩니다." + }, + "note_types": { + "text_title": "텍스트 노트" } } From 5f197107917c1c7e7051f87ef3ec8f7ff5a6349c Mon Sep 17 00:00:00 2001 From: SiriusXT <1160925501@qq.com> Date: Sat, 29 Nov 2025 22:40:49 +0800 Subject: [PATCH 43/80] fix(insertDateTime): unable to insert date/time via quick editor or shortcut --- .../widgets/type_widgets/text/EditableText.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/client/src/widgets/type_widgets/text/EditableText.tsx b/apps/client/src/widgets/type_widgets/text/EditableText.tsx index 5e3d06a769..0106ae0c09 100644 --- a/apps/client/src/widgets/type_widgets/text/EditableText.tsx +++ b/apps/client/src/widgets/type_widgets/text/EditableText.tsx @@ -98,6 +98,14 @@ export default function EditableText({ note, parentComponent, ntxId, noteContext editorApi: editorApiRef.current, }); }, + insertDateTimeToTextCommand() { + if (!editorApiRef.current) return; + const date = new Date(); + const customDateTimeFormat = options.get("customDateTimeFormat"); + const dateString = utils.formatDateTime(date, customDateTimeFormat); + + addTextToEditor(dateString); + }, // Include note functionality note addIncludeNoteToTextCommand() { if (!editorApiRef.current) return; @@ -197,14 +205,6 @@ export default function EditableText({ note, parentComponent, ntxId, noteContext }); } - useTriliumEvent("insertDateTimeToText", ({ ntxId: eventNtxId }) => { - if (eventNtxId !== ntxId) return; - const date = new Date(); - const customDateTimeFormat = options.get("customDateTimeFormat"); - const dateString = utils.formatDateTime(date, customDateTimeFormat); - - addTextToEditor(dateString); - }); useTriliumEvent("addTextToActiveEditor", ({ text }) => { if (!noteContext?.isActive()) return; addTextToEditor(text); From c1f663a200f8acc57905960f2144c7ac1c303697 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 29 Nov 2025 16:43:50 +0200 Subject: [PATCH 44/80] style(mobile): no bottom border radius on modals --- apps/client/src/stylesheets/style.css | 4 ++++ apps/client/src/widgets/dialogs/PopupEditor.css | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/apps/client/src/stylesheets/style.css b/apps/client/src/stylesheets/style.css index dc95206cb9..55551f7fb9 100644 --- a/apps/client/src/stylesheets/style.css +++ b/apps/client/src/stylesheets/style.css @@ -212,6 +212,10 @@ input::placeholder, background-color: var(--modal-backdrop-color) !important; } +body.mobile .modal .modal-content { + border-radius: var(--bs-modal-border-radius) var(--bs-modal-border-radius) 0 0; +} + .component { contain: size; } diff --git a/apps/client/src/widgets/dialogs/PopupEditor.css b/apps/client/src/widgets/dialogs/PopupEditor.css index c545a13ebb..5d8691c19a 100644 --- a/apps/client/src/widgets/dialogs/PopupEditor.css +++ b/apps/client/src/widgets/dialogs/PopupEditor.css @@ -5,11 +5,11 @@ body.popup-editor-open .ck-clipboard-drop-target-line { z-index: 1000; } body.desktop .modal.popup-editor-dialog .modal-dialog { max-width: 75vw; -} - -.modal.popup-editor-dialog .modal-dialog { border-bottom-left-radius: var(--bs-modal-border-radius); border-bottom-right-radius: var(--bs-modal-border-radius); +} + +body.desktop .modal.popup-editor-dialog .modal-dialog { overflow: hidden; } From e8bae61afc5790eeb5fa6319933e51e79a27b9ea Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 29 Nov 2025 16:46:40 +0200 Subject: [PATCH 45/80] style(mobile): center modals on tablet view --- apps/client/src/stylesheets/style.css | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/apps/client/src/stylesheets/style.css b/apps/client/src/stylesheets/style.css index 55551f7fb9..eb8bdfc7bc 100644 --- a/apps/client/src/stylesheets/style.css +++ b/apps/client/src/stylesheets/style.css @@ -212,6 +212,12 @@ input::placeholder, background-color: var(--modal-backdrop-color) !important; } +body.mobile .modal .modal-dialog { + left: 50%; + transform: translateX(-50%); + width: 100%; +} + body.mobile .modal .modal-content { border-radius: var(--bs-modal-border-radius) var(--bs-modal-border-radius) 0 0; } From 470ca3b6dc5b95bd4f371a568a3abc046f687470 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 29 Nov 2025 16:49:46 +0200 Subject: [PATCH 46/80] style(mobile): improve quick edit max width --- apps/client/src/widgets/dialogs/PopupEditor.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/client/src/widgets/dialogs/PopupEditor.css b/apps/client/src/widgets/dialogs/PopupEditor.css index 5d8691c19a..13276e33da 100644 --- a/apps/client/src/widgets/dialogs/PopupEditor.css +++ b/apps/client/src/widgets/dialogs/PopupEditor.css @@ -13,6 +13,10 @@ body.desktop .modal.popup-editor-dialog .modal-dialog { overflow: hidden; } +body.mobile .modal.popup-editor-dialog .modal-dialog { + max-width: 90vw; +} + .modal.popup-editor-dialog .modal-header .modal-title { font-size: 1.1em; } From a68cd7526b91bcebe85ca313754f285578640f2d Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 29 Nov 2025 16:55:12 +0200 Subject: [PATCH 47/80] style(mobile): improve quick edit max height --- apps/client/src/widgets/dialogs/PopupEditor.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/client/src/widgets/dialogs/PopupEditor.css b/apps/client/src/widgets/dialogs/PopupEditor.css index 13276e33da..14b6c30438 100644 --- a/apps/client/src/widgets/dialogs/PopupEditor.css +++ b/apps/client/src/widgets/dialogs/PopupEditor.css @@ -15,6 +15,8 @@ body.desktop .modal.popup-editor-dialog .modal-dialog { body.mobile .modal.popup-editor-dialog .modal-dialog { max-width: 90vw; + max-height: 90vh; + height: 100%; } .modal.popup-editor-dialog .modal-header .modal-title { From 7d8af0f252a7cb032dd76fb9e8ca35abe43f1d7b Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 29 Nov 2025 16:57:11 +0200 Subject: [PATCH 48/80] refactor(client): use var for modal max height --- apps/client/src/stylesheets/style.css | 7 ++++--- apps/client/src/widgets/dialogs/PopupEditor.css | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/client/src/stylesheets/style.css b/apps/client/src/stylesheets/style.css index eb8bdfc7bc..b19016422a 100644 --- a/apps/client/src/stylesheets/style.css +++ b/apps/client/src/stylesheets/style.css @@ -25,7 +25,8 @@ --bs-body-font-weight: var(--main-font-weight) !important; --bs-body-color: var(--main-text-color) !important; --bs-body-bg: var(--main-background-color) !important; - --ck-mention-list-max-height: 500px; + --ck-mention-list-max-height: 500px; + --tn-modal-max-height: 90vh; } body#trilium-app.motion-disabled *, @@ -1329,7 +1330,7 @@ body.mobile #context-menu-container.mobile-bottom-menu { inset-inline-end: 0 !important; bottom: 0 !important; top: unset !important; - max-height: 90vh; + max-height: var(--tn-modal-max-height); overflow: auto !important; user-select: none; -webkit-user-select: none; @@ -1589,7 +1590,7 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu { inset-inline-end: 0 !important; transform: unset !important; overflow-y: auto; - max-height: calc(90vh - var(--dropdown-bottom)); + max-height: calc(var(--tn-modal-max-height) - var(--dropdown-bottom)); } #mobile-sidebar-container { diff --git a/apps/client/src/widgets/dialogs/PopupEditor.css b/apps/client/src/widgets/dialogs/PopupEditor.css index 14b6c30438..f72cf22749 100644 --- a/apps/client/src/widgets/dialogs/PopupEditor.css +++ b/apps/client/src/widgets/dialogs/PopupEditor.css @@ -15,7 +15,7 @@ body.desktop .modal.popup-editor-dialog .modal-dialog { body.mobile .modal.popup-editor-dialog .modal-dialog { max-width: 90vw; - max-height: 90vh; + max-height: var(--tn-modal-max-height); height: 100%; } From 81a9e06b231a3e307b6fc75877386f73145b1ce1 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 29 Nov 2025 17:00:43 +0200 Subject: [PATCH 49/80] feat(quick_edit): basic reactivity to color changes --- apps/client/src/widgets/dialogs/PopupEditor.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/client/src/widgets/dialogs/PopupEditor.tsx b/apps/client/src/widgets/dialogs/PopupEditor.tsx index a6c641d8d1..143ac20b0d 100644 --- a/apps/client/src/widgets/dialogs/PopupEditor.tsx +++ b/apps/client/src/widgets/dialogs/PopupEditor.tsx @@ -1,7 +1,7 @@ import { useContext, useEffect, useMemo, useRef, useState } from "preact/hooks"; import Modal from "../react/Modal"; import "./PopupEditor.css"; -import { useNoteContext, useTriliumEvent } from "../react/hooks"; +import { useNoteContext, useNoteLabel, useTriliumEvent } from "../react/hooks"; import NoteTitleWidget from "../note_title"; import NoteIcon from "../note_icon"; import NoteContext from "../../components/note_context"; @@ -90,13 +90,14 @@ export function DialogWrapper({ children }: { children: ComponentChildren }) { const { note } = useNoteContext(); const wrapperRef = useRef(null); const [ hasTint, setHasTint ] = useState(false); + const [ color ] = useNoteLabel(note, "color"); // Apply the tinted-dialog class only if the custom color CSS class specifies a hue useEffect(() => { if (!wrapperRef.current) return; const customHue = getComputedStyle(wrapperRef.current).getPropertyValue("--custom-color-hue"); setHasTint(!!customHue); - }, [ note ]); + }, [ note, color ]); return (
From 453349be26d86d738b29f6353d77ef7a2edce02a Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 29 Nov 2025 17:19:37 +0200 Subject: [PATCH 50/80] feat(quick_edit): seamless transition between color changes --- apps/client/src/services/css_class_manager.ts | 2 +- apps/client/src/stylesheets/theme-next-dark.css | 2 +- apps/client/src/stylesheets/theme-next-light.css | 2 +- apps/client/src/widgets/dialogs/PopupEditor.tsx | 12 ++---------- 4 files changed, 5 insertions(+), 13 deletions(-) diff --git a/apps/client/src/services/css_class_manager.ts b/apps/client/src/services/css_class_manager.ts index b28b24b238..4c0c0f3608 100644 --- a/apps/client/src/services/css_class_manager.ts +++ b/apps/client/src/services/css_class_manager.ts @@ -38,7 +38,7 @@ function createClassForColor(colorString: string | null) { registeredClasses.add(className); } - return className; + return `color ${className}`; } function parseColor(color: string) { diff --git a/apps/client/src/stylesheets/theme-next-dark.css b/apps/client/src/stylesheets/theme-next-dark.css index 51db2bc27e..117eeb8b7d 100644 --- a/apps/client/src/stylesheets/theme-next-dark.css +++ b/apps/client/src/stylesheets/theme-next-dark.css @@ -300,7 +300,7 @@ body .todo-list input[type="checkbox"]:not(:checked):before { border-color: var(--muted-text-color) !important; } -.tinted-quick-edit-dialog { +.quick-edit-dialog-wrapper.color { --modal-background-color: hsl(var(--custom-color-hue), 8.8%, 11.2%); --modal-border-color: hsl(var(--custom-color-hue), 9.4%, 25.1%); --promoted-attribute-card-background-color: hsl(var(--custom-color-hue), 13.2%, 20.8%); diff --git a/apps/client/src/stylesheets/theme-next-light.css b/apps/client/src/stylesheets/theme-next-light.css index 66e3538c69..a3fc26e93a 100644 --- a/apps/client/src/stylesheets/theme-next-light.css +++ b/apps/client/src/stylesheets/theme-next-light.css @@ -276,7 +276,7 @@ --custom-bg-color: hsl(var(--custom-color-hue), 37%, 89%, 1); } -.tinted-quick-edit-dialog { +.quick-edit-dialog-wrapper.color { --modal-background-color: hsl(var(--custom-color-hue), 56%, 96%); --modal-border-color: hsl(var(--custom-color-hue), 33%, 41%); --promoted-attribute-card-background-color: hsl(var(--custom-color-hue), 40%, 88%); diff --git a/apps/client/src/widgets/dialogs/PopupEditor.tsx b/apps/client/src/widgets/dialogs/PopupEditor.tsx index 143ac20b0d..1a065c05fc 100644 --- a/apps/client/src/widgets/dialogs/PopupEditor.tsx +++ b/apps/client/src/widgets/dialogs/PopupEditor.tsx @@ -89,18 +89,10 @@ export default function PopupEditor() { export function DialogWrapper({ children }: { children: ComponentChildren }) { const { note } = useNoteContext(); const wrapperRef = useRef(null); - const [ hasTint, setHasTint ] = useState(false); - const [ color ] = useNoteLabel(note, "color"); - - // Apply the tinted-dialog class only if the custom color CSS class specifies a hue - useEffect(() => { - if (!wrapperRef.current) return; - const customHue = getComputedStyle(wrapperRef.current).getPropertyValue("--custom-color-hue"); - setHasTint(!!customHue); - }, [ note, color ]); + useNoteLabel(note, "color"); // to update color class return ( -
+
{children}
) From ee81037173e592b0edc32555be967c5b3cacf28e Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 29 Nov 2025 17:26:17 +0200 Subject: [PATCH 51/80] feat(quick_edit): smooth transition between colors --- apps/client/src/widgets/dialogs/PopupEditor.css | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/apps/client/src/widgets/dialogs/PopupEditor.css b/apps/client/src/widgets/dialogs/PopupEditor.css index f72cf22749..952e35dc59 100644 --- a/apps/client/src/widgets/dialogs/PopupEditor.css +++ b/apps/client/src/widgets/dialogs/PopupEditor.css @@ -19,6 +19,10 @@ body.mobile .modal.popup-editor-dialog .modal-dialog { height: 100%; } +.modal.popup-editor-dialog .modal-content { + transition: background-color 250ms ease-in; +} + .modal.popup-editor-dialog .modal-header .modal-title { font-size: 1.1em; } @@ -58,12 +62,16 @@ body.mobile .modal.popup-editor-dialog .modal-dialog { font-size: 1em; } +.modal.popup-editor-dialog .classic-toolbar-outer-container.visible { + background-color: transparent; +} + .modal.popup-editor-dialog .classic-toolbar-widget { position: sticky; top: 0; inset-inline-start: 0; inset-inline-end: 0; - background: var(--modal-background-color); + background: transparent; z-index: 998; align-items: flex-start; } From 8c1a04c4b28c20627185092bd59665c95b7984d4 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 29 Nov 2025 17:32:32 +0200 Subject: [PATCH 52/80] fix(mobile): shortcut keyboard + visible --- apps/client/src/layouts/mobile_layout.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/client/src/layouts/mobile_layout.tsx b/apps/client/src/layouts/mobile_layout.tsx index e08d48b616..7a177d23bd 100644 --- a/apps/client/src/layouts/mobile_layout.tsx +++ b/apps/client/src/layouts/mobile_layout.tsx @@ -32,6 +32,7 @@ import PromotedAttributes from "../widgets/PromotedAttributes.jsx"; const MOBILE_CSS = ` `); registeredClasses.add(className); + if (hue) { + colorsWithHue.add(className); + } } - return `color ${className}`; + return clsx(className, colorsWithHue.has(className) && "with-hue"); } function parseColor(color: string) { diff --git a/apps/client/src/stylesheets/theme-next-dark.css b/apps/client/src/stylesheets/theme-next-dark.css index 8da51004ee..fbb8d15468 100644 --- a/apps/client/src/stylesheets/theme-next-dark.css +++ b/apps/client/src/stylesheets/theme-next-dark.css @@ -301,7 +301,7 @@ body .todo-list input[type="checkbox"]:not(:checked):before { border-color: var(--muted-text-color) !important; } -.quick-edit-dialog-wrapper.color { +.quick-edit-dialog-wrapper.with-hue { --modal-background-color: hsl(var(--custom-color-hue), 8.8%, 11.2%); --modal-border-color: hsl(var(--custom-color-hue), 9.4%, 25.1%); --promoted-attribute-card-background-color: hsl(var(--custom-color-hue), 13.2%, 20.8%); diff --git a/apps/client/src/stylesheets/theme-next-light.css b/apps/client/src/stylesheets/theme-next-light.css index a3fc26e93a..f736538a8f 100644 --- a/apps/client/src/stylesheets/theme-next-light.css +++ b/apps/client/src/stylesheets/theme-next-light.css @@ -276,7 +276,7 @@ --custom-bg-color: hsl(var(--custom-color-hue), 37%, 89%, 1); } -.quick-edit-dialog-wrapper.color { +.quick-edit-dialog-wrapper.with-hue { --modal-background-color: hsl(var(--custom-color-hue), 56%, 96%); --modal-border-color: hsl(var(--custom-color-hue), 33%, 41%); --promoted-attribute-card-background-color: hsl(var(--custom-color-hue), 40%, 88%); From 3378746530270c4a0e6348ae35055d08f0a20a7d Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sat, 29 Nov 2025 18:50:16 +0200 Subject: [PATCH 58/80] style: disable text selection in UI --- .../src/stylesheets/theme-next/base.css | 8 ++++++++ apps/client/src/widgets/dialogs/about.tsx | 16 +++++++-------- apps/client/src/widgets/dialogs/revisions.tsx | 2 +- .../src/widgets/ribbon/FilePropertiesTab.tsx | 20 +++++++++---------- .../src/widgets/ribbon/ImagePropertiesTab.tsx | 6 +++--- .../widgets/ribbon/InheritedAttributesTab.tsx | 2 +- .../client/src/widgets/ribbon/NoteInfoTab.tsx | 10 +++++----- apps/client/src/widgets/type_widgets/Doc.css | 1 + .../widgets/type_widgets/options/backup.tsx | 2 +- .../type_widgets/options/text_notes.tsx | 2 +- .../type_widgets/text/ReadOnlyText.tsx | 2 +- 11 files changed, 40 insertions(+), 31 deletions(-) diff --git a/apps/client/src/stylesheets/theme-next/base.css b/apps/client/src/stylesheets/theme-next/base.css index f9f88c3951..5d5bd23872 100644 --- a/apps/client/src/stylesheets/theme-next/base.css +++ b/apps/client/src/stylesheets/theme-next/base.css @@ -99,6 +99,14 @@ --tree-item-dark-theme-min-color-lightness: 65; } +body { + user-select: none; +} + +.selectable-text { + user-select: text; +} + body.backdrop-effects-disabled { /* Backdrop effects are disabled, replace the menu background color with the * no-backdrop fallback color */ diff --git a/apps/client/src/widgets/dialogs/about.tsx b/apps/client/src/widgets/dialogs/about.tsx index 7fa9c2390d..f09cca3191 100644 --- a/apps/client/src/widgets/dialogs/about.tsx +++ b/apps/client/src/widgets/dialogs/about.tsx @@ -31,29 +31,29 @@ export default function AboutDialog() { {t("about.homepage")} - https://github.com/TriliumNext/Trilium + https://github.com/TriliumNext/Trilium {t("about.app_version")} - {appInfo?.appVersion} + {appInfo?.appVersion} {t("about.db_version")} - {appInfo?.dbVersion} + {appInfo?.dbVersion} {t("about.sync_version")} - {appInfo?.syncVersion} + {appInfo?.syncVersion} {t("about.build_date")} - + {appInfo?.buildDate ? formatDateTime(appInfo.buildDate) : ""} {t("about.build_revision")} - + {appInfo?.buildRevision && {appInfo.buildRevision}} @@ -76,8 +76,8 @@ function DirectoryLink({ directory, style }: { directory: string, style?: CSSPro openService.openDirectory(directory); }; - return {directory} + return {directory} } else { - return {directory}; + return {directory}; } } diff --git a/apps/client/src/widgets/dialogs/revisions.tsx b/apps/client/src/widgets/dialogs/revisions.tsx index 0effd8b084..e20c4c978f 100644 --- a/apps/client/src/widgets/dialogs/revisions.tsx +++ b/apps/client/src/widgets/dialogs/revisions.tsx @@ -208,7 +208,7 @@ function RevisionPreview({noteContent, revisionItem, showDiff, setShown, onRevis }
)}
-
+
diff --git a/apps/client/src/widgets/ribbon/FilePropertiesTab.tsx b/apps/client/src/widgets/ribbon/FilePropertiesTab.tsx index 4777f43498..76a1972797 100644 --- a/apps/client/src/widgets/ribbon/FilePropertiesTab.tsx +++ b/apps/client/src/widgets/ribbon/FilePropertiesTab.tsx @@ -17,24 +17,24 @@ export default function FilePropertiesTab({ note }: { note?: FNote | null }) { return (
{note && ( - +
- - - - + + + + - - - - + + + + - + )) ) : ( diff --git a/apps/client/src/widgets/type_widgets/options/text_notes.tsx b/apps/client/src/widgets/type_widgets/options/text_notes.tsx index 0dd1021457..6179b5bc7e 100644 --- a/apps/client/src/widgets/type_widgets/options/text_notes.tsx +++ b/apps/client/src/widgets/type_widgets/options/text_notes.tsx @@ -226,7 +226,7 @@ function CodeBlockPreview({ theme, wordWrap }: { theme: string, wordWrap: boolea return (
-
+            
                 
             
diff --git a/apps/client/src/widgets/type_widgets/text/ReadOnlyText.tsx b/apps/client/src/widgets/type_widgets/text/ReadOnlyText.tsx index 13b56bd5b5..e233800308 100644 --- a/apps/client/src/widgets/type_widgets/text/ReadOnlyText.tsx +++ b/apps/client/src/widgets/type_widgets/text/ReadOnlyText.tsx @@ -55,7 +55,7 @@ export default function ReadOnlyText({ note, noteContext, ntxId }: TypeWidgetPro <> Date: Sat, 29 Nov 2025 19:37:38 +0200 Subject: [PATCH 59/80] chore(read-only-bar): use in-app help --- apps/client/src/translations/en/translation.json | 1 - apps/client/src/widgets/ReadOnlyNoteInfoBar.tsx | 15 ++++++--------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index 53427faae6..8f6767d9a8 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -1647,7 +1647,6 @@ "read-only-info": { "read-only-note": "Currently viewing a read-only note.", "auto-read-only-note": "This note is shown in a read-only mode for faster loading.", - "auto-read-only-learn-more": "Learn more", "edit-note": "Edit note" }, "note_types": { diff --git a/apps/client/src/widgets/ReadOnlyNoteInfoBar.tsx b/apps/client/src/widgets/ReadOnlyNoteInfoBar.tsx index f10939d471..fbbe6a2ba3 100644 --- a/apps/client/src/widgets/ReadOnlyNoteInfoBar.tsx +++ b/apps/client/src/widgets/ReadOnlyNoteInfoBar.tsx @@ -3,6 +3,7 @@ import { t } from "../services/i18n"; import { useIsNoteReadOnly, useNoteContext, useTriliumEvent } from "./react/hooks" import Button from "./react/Button"; import InfoBar from "./react/InfoBar"; +import HelpButton from "./react/HelpButton"; export default function ReadOnlyNoteInfoBar(props: {}) { const {note, noteContext} = useNoteContext(); @@ -17,20 +18,16 @@ export default function ReadOnlyNoteInfoBar(props: {}) { {(isExplicitReadOnly) ? (
{t("read-only-info.read-only-note")}
) : ( -
+
{t("read-only-info.auto-read-only-note")} -   - - - {t("read-only-info.auto-read-only-learn-more")} - + {" "} +
)} - +
-} \ No newline at end of file +} From c9aa992e730255c04d88d45624134b2a62040d7a Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 29 Nov 2025 19:40:00 +0200 Subject: [PATCH 60/80] fix(read-only-bar): displayed when viewing attachments --- .../src/widgets/ReadOnlyNoteInfoBar.tsx | 42 ++++++++++--------- apps/client/src/widgets/react/hooks.tsx | 6 +-- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/apps/client/src/widgets/ReadOnlyNoteInfoBar.tsx b/apps/client/src/widgets/ReadOnlyNoteInfoBar.tsx index fbbe6a2ba3..af305fc1cc 100644 --- a/apps/client/src/widgets/ReadOnlyNoteInfoBar.tsx +++ b/apps/client/src/widgets/ReadOnlyNoteInfoBar.tsx @@ -6,28 +6,30 @@ import InfoBar from "./react/InfoBar"; import HelpButton from "./react/HelpButton"; export default function ReadOnlyNoteInfoBar(props: {}) { - const {note, noteContext} = useNoteContext(); - const {isReadOnly, enableEditing} = useIsNoteReadOnly(note, noteContext); + const { note, noteContext } = useNoteContext(); + const { isReadOnly, enableEditing } = useIsNoteReadOnly(note, noteContext); const isExplicitReadOnly = note?.isLabelTruthy("readOnly"); - return - -
- {(isExplicitReadOnly) ? ( -
{t("read-only-info.read-only-note")}
- ) : ( -
- {t("read-only-info.auto-read-only-note")} - {" "} - -
- )} - -
+
+ ); } diff --git a/apps/client/src/widgets/react/hooks.tsx b/apps/client/src/widgets/react/hooks.tsx index f9e5d073d6..07429b73c0 100644 --- a/apps/client/src/widgets/react/hooks.tsx +++ b/apps/client/src/widgets/react/hooks.tsx @@ -795,7 +795,7 @@ export function useKeyboardShortcuts(scope: "code-detail" | "text-detail", conta * and provides a way to switch to editing mode. */ export function useIsNoteReadOnly(note: FNote | null | undefined, noteContext: NoteContext | undefined) { - const [isReadOnly, setIsReadOnly] = useState(undefined); + const [ isReadOnly, setIsReadOnly ] = useState(undefined); const enableEditing = useCallback(() => { if (noteContext?.viewScope) { @@ -810,7 +810,7 @@ export function useIsNoteReadOnly(note: FNote | null | undefined, noteContext: N setIsReadOnly(readOnly); }); } - }, [note, noteContext]); + }, [ note, noteContext, noteContext?.viewScope ]); useTriliumEvent("readOnlyTemporarilyDisabled", ({noteContext: eventNoteContext}) => { if (noteContext?.ntxId === eventNoteContext.ntxId) { @@ -818,7 +818,7 @@ export function useIsNoteReadOnly(note: FNote | null | undefined, noteContext: N } }); - return {isReadOnly, enableEditing}; + return { isReadOnly, enableEditing }; } async function isNoteReadOnly(note: FNote, noteContext: NoteContext) { From e7eaa5fd5820c5cfef9849e4af86e68d4ab2e81b Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 29 Nov 2025 19:49:38 +0200 Subject: [PATCH 61/80] fix(mobile): global menu backdrop on tablet view --- apps/client/src/stylesheets/theme-next/base.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/client/src/stylesheets/theme-next/base.css b/apps/client/src/stylesheets/theme-next/base.css index 0902a9aa02..2f207ed440 100644 --- a/apps/client/src/stylesheets/theme-next/base.css +++ b/apps/client/src/stylesheets/theme-next/base.css @@ -320,6 +320,10 @@ body.mobile #context-menu-cover { &.global-menu-cover { bottom: calc(var(--mobile-bottom-offset) + var(--launcher-pane-size)); + + @media (min-width: 992px) { + bottom: 0; + } } } From b9e257a39d8f658dec38c6a276e7550939db2c7e Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 29 Nov 2025 20:18:43 +0200 Subject: [PATCH 62/80] refactor(client): redundant interface --- apps/client/src/widgets/containers/split_note_container.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/apps/client/src/widgets/containers/split_note_container.ts b/apps/client/src/widgets/containers/split_note_container.ts index 02ed8cf045..9754bbd6bf 100644 --- a/apps/client/src/widgets/containers/split_note_container.ts +++ b/apps/client/src/widgets/containers/split_note_container.ts @@ -1,12 +1,8 @@ import FlexContainer from "./flex_container.js"; import appContext, { type CommandData, type CommandListenerData, type EventData, type EventNames, type NoteSwitchedContext } from "../../components/app_context.js"; import type BasicWidget from "../basic_widget.js"; -import type NoteContext from "../../components/note_context.js"; import Component from "../../components/component.js"; import splitService from "../../services/resizer.js"; -interface NoteContextEvent { - noteContext: NoteContext; -} interface SplitNoteWidget extends BasicWidget { hasBeenAlreadyShown?: boolean; From 8b0d4e5c3b39a8625cb70d411aaae14916de5f98 Mon Sep 17 00:00:00 2001 From: "Andreas H." Date: Sat, 29 Nov 2025 18:42:52 +0100 Subject: [PATCH 63/80] Translated using Weblate (German) Currently translated at 100.0% (152 of 152 strings) Translation: Trilium Notes/Website Translate-URL: https://hosted.weblate.org/projects/trilium/website/de/ --- apps/website/src/translations/de/translation.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/website/src/translations/de/translation.json b/apps/website/src/translations/de/translation.json index 620eefd52f..07737e106a 100644 --- a/apps/website/src/translations/de/translation.json +++ b/apps/website/src/translations/de/translation.json @@ -21,7 +21,7 @@ "note_structure_description": "Notizen lassen sich hierarchisch anordnen. Ordner sind nicht nötig, da jede Notiz Unternotizen enthalten kann. Eine einzelne Notiz kann an mehreren Stellen in der Hierarchie hinzugefügt werden.", "hoisting_description": "Trennen Sie Ihre persönlichen und beruflichen Notizen ganz einfach, indem Sie sie in einem Arbeitsbereich gruppieren. Dadurch wird Ihre Notizstruktur so fokussiert, dass nur ein bestimmter Satz von Notizen angezeigt wird.", "hoisting_title": "Arbeitsbereiche und Fokusansicht", - "attributes_description": "Nutzen Sie Verbindungen zwischen Notizen oder fügen Sie Labels hinzu, um die Kategorisierung zu erleichtern. Mit hervorgehobenen („promoted“) Attributen können Sie strukturierte Informationen erfassen, die sich direkt in Tabellen und Boards verwenden lassen." + "attributes_description": "Verwenden Sie Beziehungen zwischen Notizen oder fügen Sie Beschriftungen hinzu, um die Kategorisierung zu vereinfachen. Verwenden Sie hervorgehobene Attribute, um strukturierte Informationen einzugeben, die in Tabellen und Boards verwendet werden können." }, "productivity_benefits": { "revisions_title": "Notizrevisionen", From 8e1d796870eeafe627953aaeb30a448a7d02cc8b Mon Sep 17 00:00:00 2001 From: pythaac Date: Sat, 29 Nov 2025 15:31:38 +0100 Subject: [PATCH 64/80] Translated using Weblate (Korean) Currently translated at 44.7% (68 of 152 strings) Translation: Trilium Notes/Website Translate-URL: https://hosted.weblate.org/projects/trilium/website/ko/ --- apps/website/src/translations/ko/translation.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/website/src/translations/ko/translation.json b/apps/website/src/translations/ko/translation.json index 75fa485e75..718f3444b0 100644 --- a/apps/website/src/translations/ko/translation.json +++ b/apps/website/src/translations/ko/translation.json @@ -87,6 +87,8 @@ "description_arm64": "ARM 기반 리눅스 배포판에서 aarch64 아키텍처와 호환됩니다." }, "note_types": { - "text_title": "텍스트 노트" + "text_title": "텍스트 노트", + "text_description": "노트는 WYSIWYG 편집기를 사용하며 표, 이미지, 수학 표현식, 구문 강조 기능의 코드 블록을 지원합니다. 특수문자를 사용한 마크다운 유사 구문이나 슬래시(/) 명령으로 텍스트 서식을 빠르게 지정할 수 있습니다.", + "code_title": "코드 노트" } } From 9a76a9069cc057c0aa41086e65432c268882b42d Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Sat, 29 Nov 2025 20:01:40 +0100 Subject: [PATCH 65/80] Update translation files Updated by "Cleanup translation files" add-on in Weblate. Translation: Trilium Notes/Client Translate-URL: https://hosted.weblate.org/projects/trilium/client/ --- apps/client/src/translations/cn/translation.json | 1 - apps/client/src/translations/de/translation.json | 1 - apps/client/src/translations/es/translation.json | 1 - apps/client/src/translations/it/translation.json | 1 - apps/client/src/translations/ja/translation.json | 1 - apps/client/src/translations/ro/translation.json | 1 - apps/client/src/translations/tw/translation.json | 1 - 7 files changed, 7 deletions(-) diff --git a/apps/client/src/translations/cn/translation.json b/apps/client/src/translations/cn/translation.json index 6c82a00af7..4cbe6ab502 100644 --- a/apps/client/src/translations/cn/translation.json +++ b/apps/client/src/translations/cn/translation.json @@ -2098,7 +2098,6 @@ "read-only-info": { "read-only-note": "当前正在查看一个只读笔记。", "auto-read-only-note": "这条笔记以只读模式显示便于快速加载。", - "auto-read-only-learn-more": "了解更多", "edit-note": "编辑笔记" }, "note-color": { diff --git a/apps/client/src/translations/de/translation.json b/apps/client/src/translations/de/translation.json index 49e4ad6356..9fa06df4c4 100644 --- a/apps/client/src/translations/de/translation.json +++ b/apps/client/src/translations/de/translation.json @@ -2097,7 +2097,6 @@ "read-only-info": { "read-only-note": "Aktuelle Notiz wird im Lese-Modus angezeigt.", "auto-read-only-note": "Diese Notiz wird im Nur-Lesen-Modus angezeigt, um ein schnelleres Laden zu ermöglichen.", - "auto-read-only-learn-more": "Mehr erfahren", "edit-note": "Notiz bearbeiten" }, "calendar_view": { diff --git a/apps/client/src/translations/es/translation.json b/apps/client/src/translations/es/translation.json index 54b548edc4..ce5632e1d0 100644 --- a/apps/client/src/translations/es/translation.json +++ b/apps/client/src/translations/es/translation.json @@ -2096,7 +2096,6 @@ "read-only-info": { "read-only-note": "Actualmente, está viendo una nota de solo lectura.", "auto-read-only-note": "Esta nota se muestra en modo de solo lectura para una carga más rápida.", - "auto-read-only-learn-more": "Para saber más", "edit-note": "Editar nota" }, "calendar_view": { diff --git a/apps/client/src/translations/it/translation.json b/apps/client/src/translations/it/translation.json index 77f7ce4449..a2a61b716e 100644 --- a/apps/client/src/translations/it/translation.json +++ b/apps/client/src/translations/it/translation.json @@ -2092,7 +2092,6 @@ "read-only-info": { "read-only-note": "Stai visualizzando una nota di sola lettura.", "auto-read-only-note": "Questa nota viene visualizzata in modalità di sola lettura per un caricamento più rapido.", - "auto-read-only-learn-more": "Per saperne di più", "edit-note": "Modifica nota" }, "calendar_view": { diff --git a/apps/client/src/translations/ja/translation.json b/apps/client/src/translations/ja/translation.json index 9896920d06..ab6c509dd8 100644 --- a/apps/client/src/translations/ja/translation.json +++ b/apps/client/src/translations/ja/translation.json @@ -2098,7 +2098,6 @@ "read-only-info": { "read-only-note": "現在、読み取り専用のノートを表示しています。", "auto-read-only-note": "このノートは読み込みを高速化するために読み取り専用モードで表示されています。", - "auto-read-only-learn-more": "さらに詳しく", "edit-note": "ノートを編集" }, "note-color": { diff --git a/apps/client/src/translations/ro/translation.json b/apps/client/src/translations/ro/translation.json index e550f796a0..d0eff357fa 100644 --- a/apps/client/src/translations/ro/translation.json +++ b/apps/client/src/translations/ro/translation.json @@ -2097,7 +2097,6 @@ "read-only-info": { "read-only-note": "Vizualizați o notiță în modul doar în citire.", "auto-read-only-note": "Această notiță este afișată în modul doar în citire din motive de performanță.", - "auto-read-only-learn-more": "Mai multe detalii", "edit-note": "Editează notița" }, "calendar_view": { diff --git a/apps/client/src/translations/tw/translation.json b/apps/client/src/translations/tw/translation.json index 01f8198e33..5d7463c45b 100644 --- a/apps/client/src/translations/tw/translation.json +++ b/apps/client/src/translations/tw/translation.json @@ -2098,7 +2098,6 @@ "read-only-info": { "read-only-note": "目前正在檢視唯讀筆記。", "auto-read-only-note": "此筆記以唯讀模式顯示以加快載入速度。", - "auto-read-only-learn-more": "了解更多", "edit-note": "編輯筆記" }, "note-color": { From cef242a9ce776c2c91ecc5f0f5ed0e0897b6b56c Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sun, 30 Nov 2025 00:55:34 +0200 Subject: [PATCH 66/80] style/button group: fix the appearance of the active button --- apps/client/src/stylesheets/style.css | 5 ----- apps/client/src/stylesheets/theme-next-dark.css | 3 +++ apps/client/src/stylesheets/theme-next-light.css | 3 +++ apps/client/src/stylesheets/theme-next/forms.css | 8 ++++++++ 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/apps/client/src/stylesheets/style.css b/apps/client/src/stylesheets/style.css index e3372b4af2..ea55db0410 100644 --- a/apps/client/src/stylesheets/style.css +++ b/apps/client/src/stylesheets/style.css @@ -592,11 +592,6 @@ button.btn-sm { color: var(--left-pane-text-color); } -.btn.active:not(.btn-primary) { - background-color: var(--button-disabled-background-color) !important; - opacity: 0.4; -} - .ck.ck-block-toolbar-button { transform: translateX(7px); color: var(--muted-text-color); diff --git a/apps/client/src/stylesheets/theme-next-dark.css b/apps/client/src/stylesheets/theme-next-dark.css index fbb8d15468..72271ad2ea 100644 --- a/apps/client/src/stylesheets/theme-next-dark.css +++ b/apps/client/src/stylesheets/theme-next-dark.css @@ -41,6 +41,9 @@ --cmd-button-keyboard-shortcut-color: white; --cmd-button-disabled-opacity: 0.5; + --button-group-active-button-background: #ffffff4e; + --button-group-active-button-text-color: white; + --icon-button-color: currentColor; --icon-button-hover-background: var(--hover-item-background-color); --icon-button-hover-color: var(--hover-item-text-color); diff --git a/apps/client/src/stylesheets/theme-next-light.css b/apps/client/src/stylesheets/theme-next-light.css index f736538a8f..780d519f70 100644 --- a/apps/client/src/stylesheets/theme-next-light.css +++ b/apps/client/src/stylesheets/theme-next-light.css @@ -41,6 +41,9 @@ --cmd-button-keyboard-shortcut-color: black; --cmd-button-disabled-opacity: 0.5; + --button-group-active-button-background: #00000026; + --button-group-active-button-text-color: black; + --icon-button-color: currentColor; --icon-button-hover-background: var(--hover-item-background-color); --icon-button-hover-color: var(--hover-item-text-color); diff --git a/apps/client/src/stylesheets/theme-next/forms.css b/apps/client/src/stylesheets/theme-next/forms.css index b5991b4d74..fb53f167d4 100644 --- a/apps/client/src/stylesheets/theme-next/forms.css +++ b/apps/client/src/stylesheets/theme-next/forms.css @@ -146,6 +146,14 @@ button.btn.btn-success kbd { outline: 2px solid var(--input-focus-outline-color); } +/* Button groups */ + +/* Active button */ +:root .btn-group button.btn.active { + background-color: var(--button-group-active-button-background); + color: var(--button-group-active-button-text-color); +} + /* * Input boxes */ From 6735b257b452455223f3faf3097f3684180fff63 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sun, 30 Nov 2025 01:09:07 +0200 Subject: [PATCH 67/80] style/promoted color attributes: fix the layout on narrow width --- apps/client/src/stylesheets/theme-next/shell.css | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/apps/client/src/stylesheets/theme-next/shell.css b/apps/client/src/stylesheets/theme-next/shell.css index 83517e9ad8..77d2a9ba67 100644 --- a/apps/client/src/stylesheets/theme-next/shell.css +++ b/apps/client/src/stylesheets/theme-next/shell.css @@ -1448,6 +1448,14 @@ div.promoted-attribute-cell .multiplicity:has(span) span { justify-content: center; } +div.promoted-attribute-cell.promoted-attribute-label-color { + justify-content: space-between; +} + +div.promoted-attribute-cell.promoted-attribute-label-color .input-group { + width: auto; +} + /* * Floating buttons */ From 07fb5ab0178092ceda4cb93959089317e9a4c130 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sun, 30 Nov 2025 01:44:20 +0200 Subject: [PATCH 68/80] client/dialogs: add support for custom title bar buttons --- .../src/stylesheets/theme-next/dialogs.css | 8 ++++++-- apps/client/src/widgets/react/Modal.tsx | 20 ++++++++++++++++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/apps/client/src/stylesheets/theme-next/dialogs.css b/apps/client/src/stylesheets/theme-next/dialogs.css index ed617991c3..768dc55303 100644 --- a/apps/client/src/stylesheets/theme-next/dialogs.css +++ b/apps/client/src/stylesheets/theme-next/dialogs.css @@ -25,6 +25,7 @@ .modal .modal-header .btn-close, .modal .modal-header .help-button, +.modal .modal-header .custom-title-bar-button, #toast-container .toast .toast-header .btn-close { display: flex; justify-content: center; @@ -55,15 +56,17 @@ font-family: boxicons; } -.modal .modal-header .help-button { +.modal .modal-header .help-button, +.modal .modal-header .custom-title-bar-button { margin-inline-end: 0; - font-size: calc(var(--modal-control-button-size) * .75); + font-size: calc(var(--modal-control-button-size) * .65); font-family: unset; font-weight: bold; } .modal .modal-header .btn-close:hover, .modal .modal-header .help-button:hover, +.modal .modal-header .custom-title-bar-button:hover, #toast-container .toast .toast-header .btn-close:hover { background: var(--modal-control-button-hover-background); color: var(--modal-control-button-hover-color); @@ -71,6 +74,7 @@ .modal .modal-header .btn-close:active, .modal .modal-header .help-button:active, +.modal .modal-header .custom-title-bar-button:active, #toast-container .toast .toast-header .btn-close:active { transform: scale(.85); } diff --git a/apps/client/src/widgets/react/Modal.tsx b/apps/client/src/widgets/react/Modal.tsx index 9c1e4a230f..d28244ac01 100644 --- a/apps/client/src/widgets/react/Modal.tsx +++ b/apps/client/src/widgets/react/Modal.tsx @@ -1,3 +1,4 @@ +import clsx from "clsx"; import { useEffect, useRef, useMemo } from "preact/hooks"; import { t } from "../../services/i18n"; import { ComponentChildren } from "preact"; @@ -7,9 +8,16 @@ import { Modal as BootstrapModal } from "bootstrap"; import { memo } from "preact/compat"; import { useSyncedRef } from "./hooks"; +interface CustomTitleBarButton { + title: string; + iconClassName: string; + onClick: () => void; +} + interface ModalProps { className: string; title: string | ComponentChildren; + customTitleBarButtons?: (CustomTitleBarButton | null)[]; size: "xl" | "lg" | "md" | "sm"; children: ComponentChildren; /** @@ -72,7 +80,7 @@ interface ModalProps { noFocus?: boolean; } -export default function Modal({ children, className, size, title, header, footer, footerStyle, footerAlignment, onShown, onSubmit, helpPageId, minWidth, maxWidth, zIndex, scrollable, onHidden: onHidden, modalRef: externalModalRef, formRef, bodyStyle, show, stackable, keepInDom, noFocus }: ModalProps) { +export default function Modal({ children, className, size, title, customTitleBarButtons: titleBarButtons, header, footer, footerStyle, footerAlignment, onShown, onSubmit, helpPageId, minWidth, maxWidth, zIndex, scrollable, onHidden: onHidden, modalRef: externalModalRef, formRef, bodyStyle, show, stackable, keepInDom, noFocus }: ModalProps) { const modalRef = useSyncedRef(externalModalRef); const modalInstanceRef = useRef(); const elementToFocus = useRef(); @@ -148,7 +156,17 @@ export default function Modal({ children, className, size, title, header, footer {helpPageId && ( )} + + {titleBarButtons?.filter((b) => b !== null).map((titleBarButton) => ( + + ))} + + {onSubmit ? ( From c8431181c813693f94c00c3e9ea39c78142dda21 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sun, 30 Nov 2025 01:52:55 +0200 Subject: [PATCH 69/80] client/dialogs/custom title bar buttons: tweak --- apps/client/src/stylesheets/theme-next/dialogs.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/client/src/stylesheets/theme-next/dialogs.css b/apps/client/src/stylesheets/theme-next/dialogs.css index 768dc55303..ffe6af9a5f 100644 --- a/apps/client/src/stylesheets/theme-next/dialogs.css +++ b/apps/client/src/stylesheets/theme-next/dialogs.css @@ -59,7 +59,7 @@ .modal .modal-header .help-button, .modal .modal-header .custom-title-bar-button { margin-inline-end: 0; - font-size: calc(var(--modal-control-button-size) * .65); + font-size: calc(var(--modal-control-button-size) * .70); font-family: unset; font-weight: bold; } From f5e3df0cd21cb025d94049ae8f63394e2fd1e463 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sun, 30 Nov 2025 01:54:28 +0200 Subject: [PATCH 70/80] client/quick edit: add placeholder for "open in full editor" custom title bar button --- apps/client/src/widgets/dialogs/PopupEditor.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/client/src/widgets/dialogs/PopupEditor.tsx b/apps/client/src/widgets/dialogs/PopupEditor.tsx index 1a065c05fc..0d158f8282 100644 --- a/apps/client/src/widgets/dialogs/PopupEditor.tsx +++ b/apps/client/src/widgets/dialogs/PopupEditor.tsx @@ -60,6 +60,11 @@ export default function PopupEditor() { } + customTitleBarButtons={[{ + iconClassName: "bx-expand-alt", + title: "Switch to full editor", + onClick: () => {/* TO DO */} + }]} className="popup-editor-dialog" size="lg" show={shown} From 124ef640b1f874c45a1fc23f473e56f02c743653 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sun, 30 Nov 2025 02:04:40 +0200 Subject: [PATCH 71/80] client/quick edit: tweak layout --- apps/client/src/widgets/dialogs/PopupEditor.css | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/client/src/widgets/dialogs/PopupEditor.css b/apps/client/src/widgets/dialogs/PopupEditor.css index 80e8b3e708..99d6cafff4 100644 --- a/apps/client/src/widgets/dialogs/PopupEditor.css +++ b/apps/client/src/widgets/dialogs/PopupEditor.css @@ -33,8 +33,8 @@ body.mobile .modal.popup-editor-dialog .modal-dialog { align-items: center; } -.modal.popup-editor-dialog .modal-header .title-row > * { - margin: 5px; +.modal.popup-editor-dialog .modal-header .note-title-widget { + margin-top: 8px; } .modal.popup-editor-dialog .modal-body { @@ -66,8 +66,13 @@ body.mobile .modal.popup-editor-dialog .modal-dialog { background-color: transparent; } +.modal.popup-editor-dialog div.promoted-attributes-container { + margin-block: 0; +} + .modal.popup-editor-dialog .classic-toolbar-widget { position: sticky; + margin-inline: 8px; top: 0; inset-inline-start: 0; inset-inline-end: 0; From cc71f15700834d3d7636d6ff6a58b3bc8685e03f Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sun, 30 Nov 2025 02:17:43 +0200 Subject: [PATCH 72/80] client/quick edit: remove fixed toolbar transparency --- apps/client/src/widgets/dialogs/PopupEditor.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/client/src/widgets/dialogs/PopupEditor.css b/apps/client/src/widgets/dialogs/PopupEditor.css index 99d6cafff4..41a1d87368 100644 --- a/apps/client/src/widgets/dialogs/PopupEditor.css +++ b/apps/client/src/widgets/dialogs/PopupEditor.css @@ -76,7 +76,7 @@ body.mobile .modal.popup-editor-dialog .modal-dialog { top: 0; inset-inline-start: 0; inset-inline-end: 0; - background: transparent; + background: var(--modal-background-color); z-index: 998; align-items: flex-start; } From b8748b856a84e724e91193061a6376b114b879ba Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sun, 30 Nov 2025 02:34:09 +0200 Subject: [PATCH 73/80] client/note menu: use proper style for development-only actions section header --- apps/client/src/widgets/ribbon/NoteActions.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/client/src/widgets/ribbon/NoteActions.tsx b/apps/client/src/widgets/ribbon/NoteActions.tsx index bc191b5d0b..7db764c06c 100644 --- a/apps/client/src/widgets/ribbon/NoteActions.tsx +++ b/apps/client/src/widgets/ribbon/NoteActions.tsx @@ -1,5 +1,5 @@ import { ConvertToAttachmentResponse } from "@triliumnext/commons"; -import { FormDropdownDivider, FormListItem } from "../react/FormList"; +import { FormDropdownDivider, FormListHeader, FormListItem } from "../react/FormList"; import { isElectron as getIsElectron, isMac as getIsMac } from "../../services/utils"; import { ParentComponent } from "../react/react_utils"; import { t } from "../../services/i18n" @@ -113,8 +113,7 @@ function NoteContextMenu({ note, noteContext }: { note: FNote, noteContext?: Not function DevelopmentActions({ note }: { note: FNote }) { return ( <> - - Development-only Actions + window.open(`/?print=#root/${note.noteId}`, "_blank")} From 732494dfc51286926d86d49a73d3915a4aa22ef9 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Sun, 30 Nov 2025 02:54:51 +0200 Subject: [PATCH 74/80] client/keyboard shortcuts cheatsheet: add an edit button --- apps/client/src/translations/en/translation.json | 1 + apps/client/src/widgets/dialogs/help.tsx | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index 8f6767d9a8..5143015943 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -112,6 +112,7 @@ }, "help": { "title": "Cheatsheet", + "editShortcuts": "Edit keyboard shortcuts", "noteNavigation": "Note navigation", "goUpDown": "go up/down in the list of notes", "collapseExpand": "collapse/expand node", diff --git a/apps/client/src/widgets/dialogs/help.tsx b/apps/client/src/widgets/dialogs/help.tsx index d5c2f695d5..f6c0c96d60 100644 --- a/apps/client/src/widgets/dialogs/help.tsx +++ b/apps/client/src/widgets/dialogs/help.tsx @@ -1,7 +1,7 @@ import Modal from "../react/Modal.jsx"; import { t } from "../../services/i18n.js"; import { ComponentChildren } from "preact"; -import { CommandNames } from "../../components/app_context.js"; +import appContext, { CommandNames } from "../../components/app_context.js"; import RawHtml from "../react/RawHtml.jsx"; import { useEffect, useState } from "preact/hooks"; import keyboard_actions from "../../services/keyboard_actions.js"; @@ -14,6 +14,7 @@ export default function HelpDialog() { return ( setShown(false)} show={shown} > @@ -160,3 +161,7 @@ function Card({ title, children }: { title: string, children: ComponentChildren ) } + +function editShortcuts() { + appContext.tabManager.openContextWithNote("_optionsShortcuts", { activate: true }); +} \ No newline at end of file From 0cb5941be01bfad95ad63c889f6a2a360da5aa85 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 30 Nov 2025 02:49:23 +0000 Subject: [PATCH 75/80] chore(deps): update dependency typedoc to v0.28.15 --- apps/build-docs/package.json | 2 +- pnpm-lock.yaml | 68 +++++++++++++++++------------------- 2 files changed, 34 insertions(+), 36 deletions(-) diff --git a/apps/build-docs/package.json b/apps/build-docs/package.json index 0ec82b83ad..c2d4cd9fe6 100644 --- a/apps/build-docs/package.json +++ b/apps/build-docs/package.json @@ -16,7 +16,7 @@ "fs-extra": "11.3.2", "react": "19.2.0", "react-dom": "19.2.0", - "typedoc": "0.28.14", + "typedoc": "0.28.15", "typedoc-plugin-missing-exports": "4.1.2" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0dff9e3d7a..3a7a310d25 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -149,11 +149,11 @@ importers: specifier: 19.2.0 version: 19.2.0(react@19.2.0) typedoc: - specifier: 0.28.14 - version: 0.28.14(typescript@5.9.3) + specifier: 0.28.15 + version: 0.28.15(typescript@5.9.3) typedoc-plugin-missing-exports: specifier: 4.1.2 - version: 4.1.2(typedoc@0.28.14(typescript@5.9.3)) + version: 4.1.2(typedoc@0.28.15(typescript@5.9.3)) apps/client: dependencies: @@ -3164,8 +3164,8 @@ packages: '@gar/promisify@1.1.3': resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} - '@gerrit0/mini-shiki@3.14.0': - resolution: {integrity: sha512-c5X8fwPLOtUS8TVdqhynz9iV0GlOtFUT1ppXYzUUlEXe4kbZ/mvMT8wXoT8kCwUka+zsiloq7sD3pZ3+QVTuNQ==} + '@gerrit0/mini-shiki@3.17.0': + resolution: {integrity: sha512-Bpf6WuFar20ZXL6qU6VpVl4bVQfyyYiX+6O4xrns4nkU3Mr8paeupDbS1HENpcLOYj7pN4Rkd/yCaPA0vQwKww==} '@hapi/hoek@9.3.0': resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} @@ -4701,17 +4701,17 @@ packages: '@selderee/plugin-htmlparser2@0.11.0': resolution: {integrity: sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==} - '@shikijs/engine-oniguruma@3.14.0': - resolution: {integrity: sha512-TNcYTYMbJyy+ZjzWtt0bG5y4YyMIWC2nyePz+CFMWqm+HnZZyy9SWMgo8Z6KBJVIZnx8XUXS8U2afO6Y0g1Oug==} + '@shikijs/engine-oniguruma@3.17.0': + resolution: {integrity: sha512-flSbHZAiOZDNTrEbULY8DLWavu/TyVu/E7RChpLB4WvKX4iHMfj80C6Hi3TjIWaQtHOW0KC6kzMcuB5TO1hZ8Q==} - '@shikijs/langs@3.14.0': - resolution: {integrity: sha512-DIB2EQY7yPX1/ZH7lMcwrK5pl+ZkP/xoSpUzg9YC8R+evRCCiSQ7yyrvEyBsMnfZq4eBzLzBlugMyTAf13+pzg==} + '@shikijs/langs@3.17.0': + resolution: {integrity: sha512-icmur2n5Ojb+HAiQu6NEcIIJ8oWDFGGEpiqSCe43539Sabpx7Y829WR3QuUW2zjTM4l6V8Sazgb3rrHO2orEAw==} - '@shikijs/themes@3.14.0': - resolution: {integrity: sha512-fAo/OnfWckNmv4uBoUu6dSlkcBc+SA1xzj5oUSaz5z3KqHtEbUypg/9xxgJARtM6+7RVm0Q6Xnty41xA1ma1IA==} + '@shikijs/themes@3.17.0': + resolution: {integrity: sha512-/xEizMHLBmMHwtx4JuOkRf3zwhWD2bmG5BRr0IPjpcWpaq4C3mYEuTk/USAEglN0qPrTwEHwKVpSu/y2jhferA==} - '@shikijs/types@3.14.0': - resolution: {integrity: sha512-bQGgC6vrY8U/9ObG1Z/vTro+uclbjjD/uG58RvfxKZVD5p9Yc1ka3tVyEFy7BNJLzxuWyHH5NWynP9zZZS59eQ==} + '@shikijs/types@3.17.0': + resolution: {integrity: sha512-wjLVfutYWVUnxAjsWEob98xgyaGv0dTEnMZDruU5mRjVN7szcGOfgO+997W2yR6odp+1PtSBNeSITRRTfUzK/g==} '@shikijs/vscode-textmate@10.0.2': resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} @@ -14043,8 +14043,8 @@ packages: peerDependencies: typedoc: ^0.28.1 - typedoc@0.28.14: - resolution: {integrity: sha512-ftJYPvpVfQvFzpkoSfHLkJybdA/geDJ8BGQt/ZnkkhnBYoYW6lBgPQXu6vqLxO4X75dA55hX8Af847H5KXlEFA==} + typedoc@0.28.15: + resolution: {integrity: sha512-mw2/2vTL7MlT+BVo43lOsufkkd2CJO4zeOSuWQQsiXoV2VuEn7f6IZp2jsUDPmBMABpgR0R5jlcJ2OGEFYmkyg==} engines: {node: '>= 18', pnpm: '>= 10'} hasBin: true peerDependencies: @@ -16042,8 +16042,6 @@ snapshots: '@ckeditor/ckeditor5-utils': 47.2.0 ckeditor5: 47.2.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41) es-toolkit: 1.39.5 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-editor-multi-root@47.2.0': dependencies: @@ -16093,6 +16091,8 @@ snapshots: '@ckeditor/ckeditor5-core': 47.2.0 '@ckeditor/ckeditor5-engine': 47.2.0 '@ckeditor/ckeditor5-utils': 47.2.0 + transitivePeerDependencies: + - supports-color '@ckeditor/ckeditor5-essentials@47.2.0': dependencies: @@ -16749,8 +16749,6 @@ snapshots: '@ckeditor/ckeditor5-icons': 47.2.0 '@ckeditor/ckeditor5-ui': 47.2.0 '@ckeditor/ckeditor5-utils': 47.2.0 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-upload@47.2.0': dependencies: @@ -18056,12 +18054,12 @@ snapshots: '@gar/promisify@1.1.3': {} - '@gerrit0/mini-shiki@3.14.0': + '@gerrit0/mini-shiki@3.17.0': dependencies: - '@shikijs/engine-oniguruma': 3.14.0 - '@shikijs/langs': 3.14.0 - '@shikijs/themes': 3.14.0 - '@shikijs/types': 3.14.0 + '@shikijs/engine-oniguruma': 3.17.0 + '@shikijs/langs': 3.17.0 + '@shikijs/themes': 3.17.0 + '@shikijs/types': 3.17.0 '@shikijs/vscode-textmate': 10.0.2 '@hapi/hoek@9.3.0': {} @@ -19777,20 +19775,20 @@ snapshots: domhandler: 5.0.3 selderee: 0.11.0 - '@shikijs/engine-oniguruma@3.14.0': + '@shikijs/engine-oniguruma@3.17.0': dependencies: - '@shikijs/types': 3.14.0 + '@shikijs/types': 3.17.0 '@shikijs/vscode-textmate': 10.0.2 - '@shikijs/langs@3.14.0': + '@shikijs/langs@3.17.0': dependencies: - '@shikijs/types': 3.14.0 + '@shikijs/types': 3.17.0 - '@shikijs/themes@3.14.0': + '@shikijs/themes@3.17.0': dependencies: - '@shikijs/types': 3.14.0 + '@shikijs/types': 3.17.0 - '@shikijs/types@3.14.0': + '@shikijs/types@3.17.0': dependencies: '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.4 @@ -31446,13 +31444,13 @@ snapshots: typedarray@0.0.6: {} - typedoc-plugin-missing-exports@4.1.2(typedoc@0.28.14(typescript@5.9.3)): + typedoc-plugin-missing-exports@4.1.2(typedoc@0.28.15(typescript@5.9.3)): dependencies: - typedoc: 0.28.14(typescript@5.9.3) + typedoc: 0.28.15(typescript@5.9.3) - typedoc@0.28.14(typescript@5.9.3): + typedoc@0.28.15(typescript@5.9.3): dependencies: - '@gerrit0/mini-shiki': 3.14.0 + '@gerrit0/mini-shiki': 3.17.0 lunr: 2.3.9 markdown-it: 14.1.0 minimatch: 9.0.5 From d676084cb3510b310393fe0a33536fa8a28478e7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 30 Nov 2025 02:49:59 +0000 Subject: [PATCH 76/80] chore(deps): update dependency webdriverio to v9.21.0 --- packages/ckeditor5-admonition/package.json | 2 +- packages/ckeditor5-footnotes/package.json | 2 +- .../ckeditor5-keyboard-marker/package.json | 2 +- packages/ckeditor5-math/package.json | 2 +- packages/ckeditor5-mermaid/package.json | 2 +- pnpm-lock.yaml | 114 +++++++++--------- 6 files changed, 62 insertions(+), 62 deletions(-) diff --git a/packages/ckeditor5-admonition/package.json b/packages/ckeditor5-admonition/package.json index 6b8f361ebe..75d7e844f9 100644 --- a/packages/ckeditor5-admonition/package.json +++ b/packages/ckeditor5-admonition/package.json @@ -39,7 +39,7 @@ "typescript": "5.9.3", "vite-plugin-svgo": "~2.0.0", "vitest": "4.0.14", - "webdriverio": "9.20.1" + "webdriverio": "9.21.0" }, "peerDependencies": { "ckeditor5": "47.2.0" diff --git a/packages/ckeditor5-footnotes/package.json b/packages/ckeditor5-footnotes/package.json index c9d96cc205..af4735af10 100644 --- a/packages/ckeditor5-footnotes/package.json +++ b/packages/ckeditor5-footnotes/package.json @@ -40,7 +40,7 @@ "typescript": "5.9.3", "vite-plugin-svgo": "~2.0.0", "vitest": "4.0.14", - "webdriverio": "9.20.1" + "webdriverio": "9.21.0" }, "peerDependencies": { "ckeditor5": "47.2.0" diff --git a/packages/ckeditor5-keyboard-marker/package.json b/packages/ckeditor5-keyboard-marker/package.json index 23fc474d94..459ba9bf26 100644 --- a/packages/ckeditor5-keyboard-marker/package.json +++ b/packages/ckeditor5-keyboard-marker/package.json @@ -42,7 +42,7 @@ "typescript": "5.9.3", "vite-plugin-svgo": "~2.0.0", "vitest": "4.0.14", - "webdriverio": "9.20.1" + "webdriverio": "9.21.0" }, "peerDependencies": { "ckeditor5": "47.2.0" diff --git a/packages/ckeditor5-math/package.json b/packages/ckeditor5-math/package.json index ab00a473e2..aa60cfaa31 100644 --- a/packages/ckeditor5-math/package.json +++ b/packages/ckeditor5-math/package.json @@ -43,7 +43,7 @@ "typescript": "5.9.3", "vite-plugin-svgo": "~2.0.0", "vitest": "4.0.14", - "webdriverio": "9.20.1" + "webdriverio": "9.21.0" }, "peerDependencies": { "ckeditor5": "47.2.0" diff --git a/packages/ckeditor5-mermaid/package.json b/packages/ckeditor5-mermaid/package.json index 8cad9319ce..1e79fbf540 100644 --- a/packages/ckeditor5-mermaid/package.json +++ b/packages/ckeditor5-mermaid/package.json @@ -42,7 +42,7 @@ "typescript": "5.9.3", "vite-plugin-svgo": "~2.0.0", "vitest": "4.0.14", - "webdriverio": "9.20.1" + "webdriverio": "9.21.0" }, "peerDependencies": { "ckeditor5": "47.2.0" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0dff9e3d7a..45462c6d7d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -57,7 +57,7 @@ importers: version: 24.10.1 '@vitest/browser-webdriverio': specifier: 4.0.14 - version: 4.0.14(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.1)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@4.0.14)(webdriverio@9.20.1(bufferutil@4.0.9)(utf-8-validate@6.0.5)) + version: 4.0.14(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.1)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@4.0.14)(webdriverio@9.21.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)) '@vitest/coverage-v8': specifier: 4.0.14 version: 4.0.14(@vitest/browser@4.0.14(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.1)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@4.0.14))(vitest@4.0.14) @@ -933,8 +933,8 @@ importers: specifier: 4.0.14 version: 4.0.14(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-webdriverio@4.0.14)(@vitest/ui@4.0.14)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.10.1)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) webdriverio: - specifier: 9.20.1 - version: 9.20.1(bufferutil@4.0.9)(utf-8-validate@6.0.5) + specifier: 9.21.0 + version: 9.21.0(bufferutil@4.0.9)(utf-8-validate@6.0.5) packages/ckeditor5-footnotes: devDependencies: @@ -993,8 +993,8 @@ importers: specifier: 4.0.14 version: 4.0.14(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-webdriverio@4.0.14)(@vitest/ui@4.0.14)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.10.1)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) webdriverio: - specifier: 9.20.1 - version: 9.20.1(bufferutil@4.0.9)(utf-8-validate@6.0.5) + specifier: 9.21.0 + version: 9.21.0(bufferutil@4.0.9)(utf-8-validate@6.0.5) packages/ckeditor5-keyboard-marker: devDependencies: @@ -1053,8 +1053,8 @@ importers: specifier: 4.0.14 version: 4.0.14(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-webdriverio@4.0.14)(@vitest/ui@4.0.14)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.10.1)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) webdriverio: - specifier: 9.20.1 - version: 9.20.1(bufferutil@4.0.9)(utf-8-validate@6.0.5) + specifier: 9.21.0 + version: 9.21.0(bufferutil@4.0.9)(utf-8-validate@6.0.5) packages/ckeditor5-math: dependencies: @@ -1120,8 +1120,8 @@ importers: specifier: 4.0.14 version: 4.0.14(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-webdriverio@4.0.14)(@vitest/ui@4.0.14)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.10.1)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) webdriverio: - specifier: 9.20.1 - version: 9.20.1(bufferutil@4.0.9)(utf-8-validate@6.0.5) + specifier: 9.21.0 + version: 9.21.0(bufferutil@4.0.9)(utf-8-validate@6.0.5) packages/ckeditor5-mermaid: dependencies: @@ -1187,8 +1187,8 @@ importers: specifier: 4.0.14 version: 4.0.14(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-webdriverio@4.0.14)(@vitest/ui@4.0.14)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.10.1)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) webdriverio: - specifier: 9.20.1 - version: 9.20.1(bufferutil@4.0.9)(utf-8-validate@6.0.5) + specifier: 9.21.0 + version: 9.21.0(bufferutil@4.0.9)(utf-8-validate@6.0.5) packages/codemirror: dependencies: @@ -5449,9 +5449,6 @@ packages: '@types/node@16.9.1': resolution: {integrity: sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==} - '@types/node@20.19.24': - resolution: {integrity: sha512-FE5u0ezmi6y9OZEzlJfg37mqqf6ZDSF2V/NLjUyGrR9uTZ7Sb9F7bLNZ03S4XVUNRWGA7Ck4c1kK+YnuWjl+DA==} - '@types/node@20.19.25': resolution: {integrity: sha512-ZsJzA5thDQMSQO788d7IocwwQbI8B5OPzmqNvpf3NY/+MHDAS759Wo0gd2WQeXYt5AAAQjzcrTVC6SKCuYgoCQ==} @@ -5852,8 +5849,8 @@ packages: '@vue/shared@3.5.14': resolution: {integrity: sha512-oXTwNxVfc9EtP1zzXAlSlgARLXNC84frFYkS0HHz0h3E4WZSP9sywqjqzGCP9Y34M8ipNmd380pVgmMuwELDyQ==} - '@wdio/config@9.20.1': - resolution: {integrity: sha512-npl2J+rjCDJPjVySgWpciOyhWddn6s7n5sepKXLR7x1ADQHl5zUFv1dHD3jx4OQ9l6lrGQSPaofuz+7e9mu+vg==} + '@wdio/config@9.21.0': + resolution: {integrity: sha512-8TP5/q+Agjc43LET1f0LhLmuEI803O3QtZEbSxOkkvJ7/e1jDWPm4qsL7SjQJlx8xGrW0kwRlPl7+U9Sr0dhCQ==} engines: {node: '>=18.20.0'} '@wdio/logger@9.18.0': @@ -5871,8 +5868,8 @@ packages: resolution: {integrity: sha512-zMmAtse2UMCSOW76mvK3OejauAdcFGuKopNRH7crI0gwKTZtvV89yXWRziz9cVXpFgfmJCjf9edxKFWdhuF5yw==} engines: {node: '>=18.20.0'} - '@wdio/utils@9.20.1': - resolution: {integrity: sha512-C/Gsy5NAatsGUF1eT9Ks/ErR52/X4YI7MSm7BtwNOw8v2Ko+SiCA5qXts61J0A7QYwOn4gfXfBZZnzSAng6G/w==} + '@wdio/utils@9.21.0': + resolution: {integrity: sha512-aj8ao2V/e6Sv9gZby2ZIj4dMLjwYVba47Nlr+pOfK8N4VKKU0VRLPzvTlfK1HWaoS6u/GBbVx2pefYRrvd72BQ==} engines: {node: '>=18.20.0'} '@webassemblyjs/ast@1.14.1': @@ -5933,6 +5930,10 @@ packages: '@xtuc/long@4.2.2': resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} + '@zip.js/zip.js@2.8.11': + resolution: {integrity: sha512-0fztsk/0ryJ+2PPr9EyXS5/Co7OK8q3zY/xOoozEWaUsL5x+C0cyZ4YyMuUffOO2Dx/rAdq4JMPqW0VUtm+vzA==} + engines: {bun: '>=0.7.0', deno: '>=1.0.0', node: '>=18.0.0'} + '@zip.js/zip.js@2.8.2': resolution: {integrity: sha512-PI6UdgpSeVoGvzguKHmy2bwOqI3UYkntLZOCpyJSKIi7234c5aJmQYkJB/P4P2YUJkqhbqvu7iM2/0eJZ178nA==} engines: {bun: '>=0.7.0', deno: '>=1.0.0', node: '>=16.5.0'} @@ -8599,9 +8600,9 @@ packages: engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} deprecated: This package is no longer supported. - geckodriver@5.0.0: - resolution: {integrity: sha512-vn7TtQ3b9VMJtVXsyWtQQl1fyBVFhQy7UvJF96kPuuJ0or5THH496AD3eUyaDD11+EqCxH9t6V+EP9soZQk4YQ==} - engines: {node: '>=18.0.0'} + geckodriver@6.1.0: + resolution: {integrity: sha512-ZRXLa4ZaYTTgUO4Eefw+RsQCleugU2QLb1ME7qTYxxuRj51yAhfnXaItXNs5/vUzfIaDHuZ+YnSF005hfp07nQ==} + engines: {node: '>=20.0.0'} hasBin: true generate-function@2.3.1: @@ -10616,6 +10617,10 @@ packages: resolution: {integrity: sha512-2emPTb1reeLLYwHxyVx993iYyCHEiRRO+y8NFXFPL5kl5q14sgTK76cXyEKkeKCHeRw35SfdkUJ10Q1KfHuiIQ==} engines: {node: '>= 0.4'} + modern-tar@0.7.2: + resolution: {integrity: sha512-TGG1ZRk1TAQ3neuZwahAHke3rKsSlro+ooMYtjh9sl2gGPVMLMuWiHgwC7im9T5bSM566RSo2Dko56ETgEvZcA==} + engines: {node: '>=18.0.0'} + morphdom@2.7.7: resolution: {integrity: sha512-04GmsiBcalrSCNmzfo+UjU8tt3PhZJKzcOy+r1FlGA7/zri8wre3I1WkYN9PT3sIeIKfW9bpyElA+VzOg2E24g==} @@ -14525,12 +14530,12 @@ packages: resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} engines: {node: '>= 8'} - webdriver@9.20.1: - resolution: {integrity: sha512-QtvYqPai2NOnq7qePPH6kNSwk7+tnmSvnlOnY8dIT/Y24TPdQp44NjF/BUYAWIlqoBlZqHClQFTSVwT2qvO2Tw==} + webdriver@9.21.0: + resolution: {integrity: sha512-XLOhpU/EFPo4TMk+0fRli4g1WriUujxrfDxGT/QRq0MJsfhSYPF8FdefFdL5gHIrJfSKscaQHGWkbnsHftfqeg==} engines: {node: '>=18.20.0'} - webdriverio@9.20.1: - resolution: {integrity: sha512-QVM/asb5sDESz37ow/BAOA0z2HtUJsuAjPKHdw+Vx92PaQP3EfHwTgxK2T5rgwa0WRNh+c+n/0nEqIvqBl01sA==} + webdriverio@9.21.0: + resolution: {integrity: sha512-7teaXajOuNdn2UyyKlqMLssJjf0vDEih+Lo+tE/gHOt/P+mB8CinZym4PGtsriZLcyt4xV+Cun3hDmXM+pL26A==} engines: {node: '>=18.20.0'} peerDependencies: puppeteer-core: '>=22.x || <=24.x' @@ -16749,8 +16754,6 @@ snapshots: '@ckeditor/ckeditor5-icons': 47.2.0 '@ckeditor/ckeditor5-ui': 47.2.0 '@ckeditor/ckeditor5-utils': 47.2.0 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-upload@47.2.0': dependencies: @@ -20725,7 +20728,7 @@ snapshots: '@types/mute-stream@0.0.4': dependencies: - '@types/node': 22.19.1 + '@types/node': 24.10.1 '@types/node-forge@1.3.14': dependencies: @@ -20733,10 +20736,6 @@ snapshots: '@types/node@16.9.1': {} - '@types/node@20.19.24': - dependencies: - undici-types: 6.21.0 - '@types/node@20.19.25': dependencies: undici-types: 6.21.0 @@ -20914,7 +20913,7 @@ snapshots: '@types/yauzl@2.10.3': dependencies: - '@types/node': 22.18.13 + '@types/node': 24.10.1 optional: true '@typescript-eslint/eslint-plugin@8.46.4(@typescript-eslint/parser@8.46.4(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)': @@ -21141,11 +21140,11 @@ snapshots: - bufferutil - utf-8-validate - '@vitest/browser-webdriverio@4.0.14(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.1)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@4.0.14)(webdriverio@9.20.1(bufferutil@4.0.9)(utf-8-validate@6.0.5))': + '@vitest/browser-webdriverio@4.0.14(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.1)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@4.0.14)(webdriverio@9.21.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))': dependencies: '@vitest/browser': 4.0.14(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.1)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@4.0.14) vitest: 4.0.14(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-webdriverio@4.0.14)(@vitest/ui@4.0.14)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.10.1)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) - webdriverio: 9.20.1(bufferutil@4.0.9)(utf-8-validate@6.0.5) + webdriverio: 9.21.0(bufferutil@4.0.9)(utf-8-validate@6.0.5) transitivePeerDependencies: - bufferutil - msw @@ -21301,11 +21300,11 @@ snapshots: '@vue/shared@3.5.14': {} - '@wdio/config@9.20.1': + '@wdio/config@9.21.0': dependencies: '@wdio/logger': 9.18.0 '@wdio/types': 9.20.0 - '@wdio/utils': 9.20.1 + '@wdio/utils': 9.21.0 deepmerge-ts: 7.1.5 glob: 10.4.5 import-meta-resolve: 4.2.0 @@ -21325,13 +21324,13 @@ snapshots: '@wdio/repl@9.16.2': dependencies: - '@types/node': 20.19.24 + '@types/node': 20.19.25 '@wdio/types@9.20.0': dependencies: - '@types/node': 20.19.24 + '@types/node': 20.19.25 - '@wdio/utils@9.20.1': + '@wdio/utils@9.21.0': dependencies: '@puppeteer/browsers': 2.10.10 '@wdio/logger': 9.18.0 @@ -21339,7 +21338,7 @@ snapshots: decamelize: 6.0.1 deepmerge-ts: 7.1.5 edgedriver: 6.1.2 - geckodriver: 5.0.0 + geckodriver: 6.1.0 get-port: 7.1.0 import-meta-resolve: 4.2.0 locate-app: 2.5.0 @@ -21435,6 +21434,8 @@ snapshots: '@xtuc/long@4.2.2': {} + '@zip.js/zip.js@2.8.11': {} + '@zip.js/zip.js@2.8.2': {} abab@2.0.6: {} @@ -24932,18 +24933,15 @@ snapshots: wide-align: 1.1.5 optional: true - geckodriver@5.0.0: + geckodriver@6.1.0: dependencies: '@wdio/logger': 9.18.0 - '@zip.js/zip.js': 2.8.2 + '@zip.js/zip.js': 2.8.11 decamelize: 6.0.1 http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 - node-fetch: 3.3.2 - tar-fs: 3.1.1 - which: 5.0.0 + modern-tar: 0.7.2 transitivePeerDependencies: - - bare-buffer - supports-color generate-function@2.3.1: @@ -27452,6 +27450,8 @@ snapshots: hasown: 2.0.2 isarray: 2.0.5 + modern-tar@0.7.2: {} + morphdom@2.7.7: {} mrmime@2.0.1: {} @@ -31824,7 +31824,7 @@ snapshots: optionalDependencies: '@opentelemetry/api': 1.9.0 '@types/node': 24.10.1 - '@vitest/browser-webdriverio': 4.0.14(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.1)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@4.0.14)(webdriverio@9.20.1(bufferutil@4.0.9)(utf-8-validate@6.0.5)) + '@vitest/browser-webdriverio': 4.0.14(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.1)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vitest@4.0.14)(webdriverio@9.21.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)) '@vitest/ui': 4.0.14(vitest@4.0.14) happy-dom: 20.0.11 jsdom: 26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5) @@ -31914,15 +31914,15 @@ snapshots: web-streams-polyfill@3.3.3: {} - webdriver@9.20.1(bufferutil@4.0.9)(utf-8-validate@6.0.5): + webdriver@9.21.0(bufferutil@4.0.9)(utf-8-validate@6.0.5): dependencies: - '@types/node': 20.19.24 + '@types/node': 20.19.25 '@types/ws': 8.18.1 - '@wdio/config': 9.20.1 + '@wdio/config': 9.21.0 '@wdio/logger': 9.18.0 '@wdio/protocols': 9.16.2 '@wdio/types': 9.20.0 - '@wdio/utils': 9.20.1 + '@wdio/utils': 9.21.0 deepmerge-ts: 7.1.5 https-proxy-agent: 7.0.6 undici: 6.21.3 @@ -31933,16 +31933,16 @@ snapshots: - supports-color - utf-8-validate - webdriverio@9.20.1(bufferutil@4.0.9)(utf-8-validate@6.0.5): + webdriverio@9.21.0(bufferutil@4.0.9)(utf-8-validate@6.0.5): dependencies: - '@types/node': 20.19.24 + '@types/node': 20.19.25 '@types/sinonjs__fake-timers': 8.1.5 - '@wdio/config': 9.20.1 + '@wdio/config': 9.21.0 '@wdio/logger': 9.18.0 '@wdio/protocols': 9.16.2 '@wdio/repl': 9.16.2 '@wdio/types': 9.20.0 - '@wdio/utils': 9.20.1 + '@wdio/utils': 9.21.0 archiver: 7.0.1 aria-query: 5.3.2 cheerio: 1.1.2 @@ -31959,7 +31959,7 @@ snapshots: rgb2hex: 0.2.5 serialize-error: 12.0.0 urlpattern-polyfill: 10.1.0 - webdriver: 9.20.1(bufferutil@4.0.9)(utf-8-validate@6.0.5) + webdriver: 9.21.0(bufferutil@4.0.9)(utf-8-validate@6.0.5) transitivePeerDependencies: - bare-buffer - bufferutil From d9e8f8e69b15642f212aed130112307e9cfdc060 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sun, 30 Nov 2025 10:41:26 +0200 Subject: [PATCH 77/80] refactor(options): remove unnecessary ribbon activation option --- apps/client/src/widgets/ribbon/RibbonDefinition.ts | 2 +- apps/server/src/routes/api/options.ts | 1 - apps/server/src/services/options_init.ts | 1 - packages/commons/src/lib/options_interface.ts | 1 - 4 files changed, 1 insertion(+), 4 deletions(-) diff --git a/apps/client/src/widgets/ribbon/RibbonDefinition.ts b/apps/client/src/widgets/ribbon/RibbonDefinition.ts index 9f19707cbb..8117c511a9 100644 --- a/apps/client/src/widgets/ribbon/RibbonDefinition.ts +++ b/apps/client/src/widgets/ribbon/RibbonDefinition.ts @@ -50,7 +50,7 @@ export const RIBBON_TAB_DEFINITIONS: TabConfiguration[] = [ icon: "bx bx-calendar-edit", content: EditedNotesTab, show: ({ note }) => note?.hasOwnedLabel("dateNote"), - activate: ({ note }) => (note?.getPromotedDefinitionAttributes().length === 0 || !options.is("promotedAttributesOpenInRibbon")) && options.is("editedNotesOpenInRibbon") + activate: () => options.is("editedNotesOpenInRibbon") }, { title: t("book_properties.book_properties"), diff --git a/apps/server/src/routes/api/options.ts b/apps/server/src/routes/api/options.ts index 05f659db84..503447fa10 100644 --- a/apps/server/src/routes/api/options.ts +++ b/apps/server/src/routes/api/options.ts @@ -80,7 +80,6 @@ const ALLOWED_OPTIONS = new Set([ "disableTray", "customSearchEngineName", "customSearchEngineUrl", - "promotedAttributesOpenInRibbon", "editedNotesOpenInRibbon", "locale", "formattingLocale", diff --git a/apps/server/src/services/options_init.ts b/apps/server/src/services/options_init.ts index e170b347cf..c93fbd0f01 100644 --- a/apps/server/src/services/options_init.ts +++ b/apps/server/src/services/options_init.ts @@ -129,7 +129,6 @@ const defaultOptions: DefaultOption[] = [ { name: "logRetentionDays", value: "90", isSynced: false }, // default 90 days { name: "customSearchEngineName", value: "DuckDuckGo", isSynced: true }, { name: "customSearchEngineUrl", value: "https://duckduckgo.com/?q={keyword}", isSynced: true }, - { name: "promotedAttributesOpenInRibbon", value: "true", isSynced: true }, { name: "editedNotesOpenInRibbon", value: "true", isSynced: true }, { name: "mfaEnabled", value: "false", isSynced: false }, { name: "mfaMethod", value: "totp", isSynced: false }, diff --git a/packages/commons/src/lib/options_interface.ts b/packages/commons/src/lib/options_interface.ts index 0e044d37c7..bdc223c1f6 100644 --- a/packages/commons/src/lib/options_interface.ts +++ b/packages/commons/src/lib/options_interface.ts @@ -121,7 +121,6 @@ export interface OptionDefinitions extends KeyboardShortcutsOptions Date: Sun, 30 Nov 2025 10:43:06 +0200 Subject: [PATCH 78/80] fix(ribbon): formatting toolbar overrides edited notes activation (closes #7900) --- apps/client/src/widgets/ribbon/RibbonDefinition.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/client/src/widgets/ribbon/RibbonDefinition.ts b/apps/client/src/widgets/ribbon/RibbonDefinition.ts index 8117c511a9..ae4aac3f36 100644 --- a/apps/client/src/widgets/ribbon/RibbonDefinition.ts +++ b/apps/client/src/widgets/ribbon/RibbonDefinition.ts @@ -26,7 +26,7 @@ export const RIBBON_TAB_DEFINITIONS: TabConfiguration[] = [ && !(await noteContext?.isReadOnly()), toggleCommand: "toggleRibbonTabClassicEditor", content: FormattingToolbar, - activate: true, + activate: () => !options.is("editedNotesOpenInRibbon"), stayInDom: true }, { From 15190abb6971d86ef15d8e67c0166d576fc3c014 Mon Sep 17 00:00:00 2001 From: SiriusXT <1160925501@qq.com> Date: Sun, 30 Nov 2025 16:53:14 +0800 Subject: [PATCH 79/80] feat(ckeditor5): add formatPainter --- apps/client/src/widgets/type_widgets/text/toolbar.ts | 2 ++ packages/ckeditor5/src/index.ts | 1 + packages/ckeditor5/src/plugins.ts | 5 +++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/client/src/widgets/type_widgets/text/toolbar.ts b/apps/client/src/widgets/type_widgets/text/toolbar.ts index c8ba56d4da..69e37449fd 100644 --- a/apps/client/src/widgets/type_widgets/text/toolbar.ts +++ b/apps/client/src/widgets/type_widgets/text/toolbar.ts @@ -55,6 +55,7 @@ export function buildClassicToolbar(multilineToolbar: boolean) { ...TEXT_FORMATTING_GROUP, items: ["underline", "strikethrough", "|", "superscript", "subscript", "|", "kbd"] }, + "formatPainter", "|", "fontColor", "fontBackgroundColor", @@ -104,6 +105,7 @@ export function buildFloatingToolbar() { ...TEXT_FORMATTING_GROUP, items: [ "strikethrough", "|", "superscript", "subscript", "|", "kbd" ] }, + "formatPainter", "|", "fontColor", "fontBackgroundColor", diff --git a/packages/ckeditor5/src/index.ts b/packages/ckeditor5/src/index.ts index 2d73ecdea7..17b2c775ee 100644 --- a/packages/ckeditor5/src/index.ts +++ b/packages/ckeditor5/src/index.ts @@ -1,4 +1,5 @@ import "ckeditor5/ckeditor5.css"; +import 'ckeditor5-premium-features/ckeditor5-premium-features.css'; import "./theme/code_block_toolbar.css"; import { COMMON_PLUGINS, CORE_PLUGINS, POPUP_EDITOR_PLUGINS } from "./plugins.js"; import { BalloonEditor, DecoupledEditor, FindAndReplaceEditing, FindCommand } from "ckeditor5"; diff --git a/packages/ckeditor5/src/plugins.ts b/packages/ckeditor5/src/plugins.ts index bbd613a9ec..81a8a7fe18 100644 --- a/packages/ckeditor5/src/plugins.ts +++ b/packages/ckeditor5/src/plugins.ts @@ -1,5 +1,5 @@ import { Autoformat, AutoLink, BlockQuote, BlockToolbar, Bold, CKFinderUploadAdapter, Clipboard, Code, CodeBlock, Enter, FindAndReplace, Font, FontBackgroundColor, FontColor, GeneralHtmlSupport, Heading, HeadingButtonsUI, HorizontalLine, Image, ImageCaption, ImageInline, ImageResize, ImageStyle, ImageToolbar, ImageUpload, Alignment, Indent, IndentBlock, Italic, Link, List, ListProperties, Mention, PageBreak, Paragraph, ParagraphButtonUI, PasteFromOffice, PictureEditing, RemoveFormat, SelectAll, ShiftEnter, SpecialCharacters, SpecialCharactersEssentials, Strikethrough, Style, Subscript, Superscript, Table, TableCaption, TableCellProperties, TableColumnResize, TableProperties, TableSelection, TableToolbar, TextPartLanguage, TextTransformation, TodoList, Typing, Underline, Undo, Bookmark, Emoji, Notification, EmojiMention, EmojiPicker } from "ckeditor5"; -import { SlashCommand, Template } from "ckeditor5-premium-features"; +import { SlashCommand, Template, FormatPainter } from "ckeditor5-premium-features"; import type { Plugin } from "ckeditor5"; import CutToNotePlugin from "./plugins/cuttonote.js"; import UploadimagePlugin from "./plugins/uploadimage.js"; @@ -83,7 +83,8 @@ export const CORE_PLUGINS: typeof Plugin[] = [ */ export const PREMIUM_PLUGINS: typeof Plugin[] = [ SlashCommand, - Template + Template, + FormatPainter ]; /** From 8cc43cd9a692cc8e4c03218acd452b1c489d28a6 Mon Sep 17 00:00:00 2001 From: SiriusXT <1160925501@qq.com> Date: Sun, 30 Nov 2025 20:08:27 +0800 Subject: [PATCH 80/80] docs(user): add format painter --- .../doc_notes/en/User Guide/!!!meta.json | 2 +- .../User Guide/Note Types/Text.html | 336 +++++++++--------- .../Note Types/Text/General formatting.html | 27 +- .../Text/Premium features/Format Painter.html | 45 +++ .../Format Painter_746436a2e1.svg | 1 + .../Format Painter_e144e96df9.svg | 7 + .../Premium features/Format Painter_image.png | Bin 0 -> 5251 bytes docs/User Guide/!!!meta.json | 157 ++++++-- docs/User Guide/User Guide/Note Types/Text.md | 2 +- .../Note Types/Text/General formatting.md | 4 + .../Text/Premium features/Format Painter.md | 20 ++ .../Format Painter_746436a2e1.svg | 1 + .../Format Painter_e144e96df9.svg | 7 + .../Premium features/Format Painter_image.png | Bin 0 -> 5251 bytes 14 files changed, 396 insertions(+), 213 deletions(-) create mode 100644 apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Premium features/Format Painter.html create mode 100644 apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Premium features/Format Painter_746436a2e1.svg create mode 100644 apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Premium features/Format Painter_e144e96df9.svg create mode 100644 apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Premium features/Format Painter_image.png create mode 100644 docs/User Guide/User Guide/Note Types/Text/Premium features/Format Painter.md create mode 100644 docs/User Guide/User Guide/Note Types/Text/Premium features/Format Painter_746436a2e1.svg create mode 100644 docs/User Guide/User Guide/Note Types/Text/Premium features/Format Painter_e144e96df9.svg create mode 100644 docs/User Guide/User Guide/Note Types/Text/Premium features/Format Painter_image.png diff --git a/apps/server/src/assets/doc_notes/en/User Guide/!!!meta.json b/apps/server/src/assets/doc_notes/en/User Guide/!!!meta.json index 86cdc3a724..795752fd70 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/!!!meta.json +++ b/apps/server/src/assets/doc_notes/en/User Guide/!!!meta.json @@ -1 +1 @@ -[{"id":"_help_BOCnjTMBCoxW","title":"Feature Highlights","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Feature Highlights"},{"name":"iconClass","value":"bx bx-star","type":"label"}]},{"id":"_help_Otzi9La2YAUX","title":"Installation & Setup","type":"book","attributes":[{"name":"iconClass","value":"bx bx-cog","type":"label"}],"children":[{"id":"_help_poXkQfguuA0U","title":"Desktop Installation","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Desktop Installation"},{"name":"iconClass","value":"bx bx-desktop","type":"label"}],"children":[{"id":"_help_nRqcgfTb97uV","title":"Using the desktop application as a server","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Desktop Installation/Using the desktop application "},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_Rp0q8bSP6Ayl","title":"System Requirements","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Desktop Installation/System Requirements"},{"name":"iconClass","value":"bx bx-chip","type":"label"}]},{"id":"_help_Un4wj2Mak2Ky","title":"Nix flake","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Desktop Installation/Nix flake"},{"name":"iconClass","value":"bx bxl-tux","type":"label"}]}]},{"id":"_help_WOcw2SLH6tbX","title":"Server Installation","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation"},{"name":"iconClass","value":"bx bx-server","type":"label"}],"children":[{"id":"_help_Dgg7bR3b6K9j","title":"1. Installing the server","type":"book","attributes":[{"name":"iconClass","value":"bx bx-folder","type":"label"}],"children":[{"id":"_help_3tW6mORuTHnB","title":"Packaged version for Linux","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Packaged version for Linux"},{"name":"iconClass","value":"bx bxl-tux","type":"label"}]},{"id":"_help_rWX5eY045zbE","title":"Using Docker","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Using Docker"},{"name":"iconClass","value":"bx bxl-docker","type":"label"}]},{"id":"_help_moVgBcoxE3EK","title":"On NixOS","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/On NixOS"},{"name":"iconClass","value":"bx bxl-tux","type":"label"}]},{"id":"_help_J1Bb6lVlwU5T","title":"Manually","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Manually"},{"name":"iconClass","value":"bx bx-code-alt","type":"label"}]},{"id":"_help_DCmT6e7clMoP","title":"Using Kubernetes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Using Kubernetes"},{"name":"iconClass","value":"bx bxl-kubernetes","type":"label"}]},{"id":"_help_klCWNks3ReaQ","title":"Multiple server instances","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Multiple server instances"},{"name":"iconClass","value":"bx bxs-user-account","type":"label"}]}]},{"id":"_help_vcjrb3VVYPZI","title":"2. Reverse proxy","type":"book","attributes":[{"name":"iconClass","value":"bx bx-folder","type":"label"}],"children":[{"id":"_help_ud6MShXL4WpO","title":"Nginx","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Nginx"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_fDLvzOx29Pfg","title":"Apache using Docker","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Apache using Docker"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_LLzSMXACKhUs","title":"Trusted proxy","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Trusted proxy"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_5ERVJb9s4FRD","title":"Traefik","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Traefik"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_l2VkvOwUNfZj","title":"HTTPS (TLS)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/HTTPS (TLS)"},{"name":"iconClass","value":"bx bx-lock-alt","type":"label"}]},{"id":"_help_0hzsNCP31IAB","title":"Authentication","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/Authentication"},{"name":"iconClass","value":"bx bx-user","type":"label"}]},{"id":"_help_7DAiwaf8Z7Rz","title":"Multi-Factor Authentication","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/Multi-Factor Authentication"},{"name":"iconClass","value":"bx bx-stopwatch","type":"label"}]},{"id":"_help_Un4wj2Mak2Ky","title":"Nix flake","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/Nix flake.clone"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_yeEaYqosGLSh","title":"Third-party cloud hosting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/Third-party cloud hosting"},{"name":"iconClass","value":"bx bx-cloud","type":"label"}]},{"id":"_help_iGTnKjubbXkA","title":"System Requirements","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/System Requirements"},{"name":"iconClass","value":"bx bx-chip","type":"label"}]}]},{"id":"_help_cbkrhQjrkKrh","title":"Synchronization","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Synchronization"},{"name":"iconClass","value":"bx bx-sync","type":"label"}]},{"id":"_help_RDslemsQ6gCp","title":"Mobile Frontend","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Mobile Frontend"},{"name":"iconClass","value":"bx bx-mobile-alt","type":"label"}]},{"id":"_help_MtPxeAWVAzMg","title":"Web Clipper","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Web Clipper"},{"name":"iconClass","value":"bx bx-paperclip","type":"label"}]},{"id":"_help_n1lujUxCwipy","title":"Upgrading TriliumNext","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Upgrading TriliumNext"},{"name":"iconClass","value":"bx bx-up-arrow-alt","type":"label"}]},{"id":"_help_ODY7qQn5m2FT","title":"Backup","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Backup"},{"name":"iconClass","value":"bx bx-hdd","type":"label"}]},{"id":"_help_tAassRL4RSQL","title":"Data directory","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Data directory"},{"name":"iconClass","value":"bx bx-folder-open","type":"label"}]}]},{"id":"_help_gh7bpGYxajRS","title":"Basic Concepts and Features","type":"book","attributes":[{"name":"iconClass","value":"bx bx-help-circle","type":"label"}],"children":[{"id":"_help_Vc8PjrjAGuOp","title":"UI Elements","type":"book","attributes":[{"name":"iconClass","value":"bx bx-window-alt","type":"label"}],"children":[{"id":"_help_x0JgW8UqGXvq","title":"Vertical and horizontal layout","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Vertical and horizontal layout"},{"name":"iconClass","value":"bx bxs-layout","type":"label"}]},{"id":"_help_x3i7MxGccDuM","title":"Global menu","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Global menu"},{"name":"iconClass","value":"bx bx-menu","type":"label"}]},{"id":"_help_oPVyFC7WL2Lp","title":"Note Tree","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree"},{"name":"iconClass","value":"bx bxs-tree-alt","type":"label"}],"children":[{"id":"_help_YtSN43OrfzaA","title":"Note tree contextual menu","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Note tree contextual menu"},{"name":"iconClass","value":"bx bx-menu","type":"label"}]},{"id":"_help_yTjUdsOi4CIE","title":"Multiple selection","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Multiple selection"},{"name":"iconClass","value":"bx bx-list-plus","type":"label"}]},{"id":"_help_DvdZhoQZY9Yd","title":"Keyboard shortcuts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Keyboard shortcuts"},{"name":"iconClass","value":"bx bxs-keyboard","type":"label"}]}]},{"id":"_help_BlN9DFI679QC","title":"Ribbon","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Ribbon"},{"name":"iconClass","value":"bx bx-dots-horizontal","type":"label"}]},{"id":"_help_3seOhtN8uLIY","title":"Tabs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Tabs"},{"name":"iconClass","value":"bx bx-dock-top","type":"label"}]},{"id":"_help_xYmIYSP6wE3F","title":"Launch Bar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Launch Bar"},{"name":"iconClass","value":"bx bx-sidebar","type":"label"}]},{"id":"_help_8YBEPzcpUgxw","title":"Note buttons","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note buttons"},{"name":"iconClass","value":"bx bx-dots-vertical-rounded","type":"label"}]},{"id":"_help_4TIF1oA4VQRO","title":"Options","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Options"},{"name":"iconClass","value":"bx bx-cog","type":"label"}]},{"id":"_help_luNhaphA37EO","title":"Split View","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Split View"},{"name":"iconClass","value":"bx bx-dock-right","type":"label"}]},{"id":"_help_XpOYSgsLkTJy","title":"Floating buttons","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Floating buttons"},{"name":"iconClass","value":"bx bx-rectangle","type":"label"}]},{"id":"_help_RnaPdbciOfeq","title":"Right Sidebar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Right Sidebar"},{"name":"iconClass","value":"bx bxs-dock-right","type":"label"}]},{"id":"_help_r5JGHN99bVKn","title":"Recent Changes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Recent Changes"},{"name":"iconClass","value":"bx bx-history","type":"label"}]},{"id":"_help_ny318J39E5Z0","title":"Zoom","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Zoom"},{"name":"iconClass","value":"bx bx-zoom-in","type":"label"}]},{"id":"_help_lgKX7r3aL30x","title":"Note Tooltip","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tooltip"},{"name":"iconClass","value":"bx bx-message-detail","type":"label"}]}]},{"id":"_help_BFs8mudNFgCS","title":"Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes"},{"name":"iconClass","value":"bx bx-notepad","type":"label"}],"children":[{"id":"_help_p9kXRFAkwN4o","title":"Note Icons","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Note Icons"},{"name":"iconClass","value":"bx bxs-grid","type":"label"}]},{"id":"_help_0vhv7lsOLy82","title":"Attachments","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Attachments"},{"name":"iconClass","value":"bx bx-paperclip","type":"label"}]},{"id":"_help_IakOLONlIfGI","title":"Cloning Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Cloning Notes"},{"name":"iconClass","value":"bx bx-duplicate","type":"label"}],"children":[{"id":"_help_TBwsyfadTA18","title":"Branch prefix","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Cloning Notes/Branch prefix"},{"name":"iconClass","value":"bx bx-rename","type":"label"}]}]},{"id":"_help_bwg0e8ewQMak","title":"Protected Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Protected Notes"},{"name":"iconClass","value":"bx bx-lock-alt","type":"label"}]},{"id":"_help_MKmLg5x6xkor","title":"Archived Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Archived Notes"},{"name":"iconClass","value":"bx bx-box","type":"label"}]},{"id":"_help_vZWERwf8U3nx","title":"Note Revisions","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions"},{"name":"iconClass","value":"bx bx-history","type":"label"}]},{"id":"_help_aGlEvb9hyDhS","title":"Sorting Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Sorting Notes"},{"name":"iconClass","value":"bx bx-sort-up","type":"label"}]},{"id":"_help_NRnIZmSMc5sj","title":"Printing & Exporting as PDF","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Printing & Exporting as PDF"},{"name":"iconClass","value":"bx bx-printer","type":"label"}]},{"id":"_help_CoFPLs3dRlXc","title":"Read-Only Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Read-Only Notes"},{"name":"iconClass","value":"bx bx-edit-alt","type":"label"}]},{"id":"_help_0ESUbbAxVnoK","title":"Note List","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Note List"},{"name":"iconClass","value":"bx bxs-grid","type":"label"}]}]},{"id":"_help_wArbEsdSae6g","title":"Navigation","type":"book","attributes":[{"name":"iconClass","value":"bx bx-navigation","type":"label"}],"children":[{"id":"_help_kBrnXNG3Hplm","title":"Tree Concepts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Tree Concepts"},{"name":"iconClass","value":"bx bx-pyramid","type":"label"}]},{"id":"_help_MMiBEQljMQh2","title":"Note Navigation","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Note Navigation"},{"name":"iconClass","value":"bx bxs-navigation","type":"label"}]},{"id":"_help_Ms1nauBra7gq","title":"Quick search","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Quick search"},{"name":"iconClass","value":"bx bx-search-alt-2","type":"label"}]},{"id":"_help_F1r9QtzQLZqm","title":"Jump to...","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Jump to"},{"name":"iconClass","value":"bx bx-send","type":"label"}]},{"id":"_help_eIg8jdvaoNNd","title":"Search","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Search"},{"name":"iconClass","value":"bx bx-search-alt-2","type":"label"}]},{"id":"_help_u3YFHC9tQlpm","title":"Bookmarks","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Bookmarks"},{"name":"iconClass","value":"bx bx-bookmarks","type":"label"}]},{"id":"_help_OR8WJ7Iz9K4U","title":"Note Hoisting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Note Hoisting"},{"name":"iconClass","value":"bx bxs-chevrons-up","type":"label"}]},{"id":"_help_ZjLYv08Rp3qC","title":"Quick edit","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Quick edit"},{"name":"iconClass","value":"bx bx-edit","type":"label"}]},{"id":"_help_9sRHySam5fXb","title":"Workspaces","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Workspaces"},{"name":"iconClass","value":"bx bx-door-open","type":"label"}]},{"id":"_help_xWtq5NUHOwql","title":"Similar Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Similar Notes"},{"name":"iconClass","value":"bx bx-bar-chart","type":"label"}]},{"id":"_help_McngOG2jbUWX","title":"Search in note","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Search in note"},{"name":"iconClass","value":"bx bx-search-alt-2","type":"label"}]}]},{"id":"_help_A9Oc6YKKc65v","title":"Keyboard Shortcuts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Keyboard Shortcuts"},{"name":"iconClass","value":"bx bxs-keyboard","type":"label"}]},{"id":"_help_Wy267RK4M69c","title":"Themes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Themes"},{"name":"iconClass","value":"bx bx-palette","type":"label"}],"children":[{"id":"_help_VbjZvtUek0Ln","title":"Theme Gallery","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Themes/Theme Gallery"},{"name":"iconClass","value":"bx bx-book-reader","type":"label"}]}]},{"id":"_help_mHbBMPDPkVV5","title":"Import & Export","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export"},{"name":"iconClass","value":"bx bx-import","type":"label"}],"children":[{"id":"_help_Oau6X9rCuegd","title":"Markdown","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown"},{"name":"iconClass","value":"bx bxl-markdown","type":"label"}],"children":[{"id":"_help_rJ9grSgoExl9","title":"Supported syntax","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown/Supported syntax"},{"name":"iconClass","value":"bx bx-code-alt","type":"label"}]}]},{"id":"_help_syuSEKf2rUGr","title":"Evernote","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export/Evernote"},{"name":"iconClass","value":"bx bx-window-open","type":"label"}]},{"id":"_help_GnhlmrATVqcH","title":"OneNote","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export/OneNote"},{"name":"iconClass","value":"bx bx-window-open","type":"label"}]}]},{"id":"_help_rC3pL2aptaRE","title":"Zen mode","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Zen mode"},{"name":"iconClass","value":"bx bxs-yin-yang","type":"label"}]}]},{"id":"_help_s3YCWHBfmYuM","title":"Quick Start","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Quick Start"},{"name":"iconClass","value":"bx bx-run","type":"label"}]},{"id":"_help_i6dbnitykE5D","title":"FAQ","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/FAQ"},{"name":"iconClass","value":"bx bx-question-mark","type":"label"}]},{"id":"_help_KSZ04uQ2D1St","title":"Note Types","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types"},{"name":"iconClass","value":"bx bx-edit","type":"label"}],"children":[{"id":"_help_iPIMuisry3hd","title":"Text","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text"},{"name":"iconClass","value":"bx bx-note","type":"label"}],"children":[{"id":"_help_NwBbFdNZ9h7O","title":"Block quotes & admonitions","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Block quotes & admonitions"},{"name":"iconClass","value":"bx bx-info-circle","type":"label"}]},{"id":"_help_oSuaNgyyKnhu","title":"Bookmarks","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Bookmarks"},{"name":"iconClass","value":"bx bx-bookmark","type":"label"}]},{"id":"_help_veGu4faJErEM","title":"Content language & Right-to-left support","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Content language & Right-to-le"},{"name":"iconClass","value":"bx bx-align-right","type":"label"}]},{"id":"_help_2x0ZAX9ePtzV","title":"Cut to subnote","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Cut to subnote"},{"name":"iconClass","value":"bx bx-cut","type":"label"}]},{"id":"_help_UYuUB1ZekNQU","title":"Developer-specific formatting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Developer-specific formatting"},{"name":"iconClass","value":"bx bx-code-alt","type":"label"}],"children":[{"id":"_help_QxEyIjRBizuC","title":"Code blocks","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Developer-specific formatting/Code blocks"},{"name":"iconClass","value":"bx bx-code","type":"label"}]}]},{"id":"_help_AgjCISero73a","title":"Footnotes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Footnotes"},{"name":"iconClass","value":"bx bx-bracket","type":"label"}]},{"id":"_help_nRhnJkTT8cPs","title":"Formatting toolbar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Formatting toolbar"},{"name":"iconClass","value":"bx bx-text","type":"label"}]},{"id":"_help_Gr6xFaF6ioJ5","title":"General formatting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/General formatting"},{"name":"iconClass","value":"bx bx-bold","type":"label"}]},{"id":"_help_AxshuNRegLAv","title":"Highlights list","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Highlights list"},{"name":"iconClass","value":"bx bx-highlight","type":"label"}]},{"id":"_help_mT0HEkOsz6i1","title":"Images","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Images"},{"name":"iconClass","value":"bx bx-image-alt","type":"label"}],"children":[{"id":"_help_0Ofbk1aSuVRu","title":"Image references","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Images/Image references"},{"name":"iconClass","value":"bx bxs-file-image","type":"label"}]}]},{"id":"_help_nBAXQFj20hS1","title":"Include Note","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Include Note"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_CohkqWQC1iBv","title":"Insert buttons","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Insert buttons"},{"name":"iconClass","value":"bx bx-plus","type":"label"}]},{"id":"_help_oiVPnW8QfnvS","title":"Keyboard shortcuts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Keyboard shortcuts"},{"name":"iconClass","value":"bx bxs-keyboard","type":"label"}]},{"id":"_help_QEAPj01N5f7w","title":"Links","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Links"},{"name":"iconClass","value":"bx bx-link-alt","type":"label"}],"children":[{"id":"_help_3IDVtesTQ8ds","title":"External links","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Links/External links"},{"name":"iconClass","value":"bx bx-link-external","type":"label"}]},{"id":"_help_hrZ1D00cLbal","title":"Internal (reference) links","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Links/Internal (reference) links"},{"name":"iconClass","value":"bx bx-link","type":"label"}]}]},{"id":"_help_S6Xx8QIWTV66","title":"Lists","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Lists"},{"name":"iconClass","value":"bx bx-list-ul","type":"label"}]},{"id":"_help_QrtTYPmdd1qq","title":"Markdown-like formatting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Markdown-like formatting"},{"name":"iconClass","value":"bx bxl-markdown","type":"label"}]},{"id":"_help_YfYAtQBcfo5V","title":"Math Equations","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Math Equations"},{"name":"iconClass","value":"bx bx-math","type":"label"}]},{"id":"_help_dEHYtoWWi8ct","title":"Other features","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Other features"},{"name":"iconClass","value":"bx bxs-grid","type":"label"}]},{"id":"_help_gLt3vA97tMcp","title":"Premium features","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Premium features"},{"name":"iconClass","value":"bx bx-star","type":"label"}],"children":[{"id":"_help_ZlN4nump6EbW","title":"Slash Commands","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Premium features/Slash Commands"},{"name":"iconClass","value":"bx bx-menu","type":"label"}]},{"id":"_help_pwc194wlRzcH","title":"Text Snippets","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Premium features/Text Snippets"},{"name":"iconClass","value":"bx bx-align-left","type":"label"}]}]},{"id":"_help_BFvAtE74rbP6","title":"Table of contents","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Table of contents"},{"name":"iconClass","value":"bx bx-heading","type":"label"}]},{"id":"_help_NdowYOC1GFKS","title":"Tables","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Tables"},{"name":"iconClass","value":"bx bx-table","type":"label"}]}]},{"id":"_help_6f9hih2hXXZk","title":"Code","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Code"},{"name":"iconClass","value":"bx bx-code","type":"label"}]},{"id":"_help_m523cpzocqaD","title":"Saved Search","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Saved Search"},{"name":"iconClass","value":"bx bx-file-find","type":"label"}]},{"id":"_help_iRwzGnHPzonm","title":"Relation Map","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Relation Map"},{"name":"iconClass","value":"bx bxs-network-chart","type":"label"}]},{"id":"_help_bdUJEHsAPYQR","title":"Note Map","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Note Map"},{"name":"iconClass","value":"bx bxs-network-chart","type":"label"}]},{"id":"_help_HcABDtFCkbFN","title":"Render Note","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Render Note"},{"name":"iconClass","value":"bx bx-extension","type":"label"}]},{"id":"_help_s1aBHPd79XYj","title":"Mermaid Diagrams","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Mermaid Diagrams"},{"name":"iconClass","value":"bx bx-selection","type":"label"}],"children":[{"id":"_help_RH6yLjjWJHof","title":"ELK layout","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Mermaid Diagrams/ELK layout"},{"name":"iconClass","value":"bx bxs-network-chart","type":"label"}]},{"id":"_help_WWgeUaBb7UfC","title":"Syntax reference","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://mermaid.js.org/intro/syntax-reference.html"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_grjYqerjn243","title":"Canvas","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Canvas"},{"name":"iconClass","value":"bx bx-pen","type":"label"}]},{"id":"_help_1vHRoWCEjj0L","title":"Web View","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Web View"},{"name":"iconClass","value":"bx bx-globe-alt","type":"label"}]},{"id":"_help_gBbsAeiuUxI5","title":"Mind Map","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Mind Map"},{"name":"iconClass","value":"bx bx-sitemap","type":"label"}]},{"id":"_help_W8vYD3Q1zjCR","title":"File","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/File"},{"name":"iconClass","value":"bx bx-file-blank","type":"label"}]}]},{"id":"_help_GTwFsgaA0lCt","title":"Collections","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections"},{"name":"iconClass","value":"bx bx-book","type":"label"}],"children":[{"id":"_help_xWbu3jpNWapp","title":"Calendar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Calendar"},{"name":"iconClass","value":"bx bx-calendar","type":"label"}]},{"id":"_help_2FvYrpmOXm29","title":"Table","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Table"},{"name":"iconClass","value":"bx bx-table","type":"label"}]},{"id":"_help_CtBQqbwXDx1w","title":"Kanban Board","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Kanban Board"},{"name":"iconClass","value":"bx bx-columns","type":"label"}]},{"id":"_help_81SGnPGMk7Xc","title":"Geo Map","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Geo Map"},{"name":"iconClass","value":"bx bx-map-alt","type":"label"}]},{"id":"_help_zP3PMqaG71Ct","title":"Presentation","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Presentation"},{"name":"iconClass","value":"bx bx-slideshow","type":"label"}]},{"id":"_help_8QqnMzx393bx","title":"Grid View","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Grid View"},{"name":"iconClass","value":"bx bxs-grid","type":"label"}]},{"id":"_help_mULW0Q3VojwY","title":"List View","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/List View"},{"name":"iconClass","value":"bx bx-list-ul","type":"label"}]}]},{"id":"_help_BgmBlOIl72jZ","title":"Troubleshooting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting"},{"name":"iconClass","value":"bx bx-bug","type":"label"}],"children":[{"id":"_help_wy8So3yZZlH9","title":"Reporting issues","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Reporting issues"},{"name":"iconClass","value":"bx bx-bug-alt","type":"label"}]},{"id":"_help_x59R8J8KV5Bp","title":"Anonymized Database","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Anonymized Database"},{"name":"iconClass","value":"bx bx-low-vision","type":"label"}]},{"id":"_help_qzNzp9LYQyPT","title":"Error logs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Error logs"},{"name":"iconClass","value":"bx bx-comment-error","type":"label"}],"children":[{"id":"_help_bnyigUA2UK7s","title":"Backend (server) logs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Error logs/Backend (server) logs"},{"name":"iconClass","value":"bx bx-server","type":"label"}]},{"id":"_help_9yEHzMyFirZR","title":"Frontend logs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Error logs/Frontend logs"},{"name":"iconClass","value":"bx bx-window-alt","type":"label"}]}]},{"id":"_help_vdlYGAcpXAgc","title":"Synchronization fails with 504 Gateway Timeout","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Synchronization fails with 504"},{"name":"iconClass","value":"bx bx-error","type":"label"}]},{"id":"_help_s8alTXmpFR61","title":"Refreshing the application","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Refreshing the application"},{"name":"iconClass","value":"bx bx-refresh","type":"label"}]}]},{"id":"_help_pKK96zzmvBGf","title":"Theme development","type":"book","attributes":[{"name":"iconClass","value":"bx bx-palette","type":"label"}],"children":[{"id":"_help_7NfNr5pZpVKV","title":"Creating a custom theme","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Creating a custom theme"},{"name":"iconClass","value":"bx bxs-color","type":"label"}]},{"id":"_help_WFGzWeUK6arS","title":"Customize the Next theme","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Customize the Next theme"},{"name":"iconClass","value":"bx bx-news","type":"label"}]},{"id":"_help_WN5z4M8ASACJ","title":"Reference","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Reference"},{"name":"iconClass","value":"bx bx-book-open","type":"label"}]},{"id":"_help_AlhDUqhENtH7","title":"Custom app-wide CSS","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Custom app-wide CSS"},{"name":"iconClass","value":"bx bxs-file-css","type":"label"}]}]},{"id":"_help_tC7s2alapj8V","title":"Advanced Usage","type":"book","attributes":[{"name":"iconClass","value":"bx bx-rocket","type":"label"}],"children":[{"id":"_help_zEY4DaJG4YT5","title":"Attributes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes"},{"name":"iconClass","value":"bx bx-list-check","type":"label"}],"children":[{"id":"_help_HI6GBBIduIgv","title":"Labels","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes/Labels"},{"name":"iconClass","value":"bx bx-hash","type":"label"}]},{"id":"_help_Cq5X6iKQop6R","title":"Relations","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes/Relations"},{"name":"iconClass","value":"bx bx-transfer","type":"label"}]},{"id":"_help_bwZpz2ajCEwO","title":"Attribute Inheritance","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes/Attribute Inheritance"},{"name":"iconClass","value":"bx bx-list-plus","type":"label"}]},{"id":"_help_OFXdgB2nNk1F","title":"Promoted Attributes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes/Promoted Attributes"},{"name":"iconClass","value":"bx bx-table","type":"label"}]}]},{"id":"_help_KC1HB96bqqHX","title":"Templates","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Templates"},{"name":"iconClass","value":"bx bx-copy","type":"label"}]},{"id":"_help_BCkXAVs63Ttv","title":"Note Map (Link map, Tree map)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Note Map (Link map, Tree map)"},{"name":"iconClass","value":"bx bxs-network-chart","type":"label"}]},{"id":"_help_R9pX4DGra2Vt","title":"Sharing","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Sharing"},{"name":"iconClass","value":"bx bx-share-alt","type":"label"}],"children":[{"id":"_help_Qjt68inQ2bRj","title":"Serving directly the content of a note","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Sharing/Serving directly the content o"},{"name":"iconClass","value":"bx bx-code","type":"label"}]},{"id":"_help_ycBFjKrrwE9p","title":"Exporting static HTML for web publishing","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Sharing/Exporting static HTML for web "},{"name":"iconClass","value":"bx bxs-file-html","type":"label"}]},{"id":"_help_sLIJ6f1dkJYW","title":"Reverse proxy configuration","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Sharing/Reverse proxy configuration"},{"name":"iconClass","value":"bx bx-world","type":"label"}]}]},{"id":"_help_5668rwcirq1t","title":"Advanced Showcases","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Advanced Showcases"},{"name":"iconClass","value":"bx bxs-component","type":"label"}],"children":[{"id":"_help_l0tKav7yLHGF","title":"Day Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Advanced Showcases/Day Notes"},{"name":"iconClass","value":"bx bx-calendar","type":"label"}]},{"id":"_help_R7abl2fc6Mxi","title":"Weight Tracker","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Advanced Showcases/Weight Tracker"},{"name":"iconClass","value":"bx bx-line-chart","type":"label"}]},{"id":"_help_xYjQUYhpbUEW","title":"Task Manager","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Advanced Showcases/Task Manager"},{"name":"iconClass","value":"bx bx-calendar-check","type":"label"}]}]},{"id":"_help_J5Ex1ZrMbyJ6","title":"Custom Request Handler","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Custom Request Handler"},{"name":"iconClass","value":"bx bx-globe","type":"label"}]},{"id":"_help_d3fAXQ2diepH","title":"Custom Resource Providers","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Custom Resource Providers"},{"name":"iconClass","value":"bx bxs-file-plus","type":"label"}]},{"id":"_help_pgxEVkzLl1OP","title":"ETAPI (REST API)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/ETAPI (REST API)"},{"name":"iconClass","value":"bx bx-extension","type":"label"}],"children":[{"id":"_help_9qPsTWBorUhQ","title":"API Reference","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/rest-api/etapi/"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_47ZrP6FNuoG8","title":"Default Note Title","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Default Note Title"},{"name":"iconClass","value":"bx bx-edit-alt","type":"label"}]},{"id":"_help_wX4HbRucYSDD","title":"Database","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Database"},{"name":"iconClass","value":"bx bx-data","type":"label"}],"children":[{"id":"_help_oyIAJ9PvvwHX","title":"Manually altering the database","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Database/Manually altering the database"},{"name":"iconClass","value":"bx bxs-edit","type":"label"}],"children":[{"id":"_help_YKWqdJhzi2VY","title":"SQL Console","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Database/Manually altering the database/SQL Console"},{"name":"iconClass","value":"bx bx-data","type":"label"}]}]},{"id":"_help_6tZeKvSHEUiB","title":"Demo Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Database/Demo Notes"},{"name":"iconClass","value":"bx bx-package","type":"label"}]}]},{"id":"_help_Gzjqa934BdH4","title":"Configuration (config.ini or environment variables)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Configuration (config.ini or e"},{"name":"iconClass","value":"bx bx-cog","type":"label"}],"children":[{"id":"_help_c5xB8m4g2IY6","title":"Trilium instance","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Configuration (config.ini or environment variables)/Trilium instance"},{"name":"iconClass","value":"bx bx-windows","type":"label"}]},{"id":"_help_LWtBjFej3wX3","title":"Cross-Origin Resource Sharing (CORS)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Configuration (config.ini or environment variables)/Cross-Origin Resource Sharing "},{"name":"iconClass","value":"bx bx-lock","type":"label"}]}]},{"id":"_help_ivYnonVFBxbQ","title":"Bulk Actions","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Bulk Actions"},{"name":"iconClass","value":"bx bx-list-plus","type":"label"}]},{"id":"_help_4FahAwuGTAwC","title":"Note source","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Note source"},{"name":"iconClass","value":"bx bx-code","type":"label"}]},{"id":"_help_1YeN2MzFUluU","title":"Technologies used","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used"},{"name":"iconClass","value":"bx bx-pyramid","type":"label"}],"children":[{"id":"_help_MI26XDLSAlCD","title":"CKEditor","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used/CKEditor"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_N4IDkixaDG9C","title":"MindElixir","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used/MindElixir"},{"name":"iconClass","value":"bx bx-sitemap","type":"label"}]},{"id":"_help_H0mM1lTxF9JI","title":"Excalidraw","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used/Excalidraw"},{"name":"iconClass","value":"bx bx-pen","type":"label"}]},{"id":"_help_MQHyy2dIFgxS","title":"Leaflet","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used/Leaflet"},{"name":"iconClass","value":"bx bx-map-alt","type":"label"}]}]},{"id":"_help_m1lbrzyKDaRB","title":"Note ID","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Note ID"},{"name":"iconClass","value":"bx bx-hash","type":"label"}]},{"id":"_help_0vTSyvhPTAOz","title":"Internal API","type":"book","attributes":[{"name":"iconClass","value":"bx bxs-component","type":"label"}],"children":[{"id":"_help_z8O2VG4ZZJD7","title":"API Reference","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/rest-api/internal/"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_2mUhVmZK8RF3","title":"Hidden Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Hidden Notes"},{"name":"iconClass","value":"bx bx-hide","type":"label"}]},{"id":"_help_uYF7pmepw27K","title":"Metrics","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Metrics"},{"name":"iconClass","value":"bx bxs-data","type":"label"}],"children":[{"id":"_help_bOP3TB56fL1V","title":"grafana-dashboard.json","type":"doc","attributes":[{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_64ZTlUPgEPtW","title":"Safe mode","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Safe mode"},{"name":"iconClass","value":"bx bxs-virus-block","type":"label"}]},{"id":"_help_HAIOFBoYIIdO","title":"Nightly release","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Nightly release"},{"name":"iconClass","value":"bx bx-moon","type":"label"}]},{"id":"_help_ZmT9ln8XJX2o","title":"Read-only database","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Read-only database"},{"name":"iconClass","value":"bx bx-book-reader","type":"label"}]}]},{"id":"_help_GBBMSlVSOIGP","title":"AI","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/AI"},{"name":"iconClass","value":"bx bx-bot","type":"label"}],"children":[{"id":"_help_WkM7gsEUyCXs","title":"Providers","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/AI/Providers"},{"name":"iconClass","value":"bx bx-select-multiple","type":"label"}],"children":[{"id":"_help_7EdTxPADv95W","title":"Ollama","type":"book","attributes":[{"name":"iconClass","value":"bx bx-message-dots","type":"label"}],"children":[{"id":"_help_vvUCN7FDkq7G","title":"Installing Ollama","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/AI/Providers/Ollama/Installing Ollama"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_ZavFigBX9AwP","title":"OpenAI","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/AI/Providers/OpenAI"},{"name":"iconClass","value":"bx bx-message-dots","type":"label"}]},{"id":"_help_e0lkirXEiSNc","title":"Anthropic","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/AI/Providers/Anthropic"},{"name":"iconClass","value":"bx bx-message-dots","type":"label"}]}]}]},{"id":"_help_CdNpE2pqjmI6","title":"Scripting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting"},{"name":"iconClass","value":"bx bxs-file-js","type":"label"}],"children":[{"id":"_help_yIhgI5H7A2Sm","title":"Frontend Basics","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics"},{"name":"iconClass","value":"bx bx-window","type":"label"}],"children":[{"id":"_help_MgibgPcfeuGz","title":"Custom Widgets","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets"},{"name":"iconClass","value":"bx bxs-widget","type":"label"}],"children":[{"id":"_help_YNxAqkI5Kg1M","title":"Word count widget","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Word count widget"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_SynTBQiBsdYJ","title":"Widget Basics","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Widget Basics"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_M8IppdwVHSjG","title":"Right pane widget","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Right pane widget"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_VqGQnnPGnqAU","title":"CSS","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/CSS"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_es8OU2GuguFU","title":"Examples","type":"book","attributes":[{"name":"iconClass","value":"bx bx-code-alt","type":"label"}],"children":[{"id":"_help_TjLYAo3JMO8X","title":"\"New Task\" launcher button","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Examples/New Task launcher button"},{"name":"iconClass","value":"bx bx-task","type":"label"}]},{"id":"_help_7kZPMD0uFwkH","title":"Downloading responses from Google Forms","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Examples/Downloading responses from Goo"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_DL92EjAaXT26","title":"Using promoted attributes to configure scripts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Examples/Using promoted attributes to c"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]}]},{"id":"_help_SPirpZypehBG","title":"Backend scripts","type":"book","attributes":[{"name":"iconClass","value":"bx bx-server","type":"label"}],"children":[{"id":"_help_fZ2IGYFXjkEy","title":"Server-side imports","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Backend scripts/Server-side imports"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_GPERMystNGTB","title":"Events","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Backend scripts/Events"},{"name":"iconClass","value":"bx bx-rss","type":"label"}]}]},{"id":"_help_GLks18SNjxmC","title":"Script API","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Script API"},{"name":"iconClass","value":"bx bx-code-curly","type":"label"}],"children":[{"id":"_help_Q2z6av6JZVWm","title":"Frontend API","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/script-api/frontend"},{"name":"iconClass","value":"bx bx-folder","type":"label"}],"enforceAttributes":true,"children":[{"id":"_help_habiZ3HU8Kw8","title":"FNote","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/script-api/frontend/interfaces/FNote.html"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_MEtfsqa5VwNi","title":"Backend API","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/script-api/backend"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_vElnKeDNPSVl","title":"Logging","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Logging"},{"name":"iconClass","value":"bx bx-terminal","type":"label"}]}]},{"id":"_help_Fm0j45KqyHpU","title":"Miscellaneous","type":"book","attributes":[{"name":"iconClass","value":"bx bx-info-circle","type":"label"}],"children":[{"id":"_help_WFbFXrgnDyyU","title":"Privacy Policy","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Miscellaneous/Privacy Policy"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_NcsmUYZRWEW4","title":"Patterns of personal knowledge","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Miscellaneous/Patterns of personal knowledge"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]}] \ No newline at end of file +[{"id":"_help_BOCnjTMBCoxW","title":"Feature Highlights","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Feature Highlights"},{"name":"iconClass","value":"bx bx-star","type":"label"}]},{"id":"_help_Otzi9La2YAUX","title":"Installation & Setup","type":"book","attributes":[{"name":"iconClass","value":"bx bx-cog","type":"label"}],"children":[{"id":"_help_poXkQfguuA0U","title":"Desktop Installation","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Desktop Installation"},{"name":"iconClass","value":"bx bx-desktop","type":"label"}],"children":[{"id":"_help_nRqcgfTb97uV","title":"Using the desktop application as a server","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Desktop Installation/Using the desktop application "},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_Rp0q8bSP6Ayl","title":"System Requirements","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Desktop Installation/System Requirements"},{"name":"iconClass","value":"bx bx-chip","type":"label"}]},{"id":"_help_Un4wj2Mak2Ky","title":"Nix flake","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Desktop Installation/Nix flake"},{"name":"iconClass","value":"bx bxl-tux","type":"label"}]}]},{"id":"_help_WOcw2SLH6tbX","title":"Server Installation","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation"},{"name":"iconClass","value":"bx bx-server","type":"label"}],"children":[{"id":"_help_Dgg7bR3b6K9j","title":"1. Installing the server","type":"book","attributes":[{"name":"iconClass","value":"bx bx-folder","type":"label"}],"children":[{"id":"_help_3tW6mORuTHnB","title":"Packaged version for Linux","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Packaged version for Linux"},{"name":"iconClass","value":"bx bxl-tux","type":"label"}]},{"id":"_help_rWX5eY045zbE","title":"Using Docker","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Using Docker"},{"name":"iconClass","value":"bx bxl-docker","type":"label"}]},{"id":"_help_moVgBcoxE3EK","title":"On NixOS","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/On NixOS"},{"name":"iconClass","value":"bx bxl-tux","type":"label"}]},{"id":"_help_J1Bb6lVlwU5T","title":"Manually","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Manually"},{"name":"iconClass","value":"bx bx-code-alt","type":"label"}]},{"id":"_help_DCmT6e7clMoP","title":"Using Kubernetes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Using Kubernetes"},{"name":"iconClass","value":"bx bxl-kubernetes","type":"label"}]},{"id":"_help_klCWNks3ReaQ","title":"Multiple server instances","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Multiple server instances"},{"name":"iconClass","value":"bx bxs-user-account","type":"label"}]}]},{"id":"_help_vcjrb3VVYPZI","title":"2. Reverse proxy","type":"book","attributes":[{"name":"iconClass","value":"bx bx-folder","type":"label"}],"children":[{"id":"_help_ud6MShXL4WpO","title":"Nginx","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Nginx"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_fDLvzOx29Pfg","title":"Apache using Docker","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Apache using Docker"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_LLzSMXACKhUs","title":"Trusted proxy","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Trusted proxy"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_5ERVJb9s4FRD","title":"Traefik","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Traefik"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_l2VkvOwUNfZj","title":"HTTPS (TLS)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/HTTPS (TLS)"},{"name":"iconClass","value":"bx bx-lock-alt","type":"label"}]},{"id":"_help_0hzsNCP31IAB","title":"Authentication","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/Authentication"},{"name":"iconClass","value":"bx bx-user","type":"label"}]},{"id":"_help_7DAiwaf8Z7Rz","title":"Multi-Factor Authentication","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/Multi-Factor Authentication"},{"name":"iconClass","value":"bx bx-stopwatch","type":"label"}]},{"id":"_help_Un4wj2Mak2Ky","title":"Nix flake","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/Nix flake.clone"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_yeEaYqosGLSh","title":"Third-party cloud hosting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/Third-party cloud hosting"},{"name":"iconClass","value":"bx bx-cloud","type":"label"}]},{"id":"_help_iGTnKjubbXkA","title":"System Requirements","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Server Installation/System Requirements"},{"name":"iconClass","value":"bx bx-chip","type":"label"}]}]},{"id":"_help_cbkrhQjrkKrh","title":"Synchronization","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Synchronization"},{"name":"iconClass","value":"bx bx-sync","type":"label"}]},{"id":"_help_RDslemsQ6gCp","title":"Mobile Frontend","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Mobile Frontend"},{"name":"iconClass","value":"bx bx-mobile-alt","type":"label"}]},{"id":"_help_MtPxeAWVAzMg","title":"Web Clipper","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Web Clipper"},{"name":"iconClass","value":"bx bx-paperclip","type":"label"}]},{"id":"_help_n1lujUxCwipy","title":"Upgrading TriliumNext","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Upgrading TriliumNext"},{"name":"iconClass","value":"bx bx-up-arrow-alt","type":"label"}]},{"id":"_help_ODY7qQn5m2FT","title":"Backup","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Backup"},{"name":"iconClass","value":"bx bx-hdd","type":"label"}]},{"id":"_help_tAassRL4RSQL","title":"Data directory","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Installation & Setup/Data directory"},{"name":"iconClass","value":"bx bx-folder-open","type":"label"}]}]},{"id":"_help_gh7bpGYxajRS","title":"Basic Concepts and Features","type":"book","attributes":[{"name":"iconClass","value":"bx bx-help-circle","type":"label"}],"children":[{"id":"_help_Vc8PjrjAGuOp","title":"UI Elements","type":"book","attributes":[{"name":"iconClass","value":"bx bx-window-alt","type":"label"}],"children":[{"id":"_help_x0JgW8UqGXvq","title":"Vertical and horizontal layout","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Vertical and horizontal layout"},{"name":"iconClass","value":"bx bxs-layout","type":"label"}]},{"id":"_help_x3i7MxGccDuM","title":"Global menu","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Global menu"},{"name":"iconClass","value":"bx bx-menu","type":"label"}]},{"id":"_help_oPVyFC7WL2Lp","title":"Note Tree","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree"},{"name":"iconClass","value":"bx bxs-tree-alt","type":"label"}],"children":[{"id":"_help_YtSN43OrfzaA","title":"Note tree contextual menu","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Note tree contextual menu"},{"name":"iconClass","value":"bx bx-menu","type":"label"}]},{"id":"_help_yTjUdsOi4CIE","title":"Multiple selection","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Multiple selection"},{"name":"iconClass","value":"bx bx-list-plus","type":"label"}]},{"id":"_help_DvdZhoQZY9Yd","title":"Keyboard shortcuts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Keyboard shortcuts"},{"name":"iconClass","value":"bx bxs-keyboard","type":"label"}]}]},{"id":"_help_BlN9DFI679QC","title":"Ribbon","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Ribbon"},{"name":"iconClass","value":"bx bx-dots-horizontal","type":"label"}]},{"id":"_help_3seOhtN8uLIY","title":"Tabs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Tabs"},{"name":"iconClass","value":"bx bx-dock-top","type":"label"}]},{"id":"_help_xYmIYSP6wE3F","title":"Launch Bar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Launch Bar"},{"name":"iconClass","value":"bx bx-sidebar","type":"label"}]},{"id":"_help_8YBEPzcpUgxw","title":"Note buttons","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note buttons"},{"name":"iconClass","value":"bx bx-dots-vertical-rounded","type":"label"}]},{"id":"_help_4TIF1oA4VQRO","title":"Options","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Options"},{"name":"iconClass","value":"bx bx-cog","type":"label"}]},{"id":"_help_luNhaphA37EO","title":"Split View","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Split View"},{"name":"iconClass","value":"bx bx-dock-right","type":"label"}]},{"id":"_help_XpOYSgsLkTJy","title":"Floating buttons","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Floating buttons"},{"name":"iconClass","value":"bx bx-rectangle","type":"label"}]},{"id":"_help_RnaPdbciOfeq","title":"Right Sidebar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Right Sidebar"},{"name":"iconClass","value":"bx bxs-dock-right","type":"label"}]},{"id":"_help_r5JGHN99bVKn","title":"Recent Changes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Recent Changes"},{"name":"iconClass","value":"bx bx-history","type":"label"}]},{"id":"_help_ny318J39E5Z0","title":"Zoom","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Zoom"},{"name":"iconClass","value":"bx bx-zoom-in","type":"label"}]},{"id":"_help_lgKX7r3aL30x","title":"Note Tooltip","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tooltip"},{"name":"iconClass","value":"bx bx-message-detail","type":"label"}]}]},{"id":"_help_BFs8mudNFgCS","title":"Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes"},{"name":"iconClass","value":"bx bx-notepad","type":"label"}],"children":[{"id":"_help_p9kXRFAkwN4o","title":"Note Icons","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Note Icons"},{"name":"iconClass","value":"bx bxs-grid","type":"label"}]},{"id":"_help_0vhv7lsOLy82","title":"Attachments","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Attachments"},{"name":"iconClass","value":"bx bx-paperclip","type":"label"}]},{"id":"_help_IakOLONlIfGI","title":"Cloning Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Cloning Notes"},{"name":"iconClass","value":"bx bx-duplicate","type":"label"}],"children":[{"id":"_help_TBwsyfadTA18","title":"Branch prefix","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Cloning Notes/Branch prefix"},{"name":"iconClass","value":"bx bx-rename","type":"label"}]}]},{"id":"_help_bwg0e8ewQMak","title":"Protected Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Protected Notes"},{"name":"iconClass","value":"bx bx-lock-alt","type":"label"}]},{"id":"_help_MKmLg5x6xkor","title":"Archived Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Archived Notes"},{"name":"iconClass","value":"bx bx-box","type":"label"}]},{"id":"_help_vZWERwf8U3nx","title":"Note Revisions","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions"},{"name":"iconClass","value":"bx bx-history","type":"label"}]},{"id":"_help_aGlEvb9hyDhS","title":"Sorting Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Sorting Notes"},{"name":"iconClass","value":"bx bx-sort-up","type":"label"}]},{"id":"_help_NRnIZmSMc5sj","title":"Printing & Exporting as PDF","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Printing & Exporting as PDF"},{"name":"iconClass","value":"bx bx-printer","type":"label"}]},{"id":"_help_CoFPLs3dRlXc","title":"Read-Only Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Read-Only Notes"},{"name":"iconClass","value":"bx bx-edit-alt","type":"label"}]},{"id":"_help_0ESUbbAxVnoK","title":"Note List","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Notes/Note List"},{"name":"iconClass","value":"bx bxs-grid","type":"label"}]}]},{"id":"_help_wArbEsdSae6g","title":"Navigation","type":"book","attributes":[{"name":"iconClass","value":"bx bx-navigation","type":"label"}],"children":[{"id":"_help_kBrnXNG3Hplm","title":"Tree Concepts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Tree Concepts"},{"name":"iconClass","value":"bx bx-pyramid","type":"label"}]},{"id":"_help_MMiBEQljMQh2","title":"Note Navigation","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Note Navigation"},{"name":"iconClass","value":"bx bxs-navigation","type":"label"}]},{"id":"_help_Ms1nauBra7gq","title":"Quick search","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Quick search"},{"name":"iconClass","value":"bx bx-search-alt-2","type":"label"}]},{"id":"_help_F1r9QtzQLZqm","title":"Jump to...","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Jump to"},{"name":"iconClass","value":"bx bx-send","type":"label"}]},{"id":"_help_eIg8jdvaoNNd","title":"Search","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Search"},{"name":"iconClass","value":"bx bx-search-alt-2","type":"label"}]},{"id":"_help_u3YFHC9tQlpm","title":"Bookmarks","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Bookmarks"},{"name":"iconClass","value":"bx bx-bookmarks","type":"label"}]},{"id":"_help_OR8WJ7Iz9K4U","title":"Note Hoisting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Note Hoisting"},{"name":"iconClass","value":"bx bxs-chevrons-up","type":"label"}]},{"id":"_help_ZjLYv08Rp3qC","title":"Quick edit","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Quick edit"},{"name":"iconClass","value":"bx bx-edit","type":"label"}]},{"id":"_help_9sRHySam5fXb","title":"Workspaces","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Workspaces"},{"name":"iconClass","value":"bx bx-door-open","type":"label"}]},{"id":"_help_xWtq5NUHOwql","title":"Similar Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Similar Notes"},{"name":"iconClass","value":"bx bx-bar-chart","type":"label"}]},{"id":"_help_McngOG2jbUWX","title":"Search in note","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Navigation/Search in note"},{"name":"iconClass","value":"bx bx-search-alt-2","type":"label"}]}]},{"id":"_help_A9Oc6YKKc65v","title":"Keyboard Shortcuts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Keyboard Shortcuts"},{"name":"iconClass","value":"bx bxs-keyboard","type":"label"}]},{"id":"_help_Wy267RK4M69c","title":"Themes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Themes"},{"name":"iconClass","value":"bx bx-palette","type":"label"}],"children":[{"id":"_help_VbjZvtUek0Ln","title":"Theme Gallery","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Themes/Theme Gallery"},{"name":"iconClass","value":"bx bx-book-reader","type":"label"}]}]},{"id":"_help_mHbBMPDPkVV5","title":"Import & Export","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export"},{"name":"iconClass","value":"bx bx-import","type":"label"}],"children":[{"id":"_help_Oau6X9rCuegd","title":"Markdown","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown"},{"name":"iconClass","value":"bx bxl-markdown","type":"label"}],"children":[{"id":"_help_rJ9grSgoExl9","title":"Supported syntax","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown/Supported syntax"},{"name":"iconClass","value":"bx bx-code-alt","type":"label"}]}]},{"id":"_help_syuSEKf2rUGr","title":"Evernote","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export/Evernote"},{"name":"iconClass","value":"bx bx-window-open","type":"label"}]},{"id":"_help_GnhlmrATVqcH","title":"OneNote","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Import & Export/OneNote"},{"name":"iconClass","value":"bx bx-window-open","type":"label"}]}]},{"id":"_help_rC3pL2aptaRE","title":"Zen mode","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Basic Concepts and Features/Zen mode"},{"name":"iconClass","value":"bx bxs-yin-yang","type":"label"}]}]},{"id":"_help_s3YCWHBfmYuM","title":"Quick Start","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Quick Start"},{"name":"iconClass","value":"bx bx-run","type":"label"}]},{"id":"_help_i6dbnitykE5D","title":"FAQ","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/FAQ"},{"name":"iconClass","value":"bx bx-question-mark","type":"label"}]},{"id":"_help_KSZ04uQ2D1St","title":"Note Types","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types"},{"name":"iconClass","value":"bx bx-edit","type":"label"}],"children":[{"id":"_help_iPIMuisry3hd","title":"Text","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text"},{"name":"iconClass","value":"bx bx-note","type":"label"}],"children":[{"id":"_help_NwBbFdNZ9h7O","title":"Block quotes & admonitions","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Block quotes & admonitions"},{"name":"iconClass","value":"bx bx-info-circle","type":"label"}]},{"id":"_help_oSuaNgyyKnhu","title":"Bookmarks","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Bookmarks"},{"name":"iconClass","value":"bx bx-bookmark","type":"label"}]},{"id":"_help_veGu4faJErEM","title":"Content language & Right-to-left support","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Content language & Right-to-le"},{"name":"iconClass","value":"bx bx-align-right","type":"label"}]},{"id":"_help_2x0ZAX9ePtzV","title":"Cut to subnote","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Cut to subnote"},{"name":"iconClass","value":"bx bx-cut","type":"label"}]},{"id":"_help_UYuUB1ZekNQU","title":"Developer-specific formatting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Developer-specific formatting"},{"name":"iconClass","value":"bx bx-code-alt","type":"label"}],"children":[{"id":"_help_QxEyIjRBizuC","title":"Code blocks","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Developer-specific formatting/Code blocks"},{"name":"iconClass","value":"bx bx-code","type":"label"}]}]},{"id":"_help_AgjCISero73a","title":"Footnotes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Footnotes"},{"name":"iconClass","value":"bx bx-bracket","type":"label"}]},{"id":"_help_nRhnJkTT8cPs","title":"Formatting toolbar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Formatting toolbar"},{"name":"iconClass","value":"bx bx-text","type":"label"}]},{"id":"_help_Gr6xFaF6ioJ5","title":"General formatting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/General formatting"},{"name":"iconClass","value":"bx bx-bold","type":"label"}]},{"id":"_help_AxshuNRegLAv","title":"Highlights list","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Highlights list"},{"name":"iconClass","value":"bx bx-highlight","type":"label"}]},{"id":"_help_mT0HEkOsz6i1","title":"Images","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Images"},{"name":"iconClass","value":"bx bx-image-alt","type":"label"}],"children":[{"id":"_help_0Ofbk1aSuVRu","title":"Image references","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Images/Image references"},{"name":"iconClass","value":"bx bxs-file-image","type":"label"}]}]},{"id":"_help_nBAXQFj20hS1","title":"Include Note","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Include Note"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_CohkqWQC1iBv","title":"Insert buttons","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Insert buttons"},{"name":"iconClass","value":"bx bx-plus","type":"label"}]},{"id":"_help_oiVPnW8QfnvS","title":"Keyboard shortcuts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Keyboard shortcuts"},{"name":"iconClass","value":"bx bxs-keyboard","type":"label"}]},{"id":"_help_QEAPj01N5f7w","title":"Links","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Links"},{"name":"iconClass","value":"bx bx-link-alt","type":"label"}],"children":[{"id":"_help_3IDVtesTQ8ds","title":"External links","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Links/External links"},{"name":"iconClass","value":"bx bx-link-external","type":"label"}]},{"id":"_help_hrZ1D00cLbal","title":"Internal (reference) links","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Links/Internal (reference) links"},{"name":"iconClass","value":"bx bx-link","type":"label"}]}]},{"id":"_help_S6Xx8QIWTV66","title":"Lists","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Lists"},{"name":"iconClass","value":"bx bx-list-ul","type":"label"}]},{"id":"_help_QrtTYPmdd1qq","title":"Markdown-like formatting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Markdown-like formatting"},{"name":"iconClass","value":"bx bxl-markdown","type":"label"}]},{"id":"_help_YfYAtQBcfo5V","title":"Math Equations","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Math Equations"},{"name":"iconClass","value":"bx bx-math","type":"label"}]},{"id":"_help_dEHYtoWWi8ct","title":"Other features","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Other features"},{"name":"iconClass","value":"bx bxs-grid","type":"label"}]},{"id":"_help_gLt3vA97tMcp","title":"Premium features","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Premium features"},{"name":"iconClass","value":"bx bx-star","type":"label"}],"children":[{"id":"_help_ZlN4nump6EbW","title":"Slash Commands","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Premium features/Slash Commands"},{"name":"iconClass","value":"bx bx-menu","type":"label"}]},{"id":"_help_pwc194wlRzcH","title":"Text Snippets","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Premium features/Text Snippets"},{"name":"iconClass","value":"bx bx-align-left","type":"label"}]},{"id":"_help_5wZallV2Qo1t","title":"Format Painter","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Premium features/Format Painter"},{"name":"iconClass","value":"bx bxs-paint-roll","type":"label"}]}]},{"id":"_help_BFvAtE74rbP6","title":"Table of contents","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Table of contents"},{"name":"iconClass","value":"bx bx-heading","type":"label"}]},{"id":"_help_NdowYOC1GFKS","title":"Tables","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Text/Tables"},{"name":"iconClass","value":"bx bx-table","type":"label"}]}]},{"id":"_help_6f9hih2hXXZk","title":"Code","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Code"},{"name":"iconClass","value":"bx bx-code","type":"label"}]},{"id":"_help_m523cpzocqaD","title":"Saved Search","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Saved Search"},{"name":"iconClass","value":"bx bx-file-find","type":"label"}]},{"id":"_help_iRwzGnHPzonm","title":"Relation Map","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Relation Map"},{"name":"iconClass","value":"bx bxs-network-chart","type":"label"}]},{"id":"_help_bdUJEHsAPYQR","title":"Note Map","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Note Map"},{"name":"iconClass","value":"bx bxs-network-chart","type":"label"}]},{"id":"_help_HcABDtFCkbFN","title":"Render Note","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Render Note"},{"name":"iconClass","value":"bx bx-extension","type":"label"}]},{"id":"_help_s1aBHPd79XYj","title":"Mermaid Diagrams","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Mermaid Diagrams"},{"name":"iconClass","value":"bx bx-selection","type":"label"}],"children":[{"id":"_help_RH6yLjjWJHof","title":"ELK layout","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Mermaid Diagrams/ELK layout"},{"name":"iconClass","value":"bx bxs-network-chart","type":"label"}]},{"id":"_help_WWgeUaBb7UfC","title":"Syntax reference","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://mermaid.js.org/intro/syntax-reference.html"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_grjYqerjn243","title":"Canvas","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Canvas"},{"name":"iconClass","value":"bx bx-pen","type":"label"}]},{"id":"_help_1vHRoWCEjj0L","title":"Web View","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Web View"},{"name":"iconClass","value":"bx bx-globe-alt","type":"label"}]},{"id":"_help_gBbsAeiuUxI5","title":"Mind Map","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/Mind Map"},{"name":"iconClass","value":"bx bx-sitemap","type":"label"}]},{"id":"_help_W8vYD3Q1zjCR","title":"File","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Note Types/File"},{"name":"iconClass","value":"bx bx-file-blank","type":"label"}]}]},{"id":"_help_GTwFsgaA0lCt","title":"Collections","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections"},{"name":"iconClass","value":"bx bx-book","type":"label"}],"children":[{"id":"_help_xWbu3jpNWapp","title":"Calendar","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Calendar"},{"name":"iconClass","value":"bx bx-calendar","type":"label"}]},{"id":"_help_2FvYrpmOXm29","title":"Table","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Table"},{"name":"iconClass","value":"bx bx-table","type":"label"}]},{"id":"_help_CtBQqbwXDx1w","title":"Kanban Board","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Kanban Board"},{"name":"iconClass","value":"bx bx-columns","type":"label"}]},{"id":"_help_81SGnPGMk7Xc","title":"Geo Map","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Geo Map"},{"name":"iconClass","value":"bx bx-map-alt","type":"label"}]},{"id":"_help_zP3PMqaG71Ct","title":"Presentation","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Presentation"},{"name":"iconClass","value":"bx bx-slideshow","type":"label"}]},{"id":"_help_8QqnMzx393bx","title":"Grid View","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/Grid View"},{"name":"iconClass","value":"bx bxs-grid","type":"label"}]},{"id":"_help_mULW0Q3VojwY","title":"List View","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Collections/List View"},{"name":"iconClass","value":"bx bx-list-ul","type":"label"}]}]},{"id":"_help_BgmBlOIl72jZ","title":"Troubleshooting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting"},{"name":"iconClass","value":"bx bx-bug","type":"label"}],"children":[{"id":"_help_wy8So3yZZlH9","title":"Reporting issues","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Reporting issues"},{"name":"iconClass","value":"bx bx-bug-alt","type":"label"}]},{"id":"_help_x59R8J8KV5Bp","title":"Anonymized Database","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Anonymized Database"},{"name":"iconClass","value":"bx bx-low-vision","type":"label"}]},{"id":"_help_qzNzp9LYQyPT","title":"Error logs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Error logs"},{"name":"iconClass","value":"bx bx-comment-error","type":"label"}],"children":[{"id":"_help_bnyigUA2UK7s","title":"Backend (server) logs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Error logs/Backend (server) logs"},{"name":"iconClass","value":"bx bx-server","type":"label"}]},{"id":"_help_9yEHzMyFirZR","title":"Frontend logs","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Error logs/Frontend logs"},{"name":"iconClass","value":"bx bx-window-alt","type":"label"}]}]},{"id":"_help_vdlYGAcpXAgc","title":"Synchronization fails with 504 Gateway Timeout","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Synchronization fails with 504"},{"name":"iconClass","value":"bx bx-error","type":"label"}]},{"id":"_help_s8alTXmpFR61","title":"Refreshing the application","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Troubleshooting/Refreshing the application"},{"name":"iconClass","value":"bx bx-refresh","type":"label"}]}]},{"id":"_help_pKK96zzmvBGf","title":"Theme development","type":"book","attributes":[{"name":"iconClass","value":"bx bx-palette","type":"label"}],"children":[{"id":"_help_7NfNr5pZpVKV","title":"Creating a custom theme","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Creating a custom theme"},{"name":"iconClass","value":"bx bxs-color","type":"label"}]},{"id":"_help_WFGzWeUK6arS","title":"Customize the Next theme","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Customize the Next theme"},{"name":"iconClass","value":"bx bx-news","type":"label"}]},{"id":"_help_WN5z4M8ASACJ","title":"Reference","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Reference"},{"name":"iconClass","value":"bx bx-book-open","type":"label"}]},{"id":"_help_AlhDUqhENtH7","title":"Custom app-wide CSS","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Theme development/Custom app-wide CSS"},{"name":"iconClass","value":"bx bxs-file-css","type":"label"}]}]},{"id":"_help_tC7s2alapj8V","title":"Advanced Usage","type":"book","attributes":[{"name":"iconClass","value":"bx bx-rocket","type":"label"}],"children":[{"id":"_help_zEY4DaJG4YT5","title":"Attributes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes"},{"name":"iconClass","value":"bx bx-list-check","type":"label"}],"children":[{"id":"_help_HI6GBBIduIgv","title":"Labels","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes/Labels"},{"name":"iconClass","value":"bx bx-hash","type":"label"}]},{"id":"_help_Cq5X6iKQop6R","title":"Relations","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes/Relations"},{"name":"iconClass","value":"bx bx-transfer","type":"label"}]},{"id":"_help_bwZpz2ajCEwO","title":"Attribute Inheritance","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes/Attribute Inheritance"},{"name":"iconClass","value":"bx bx-list-plus","type":"label"}]},{"id":"_help_OFXdgB2nNk1F","title":"Promoted Attributes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Attributes/Promoted Attributes"},{"name":"iconClass","value":"bx bx-table","type":"label"}]}]},{"id":"_help_KC1HB96bqqHX","title":"Templates","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Templates"},{"name":"iconClass","value":"bx bx-copy","type":"label"}]},{"id":"_help_BCkXAVs63Ttv","title":"Note Map (Link map, Tree map)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Note Map (Link map, Tree map)"},{"name":"iconClass","value":"bx bxs-network-chart","type":"label"}]},{"id":"_help_R9pX4DGra2Vt","title":"Sharing","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Sharing"},{"name":"iconClass","value":"bx bx-share-alt","type":"label"}],"children":[{"id":"_help_Qjt68inQ2bRj","title":"Serving directly the content of a note","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Sharing/Serving directly the content o"},{"name":"iconClass","value":"bx bx-code","type":"label"}]},{"id":"_help_ycBFjKrrwE9p","title":"Exporting static HTML for web publishing","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Sharing/Exporting static HTML for web "},{"name":"iconClass","value":"bx bxs-file-html","type":"label"}]},{"id":"_help_sLIJ6f1dkJYW","title":"Reverse proxy configuration","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Sharing/Reverse proxy configuration"},{"name":"iconClass","value":"bx bx-world","type":"label"}]}]},{"id":"_help_5668rwcirq1t","title":"Advanced Showcases","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Advanced Showcases"},{"name":"iconClass","value":"bx bxs-component","type":"label"}],"children":[{"id":"_help_l0tKav7yLHGF","title":"Day Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Advanced Showcases/Day Notes"},{"name":"iconClass","value":"bx bx-calendar","type":"label"}]},{"id":"_help_R7abl2fc6Mxi","title":"Weight Tracker","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Advanced Showcases/Weight Tracker"},{"name":"iconClass","value":"bx bx-line-chart","type":"label"}]},{"id":"_help_xYjQUYhpbUEW","title":"Task Manager","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Advanced Showcases/Task Manager"},{"name":"iconClass","value":"bx bx-calendar-check","type":"label"}]}]},{"id":"_help_J5Ex1ZrMbyJ6","title":"Custom Request Handler","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Custom Request Handler"},{"name":"iconClass","value":"bx bx-globe","type":"label"}]},{"id":"_help_d3fAXQ2diepH","title":"Custom Resource Providers","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Custom Resource Providers"},{"name":"iconClass","value":"bx bxs-file-plus","type":"label"}]},{"id":"_help_pgxEVkzLl1OP","title":"ETAPI (REST API)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/ETAPI (REST API)"},{"name":"iconClass","value":"bx bx-extension","type":"label"}],"children":[{"id":"_help_9qPsTWBorUhQ","title":"API Reference","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/rest-api/etapi/"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_47ZrP6FNuoG8","title":"Default Note Title","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Default Note Title"},{"name":"iconClass","value":"bx bx-edit-alt","type":"label"}]},{"id":"_help_wX4HbRucYSDD","title":"Database","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Database"},{"name":"iconClass","value":"bx bx-data","type":"label"}],"children":[{"id":"_help_oyIAJ9PvvwHX","title":"Manually altering the database","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Database/Manually altering the database"},{"name":"iconClass","value":"bx bxs-edit","type":"label"}],"children":[{"id":"_help_YKWqdJhzi2VY","title":"SQL Console","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Database/Manually altering the database/SQL Console"},{"name":"iconClass","value":"bx bx-data","type":"label"}]}]},{"id":"_help_6tZeKvSHEUiB","title":"Demo Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Database/Demo Notes"},{"name":"iconClass","value":"bx bx-package","type":"label"}]}]},{"id":"_help_Gzjqa934BdH4","title":"Configuration (config.ini or environment variables)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Configuration (config.ini or e"},{"name":"iconClass","value":"bx bx-cog","type":"label"}],"children":[{"id":"_help_c5xB8m4g2IY6","title":"Trilium instance","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Configuration (config.ini or environment variables)/Trilium instance"},{"name":"iconClass","value":"bx bx-windows","type":"label"}]},{"id":"_help_LWtBjFej3wX3","title":"Cross-Origin Resource Sharing (CORS)","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Configuration (config.ini or environment variables)/Cross-Origin Resource Sharing "},{"name":"iconClass","value":"bx bx-lock","type":"label"}]}]},{"id":"_help_ivYnonVFBxbQ","title":"Bulk Actions","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Bulk Actions"},{"name":"iconClass","value":"bx bx-list-plus","type":"label"}]},{"id":"_help_4FahAwuGTAwC","title":"Note source","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Note source"},{"name":"iconClass","value":"bx bx-code","type":"label"}]},{"id":"_help_1YeN2MzFUluU","title":"Technologies used","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used"},{"name":"iconClass","value":"bx bx-pyramid","type":"label"}],"children":[{"id":"_help_MI26XDLSAlCD","title":"CKEditor","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used/CKEditor"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_N4IDkixaDG9C","title":"MindElixir","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used/MindElixir"},{"name":"iconClass","value":"bx bx-sitemap","type":"label"}]},{"id":"_help_H0mM1lTxF9JI","title":"Excalidraw","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used/Excalidraw"},{"name":"iconClass","value":"bx bx-pen","type":"label"}]},{"id":"_help_MQHyy2dIFgxS","title":"Leaflet","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Technologies used/Leaflet"},{"name":"iconClass","value":"bx bx-map-alt","type":"label"}]}]},{"id":"_help_m1lbrzyKDaRB","title":"Note ID","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Note ID"},{"name":"iconClass","value":"bx bx-hash","type":"label"}]},{"id":"_help_0vTSyvhPTAOz","title":"Internal API","type":"book","attributes":[{"name":"iconClass","value":"bx bxs-component","type":"label"}],"children":[{"id":"_help_z8O2VG4ZZJD7","title":"API Reference","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/rest-api/internal/"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_2mUhVmZK8RF3","title":"Hidden Notes","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Hidden Notes"},{"name":"iconClass","value":"bx bx-hide","type":"label"}]},{"id":"_help_uYF7pmepw27K","title":"Metrics","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Metrics"},{"name":"iconClass","value":"bx bxs-data","type":"label"}],"children":[{"id":"_help_bOP3TB56fL1V","title":"grafana-dashboard.json","type":"doc","attributes":[{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_64ZTlUPgEPtW","title":"Safe mode","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Safe mode"},{"name":"iconClass","value":"bx bxs-virus-block","type":"label"}]},{"id":"_help_HAIOFBoYIIdO","title":"Nightly release","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Nightly release"},{"name":"iconClass","value":"bx bx-moon","type":"label"}]},{"id":"_help_ZmT9ln8XJX2o","title":"Read-only database","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Advanced Usage/Read-only database"},{"name":"iconClass","value":"bx bx-book-reader","type":"label"}]}]},{"id":"_help_GBBMSlVSOIGP","title":"AI","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/AI"},{"name":"iconClass","value":"bx bx-bot","type":"label"}],"children":[{"id":"_help_WkM7gsEUyCXs","title":"Providers","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/AI/Providers"},{"name":"iconClass","value":"bx bx-select-multiple","type":"label"}],"children":[{"id":"_help_7EdTxPADv95W","title":"Ollama","type":"book","attributes":[{"name":"iconClass","value":"bx bx-message-dots","type":"label"}],"children":[{"id":"_help_vvUCN7FDkq7G","title":"Installing Ollama","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/AI/Providers/Ollama/Installing Ollama"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_ZavFigBX9AwP","title":"OpenAI","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/AI/Providers/OpenAI"},{"name":"iconClass","value":"bx bx-message-dots","type":"label"}]},{"id":"_help_e0lkirXEiSNc","title":"Anthropic","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/AI/Providers/Anthropic"},{"name":"iconClass","value":"bx bx-message-dots","type":"label"}]}]}]},{"id":"_help_CdNpE2pqjmI6","title":"Scripting","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting"},{"name":"iconClass","value":"bx bxs-file-js","type":"label"}],"children":[{"id":"_help_yIhgI5H7A2Sm","title":"Frontend Basics","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics"},{"name":"iconClass","value":"bx bx-window","type":"label"}],"children":[{"id":"_help_MgibgPcfeuGz","title":"Custom Widgets","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets"},{"name":"iconClass","value":"bx bxs-widget","type":"label"}],"children":[{"id":"_help_YNxAqkI5Kg1M","title":"Word count widget","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Word count widget"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_SynTBQiBsdYJ","title":"Widget Basics","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Widget Basics"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_M8IppdwVHSjG","title":"Right pane widget","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/Right pane widget"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_VqGQnnPGnqAU","title":"CSS","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets/CSS"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]},{"id":"_help_es8OU2GuguFU","title":"Examples","type":"book","attributes":[{"name":"iconClass","value":"bx bx-code-alt","type":"label"}],"children":[{"id":"_help_TjLYAo3JMO8X","title":"\"New Task\" launcher button","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Examples/New Task launcher button"},{"name":"iconClass","value":"bx bx-task","type":"label"}]},{"id":"_help_7kZPMD0uFwkH","title":"Downloading responses from Google Forms","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Examples/Downloading responses from Goo"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_DL92EjAaXT26","title":"Using promoted attributes to configure scripts","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Frontend Basics/Examples/Using promoted attributes to c"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]}]},{"id":"_help_SPirpZypehBG","title":"Backend scripts","type":"book","attributes":[{"name":"iconClass","value":"bx bx-server","type":"label"}],"children":[{"id":"_help_fZ2IGYFXjkEy","title":"Server-side imports","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Backend scripts/Server-side imports"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_GPERMystNGTB","title":"Events","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Backend scripts/Events"},{"name":"iconClass","value":"bx bx-rss","type":"label"}]}]},{"id":"_help_GLks18SNjxmC","title":"Script API","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Script API"},{"name":"iconClass","value":"bx bx-code-curly","type":"label"}],"children":[{"id":"_help_Q2z6av6JZVWm","title":"Frontend API","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/script-api/frontend"},{"name":"iconClass","value":"bx bx-folder","type":"label"}],"enforceAttributes":true,"children":[{"id":"_help_habiZ3HU8Kw8","title":"FNote","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/script-api/frontend/interfaces/FNote.html"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_MEtfsqa5VwNi","title":"Backend API","type":"webView","attributes":[{"type":"label","name":"webViewSrc","value":"https://docs.triliumnotes.org/script-api/backend"},{"name":"iconClass","value":"bx bx-file","type":"label"}],"enforceAttributes":true}]},{"id":"_help_vElnKeDNPSVl","title":"Logging","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Scripting/Logging"},{"name":"iconClass","value":"bx bx-terminal","type":"label"}]}]},{"id":"_help_Fm0j45KqyHpU","title":"Miscellaneous","type":"book","attributes":[{"name":"iconClass","value":"bx bx-info-circle","type":"label"}],"children":[{"id":"_help_WFbFXrgnDyyU","title":"Privacy Policy","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Miscellaneous/Privacy Policy"},{"name":"iconClass","value":"bx bx-file","type":"label"}]},{"id":"_help_NcsmUYZRWEW4","title":"Patterns of personal knowledge","type":"doc","attributes":[{"type":"label","name":"docName","value":"User Guide/User Guide/Miscellaneous/Patterns of personal knowledge"},{"name":"iconClass","value":"bx bx-file","type":"label"}]}]}] \ No newline at end of file diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text.html index 2c55d232cd..fad87118db 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text.html +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text.html @@ -4,7 +4,7 @@

Most of the interaction with text notes is done via the built-in toolbars. Depending on preference, there are two different layouts:

    -
  • The Floating toolbar is hidden by default and only appears when +
  • The Floating toolbar is hidden by default and only appears when needed. In this mode there are actually two different toolbars:
  • -
  • A toolbar that appears when text is selected. This provides text-level +
  • A toolbar that appears when text is selected. This provides text-level formatting such as bold, italic, text colors, inline code, etc.
  • @@ -20,167 +20,171 @@

    Fore more information see Formatting toolbar.

    Features and formatting

    Here's a list of various features supported by text notes:

    -
{t("file_properties.note_id")}:{note.noteId}{t("file_properties.original_file_name")}:{originalFileName ?? "?"}{t("file_properties.note_id")}:{note.noteId}{t("file_properties.original_file_name")}:{originalFileName ?? "?"}
{t("file_properties.file_type")}:{note.mime}{t("file_properties.file_size")}:{formatSize(blob?.contentLength ?? 0)}{t("file_properties.file_type")}:{note.mime}{t("file_properties.file_size")}:{formatSize(blob?.contentLength ?? 0)}
-
+
diff --git a/apps/client/src/widgets/ribbon/InheritedAttributesTab.tsx b/apps/client/src/widgets/ribbon/InheritedAttributesTab.tsx index d9eb32b7f9..bc6f3eb49e 100644 --- a/apps/client/src/widgets/ribbon/InheritedAttributesTab.tsx +++ b/apps/client/src/widgets/ribbon/InheritedAttributesTab.tsx @@ -37,7 +37,7 @@ export default function InheritedAttributesTab({ note, componentId }: TabContext return (
-
+
{inheritedAttributes?.length ? ( joinElements(inheritedAttributes.map(attribute => (
{t("note_info_widget.note_id")}: - {note.noteId} + {note.noteId}
{t("note_info_widget.created")}: - {formatDateTime(metadata?.dateCreated)} + {formatDateTime(metadata?.dateCreated)}
{t("note_info_widget.modified")}: - {formatDateTime(metadata?.dateModified)} + {formatDateTime(metadata?.dateModified)}
{t("note_info_widget.type")}: {note.type}{' '} - {note.mime && ({note.mime})} + {note.mime && ({note.mime})}
@@ -77,7 +77,7 @@ export default function NoteInfoTab({ note }: TabContext) { /> )} - + {formatSize(noteSizeResponse?.noteSize)} {" "} {subtreeSizeResponse && subtreeSizeResponse.subTreeNoteCount > 1 && diff --git a/apps/client/src/widgets/type_widgets/Doc.css b/apps/client/src/widgets/type_widgets/Doc.css index 0081da3c76..3dc440bcfa 100644 --- a/apps/client/src/widgets/type_widgets/Doc.css +++ b/apps/client/src/widgets/type_widgets/Doc.css @@ -1,5 +1,6 @@ .note-detail-doc-content { padding: 15px; + user-select: text; } .note-detail-doc-content pre { diff --git a/apps/client/src/widgets/type_widgets/options/backup.tsx b/apps/client/src/widgets/type_widgets/options/backup.tsx index 5cf240bf90..2f1a2d63ba 100644 --- a/apps/client/src/widgets/type_widgets/options/backup.tsx +++ b/apps/client/src/widgets/type_widgets/options/backup.tsx @@ -104,7 +104,7 @@ export function BackupList({ backups }: { backups: DatabaseBackup[] }) { backups.map(({ mtime, filePath }) => (
{mtime ? formatDateTime(mtime) : "-"}{filePath}{filePath}
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Dedicated articleFeature
General formatting - -
    -
  • Headings (section titles, paragraph)
  • -
  • Font size
  • -
  • Bold, italic, underline, strike-through
  • -
  • Superscript, subscript
  • -
  • Font color & background color
  • -
  • Remove formatting
  • -
-
Lists - -
    -
  • Bulleted lists
  • -
  • Numbered lists
  • -
  • To-do lists
  • -
-
Block quotes & admonitions - -
    -
  • Block quotes
  • -
  • Admonitions
  • -
-
Tables - -
    -
  • Basic tables
  • -
  • Merging cells
  • -
  • Styling tables and cells.
  • -
  • Table captions
  • -
-
Developer-specific formatting - -
    -
  • Inline code
  • -
  • Code blocks
  • -
  • Keyboard shortcuts
  • -
-
Footnotes - -
    -
  • Footnotes
  • -
-
Images - -
    -
  • Images
  • -
-
Links - -
    -
  • External links
  • -
  • Internal Trilium links
  • -
-
Include Note - -
    -
  • Include note
  • -
-
Insert buttons - -
    -
  • Symbols
  • -
  • Math Equations -
  • -
  • Mermaid diagrams
  • -
  • Horizontal ruler
  • -
  • Page break
  • -
-
Other features - - -
Premium features - - -
- -

Read-Only vs. Editing Mode

-

Text notes are usually opened in edit mode. However, they may open in - read-only mode if the note is too big or the note is explicitly marked - as read-only. For more information, see Read-Only Notes.

-

Keyboard shortcuts

-

There are numerous keyboard shortcuts to format the text without having - to use the mouse. For a reference of all the key combinations, see  - Keyboard Shortcuts. In addition, see Markdown-like formatting as an alternative - to the keyboard shortcuts.

-

Technical details

-

For the text editing functionality, Trilium uses a commercial product - (with an open-source base) called CKEditor. - This brings the benefit of having a powerful WYSIWYG (What You See Is What - You Get) editor.

\ No newline at end of file +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Dedicated articleFeature
General formatting + +
    +
  • Headings (section titles, paragraph)
  • +
  • Font size
  • +
  • Bold, italic, underline, strike-through
  • +
  • Superscript, subscript
  • +
  • Font color & background color
  • +
  • Remove formatting
  • +
+
Lists + +
    +
  • Bulleted lists
  • +
  • Numbered lists
  • +
  • To-do lists
  • +
+
Block quotes & admonitions + +
    +
  • Block quotes
  • +
  • Admonitions
  • +
+
Tables + +
    +
  • Basic tables
  • +
  • Merging cells
  • +
  • Styling tables and cells.
  • +
  • Table captions
  • +
+
Developer-specific formatting + +
    +
  • Inline code
  • +
  • Code blocks
  • +
  • Keyboard shortcuts
  • +
+
Footnotes + +
    +
  • Footnotes
  • +
+
Images + +
    +
  • Images
  • +
+
Links + +
    +
  • External links
  • +
  • Internal Trilium links
  • +
+
Include Note + +
    +
  • Include note
  • +
+
Insert buttons + +
    +
  • Symbols
  • +
  • Math Equations +
  • +
  • Mermaid diagrams
  • +
  • Horizontal ruler
  • +
  • Page break
  • +
+
Other features + + +
Premium features + + +
+
+

Read-Only vs. Editing Mode

+

Text notes are usually opened in edit mode. However, they may open in + read-only mode if the note is too big or the note is explicitly marked + as read-only. For more information, see Read-Only Notes.

+

Keyboard shortcuts

+

There are numerous keyboard shortcuts to format the text without having + to use the mouse. For a reference of all the key combinations, see  + Keyboard Shortcuts. In addition, see Markdown-like formatting as an alternative + to the keyboard shortcuts.

+

Technical details

+

For the text editing functionality, Trilium uses a commercial product + (with an open-source base) called CKEditor. + This brings the benefit of having a powerful WYSIWYG (What You See Is What + You Get) editor.

\ No newline at end of file diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/General formatting.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/General formatting.html index 6879504599..ad458585aa 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/General formatting.html +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/General formatting.html @@ -12,11 +12,11 @@

Apart from using the UI, it is also possible to quickly insert headings using the Markdown-like shortcuts:

    -
  • ## for Heading 2
  • -
  • ### for Heading 3
  • -
  • #### for Heading 4
  • -
  • ##### for Heading 5
  • -
  • ###### for Heading 6
  • +
  • ## for Heading 2
  • +
  • ### for Heading 3
  • +
  • #### for Heading 4
  • +
  • ##### for Heading 5
  • +
  • ###### for Heading 6

Font size

@@ -44,17 +44,17 @@

This formatting can be easily removed using the Remove formatting item.

The following keyboard shortcuts can be used here:

    -
  • Ctrl+B for bold
  • -
  • Ctrl+I for italic
  • -
  • Ctrl+U for underline
  • +
  • Ctrl+B for bold
  • +
  • Ctrl+I for italic
  • +
  • Ctrl+U for underline

Alternatively, Markdown-like formatting can be used:

    -
  • Bold: Type **text** or __text__ +
  • Bold: Type **text** or __text__
  • -
  • Italic: Type *text* or _text_ +
  • Italic: Type *text* or _text_
  • -
  • Strikethrough: Type ~~text~~ +
  • Strikethrough: Type ~~text~~

Superscript, subscript

@@ -89,6 +89,11 @@ be manually changed back to a paragraph according to the Headings section.

When pasting content that comes with undesired formatting, an alternative to pasting and then removing formatting is pasting as plain text via Ctrl+Shift+V.

+

Format painter

+

The Format Painter allows + users to copy the formatting of text (such as bold, italic, Strikethrough, + etc.) and apply it to other parts of the document. It helps maintain consistent + formatting and accelerates the creation of rich content.

Support for Markdown

When exported to Markdown, most of the general formatting is maintained such as headings, bold, italic, diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Premium features/Format Painter.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Premium features/Format Painter.html new file mode 100644 index 0000000000..2d2bc60fc6 --- /dev/null +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Premium features/Format Painter.html @@ -0,0 +1,45 @@ +

+ +
+ +

The Format Painter is a feature in text notes that allows users to copy + the formatting of text (such as bold, italic, Strikethrough, + etc.) and apply it to other parts of the document. It helps maintain consistent + formatting and accelerates the creation of rich content.

+

Usage Instructions

+

Click the text that you want to copy the formatting from and use the paint + formatting toolbar button (Format painter) to + copy the style. Then select the target text with your mouse to apply the + formatting.

+
    +
  • To copy the formatting: Place the cursor inside a text + with some formatting and click the paint formatting toolbar button. Notice + that the mouse cursor changes to the Format painter text cursor.
  • +
  • To paint with the copied formatting: Click any word in + the document and the new formatting will be applied. Alternatively, instead + of clicking a single word, you can select a text fragment (like an entire + paragraph). Notice that the cursor will go back to the default one after + the formatting is applied.
  • +
  • To keep painting using the same formatting: Open the + toolbar dropdown and enable the continuous painting mode. Once copied, + the same formatting can be applied multiple times in different places until + the paint formatting button is clicked (the cursor will then revert to + the regular one).
  • +
+

Limitations

+
    +
  1. Painting with block-level formatting (like headings or image styles) is + not supported yet. This is because, in CKEditor, + they are considered a part of the content rather than text formatting.
  2. +
  3. When applying formatting to words, spaces or other Western punctuation + are used as word boundaries, which prevents proper handling of languages + that do not use space-based word segmentation.
  4. +
\ No newline at end of file diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Premium features/Format Painter_746436a2e1.svg b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Premium features/Format Painter_746436a2e1.svg new file mode 100644 index 0000000000..77ad84f56b --- /dev/null +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Premium features/Format Painter_746436a2e1.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Premium features/Format Painter_e144e96df9.svg b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Premium features/Format Painter_e144e96df9.svg new file mode 100644 index 0000000000..06342b7c73 --- /dev/null +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Premium features/Format Painter_e144e96df9.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Premium features/Format Painter_image.png b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Premium features/Format Painter_image.png new file mode 100644 index 0000000000000000000000000000000000000000..db5cbbbd1155a5b022d82204e6c2e74e707fae09 GIT binary patch literal 5251 zcmYkAXH*l<*MO4{Afbj(q#Fpm2?B!BLKl$Uq@(mAgd$ZTAiWAAO+Z8g2m;cJ^dd!y zbRr6&7m+Fmg7U7v^Z)RE*x7St_w3Hj-uuimH{L)`lbV8+0t5n4Yu#2e0?uE7;|>f0 zwDGoj&p{vrNJ~xGBnZ5dAB<(_yV5Ts3?_lcLy?^V5m%Lz|2&UTHN=F`U6VJs?3{-v zi;f-Qj6O{)|L&*PmRF`^7%K0jR}N3`4FYAVbid-s1E*tfQBhEc%8ib(-Nd$Mgq&{# z0s)b}6{2X{5%#C$d?e5|aI7ro`?qC{!W{L^?-GLjDI9WGVrPLusJ4UH*}YFO)NBDe zb3Uj0_nyT!ZJS*II~YLH9-p5~&&>RO)E*SOdU~)@7(Q97%gD%h!1?Jo+(@kxl(9N6 zG&EHF^3Q0#Trf*+m~~+9Iun@0U}kD6uhb&FpkCFRP@``3aIHzB@JwwUl%bi*nf!gZ zN4Bc6l4f%IMtwSr8CL@zP5VN0cN)$5QYPFu3iM2fAUtN?S-98^ht!ijHZ&Zsxs8|Z z?RqP1NxHV&m#CS-9$X)sBjFHZ?3d7&N<=f!j-PPI1$d4XC|s*IC^}}ZP*~jKHmXz9 zk83kE(8#m4vHA9MYf|ZK^;uk|k2L6NAy1|1W?sjyh0t5NUS7L4f#2}PVw4Q|6J0{H z8JFrpb90<&jSBwwhPLQESH=u8n%oZoKWzt>_+O^L>u_5)9Jw5%( z3tP9#%57m*ULStkn16;XLrbvI3sm>_on-Lo7f=}mJKyPTpl9QVrQx`BzZW)bD4v^_ zC&CK-40p%7KdI#osg{zJ3f#4h^t>%kD)Dic(}I+DVNXivk~*W|!F<@yam_b_FTC4X zKGCZ{{bV5-N8&7WE7LwDIfn)5HBXFQva^UgpzP%BBNDTz)^aBzNqs_ z5JTY#-v!BkX;JHZ@V!OP?KK4w!^05|gX{^{FhWLd zN&bd-BO6;7rUTDH?^Ha-q)%_*E8X9^bSbhqdU-IOfO>z#6sL*7=kC=AP-uMz$ZYcBD51~%-`KLysEo3Q!(EiP1)rHq#9;* z-n&D=z7yxl&OA>6(eR*XBDeiGlU%P5@^h}?0UIY0iQKGl97K)|ChK-j$JHR7Jn?Q> zp;jqm({_tCmVU#`kJx@@=OO36i6~QwV9l)Jjn;{87NfiiaoW6(;c@8XiYkqJ1Q%OE zT|Z$T{7i%^x{R`?_$PpPg|ql9d+0MeVKnL7>o+9LsT3Y=Px&M#s(Vv$oI@S&TR|?F z5>GH%%NfPF7&-!(%Y6N~PRk}LDxLR;rsrYY8$pOb-<5z-WE?ar1(hB@@lUt`!;wGcidpY^(8g%3&%^)t-|J>b|m(V(nmFfnJC~E@4ncfwzac3Q9^>BaS*S zH|&`?*c2ZHRoS)?Cz2ml-;zYW5VywmrFS{G4pU( ztVc>LotjL+GG2`gi6x=h^cXfwNf1dXh3E_^pZltD^h?&$KSSoQ!;JtYB;woX27j?PS*X{2tADRdvuHyVc`5BsD$SJOUjbnCg;Kbp`JVC< zGC?*;!@zh^YnVHsK7>$L5*;)G(45Y(-@Q#zuygVFl|~t~4R| zofI`qO--L?W$j&-WLSv-t5k`a@!yN1F={V2WxBgnf+FRGg@sK`+1?PMu1+LI3PxR+ zLBXyf+}hBPIW`UuLRVj3>3pa5{P_E<5{(niD%T0RykB}w!i9t8ffzqS>?u4kH0kcx zb2A|*OyuaHC>s4*|D__pFCMvDO{*HHk1!Aq5n7640+Bf5M)Z%5gEVm8C3%HdQ`m2I z>(c>?sjjZB`bs(*xE~Fw12Kz}01v!O2vrvD^)|+;%LVKZL%ofRki}xnbaBSe|8AfN zf?>vml{k))DO6&P#+4)_4(cZL5+_Zp8@-?=P#lXri7!Z>7)xAi*Lr~nz{VxsX!I@v z9^e`Y1KmK8?=wiZY{oSd7Z?9~y*OJSOa`I`dJn$Y#c4Y5Qt(XGq&t;E?js`{uj2*H zML}@X1Mrh58At860-V3zHjzjLLsQP>pVuFU(#&L;^{EAQ(k`%DM?eZ-WQG1%@mW*9 zILwIQSmvMh*5#Iw^G6?q9`l-JmNJ~O8v2<2$^3JC#@k-8b{rJo9s$u@qMnzj#M5X7 zyzNs1F?flT%VFm(-M$dimul^+Xp?R&GZEoSBO@8mSA7!=zE?jyu+ECT{J}_rvgJZ{ z0fQyEzm0`;;h7L%U&pgoDC_ijUdO=0za=kZHhvo4=aMIqdkd*0Aw%1tK?xT*$i1=@ z%ryR)0wnKb;GR39h1-H&!Q(UG@KfwUo`rWCC*=}YDX6F9aO`eUY1s`Zu4I5#TPP@k zlB*HozNGWjnB&5#8KbXD$n1%wwF^623tW8st4Cw)RV-)A$rq0^M`j7J`uh6l=;))3 zu__V4&f1!5<#1;we4QBVgy;|VS~R+%_r$ojD(4x$e*0eg`9k>RAJteILI5BWmPKaP z)}HgKt#X!mO9w0c{CBeVzj##jc`H7uT4Lh`FgwGTL!hM+Yx_Cz znNM;gRq1b>%S9p>eZ6wvMiYpZ=1e)Bl4pqd`JeR{-Z4}x-Bo*r z!JLxL!<5%rF#xc6L04dn}}kEBBMaO{Y`JGnhzmA!j#8)9KzUSyn5lnb`736v)|WDW3n7mXneAhIY-~6(1**H?zUu0vm1^rHkuSr3Z%yheeXDb$FUL=RPUoW%@5vU+7DRfl zt*zOG|2YO^kkI-j-lr?4L1(_6-Yj-u*1!obR$Rn$Oc+IAmSpTFg#lxhyN=Fc%c1kcV*XusLaO z(-q?27sD?ff1jz)mp@Q*a$3uk_V}30_G|T-{>0;*x$3IcLkb#0 z-`kz=!;>HLb|G85j$!Nk&F#lCRv7oGQbPfYhF5FvENX)uq;M(>$sNr(q=K(pz?PDa zW^`q~)de4|-}GCz2IiuPw22l<;XMV!%p1x~XUSekm|W04s(ilDdlB%!f9~eY+~P>) z6ngLMo!9T5TOtUD48yc**#Zg=TH&oo!-tJtNiG+{p+B0mS)O;2L|)_=wHVT+yYJ*t z0Y9mCp~5;pWc#g~o16TU%t8Q!Ol4m=BpG@&ANki9?cuXQ1!D-l;~e|`dULOdIEffRUmeaIQE%s7V~n9e8<&Eu6@6o zQpR%*HTc${KSdxoisP0)MjUNPPfzbg>Sy`BXdDS=-ndVw_b?xQ&CAPcNy57rypeCM zDAq)TOc(*#D|_;m4~m;>3k`%?`!My2mh!ryc8U_kR8-Ago9dW33!Jp@(z8!s_c|9v zy9M}9!l!v8Jz4eS8PAjjUkg1qaoE_%59G{=uP|=@eYWwE0FIX~j6%3Bv+Tpb+%+q` zgZhtZZrOq`BBmTJAHLSQ(B{CyMx-W|03yDxE zvX~6_A4*8b)m3IO>eJQ3-f?>GCZ}1xYA!z^b$E!1C>R`T<0ZOL5Gqz;YKuHEXc6G1 z^92_TagNAD0j}b6%Mm_n6KE3>a%+~M7JBE3y65J-^p@*rSwMG*)4bOKIJWYay*-Bg zy)*b^D&08IrFO+1W(Hy^8PpMLcAR*lh1N{r5o|wQPR#omAu`V`Gc*2L^96OtC(%ai zLdU^JwgU&}Cx7$&Mwi^fXDnO})M(jdQT*g5W|)sBLjtslr$hiRG%+foT@)Mgm1@K! zv0q>PXpOr|ijtD3Y`H9b6oI{yqUTZ+2a{xm)RGy?3wSFnj+47Nmr%$r%Wf3>L00!L z?ZwzP0V@(Wx=nJYi=@-DWTRao}*W>aw@s9XjH zBRp6*PvN-f>Im@%Op(=8QAUn2D;i@erx5i*l*Iedwp{Pk{>R5u58AvXK_DW2fe(03h5{T`3H{WSbpr zb#spVLiKmKG+-8}-w)7?-st}0J($k>2qP|eW0Jp-vUuoE?DpD6H+%M?<@>BflqH># zf1gJOSmW!snhKK;QZ*uhekX5X0i)7Sbo3y=#(L?ftW96#L2JR}7a3yu%fFAbSRVPT zBr0dC-KHng$r7t?rO%1W|3QNmAotS5`HuysGP3v>Dc}o^M(`@{5hYLSH-Jqw90WvD{ z&g!RHN&O|Jn?1$P$yBWdD-DT3(B_$ya zT=GA6^Pc*({Ic7E2c>A*|15N*x{?KbwMMt-F_Dg(d+?!zulK(}uv5`JeUhO{VsLmQ z+#xJLX^urBX8%cH2}cn)gUFCh7IypnVVic6&F+8h3S4-&OpcF4Lwfhd@p!x?+B^V_ z==h&T2B-P297tXnDk~GpU#MuI!^%TCsQ{0xa0xFqd6*k*WMl-C9n7q(%5(D&)>plt ztm+^fxE82`XjrE9(`tjct?Rj5932@L7(kAAe^MC;jRwdSEN;Jk{JYTuRWe{_jusS! z6#D~NB`hNHuCj7H;mxphS2FI$|JQ2Ww5DShZJu#%m=@!LqQS}TxAR%Ma6ktts;$gE z;7Qdx#VBT0*Ve#1Lk%+ddtnj$LBkAhcaVoY6_@;8LbI) z>T;%o(~~F~g|aNM(4>OkbRyUugM&gu?fF12r5pjHXJ}DFq;R^=wHq2n2pa{PLYK-+ zp@u>!AT6M5BUVp@4Hz?3W@<57e0rGeneral formatting
  • Headings (section titles, paragraph)
  • Font size
  • Bold, italic, underline, strike-through
  • Superscript, subscript
  • Font color & background color
  • Remove formatting
Lists
  • Bulleted lists
  • Numbered lists
  • To-do lists
Block quotes & admonitions
  • Block quotes
  • Admonitions
Tables
  • Basic tables
  • Merging cells
  • Styling tables and cells.
  • Table captions
Developer-specific formatting
  • Inline code
  • Code blocks
  • Keyboard shortcuts
Footnotes
  • Footnotes
Images
  • Images
Links
  • External links
  • Internal Trilium links
Include Note
  • Include note
Insert buttonsOther featuresPremium features +
Dedicated articleFeature
General formatting
  • Headings (section titles, paragraph)
  • Font size
  • Bold, italic, underline, strike-through
  • Superscript, subscript
  • Font color & background color
  • Remove formatting
Lists
  • Bulleted lists
  • Numbered lists
  • To-do lists
Block quotes & admonitions
  • Block quotes
  • Admonitions
Tables
  • Basic tables
  • Merging cells
  • Styling tables and cells.
  • Table captions
Developer-specific formatting
  • Inline code
  • Code blocks
  • Keyboard shortcuts
Footnotes
  • Footnotes
Images
  • Images
Links
  • External links
  • Internal Trilium links
Include Note
  • Include note
Insert buttons
Other features
Premium features
## Read-Only vs. Editing Mode diff --git a/docs/User Guide/User Guide/Note Types/Text/General formatting.md b/docs/User Guide/User Guide/Note Types/Text/General formatting.md index e05d730aad..28ffb5f033 100644 --- a/docs/User Guide/User Guide/Note Types/Text/General formatting.md +++ b/docs/User Guide/User Guide/Note Types/Text/General formatting.md @@ -79,6 +79,10 @@ Note that heading styles are not taken into consideration, these must be manuall When pasting content that comes with undesired formatting, an alternative to pasting and then removing formatting is pasting as plain text via Ctrl+Shift+V. +## Format painter + +The Format Painter allows users to copy the formatting of text (such as bold, italic, Strikethrough, etc.) and apply it to other parts of the document. It helps maintain consistent formatting and accelerates the creation of rich content. + ## Support for Markdown When exported to Markdown, most of the general formatting is maintained such as headings, bold, italic, underline, etc. \ No newline at end of file diff --git a/docs/User Guide/User Guide/Note Types/Text/Premium features/Format Painter.md b/docs/User Guide/User Guide/Note Types/Text/Premium features/Format Painter.md new file mode 100644 index 0000000000..8bc94c6f7c --- /dev/null +++ b/docs/User Guide/User Guide/Note Types/Text/Premium features/Format Painter.md @@ -0,0 +1,20 @@ +# Format Painter +
+ +> [!NOTE] +> This is a premium feature of the editor we are using (CKEditor) and we benefit from it thanks to an written agreement with the team. See  Premium features for more information. + +The Format Painter is a feature in text notes that allows users to copy the formatting of text (such as **bold**, _italic_, ~~Strikethrough~~, etc.) and apply it to other parts of the document. It helps maintain consistent formatting and accelerates the creation of rich content. + +## Usage Instructions + +Click the text that you want to copy the formatting from and use the paint formatting toolbar button (Format painter) to copy the style. Then select the target text with your mouse to apply the formatting. + +* **To copy the formatting**: Place the cursor inside a text with some formatting and click the paint formatting toolbar button. Notice that the mouse cursor changes to the Format painter text cursor. +* **To paint with the copied formatting**: Click any word in the document and the new formatting will be applied. Alternatively, instead of clicking a single word, you can select a text fragment (like an entire paragraph). Notice that the cursor will go back to the default one after the formatting is applied. +* **To keep painting using the same formatting**: Open the toolbar dropdown and enable the continuous painting mode. Once copied, the same formatting can be applied multiple times in different places until the paint formatting button is clicked (the cursor will then revert to the regular one). + +## Limitations + +1. Painting with block-level formatting (like headings or image styles) is not supported yet. This is because, in CKEditor, they are considered a part of the content rather than text formatting. +2. When applying formatting to words, spaces or other Western punctuation are used as word boundaries, which prevents proper handling of languages that do not use space-based word segmentation. \ No newline at end of file diff --git a/docs/User Guide/User Guide/Note Types/Text/Premium features/Format Painter_746436a2e1.svg b/docs/User Guide/User Guide/Note Types/Text/Premium features/Format Painter_746436a2e1.svg new file mode 100644 index 0000000000..77ad84f56b --- /dev/null +++ b/docs/User Guide/User Guide/Note Types/Text/Premium features/Format Painter_746436a2e1.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/User Guide/User Guide/Note Types/Text/Premium features/Format Painter_e144e96df9.svg b/docs/User Guide/User Guide/Note Types/Text/Premium features/Format Painter_e144e96df9.svg new file mode 100644 index 0000000000..06342b7c73 --- /dev/null +++ b/docs/User Guide/User Guide/Note Types/Text/Premium features/Format Painter_e144e96df9.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/docs/User Guide/User Guide/Note Types/Text/Premium features/Format Painter_image.png b/docs/User Guide/User Guide/Note Types/Text/Premium features/Format Painter_image.png new file mode 100644 index 0000000000000000000000000000000000000000..db5cbbbd1155a5b022d82204e6c2e74e707fae09 GIT binary patch literal 5251 zcmYkAXH*l<*MO4{Afbj(q#Fpm2?B!BLKl$Uq@(mAgd$ZTAiWAAO+Z8g2m;cJ^dd!y zbRr6&7m+Fmg7U7v^Z)RE*x7St_w3Hj-uuimH{L)`lbV8+0t5n4Yu#2e0?uE7;|>f0 zwDGoj&p{vrNJ~xGBnZ5dAB<(_yV5Ts3?_lcLy?^V5m%Lz|2&UTHN=F`U6VJs?3{-v zi;f-Qj6O{)|L&*PmRF`^7%K0jR}N3`4FYAVbid-s1E*tfQBhEc%8ib(-Nd$Mgq&{# z0s)b}6{2X{5%#C$d?e5|aI7ro`?qC{!W{L^?-GLjDI9WGVrPLusJ4UH*}YFO)NBDe zb3Uj0_nyT!ZJS*II~YLH9-p5~&&>RO)E*SOdU~)@7(Q97%gD%h!1?Jo+(@kxl(9N6 zG&EHF^3Q0#Trf*+m~~+9Iun@0U}kD6uhb&FpkCFRP@``3aIHzB@JwwUl%bi*nf!gZ zN4Bc6l4f%IMtwSr8CL@zP5VN0cN)$5QYPFu3iM2fAUtN?S-98^ht!ijHZ&Zsxs8|Z z?RqP1NxHV&m#CS-9$X)sBjFHZ?3d7&N<=f!j-PPI1$d4XC|s*IC^}}ZP*~jKHmXz9 zk83kE(8#m4vHA9MYf|ZK^;uk|k2L6NAy1|1W?sjyh0t5NUS7L4f#2}PVw4Q|6J0{H z8JFrpb90<&jSBwwhPLQESH=u8n%oZoKWzt>_+O^L>u_5)9Jw5%( z3tP9#%57m*ULStkn16;XLrbvI3sm>_on-Lo7f=}mJKyPTpl9QVrQx`BzZW)bD4v^_ zC&CK-40p%7KdI#osg{zJ3f#4h^t>%kD)Dic(}I+DVNXivk~*W|!F<@yam_b_FTC4X zKGCZ{{bV5-N8&7WE7LwDIfn)5HBXFQva^UgpzP%BBNDTz)^aBzNqs_ z5JTY#-v!BkX;JHZ@V!OP?KK4w!^05|gX{^{FhWLd zN&bd-BO6;7rUTDH?^Ha-q)%_*E8X9^bSbhqdU-IOfO>z#6sL*7=kC=AP-uMz$ZYcBD51~%-`KLysEo3Q!(EiP1)rHq#9;* z-n&D=z7yxl&OA>6(eR*XBDeiGlU%P5@^h}?0UIY0iQKGl97K)|ChK-j$JHR7Jn?Q> zp;jqm({_tCmVU#`kJx@@=OO36i6~QwV9l)Jjn;{87NfiiaoW6(;c@8XiYkqJ1Q%OE zT|Z$T{7i%^x{R`?_$PpPg|ql9d+0MeVKnL7>o+9LsT3Y=Px&M#s(Vv$oI@S&TR|?F z5>GH%%NfPF7&-!(%Y6N~PRk}LDxLR;rsrYY8$pOb-<5z-WE?ar1(hB@@lUt`!;wGcidpY^(8g%3&%^)t-|J>b|m(V(nmFfnJC~E@4ncfwzac3Q9^>BaS*S zH|&`?*c2ZHRoS)?Cz2ml-;zYW5VywmrFS{G4pU( ztVc>LotjL+GG2`gi6x=h^cXfwNf1dXh3E_^pZltD^h?&$KSSoQ!;JtYB;woX27j?PS*X{2tADRdvuHyVc`5BsD$SJOUjbnCg;Kbp`JVC< zGC?*;!@zh^YnVHsK7>$L5*;)G(45Y(-@Q#zuygVFl|~t~4R| zofI`qO--L?W$j&-WLSv-t5k`a@!yN1F={V2WxBgnf+FRGg@sK`+1?PMu1+LI3PxR+ zLBXyf+}hBPIW`UuLRVj3>3pa5{P_E<5{(niD%T0RykB}w!i9t8ffzqS>?u4kH0kcx zb2A|*OyuaHC>s4*|D__pFCMvDO{*HHk1!Aq5n7640+Bf5M)Z%5gEVm8C3%HdQ`m2I z>(c>?sjjZB`bs(*xE~Fw12Kz}01v!O2vrvD^)|+;%LVKZL%ofRki}xnbaBSe|8AfN zf?>vml{k))DO6&P#+4)_4(cZL5+_Zp8@-?=P#lXri7!Z>7)xAi*Lr~nz{VxsX!I@v z9^e`Y1KmK8?=wiZY{oSd7Z?9~y*OJSOa`I`dJn$Y#c4Y5Qt(XGq&t;E?js`{uj2*H zML}@X1Mrh58At860-V3zHjzjLLsQP>pVuFU(#&L;^{EAQ(k`%DM?eZ-WQG1%@mW*9 zILwIQSmvMh*5#Iw^G6?q9`l-JmNJ~O8v2<2$^3JC#@k-8b{rJo9s$u@qMnzj#M5X7 zyzNs1F?flT%VFm(-M$dimul^+Xp?R&GZEoSBO@8mSA7!=zE?jyu+ECT{J}_rvgJZ{ z0fQyEzm0`;;h7L%U&pgoDC_ijUdO=0za=kZHhvo4=aMIqdkd*0Aw%1tK?xT*$i1=@ z%ryR)0wnKb;GR39h1-H&!Q(UG@KfwUo`rWCC*=}YDX6F9aO`eUY1s`Zu4I5#TPP@k zlB*HozNGWjnB&5#8KbXD$n1%wwF^623tW8st4Cw)RV-)A$rq0^M`j7J`uh6l=;))3 zu__V4&f1!5<#1;we4QBVgy;|VS~R+%_r$ojD(4x$e*0eg`9k>RAJteILI5BWmPKaP z)}HgKt#X!mO9w0c{CBeVzj##jc`H7uT4Lh`FgwGTL!hM+Yx_Cz znNM;gRq1b>%S9p>eZ6wvMiYpZ=1e)Bl4pqd`JeR{-Z4}x-Bo*r z!JLxL!<5%rF#xc6L04dn}}kEBBMaO{Y`JGnhzmA!j#8)9KzUSyn5lnb`736v)|WDW3n7mXneAhIY-~6(1**H?zUu0vm1^rHkuSr3Z%yheeXDb$FUL=RPUoW%@5vU+7DRfl zt*zOG|2YO^kkI-j-lr?4L1(_6-Yj-u*1!obR$Rn$Oc+IAmSpTFg#lxhyN=Fc%c1kcV*XusLaO z(-q?27sD?ff1jz)mp@Q*a$3uk_V}30_G|T-{>0;*x$3IcLkb#0 z-`kz=!;>HLb|G85j$!Nk&F#lCRv7oGQbPfYhF5FvENX)uq;M(>$sNr(q=K(pz?PDa zW^`q~)de4|-}GCz2IiuPw22l<;XMV!%p1x~XUSekm|W04s(ilDdlB%!f9~eY+~P>) z6ngLMo!9T5TOtUD48yc**#Zg=TH&oo!-tJtNiG+{p+B0mS)O;2L|)_=wHVT+yYJ*t z0Y9mCp~5;pWc#g~o16TU%t8Q!Ol4m=BpG@&ANki9?cuXQ1!D-l;~e|`dULOdIEffRUmeaIQE%s7V~n9e8<&Eu6@6o zQpR%*HTc${KSdxoisP0)MjUNPPfzbg>Sy`BXdDS=-ndVw_b?xQ&CAPcNy57rypeCM zDAq)TOc(*#D|_;m4~m;>3k`%?`!My2mh!ryc8U_kR8-Ago9dW33!Jp@(z8!s_c|9v zy9M}9!l!v8Jz4eS8PAjjUkg1qaoE_%59G{=uP|=@eYWwE0FIX~j6%3Bv+Tpb+%+q` zgZhtZZrOq`BBmTJAHLSQ(B{CyMx-W|03yDxE zvX~6_A4*8b)m3IO>eJQ3-f?>GCZ}1xYA!z^b$E!1C>R`T<0ZOL5Gqz;YKuHEXc6G1 z^92_TagNAD0j}b6%Mm_n6KE3>a%+~M7JBE3y65J-^p@*rSwMG*)4bOKIJWYay*-Bg zy)*b^D&08IrFO+1W(Hy^8PpMLcAR*lh1N{r5o|wQPR#omAu`V`Gc*2L^96OtC(%ai zLdU^JwgU&}Cx7$&Mwi^fXDnO})M(jdQT*g5W|)sBLjtslr$hiRG%+foT@)Mgm1@K! zv0q>PXpOr|ijtD3Y`H9b6oI{yqUTZ+2a{xm)RGy?3wSFnj+47Nmr%$r%Wf3>L00!L z?ZwzP0V@(Wx=nJYi=@-DWTRao}*W>aw@s9XjH zBRp6*PvN-f>Im@%Op(=8QAUn2D;i@erx5i*l*Iedwp{Pk{>R5u58AvXK_DW2fe(03h5{T`3H{WSbpr zb#spVLiKmKG+-8}-w)7?-st}0J($k>2qP|eW0Jp-vUuoE?DpD6H+%M?<@>BflqH># zf1gJOSmW!snhKK;QZ*uhekX5X0i)7Sbo3y=#(L?ftW96#L2JR}7a3yu%fFAbSRVPT zBr0dC-KHng$r7t?rO%1W|3QNmAotS5`HuysGP3v>Dc}o^M(`@{5hYLSH-Jqw90WvD{ z&g!RHN&O|Jn?1$P$yBWdD-DT3(B_$ya zT=GA6^Pc*({Ic7E2c>A*|15N*x{?KbwMMt-F_Dg(d+?!zulK(}uv5`JeUhO{VsLmQ z+#xJLX^urBX8%cH2}cn)gUFCh7IypnVVic6&F+8h3S4-&OpcF4Lwfhd@p!x?+B^V_ z==h&T2B-P297tXnDk~GpU#MuI!^%TCsQ{0xa0xFqd6*k*WMl-C9n7q(%5(D&)>plt ztm+^fxE82`XjrE9(`tjct?Rj5932@L7(kAAe^MC;jRwdSEN;Jk{JYTuRWe{_jusS! z6#D~NB`hNHuCj7H;mxphS2FI$|JQ2Ww5DShZJu#%m=@!LqQS}TxAR%Ma6ktts;$gE z;7Qdx#VBT0*Ve#1Lk%+ddtnj$LBkAhcaVoY6_@;8LbI) z>T;%o(~~F~g|aNM(4>OkbRyUugM&gu?fF12r5pjHXJ}DFq;R^=wHq2n2pa{PLYK-+ zp@u>!AT6M5BUVp@4Hz?3W@<57e0r