diff --git a/README.md b/README.md index 9f7fba27a..02a9c969b 100644 --- a/README.md +++ b/README.md @@ -4,15 +4,47 @@ [English](./README.md) | [Chinese](./docs/README-ZH_CN.md) | [Russian](./docs/README.ru.md) | [Japanese](./docs/README.ja.md) | [Italian](./docs/README.it.md) | [Spanish](./docs/README.es.md) -TriliumNext Notes is an open-source, cross-platform hierarchical note taking application with focus on building large personal knowledge bases. +TriliumNext Notes is a free and open-source, cross-platform hierarchical note taking application with focus on building large personal knowledge bases. See [screenshots](https://triliumnext.github.io/Docs/Wiki/screenshot-tour) for quick overview: Trilium Screenshot +## 🎁 Features + +* Notes can be arranged into arbitrarily deep tree. Single note can be placed into multiple places in the tree (see [cloning](https://triliumnext.github.io/Docs/Wiki/cloning-notes)) +* Rich WYSIWYG note editor including e.g. tables, images and [math](https://triliumnext.github.io/Docs/Wiki/text-notes) with markdown [autoformat](https://triliumnext.github.io/Docs/Wiki/text-notes#autoformat) +* Support for editing [notes with source code](https://triliumnext.github.io/Docs/Wiki/code-notes), including syntax highlighting +* Fast and easy [navigation between notes](https://triliumnext.github.io/Docs/Wiki/note-navigation), full text search and [note hoisting](https://triliumnext.github.io/Docs/Wiki/note-hoisting) +* Seamless [note versioning](https://triliumnext.github.io/Docs/Wiki/note-revisions) +* Note [attributes](https://triliumnext.github.io/Docs/Wiki/attributes) can be used for note organization, querying and advanced [scripting](https://triliumnext.github.io/Docs/Wiki/scripts) +* UI available in English, German, Spanish, French, Romanian, and Chinese (simplified and traditional) +* Direct [OpenID and TOTP integration](.docs/User%20Guide/User%20Guide/Installation%20%26%20Setup/Server%20Installation/Multi-Factor%20Authentication.md") for more secure login +* [Synchronization](https://triliumnext.github.io/Docs/Wiki/synchronization) with self-hosted sync server + * there's a [3rd party service for hosting synchronisation server](https://trilium.cc/paid-hosting) +* [Sharing](https://triliumnext.github.io/Docs/Wiki/sharing) (publishing) notes to public internet +* Strong [note encryption](https://triliumnext.github.io/Docs/Wiki/protected-notes) with per-note granularity +* Sketching diagrams, based on [Excalidraw](https://excalidraw.com/) (note type "canvas") +* [Relation maps](https://triliumnext.github.io/Docs/Wiki/relation-map) and [link maps](https://triliumnext.github.io/Docs/Wiki/link-map) for visualizing notes and their relations +* Mind maps, based on [Mind Elixir](https://docs.mind-elixir.com/) +* [Geo maps](./docs/User%20Guide/User%20Guide/Note%20Types/Geo%20Map.md) with location pins and GPX tracks +* [Scripting](https://triliumnext.github.io/Docs/Wiki/scripts) - see [Advanced showcases](https://triliumnext.github.io/Docs/Wiki/advanced-showcases) +* [REST API](https://triliumnext.github.io/Docs/Wiki/etapi) for automation +* Scales well in both usability and performance upwards of 100 000 notes +* Touch optimized [mobile frontend](https://triliumnext.github.io/Docs/Wiki/mobile-frontend) for smartphones and tablets +* Built-in [dark theme](https://triliumnext.github.io/Docs/Wiki/themes), support for user themes +* [Evernote](https://triliumnext.github.io/Docs/Wiki/evernote-import) and [Markdown import & export](https://triliumnext.github.io/Docs/Wiki/markdown) +* [Web Clipper](https://triliumnext.github.io/Docs/Wiki/web-clipper) for easy saving of web content +* Customizable UI (sidebar buttons, user-defined widgets, ...) + +✨ Check out the following third-party resources/communities for more TriliumNext related goodies: + +- [awesome-trilium](https://github.com/Nriver/awesome-trilium) for 3rd party themes, scripts, plugins and more. +- [TriliumRocks!](https://trilium.rocks/) for tutorials, guides, and much more. + ## ⚠️ Why TriliumNext? -[The original Trilium project is in maintenance mode](https://github.com/zadam/trilium/issues/4620) +[The original Trilium project is in maintenance mode](https://github.com/zadam/trilium/issues/4620). ### Migrating from Trilium? @@ -20,7 +52,7 @@ There are no special migration steps to migrate from a zadam/Trilium instance to Versions up to and including [v0.90.4](https://github.com/TriliumNext/Notes/releases/tag/v0.90.4) are compatible with the latest zadam/trilium version of [v0.63.7](https://github.com/zadam/trilium/releases/tag/v0.63.7). Any later versions of TriliumNext have their sync versions incremented. -## Documentation +## 📖 Documentation We're currently in the progress of moving the documentation to in-app (hit the `F1` key within Trilium). As a result, there may be some missing parts until we've completed the migration. If you'd prefer to navigate through the documentation within GitHub, you can navigate the [User Guide](./docs/User%20Guide/User%20Guide/) documentation. @@ -29,55 +61,40 @@ Below are some quick links for your convenience to navigate the documentation: - [Docker installation](./docs/User%20Guide/User%20Guide/Installation%20&%20Setup/Server%20Installation/1.%20Installing%20the%20server/Using%20Docker.md) - [Upgrading TriliumNext](./docs/User%20Guide/User%20Guide/Installation%20%26%20Setup/Upgrading%20TriliumNext.md) - [Concepts and Features - Note](./docs/User%20Guide/User%20Guide/Basic%20Concepts%20and%20Features/Notes.md) +- [Patterns of personal knowledge base](https://triliumnext.github.io/Docs/Wiki/patterns-of-personal-knowledge) +Until we finish reorganizing the documentation, you may also want to [browse the old documentation](https://triliumnext.github.io/Docs). ## 💬 Discuss with us Feel free to join our official conversations. We would love to hear what features, suggestions, or issues you may have! -- [Matrix](https://matrix.to/#/#triliumnext:matrix.org) (For synchronous discussions) +- [Matrix](https://matrix.to/#/#triliumnext:matrix.org) (For synchronous discussions.) - The `General` Matrix room is also bridged to [XMPP](xmpp:discuss@trilium.thisgreat.party?join) -- [Github Discussions](https://github.com/TriliumNext/Notes/discussions) (For Asynchronous discussions) -- [Wiki](https://triliumnext.github.io/Docs/) (For common how-to questions and user guides) - -## 🎁 Features - -* Notes can be arranged into arbitrarily deep tree. Single note can be placed into multiple places in the tree (see [cloning](https://triliumnext.github.io/Docs/Wiki/cloning-notes)) -* Rich WYSIWYG note editing including e.g. tables, images and [math](https://triliumnext.github.io/Docs/Wiki/text-notes) with markdown [autoformat](https://triliumnext.github.io/Docs/Wiki/text-notes#autoformat) -* Support for editing [notes with source code](https://triliumnext.github.io/Docs/Wiki/code-notes), including syntax highlighting -* Fast and easy [navigation between notes](https://triliumnext.github.io/Docs/Wiki/note-navigation), full text search and [note hoisting](https://triliumnext.github.io/Docs/Wiki/note-hoisting) -* Seamless [note versioning](https://triliumnext.github.io/Docs/Wiki/note-revisions) -* Note [attributes](https://triliumnext.github.io/Docs/Wiki/attributes) can be used for note organization, querying and advanced [scripting](https://triliumnext.github.io/Docs/Wiki/scripts) -* Direct OpenID and TOTP integration for more secure login -* [Synchronization](https://triliumnext.github.io/Docs/Wiki/synchronization) with self-hosted sync server - * there's a [3rd party service for hosting synchronisation server](https://trilium.cc/paid-hosting) -* [Sharing](https://triliumnext.github.io/Docs/Wiki/sharing) (publishing) notes to public internet -* Strong [note encryption](https://triliumnext.github.io/Docs/Wiki/protected-notes) with per-note granularity -* Sketching diagrams with built-in Excalidraw (note type "canvas") -* [Relation maps](https://triliumnext.github.io/Docs/Wiki/relation-map) and [link maps](https://triliumnext.github.io/Docs/Wiki/link-map) for visualizing notes and their relations -* [Scripting](https://triliumnext.github.io/Docs/Wiki/scripts) - see [Advanced showcases](https://triliumnext.github.io/Docs/Wiki/advanced-showcases) -* [REST API](https://triliumnext.github.io/Docs/Wiki/etapi) for automation -* Scales well in both usability and performance upwards of 100 000 notes -* Touch optimized [mobile frontend](https://triliumnext.github.io/Docs/Wiki/mobile-frontend) for smartphones and tablets -* [Night theme](https://triliumnext.github.io/Docs/Wiki/themes) -* [Evernote](https://triliumnext.github.io/Docs/Wiki/evernote-import) and [Markdown import & export](https://triliumnext.github.io/Docs/Wiki/markdown) -* [Web Clipper](https://triliumnext.github.io/Docs/Wiki/web-clipper) for easy saving of web content - -✨ Check out the following third-party resources/communities for more TriliumNext related goodies: - -- [awesome-trilium](https://github.com/Nriver/awesome-trilium) for 3rd party themes, scripts, plugins and more. -- [TriliumRocks!](https://trilium.rocks/) for tutorials, guides, and much more. +- [Github Discussions](https://github.com/TriliumNext/Notes/discussions) (For asynchronous discussions.) +- [Github Issues](https://github.com/TriliumNext/Notes/issues) (For bug reports and feature requests.) ## 🏗 Installation -### Desktop +### Windows / MacOS -To use TriliumNext on your desktop machine (Linux, MacOS, and Windows) you have a few options: +Download the binary release for your platform from the [latest release page](https://github.com/TriliumNext/Notes/releases/latest), unzip the package and run the `trilium` executable. -* Download the binary release for your platform from the [latest release page](https://github.com/TriliumNext/Notes/releases/latest), unzip the package and run the `trilium` executable. -* Access TriliumNext via the web interface of a server installation (see below) - * Currently only the latest versions of Chrome & Firefox are supported (and tested). -* TriliumNext is also provided as a Flatpak, but not yet published on FlatHub. +### Linux + +If your distribution is listed in the table below, use your distribution's package. + +[![Packaging status](https://repology.org/badge/vertical-allrepos/trilium-next-desktop.svg)](https://repology.org/project/trilium-next-desktop/versions) + +You may also download the binary release for your platform from the [latest release page](https://github.com/TriliumNext/Notes/releases/latest), unzip the package and run the `trilium` executable. + +TriliumNext is also provided as a Flatpak, but not yet published on FlatHub. + +### Browser (any OS) + +If you use a server installation (see below), you can directly access the web interface (which is almost identical to the desktop app). + +Currently only the latest versions of Chrome & Firefox are supported (and tested). ### Mobile @@ -91,11 +108,6 @@ See issue https://github.com/TriliumNext/Notes/issues/72 for more information on To install TriliumNext on your own server (including via Docker from [Dockerhub](https://hub.docker.com/r/triliumnext/notes)) follow [the server installation docs](https://triliumnext.github.io/Docs/Wiki/server-installation). -## 📝 Documentation - -[See wiki for complete list of documentation pages.](https://triliumnext.github.io/Docs) - -You can also read [Patterns of personal knowledge base](https://triliumnext.github.io/Docs/Wiki/patterns-of-personal-knowledge) to get some inspiration on how you might use TriliumNext. ## 💻 Contribute @@ -150,4 +162,6 @@ Support for the TriliumNext organization will be possible in the near future. Fo ## 🔑 License +Copyright 2017-2025 zadam, Elian Doran, and other contributors + This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. diff --git a/_regroup/package.json b/_regroup/package.json index e861ae79c..3420f8a0c 100644 --- a/_regroup/package.json +++ b/_regroup/package.json @@ -40,7 +40,7 @@ "@types/express": "5.0.1", "@types/node": "22.15.19", "@types/yargs": "17.0.33", - "@vitest/coverage-v8": "3.1.3", + "@vitest/coverage-v8": "3.1.4", "eslint": "9.27.0", "eslint-plugin-simple-import-sort": "12.1.1", "esm": "3.2.25", diff --git a/apps/client/package.json b/apps/client/package.json index 1fea6052a..18e28608e 100644 --- a/apps/client/package.json +++ b/apps/client/package.json @@ -33,7 +33,7 @@ "draggabilly": "3.0.0", "force-graph": "1.49.6", "globals": "16.1.0", - "i18next": "25.1.3", + "i18next": "25.2.0", "i18next-http-backend": "3.0.2", "jquery": "3.7.1", "jquery-hotkeys": "0.2.2", @@ -44,7 +44,7 @@ "leaflet": "1.9.4", "leaflet-gpx": "2.2.0", "mark.js": "8.11.1", - "marked": "15.0.11", + "marked": "15.0.12", "mermaid": "11.6.0", "mind-elixir": "4.5.2", "normalize.css": "8.0.1", @@ -59,7 +59,7 @@ "@ckeditor/ckeditor5-inspector": "4.1.0", "@types/bootstrap": "5.2.10", "@types/jquery": "3.5.32", - "@types/leaflet": "1.9.17", + "@types/leaflet": "1.9.18", "@types/leaflet-gpx": "1.3.7", "@types/mark.js": "8.11.12", "@types/react": "19.1.4", diff --git a/apps/client/src/components/app_context.ts b/apps/client/src/components/app_context.ts index 1855876d3..b64678011 100644 --- a/apps/client/src/components/app_context.ts +++ b/apps/client/src/components/app_context.ts @@ -283,6 +283,9 @@ export type CommandMappings = { type EventMappings = { initialRenderComplete: {}; frocaReloaded: {}; + setLeftPaneVisibility: { + leftPaneVisible: boolean | null; + } protectedSessionStarted: {}; notesReloaded: { noteIds: string[]; diff --git a/apps/client/src/components/root_command_executor.ts b/apps/client/src/components/root_command_executor.ts index 1e16fae81..8e7df9494 100644 --- a/apps/client/src/components/root_command_executor.ts +++ b/apps/client/src/components/root_command_executor.ts @@ -78,15 +78,15 @@ export default class RootCommandExecutor extends Component { } hideLeftPaneCommand() { - options.save(`leftPaneVisible`, "false"); + appContext.triggerEvent("setLeftPaneVisibility", { leftPaneVisible: false }); } showLeftPaneCommand() { - options.save(`leftPaneVisible`, "true"); + appContext.triggerEvent("setLeftPaneVisibility", { leftPaneVisible: true }); } toggleLeftPaneCommand() { - options.toggle("leftPaneVisible"); + appContext.triggerEvent("setLeftPaneVisibility", { leftPaneVisible: null }); } async showBackendLogCommand() { diff --git a/apps/client/src/services/resizer.ts b/apps/client/src/services/resizer.ts index 1cce0f993..e0dc40995 100644 --- a/apps/client/src/services/resizer.ts +++ b/apps/client/src/services/resizer.ts @@ -3,7 +3,11 @@ import Split from "split.js" export const DEFAULT_GUTTER_SIZE = 5; +let leftPaneWidth: number; +let reservedPx: number; +let layoutOrientation: string; let leftInstance: ReturnType | null; +let rightPaneWidth: number; let rightInstance: ReturnType | null; function setupLeftPaneResizer(leftPaneVisible: boolean) { @@ -14,27 +18,34 @@ function setupLeftPaneResizer(leftPaneVisible: boolean) { $("#left-pane").toggle(leftPaneVisible); + layoutOrientation = layoutOrientation ?? options.get("layoutOrientation"); + reservedPx = reservedPx ?? (layoutOrientation === "vertical" ? ($("#launcher-pane").outerWidth() || 0) : 0); + // Window resizing causes `window.innerWidth` to change, so `reservedWidth` needs to be recalculated each time. + const reservedWidth = reservedPx / window.innerWidth * 100; if (!leftPaneVisible) { - $("#rest-pane").css("width", "100%"); - + $("#rest-pane").css("width", layoutOrientation === "vertical" ? `${100 - reservedWidth}%` : "100%"); return; } - let leftPaneWidth = options.getInt("leftPaneWidth"); + leftPaneWidth = leftPaneWidth ?? (options.getInt("leftPaneWidth") ?? 0); if (!leftPaneWidth || leftPaneWidth < 5) { leftPaneWidth = 5; } + const restPaneWidth = 100 - leftPaneWidth - reservedWidth; if (leftPaneVisible) { // Delayed initialization ensures that all DOM elements are fully rendered and part of the layout, // preventing Split.js from retrieving incorrect dimensions due to #left-pane not being rendered yet, // which would cause the minSize setting to have no effect. requestAnimationFrame(() => { leftInstance = Split(["#left-pane", "#rest-pane"], { - sizes: [leftPaneWidth, 100 - leftPaneWidth], + sizes: [leftPaneWidth, restPaneWidth], gutterSize: DEFAULT_GUTTER_SIZE, minSize: [150, 300], - onDragEnd: (sizes) => options.save("leftPaneWidth", Math.round(sizes[0])) + onDragEnd: (sizes) => { + leftPaneWidth = Math.round(sizes[0]); + options.save("leftPaneWidth", Math.round(sizes[0])); + } }); }); } @@ -54,7 +65,7 @@ function setupRightPaneResizer() { return; } - let rightPaneWidth = options.getInt("rightPaneWidth"); + rightPaneWidth = rightPaneWidth ?? (options.getInt("rightPaneWidth") ?? 0); if (!rightPaneWidth || rightPaneWidth < 5) { rightPaneWidth = 5; } @@ -63,8 +74,11 @@ function setupRightPaneResizer() { rightInstance = Split(["#center-pane", "#right-pane"], { sizes: [100 - rightPaneWidth, rightPaneWidth], gutterSize: DEFAULT_GUTTER_SIZE, - minSize: [ 300, 180 ], - onDragEnd: (sizes) => options.save("rightPaneWidth", Math.round(sizes[1])) + minSize: [300, 180], + onDragEnd: (sizes) => { + rightPaneWidth = Math.round(sizes[1]); + options.save("rightPaneWidth", Math.round(sizes[1])); + } }); } } diff --git a/apps/client/src/stylesheets/theme-next/shell.css b/apps/client/src/stylesheets/theme-next/shell.css index 2bcdf942f..a77715136 100644 --- a/apps/client/src/stylesheets/theme-next/shell.css +++ b/apps/client/src/stylesheets/theme-next/shell.css @@ -127,6 +127,7 @@ body.layout-horizontal > .horizontal { --launcher-pane-button-gap: var(--launcher-pane-vert-button-gap); width: var(--launcher-pane-size) !important; + min-width: var(--launcher-pane-size) !important; padding-bottom: var(--launcher-pane-button-gap); } diff --git a/apps/client/src/widgets/buttons/global_menu.ts b/apps/client/src/widgets/buttons/global_menu.ts index d21e43b0d..47323e271 100644 --- a/apps/client/src/widgets/buttons/global_menu.ts +++ b/apps/client/src/widgets/buttons/global_menu.ts @@ -53,10 +53,6 @@ const TPL = /*html*/` pointer-events: none; } - .update-to-latest-version-button { - display: none; - } - .global-menu .zoom-container { display: flex; flex-direction: row; @@ -235,7 +231,7 @@ const TPL = /*html*/` ${t("global_menu.about")} -