Merge remote-tracking branch 'origin/develop' into client_vite

This commit is contained in:
Elian Doran 2025-05-20 11:02:01 +03:00
commit 57108d4dfd
No known key found for this signature in database
14 changed files with 288 additions and 550 deletions

104
README.md
View File

@ -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:
<a href="https://triliumnext.github.io/Docs/Wiki/screenshot-tour"><img src="./docs/app.png" alt="Trilium Screenshot" width="1000"></a>
## 🎁 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.

View File

@ -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",

View File

@ -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",

View File

@ -283,6 +283,9 @@ export type CommandMappings = {
type EventMappings = {
initialRenderComplete: {};
frocaReloaded: {};
setLeftPaneVisibility: {
leftPaneVisible: boolean | null;
}
protectedSessionStarted: {};
notesReloaded: {
noteIds: string[];

View File

@ -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() {

View File

@ -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<typeof Split> | null;
let rightPaneWidth: number;
let rightInstance: ReturnType<typeof Split> | 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]));
}
});
}
}

View File

@ -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);
}

View File

@ -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")}
</li>
<li class="dropdown-item update-to-latest-version-button" data-trigger-command="downloadLatestVersion">
<li class="dropdown-item update-to-latest-version-button" style="display: none;" data-trigger-command="downloadLatestVersion">
<span class="bx bx-sync"></span>
<span class="version-text"></span>

View File

@ -19,10 +19,10 @@ export default class LeftPaneToggleWidget extends CommandButtonWidget {
return "bx-sidebar";
}
return options.is("leftPaneVisible") ? "bx-chevrons-left" : "bx-chevrons-right";
return this.currentLeftPaneVisible ? "bx-chevrons-left" : "bx-chevrons-right";
};
this.settings.title = () => (options.is("leftPaneVisible") ? t("left_pane_toggle.hide_panel") : t("left_pane_toggle.show_panel"));
this.settings.title = () => (this.currentLeftPaneVisible ? t("left_pane_toggle.hide_panel") : t("left_pane_toggle.show_panel"));
this.settings.command = () => (this.currentLeftPaneVisible ? "hideLeftPane" : "showLeftPane");
@ -32,16 +32,12 @@ export default class LeftPaneToggleWidget extends CommandButtonWidget {
}
refreshIcon() {
if (document.hasFocus() || this.currentLeftPaneVisible === true) {
super.refreshIcon();
splitService.setupLeftPaneResizer(this.currentLeftPaneVisible);
}
super.refreshIcon();
splitService.setupLeftPaneResizer(this.currentLeftPaneVisible);
}
entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) {
if (loadResults.isOptionReloaded("leftPaneVisible") && document.hasFocus()) {
this.currentLeftPaneVisible = options.is("leftPaneVisible");
this.refreshIcon();
}
setLeftPaneVisibilityEvent({ leftPaneVisible }: EventData<"setLeftPaneVisibility">) {
this.currentLeftPaneVisible = leftPaneVisible ?? !this.currentLeftPaneVisible;
this.refreshIcon();
}
}

View File

@ -4,28 +4,33 @@ import appContext, { type EventData } from "../../components/app_context.js";
import type Component from "../../components/component.js";
export default class LeftPaneContainer extends FlexContainer<Component> {
private currentLeftPaneVisible: boolean;
constructor() {
super("column");
this.currentLeftPaneVisible = options.is("leftPaneVisible");
this.id("left-pane");
this.css("height", "100%");
this.collapsible();
}
isEnabled() {
return super.isEnabled() && options.is("leftPaneVisible");
return super.isEnabled() && this.currentLeftPaneVisible;
}
entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) {
if (loadResults.isOptionReloaded("leftPaneVisible") && document.hasFocus()) {
const visible = this.isEnabled();
this.toggleInt(visible);
setLeftPaneVisibilityEvent({ leftPaneVisible }: EventData<"setLeftPaneVisibility">) {
this.currentLeftPaneVisible = leftPaneVisible ?? !this.currentLeftPaneVisible;
const visible = this.isEnabled();
this.toggleInt(visible);
if (visible) {
this.triggerEvent("focusTree", {});
} else {
this.triggerEvent("focusOnDetail", { ntxId: appContext.tabManager.getActiveContext()?.ntxId });
}
if (visible) {
this.triggerEvent("focusTree", {});
} else {
this.triggerEvent("focusOnDetail", { ntxId: appContext.tabManager.getActiveContext()?.ntxId });
}
options.save("leftPaneVisible", this.currentLeftPaneVisible.toString());
}
}

View File

@ -67,8 +67,5 @@
}
}
}
},
"devDependencies": {
"@types/diff": "^7.0.2"
}
}

View File

@ -74,7 +74,7 @@
"html2plaintext": "2.1.4",
"http-proxy-agent": "7.0.2",
"https-proxy-agent": "7.0.6",
"i18next": "25.1.3",
"i18next": "25.2.0",
"i18next-fs-backend": "2.6.0",
"image-type": "5.2.0",
"ini": "5.0.0",
@ -83,9 +83,9 @@
"jimp": "1.6.0",
"js-yaml": "4.1.0",
"jsdom": "26.1.0",
"marked": "15.0.11",
"marked": "15.0.12",
"mime-types": "3.0.1",
"multer": "1.4.5-lts.2",
"multer": "2.0.0",
"normalize-strings": "1.1.1",
"ollama": "0.5.15",
"openai": "4.100.0",

View File

@ -21,6 +21,7 @@
* [Inconsistent Find and Replace Behavior in Large Code Notes](https://github.com/TriliumNext/Notes/issues/1826) by @SiriusXT
* [Incorrect import of multiple inline math](https://github.com/TriliumNext/Notes/pull/1906) by @SiriusXT
* [Random EPERM: operation not permitted on Windows](https://github.com/TriliumNext/Notes/issues/249)
* [The update button is sometimes blank](https://github.com/TriliumNext/Notes/pull/1975) by @SiriusXT
## ✨ Improvements
@ -64,6 +65,7 @@
* Documented the new text note features: bookmarks and emojis.
* Add documentation links and updated pnpm commands to README by @perfectra1n
* Add documentation around setting the various environment variables to control upload size limit by @perfectra1n
* README improvements by @FliegendeWurst
## 🌍 Internationalization

624
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff