diff --git a/.dprint.json b/.dprint.json
deleted file mode 100644
index 21e6f8585d..0000000000
--- a/.dprint.json
+++ /dev/null
@@ -1,44 +0,0 @@
-{
- "typescript": {
- "indentWidth": 4,
- "quoteStyle": "preferDouble",
- "semiColons": "prefer",
- "quoteProps": "asNeeded",
- "newLineKind": "lf",
- "lineWidth": 200,
- "trailingCommas": "never",
- "arrayPattern.spaceAround": true,
- "arrayExpression.spaceAround": true
- },
- "json": {
- },
- "markdown": {
- },
- "dockerfile": {
- },
- "malva": {
- },
- "markup": {
- },
- "yaml": {
- },
- "excludes": [
- "**/node_modules",
- "**/*-lock.json",
- "*.html",
- "*.md",
- "*.yml",
- "libraries/*",
- "docs/*",
- "src/public/app/doc_notes"
- ],
- "plugins": [
- "https://plugins.dprint.dev/typescript-0.94.0.wasm",
- "https://plugins.dprint.dev/json-0.20.0.wasm",
- "https://plugins.dprint.dev/markdown-0.18.0.wasm",
- "https://plugins.dprint.dev/dockerfile-0.3.2.wasm",
- "https://plugins.dprint.dev/g-plane/malva-v0.11.1.wasm",
- "https://plugins.dprint.dev/g-plane/markup_fmt-v0.19.0.wasm",
- "https://plugins.dprint.dev/g-plane/pretty_yaml-v0.5.0.wasm"
- ]
-}
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
index cd49e608f7..17970ebe81 100644
--- a/.vscode/extensions.json
+++ b/.vscode/extensions.json
@@ -4,6 +4,7 @@
"editorconfig.editorconfig",
"vitest.explorer",
"ms-playwright.playwright",
- "tobermory.es6-string-html"
+ "tobermory.es6-string-html",
+ "dbaeumer.vscode-eslint"
]
}
diff --git a/docs/User Guide/!!!meta.json b/docs/User Guide/!!!meta.json
index a2c35b3c59..0e2651b7c9 100644
--- a/docs/User Guide/!!!meta.json
+++ b/docs/User Guide/!!!meta.json
@@ -1,6 +1,6 @@
{
"formatVersion": 2,
- "appVersion": "0.92.4",
+ "appVersion": "0.92.5-beta",
"files": [
{
"isClone": false,
@@ -1433,28 +1433,28 @@
{
"type": "relation",
"name": "internalLink",
- "value": "BlN9DFI679QC",
+ "value": "vZWERwf8U3nx",
"isInheritable": false,
"position": 10
},
{
"type": "relation",
"name": "internalLink",
- "value": "vZWERwf8U3nx",
+ "value": "4FahAwuGTAwC",
"isInheritable": false,
"position": 20
},
{
"type": "relation",
"name": "internalLink",
- "value": "4FahAwuGTAwC",
+ "value": "0vhv7lsOLy82",
"isInheritable": false,
"position": 30
},
{
"type": "relation",
"name": "internalLink",
- "value": "0vhv7lsOLy82",
+ "value": "BlN9DFI679QC",
"isInheritable": false,
"position": 40
},
@@ -3058,6 +3058,20 @@
"isInheritable": false,
"position": 50
},
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "QxEyIjRBizuC",
+ "isInheritable": false,
+ "position": 60
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "UYuUB1ZekNQU",
+ "isInheritable": false,
+ "position": 70
+ },
{
"type": "label",
"name": "shareAlias",
@@ -3085,20 +3099,6 @@
"value": "",
"isInheritable": false,
"position": 40
- },
- {
- "type": "relation",
- "name": "internalLink",
- "value": "UYuUB1ZekNQU",
- "isInheritable": false,
- "position": 60
- },
- {
- "type": "relation",
- "name": "internalLink",
- "value": "QxEyIjRBizuC",
- "isInheritable": false,
- "position": 70
}
],
"format": "markdown",
@@ -3231,14 +3231,14 @@
{
"type": "relation",
"name": "internalLink",
- "value": "QxEyIjRBizuC",
+ "value": "6f9hih2hXXZk",
"isInheritable": false,
"position": 20
},
{
"type": "relation",
"name": "internalLink",
- "value": "6f9hih2hXXZk",
+ "value": "QxEyIjRBizuC",
"isInheritable": false,
"position": 30
},
@@ -3324,44 +3324,44 @@
{
"type": "relation",
"name": "internalLink",
- "value": "6f9hih2hXXZk",
+ "value": "QxEyIjRBizuC",
"isInheritable": false,
"position": 10
},
{
"type": "relation",
"name": "internalLink",
- "value": "4TIF1oA4VQRO",
+ "value": "6f9hih2hXXZk",
"isInheritable": false,
"position": 20
},
{
"type": "relation",
"name": "internalLink",
- "value": "nRhnJkTT8cPs",
+ "value": "4TIF1oA4VQRO",
"isInheritable": false,
"position": 30
},
{
"type": "relation",
"name": "internalLink",
- "value": "s8alTXmpFR61",
+ "value": "nRhnJkTT8cPs",
"isInheritable": false,
"position": 40
},
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "s8alTXmpFR61",
+ "isInheritable": false,
+ "position": 50
+ },
{
"type": "label",
"name": "iconClass",
"value": "bx bx-code",
"isInheritable": false,
"position": 50
- },
- {
- "type": "relation",
- "name": "internalLink",
- "value": "QxEyIjRBizuC",
- "isInheritable": false,
- "position": 60
}
],
"format": "markdown",
@@ -4091,48 +4091,62 @@
"type": "text",
"mime": "text/markdown",
"attributes": [
- {
- "type": "relation",
- "name": "internalLink",
- "value": "zEY4DaJG4YT5",
- "isInheritable": false,
- "position": 10
- },
- {
- "type": "relation",
- "name": "internalLink",
- "value": "OFXdgB2nNk1F",
- "isInheritable": false,
- "position": 20
- },
- {
- "type": "relation",
- "name": "internalLink",
- "value": "wX4HbRucYSDD",
- "isInheritable": false,
- "position": 30
- },
{
"type": "relation",
"name": "imageLink",
"value": "EH6qNioOHeyT",
"isInheritable": false,
- "position": 50
+ "position": 10
},
{
"type": "relation",
"name": "imageLink",
"value": "xeZPrfi77XPu",
"isInheritable": false,
- "position": 60
+ "position": 20
},
{
"type": "relation",
"name": "imageLink",
"value": "N98UhifxrVpZ",
"isInheritable": false,
+ "position": 30
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "BFs8mudNFgCS",
+ "isInheritable": false,
+ "position": 40
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "zEY4DaJG4YT5",
+ "isInheritable": false,
+ "position": 50
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "OFXdgB2nNk1F",
+ "isInheritable": false,
+ "position": 60
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "wX4HbRucYSDD",
+ "isInheritable": false,
"position": 70
},
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "BCkXAVs63Ttv",
+ "isInheritable": false,
+ "position": 80
+ },
{
"type": "label",
"name": "shareAlias",
@@ -4146,20 +4160,6 @@
"value": "bx bxs-network-chart",
"isInheritable": false,
"position": 20
- },
- {
- "type": "relation",
- "name": "internalLink",
- "value": "BFs8mudNFgCS",
- "isInheritable": false,
- "position": 80
- },
- {
- "type": "relation",
- "name": "internalLink",
- "value": "BCkXAVs63Ttv",
- "isInheritable": false,
- "position": 90
}
],
"format": "markdown",
@@ -4190,19 +4190,19 @@
"type": "text",
"mime": "text/html",
"attributes": [
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "BCkXAVs63Ttv",
+ "isInheritable": false,
+ "position": 10
+ },
{
"type": "label",
"name": "iconClass",
"value": "bx bxs-network-chart",
"isInheritable": false,
"position": 10
- },
- {
- "type": "relation",
- "name": "internalLink",
- "value": "BCkXAVs63Ttv",
- "isInheritable": false,
- "position": 20
}
],
"format": "markdown",
@@ -5916,23 +5916,23 @@
{
"type": "relation",
"name": "internalLink",
- "value": "iRwzGnHPzonm",
+ "value": "bdUJEHsAPYQR",
"isInheritable": false,
"position": 20
},
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "iRwzGnHPzonm",
+ "isInheritable": false,
+ "position": 30
+ },
{
"type": "label",
"name": "shareAlias",
"value": "note-map",
"isInheritable": false,
"position": 30
- },
- {
- "type": "relation",
- "name": "internalLink",
- "value": "bdUJEHsAPYQR",
- "isInheritable": false,
- "position": 40
}
],
"format": "markdown",
@@ -6887,21 +6887,21 @@
{
"type": "relation",
"name": "internalLink",
- "value": "KSZ04uQ2D1St",
+ "value": "_optionsTextNotes",
"isInheritable": false,
"position": 10
},
{
"type": "relation",
"name": "internalLink",
- "value": "_optionsTextNotes",
+ "value": "_optionsCodeNotes",
"isInheritable": false,
"position": 20
},
{
"type": "relation",
"name": "internalLink",
- "value": "_optionsCodeNotes",
+ "value": "KSZ04uQ2D1St",
"isInheritable": false,
"position": 30
},
@@ -6929,21 +6929,21 @@
{
"type": "relation",
"name": "internalLink",
- "value": "gBbsAeiuUxI5",
+ "value": "H0mM1lTxF9JI",
"isInheritable": false,
"position": 70
},
{
"type": "relation",
"name": "internalLink",
- "value": "N4IDkixaDG9C",
+ "value": "gBbsAeiuUxI5",
"isInheritable": false,
"position": 80
},
{
"type": "relation",
"name": "internalLink",
- "value": "H0mM1lTxF9JI",
+ "value": "N4IDkixaDG9C",
"isInheritable": false,
"position": 90
},
diff --git a/docs/User Guide/User Guide/Advanced Usage/ETAPI (REST API).md b/docs/User Guide/User Guide/Advanced Usage/ETAPI (REST API).md
index a5836d2e34..b9c4db4f3b 100644
--- a/docs/User Guide/User Guide/Advanced Usage/ETAPI (REST API).md
+++ b/docs/User Guide/User Guide/Advanced Usage/ETAPI (REST API).md
@@ -35,7 +35,7 @@ Basic Auth is meant to be used with tools which support only basic auth.
It is possible to write simple Bash scripts to interact with Trilium. As an example, here's how to obtain the HTML content of a note:
-```sh
+```
#!/usr/bin/env bash
# Configuration
diff --git a/docs/User Guide/User Guide/Advanced Usage/Note Map (Link map, Tree map).md b/docs/User Guide/User Guide/Advanced Usage/Note Map (Link map, Tree map).md
index 67ad6dcf28..37838fd136 100644
--- a/docs/User Guide/User Guide/Advanced Usage/Note Map (Link map, Tree map).md
+++ b/docs/User Guide/User Guide/Advanced Usage/Note Map (Link map, Tree map).md
@@ -1,4 +1,4 @@
-# Note Map (Link map, Tree map)
+# Note Map (Link map, Tree map)
Note map is a visualisation of connections between notes.
This provides an insight into a structure ("web") of notes.
diff --git a/docs/User Guide/User Guide/Advanced Usage/Note source.md b/docs/User Guide/User Guide/Advanced Usage/Note source.md
index 7b0402fda1..7f808d4303 100644
--- a/docs/User Guide/User Guide/Advanced Usage/Note source.md
+++ b/docs/User Guide/User Guide/Advanced Usage/Note source.md
@@ -1,4 +1,4 @@
-# Note source
+# Note source
## Understanding the source code of the different notes
Internally, the structure of the content of each note is different based on the [Note Types](../Note%20Types).
@@ -15,7 +15,7 @@ Note that some information is also stored as [Attachments](../Attachments). For
Here's part of the HTML representation of this note, as it's stored in the database (but prettified).
-```html
+```
Understanding the source code of the different notes
diff --git a/docs/User Guide/User Guide/Advanced Usage/Technologies used.md b/docs/User Guide/User Guide/Advanced Usage/Technologies used.md
index 442b589a7c..a2ad1c8148 100644
--- a/docs/User Guide/User Guide/Advanced Usage/Technologies used.md
+++ b/docs/User Guide/User Guide/Advanced Usage/Technologies used.md
@@ -1,4 +1,4 @@
-# Technologies used
+# Technologies used
One core aspect of Trilium that allows it to have support for multiple [Note Types](../Note%20Types) is the fact that it makes use of various off-the-shelf or reusable libraries.
The sub-pages showcase some of the technologies used, for a better understanding of how Trilium works but also to credit the developers of that particular technology.
\ No newline at end of file
diff --git a/docs/User Guide/User Guide/Advanced Usage/Technologies used/CKEditor.md b/docs/User Guide/User Guide/Advanced Usage/Technologies used/CKEditor.md
index 8ade8060c5..f7738d104b 100644
--- a/docs/User Guide/User Guide/Advanced Usage/Technologies used/CKEditor.md
+++ b/docs/User Guide/User Guide/Advanced Usage/Technologies used/CKEditor.md
@@ -1,4 +1,4 @@
-# CKEditor
+# CKEditor
## Editor core
The CKEditor is the WYSIWYG (standing for What You See Is What You Get) editor behind [Text](../../Note%20Types/Text.md) notes.
@@ -21,7 +21,7 @@ Trilium makes use of such features:
* The math feature is added by a version of [isaul32/ckeditor5-math: Math feature for CKEditor 5.](https://github.com/isaul32/ckeditor5-math) modified by us to fit our needs.
* We also make use of modified upstream plugins such as [ckeditor/ckeditor5-mermaid](https://github.com/ckeditor/ckeditor5-mermaid) to allow inline Mermaid code.
-* [mlewand/ckeditor5-keyboard-marker: Plugin adds support for the keyboard input element () to CKEditor 5.](https://github.com/mlewand/ckeditor5-keyboard-marker)
+* [mlewand/ckeditor5-keyboard-marker: Plugin adds support for the keyboard input element (``) to CKEditor 5.](https://github.com/mlewand/ckeditor5-keyboard-marker)
* A modified version of [ThomasAitken/ckeditor5-footnotes: Footnotes plugin for CKEditor5](https://github.com/ThomasAitken/ckeditor5-footnotes) to allow footnotes.
Apart from that, Trilium also has its own set of specific plugins such as:
diff --git a/docs/User Guide/User Guide/Advanced Usage/Technologies used/Excalidraw.md b/docs/User Guide/User Guide/Advanced Usage/Technologies used/Excalidraw.md
index ab0bb1e397..fa7c9bf949 100644
--- a/docs/User Guide/User Guide/Advanced Usage/Technologies used/Excalidraw.md
+++ b/docs/User Guide/User Guide/Advanced Usage/Technologies used/Excalidraw.md
@@ -1,4 +1,4 @@
-# Excalidraw
+# Excalidraw
[Excalidraw](https://excalidraw.com/) is the technology behind the [Canvas](../../Note%20Types/Canvas.md) notes. The source code of the library is available on [GitHub](https://github.com/excalidraw/excalidraw).
We are using an unmodified version of it, so it shares the same [issues](https://github.com/excalidraw/excalidraw/issues) as the original.
\ No newline at end of file
diff --git a/docs/User Guide/User Guide/Advanced Usage/Technologies used/Leaflet.md b/docs/User Guide/User Guide/Advanced Usage/Technologies used/Leaflet.md
index 181bcd9d55..02f245f006 100644
--- a/docs/User Guide/User Guide/Advanced Usage/Technologies used/Leaflet.md
+++ b/docs/User Guide/User Guide/Advanced Usage/Technologies used/Leaflet.md
@@ -1,4 +1,4 @@
-# Leaflet
+# Leaflet
Leaflet is the library behind [Geo map](../../Note%20Types/Geo%20map.md) notes.
## Plugins
diff --git a/docs/User Guide/User Guide/Advanced Usage/Technologies used/MindElixir.md b/docs/User Guide/User Guide/Advanced Usage/Technologies used/MindElixir.md
index a969d480a4..0280cfca50 100644
--- a/docs/User Guide/User Guide/Advanced Usage/Technologies used/MindElixir.md
+++ b/docs/User Guide/User Guide/Advanced Usage/Technologies used/MindElixir.md
@@ -1,4 +1,4 @@
-# MindElixir
+# MindElixir
MindElixir is the library we are using for the [Mind Map](../../Note%20Types/Mind%20Map.md) note types.
The main library is available on [GitHub as mind-elixir-core](https://github.com/SSShooter/mind-elixir-core/issues).
diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Import & Export/Evernote.md b/docs/User Guide/User Guide/Basic Concepts and Features/Import & Export/Evernote.md
index bda28e61d3..3815c2477d 100644
--- a/docs/User Guide/User Guide/Basic Concepts and Features/Import & Export/Evernote.md
+++ b/docs/User Guide/User Guide/Basic Concepts and Features/Import & Export/Evernote.md
@@ -1,4 +1,4 @@
-# Evernote
+# Evernote
Trilium can import ENEX files which are used by Evernote for backup/export. One ENEX file represents content (notes and resources) of one notebook.
## Export ENEX from Evernote
diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown.md b/docs/User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown.md
index b3390a5a72..0a7a961421 100644
--- a/docs/User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown.md
+++ b/docs/User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown.md
@@ -1,4 +1,4 @@
-# Markdown
+# Markdown
Trilium Notes supports importing Markdown restricted to the [CommonMark specification](https://spec.commonmark.org/current/) (where [tables are not supported](https://github.com/TriliumNext/Notes/issues/2026))
## Import
diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Import & Export/OneNote.md b/docs/User Guide/User Guide/Basic Concepts and Features/Import & Export/OneNote.md
index 5c8d94aab8..0ccc24cdf3 100644
--- a/docs/User Guide/User Guide/Basic Concepts and Features/Import & Export/OneNote.md
+++ b/docs/User Guide/User Guide/Basic Concepts and Features/Import & Export/OneNote.md
@@ -1,4 +1,4 @@
-# OneNote
+# OneNote
**This page describes a method to migrate via EverNote Legacy, but this app is no longer available/working.**
## Prep Onenote notes for best compatibility
diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Keyboard Shortcuts.md b/docs/User Guide/User Guide/Basic Concepts and Features/Keyboard Shortcuts.md
index 67766fa8f3..76c26d6f4b 100644
--- a/docs/User Guide/User Guide/Basic Concepts and Features/Keyboard Shortcuts.md
+++ b/docs/User Guide/User Guide/Basic Concepts and Features/Keyboard Shortcuts.md
@@ -1,4 +1,4 @@
-# Keyboard Shortcuts
+# Keyboard Shortcuts
This is supposed to be a complete list of keyboard shortcuts. Note that some of these may work only in certain contexts (e.g. in tree pane or note editor).
It is also possible to configure most keyboard shortcuts in Options -> Keyboard shortcuts. Using `global:` prefix, you can assign a shortcut which will work even without Trilium being in focus (requires app restart to take effect).
diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Navigation/Bookmarks.md b/docs/User Guide/User Guide/Basic Concepts and Features/Navigation/Bookmarks.md
index 5e5481f1a2..659d031fce 100644
--- a/docs/User Guide/User Guide/Basic Concepts and Features/Navigation/Bookmarks.md
+++ b/docs/User Guide/User Guide/Basic Concepts and Features/Navigation/Bookmarks.md
@@ -1,4 +1,4 @@
-# Bookmarks
+# Bookmarks
To easily access selected notes, you can bookmark them. See demo:

diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Navigation/Note Hoisting.md b/docs/User Guide/User Guide/Basic Concepts and Features/Navigation/Note Hoisting.md
index 465483f721..40c7b1dbd0 100644
--- a/docs/User Guide/User Guide/Basic Concepts and Features/Navigation/Note Hoisting.md
+++ b/docs/User Guide/User Guide/Basic Concepts and Features/Navigation/Note Hoisting.md
@@ -1,4 +1,4 @@
-# Note Hoisting
+# Note Hoisting
Hoisting is a standard outliner feature which allows you to focus on (or "zoom into") a specific note and its subtree by hiding all parent and sibling notes. Demo:

diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Navigation/Note Navigation.md b/docs/User Guide/User Guide/Basic Concepts and Features/Navigation/Note Navigation.md
index 200e334eaf..aa04950662 100644
--- a/docs/User Guide/User Guide/Basic Concepts and Features/Navigation/Note Navigation.md
+++ b/docs/User Guide/User Guide/Basic Concepts and Features/Navigation/Note Navigation.md
@@ -1,4 +1,4 @@
-# Note Navigation
+# Note Navigation
One of the Trilium's goals is to provide fast and comfortable navigation between notes.
## Backwards and forward
diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Navigation/Search.md b/docs/User Guide/User Guide/Basic Concepts and Features/Navigation/Search.md
index 8c195571c6..945acdfe5d 100644
--- a/docs/User Guide/User Guide/Basic Concepts and Features/Navigation/Search.md
+++ b/docs/User Guide/User Guide/Basic Concepts and Features/Navigation/Search.md
@@ -1,4 +1,4 @@
-# Search
+# Search
## Local Search
Local search allows you to search within the currently displayed note. To initiate a local search, press Ctrl + F. If using a web browser, this will be handled by the browser's native search functionality. In the desktop (electron) version, a separate dialog will apear.
diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Navigation/Tree Concepts.md b/docs/User Guide/User Guide/Basic Concepts and Features/Navigation/Tree Concepts.md
index a021b65119..6303bb28f1 100644
--- a/docs/User Guide/User Guide/Basic Concepts and Features/Navigation/Tree Concepts.md
+++ b/docs/User Guide/User Guide/Basic Concepts and Features/Navigation/Tree Concepts.md
@@ -1,4 +1,4 @@
-# Tree Concepts
+# Tree Concepts
This page explains the basic concepts related to the tree structure of notes in TriliumNext.
## Note
diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Navigation/Workspace.md b/docs/User Guide/User Guide/Basic Concepts and Features/Navigation/Workspace.md
index dd0ff17e40..32c33349db 100644
--- a/docs/User Guide/User Guide/Basic Concepts and Features/Navigation/Workspace.md
+++ b/docs/User Guide/User Guide/Basic Concepts and Features/Navigation/Workspace.md
@@ -1,4 +1,4 @@
-# Workspace
+# Workspace
Workspace is a concept built up on top of [note hoisting](Note%20Hoisting.md). It is based on the idea that a user has several distinct spheres of interest. An example might be "Personal" and "Work", these two spheres are quite distinct and don't interact together. When I focus on Work, I don't really care about personal notes.
So far workspace consists of these features:
diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Notes.md b/docs/User Guide/User Guide/Basic Concepts and Features/Notes.md
index db61a206e8..99cc9dff35 100644
--- a/docs/User Guide/User Guide/Basic Concepts and Features/Notes.md
+++ b/docs/User Guide/User Guide/Basic Concepts and Features/Notes.md
@@ -1,4 +1,4 @@
-# Notes
+# Notes
Note is a central entity in Trilium. Main attributes of note are title and content.
### Note types
diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Archived Notes.md b/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Archived Notes.md
index 9190649d16..da64e051a3 100644
--- a/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Archived Notes.md
+++ b/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Archived Notes.md
@@ -1,4 +1,4 @@
-# Archived Notes
+# Archived Notes
Archived notes are notes which have `archived` [attribute](../../Advanced%20Usage/Attributes.md) - either directly or [inherited](../../Advanced%20Usage/Attributes/Attribute%20Inheritance.md).
Such notes are then by default not shown in the autocomplete and in the full text [search](../Navigation/Search.md).
diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Attachments.md b/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Attachments.md
index 5815baee8a..91076bef03 100644
--- a/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Attachments.md
+++ b/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Attachments.md
@@ -1,4 +1,4 @@
-# Attachments
+# Attachments
A [note](../Notes.md) in Trilium can _own_ one or more attachments, which can be either images or files. These attachments can be displayed or linked within the note that owns them.
This can be especially useful to include dependencies for your [scripts](../../Note%20Types/Code/Scripts.md). The [Weight Tracker](../../Advanced%20Usage/Advanced%20Showcases/Weight%20Tracker.md) shows how to use [chartjs](https://chartjs.org/) which is attached to the [script note](#root/HcUYTojFohtb).
diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Cloning Notes.md b/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Cloning Notes.md
index e185bec248..9dec36737b 100644
--- a/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Cloning Notes.md
+++ b/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Cloning Notes.md
@@ -1,4 +1,4 @@
-# Cloning Notes
+# Cloning Notes
## Motivation
Trilium's core feature is the ability to structure your notes into hierarchical tree-like structure.
diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Export as PDF.md b/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Export as PDF.md
index d8f6d9aa45..7c11eb8303 100644
--- a/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Export as PDF.md
+++ b/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Export as PDF.md
@@ -1,4 +1,4 @@
-# Export as PDF
+# Export as PDF

Screenshot of the note contextual menu indicating the “Export as PDF” option.
diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Note Icons.md b/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Note Icons.md
index 7be96288f4..9d50600177 100644
--- a/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Note Icons.md
+++ b/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Note Icons.md
@@ -1,4 +1,4 @@
-# Note Icons
+# Note Icons
Icons are useful for distinguishing notes. At the technical level, they are set by the `iconClass` attribute which adds a CSS class to the note. For example `#iconClass="bx bx-calendar"` will show a calendar instead of the default page or folder icon. Looking up and remembering the css class names is not necessary. While editing a note, click on the icon next to the title to bring up a chooser gallery:

diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions.md b/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions.md
index a486804b24..6dbfb9673b 100644
--- a/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions.md
+++ b/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions.md
@@ -1,4 +1,4 @@
-# Note Revisions
+# Note Revisions
Trilium supports seamless versioning of notes by storing snapshots ("revisions") of notes at regular intervals.
## Note Revisions Snapshot Interval
diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Protected Notes.md b/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Protected Notes.md
index 1d1578cb99..2b74cdefb0 100644
--- a/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Protected Notes.md
+++ b/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Protected Notes.md
@@ -1,4 +1,4 @@
-# Protected Notes
+# Protected Notes
Trilium is designed to store a wide variety of data, including sensitive information such as personal journals, credentials, or confidential documents. To safeguard this type of content, Trilium offers the option to protect notes, which involves the following measures:
* **Encryption:** Protected notes are encrypted using a key derived from your password. This ensures that without the correct password, protected notes remain indecipherable. Even if someone gains access to your Trilium [database](../../Advanced%20Usage/Database.md), they won't be able to read your encrypted notes.
diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Read-Only Notes.md b/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Read-Only Notes.md
index 2faacd35b8..60491d724c 100644
--- a/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Read-Only Notes.md
+++ b/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Read-Only Notes.md
@@ -1,4 +1,4 @@
-# Read-Only Notes
+# Read-Only Notes
Both [text](../../Note%20Types/Text.md) and [code](../../Note%20Types/Code.md) notes in Trilium can be set to read-only. When a note is in read-only mode, it is presented to the user in a non-editable view, with the option to switch to editing mode if needed.
## Setting Read-Only Mode with a Label
diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Sorting Notes.md b/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Sorting Notes.md
index 35e2e33a9a..a2a063e33b 100644
--- a/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Sorting Notes.md
+++ b/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Sorting Notes.md
@@ -1,4 +1,4 @@
-# Sorting Notes
+# Sorting Notes
## Sorting Notes
You can sort notes by right-clicking the parent note in the note tree and selecting Advanced -> Sort notes by ... This will sort existing notes, but will not automatically sort future notes added to this parent note
diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Themes.md b/docs/User Guide/User Guide/Basic Concepts and Features/Themes.md
index c058f0db36..7a44f9f570 100644
--- a/docs/User Guide/User Guide/Basic Concepts and Features/Themes.md
+++ b/docs/User Guide/User Guide/Basic Concepts and Features/Themes.md
@@ -1,4 +1,4 @@
-# Themes
+# Themes
## Default Themes
Trilium comes with a couple pre-installed color themes, with the default being a light theme. To switch to a dark theme or any other available theme, navigate to the Options menu (accessible via the app icon in the top-left corner), select the Appearance tab, and choose your preferred theme.
diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Themes/Theme Gallery.md b/docs/User Guide/User Guide/Basic Concepts and Features/Themes/Theme Gallery.md
index c09c3223eb..f256cc6dd5 100644
--- a/docs/User Guide/User Guide/Basic Concepts and Features/Themes/Theme Gallery.md
+++ b/docs/User Guide/User Guide/Basic Concepts and Features/Themes/Theme Gallery.md
@@ -1,4 +1,4 @@
-# Theme Gallery
+# Theme Gallery
These are user-created themes which were made publicly available:
## Legacy Themes
diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/UI Elements/Global menu.md b/docs/User Guide/User Guide/Basic Concepts and Features/UI Elements/Global menu.md
index ead4bba18e..77105f456f 100644
--- a/docs/User Guide/User Guide/Basic Concepts and Features/UI Elements/Global menu.md
+++ b/docs/User Guide/User Guide/Basic Concepts and Features/UI Elements/Global menu.md
@@ -1,4 +1,4 @@
-# Global menu
+# Global menu
The global menu configures the current window (zoom, keeping the window on top) and offers access to some more advanced options.

diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/UI Elements/Launch Bar.md b/docs/User Guide/User Guide/Basic Concepts and Features/UI Elements/Launch Bar.md
index 312486bb40..d5fed8ae17 100644
--- a/docs/User Guide/User Guide/Basic Concepts and Features/UI Elements/Launch Bar.md
+++ b/docs/User Guide/User Guide/Basic Concepts and Features/UI Elements/Launch Bar.md
@@ -1,4 +1,4 @@
-# Launch Bar
+# Launch Bar
## Position of the Launch bar
Depending on the layout selected, the launcher bar will either be on the left side of the screen with buttons displayed vertically or at the top of the screen. See [Vertical and horizontal layout](Vertical%20and%20horizontal%20layout.md) for more information.
diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree.md b/docs/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree.md
index 9280f70ec8..f77cbec170 100644
--- a/docs/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree.md
+++ b/docs/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree.md
@@ -1,4 +1,4 @@
-# Note Tree
+# Note Tree
This page explains how to manipulate the note tree in TriliumNext, focusing on moving notes.

diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note buttons.md b/docs/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note buttons.md
index 3ec6426569..c75bc62dcc 100644
--- a/docs/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note buttons.md
+++ b/docs/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note buttons.md
@@ -1,4 +1,4 @@
-# Note buttons
+# Note buttons
To the right of the [Ribbon](Ribbon.md) there are a few more buttons: 
* The Note Revisions button displays the [Note Revisions](../Notes/Note%20Revisions.md) for that particular note.
diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/UI Elements/Ribbon.md b/docs/User Guide/User Guide/Basic Concepts and Features/UI Elements/Ribbon.md
index 3e507e31a1..e99138df62 100644
--- a/docs/User Guide/User Guide/Basic Concepts and Features/UI Elements/Ribbon.md
+++ b/docs/User Guide/User Guide/Basic Concepts and Features/UI Elements/Ribbon.md
@@ -1,4 +1,4 @@
-# Ribbon
+# Ribbon

The ribbon allows changing options, attributes and viewing information about the current note.
diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/UI Elements/Vertical and horizontal layout.md b/docs/User Guide/User Guide/Basic Concepts and Features/UI Elements/Vertical and horizontal layout.md
index 1746f348d1..2699374d60 100644
--- a/docs/User Guide/User Guide/Basic Concepts and Features/UI Elements/Vertical and horizontal layout.md
+++ b/docs/User Guide/User Guide/Basic Concepts and Features/UI Elements/Vertical and horizontal layout.md
@@ -1,4 +1,4 @@
-# Vertical and horizontal layout
+# Vertical and horizontal layout
## Layouts
Trilium supports two different layouts, based on your preference.
diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Zen mode.md b/docs/User Guide/User Guide/Basic Concepts and Features/Zen mode.md
index dff47ba17c..8bd9b8ad63 100644
--- a/docs/User Guide/User Guide/Basic Concepts and Features/Zen mode.md
+++ b/docs/User Guide/User Guide/Basic Concepts and Features/Zen mode.md
@@ -1,4 +1,4 @@
-# Zen mode
+# Zen mode

Screenshot of Zen Mode activated on a Windows 11 system with native title bar off and background effects on.
diff --git a/docs/User Guide/User Guide/Note Types/Note Map.md b/docs/User Guide/User Guide/Note Types/Note Map.md
index 930efb82f7..9d3c4fa773 100644
--- a/docs/User Guide/User Guide/Note Types/Note Map.md
+++ b/docs/User Guide/User Guide/Note Types/Note Map.md
@@ -1,4 +1,4 @@
-# Note Map
+# Note Map
A Note map is a note type which displays a standalone version of the feature of the same name: [Note Map (Link map, Tree map)](../Advanced%20Usage/Note%20Map%20\(Link%20map%2C%20Tree%20map\).md).
Once created, the note map will display the relations between notes. Only the notes that are part of the parent of the note map will be displayed (including their children).
diff --git a/docs/User Guide/User Guide/Note Types/Relation Map.md b/docs/User Guide/User Guide/Note Types/Relation Map.md
index b80c1f1e95..3fc9fcceda 100644
--- a/docs/User Guide/User Guide/Note Types/Relation Map.md
+++ b/docs/User Guide/User Guide/Note Types/Relation Map.md
@@ -1,4 +1,4 @@
-# Relation Map
+# Relation Map
Relation map is a type of [Note](../Basic%20Concepts%20and%20Features/Notes.md) which visualizes notes and their [relations](../Advanced%20Usage/Attributes.md). See an example:
## Development process demo
diff --git a/docs/User Guide/User Guide/Note Types/Text/Developer-specific formatting.md b/docs/User Guide/User Guide/Note Types/Text/Developer-specific formatting.md
index bf8aa08c67..db47586ac7 100644
--- a/docs/User Guide/User Guide/Note Types/Text/Developer-specific formatting.md
+++ b/docs/User Guide/User Guide/Note Types/Text/Developer-specific formatting.md
@@ -1,4 +1,4 @@
-# Developer-specific formatting
+# Developer-specific formatting
### Inline code
Inline code formats text using a monospace font to indicate technical content in a sentence such as code, paths, etc.
diff --git a/docs/User Guide/User Guide/Note Types/Text/Developer-specific formatting/Code blocks.md b/docs/User Guide/User Guide/Note Types/Text/Developer-specific formatting/Code blocks.md
index af0c03be29..dd3c544550 100644
--- a/docs/User Guide/User Guide/Note Types/Text/Developer-specific formatting/Code blocks.md
+++ b/docs/User Guide/User Guide/Note Types/Text/Developer-specific formatting/Code blocks.md
@@ -1,4 +1,4 @@
-# Code blocks
+# Code blocks

The code blocks feature allows entering pieces of code in text notes.
diff --git a/e2e/help.spec.ts b/e2e/help.spec.ts
index 4402ffa300..6416afb6fe 100644
--- a/e2e/help.spec.ts
+++ b/e2e/help.spec.ts
@@ -25,3 +25,40 @@ test("Complete help in search", async ({ page, context }) => {
const popup = await popupPromise;
expect(popup.url()).toBe("https://triliumnext.github.io/Docs/Wiki/search.html");
});
+
+test("In-app-help works in English", async ({ page, context }) => {
+ const app = new App(page, context);
+ await app.goto();
+
+ await app.currentNoteSplit.press("F1");
+ const title = "User Guide";
+ await expect(app.noteTreeHoistedNote).toContainText(title);
+ await expect(app.currentNoteSplitTitle).toHaveValue(title);
+
+ app.noteTree.getByText("Troubleshooting").click();
+ await expect(app.currentNoteSplitTitle).toHaveValue("Troubleshooting");
+ await app.currentNoteSplitContent.locator("p").first().waitFor({ state: "visible" });
+ expect(await app.currentNoteSplitContent.locator("p").count()).toBeGreaterThan(10);
+});
+
+test("In-app-help works in other languages", async ({ page, context }) => {
+ const app = new App(page, context);
+ try {
+ await app.goto();
+ await app.setOption("locale", "cn");
+ await app.goto();
+
+ await app.currentNoteSplit.press("F1");
+ const title = "用户指南";
+ await expect(app.noteTreeHoistedNote).toContainText(title);
+ await expect(app.currentNoteSplitTitle).toHaveValue(title);
+
+ app.noteTree.getByText("Troubleshooting").click();
+ await expect(app.currentNoteSplitTitle).toHaveValue("Troubleshooting");
+ await app.currentNoteSplitContent.locator("p").first().waitFor({ state: "visible" });
+ expect(await app.currentNoteSplitContent.locator("p").count()).toBeGreaterThan(10);
+ } finally {
+ // Ensure English is set after each locale change to avoid any leaks to other tests.
+ await app.setOption("locale", "en");
+ }
+});
diff --git a/e2e/layout/tab_bar.spec.ts b/e2e/layout/tab_bar.spec.ts
index e6df6f3283..fe5a06a54b 100644
--- a/e2e/layout/tab_bar.spec.ts
+++ b/e2e/layout/tab_bar.spec.ts
@@ -57,3 +57,46 @@ test("Can drag tab to new window", async ({ page, context }) => {
const popupApp = new App(popup, context);
await expect(popupApp.getActiveTab()).toHaveText(NOTE_TITLE);
});
+
+test("Tabs are restored in right order", async ({ page, context }) => {
+ const app = new App(page, context);
+ await app.goto();
+
+ // Open three tabs.
+ await app.closeAllTabs();
+ await app.goToNoteInNewTab("Code notes");
+ await app.addNewTab();
+ await app.goToNoteInNewTab("Text notes");
+ await app.addNewTab();
+ await app.goToNoteInNewTab("Mermaid");
+
+ // Select the mid one.
+ await app.getTab(1).click();
+
+ // Refresh the page and check the order.
+ await app.goto( { preserveTabs: true });
+ await expect(app.getTab(0)).toContainText("Code notes");
+ await expect(app.getTab(1)).toContainText("Text notes");
+ await expect(app.getTab(2)).toContainText("Mermaid");
+
+ // Check the note tree has the right active node.
+ await expect(app.noteTreeActiveNote).toContainText("Text notes");
+});
+
+test("Empty tabs are cleared out", async ({ page, context }) => {
+ const app = new App(page, context);
+ await app.goto();
+
+ // Open three tabs.
+ await app.closeAllTabs();
+ await app.addNewTab();
+ await app.goToNoteInNewTab("Code notes");
+ await app.addNewTab();
+ await app.addNewTab();
+
+ // Refresh the page and check the order.
+ await app.goto({ preserveTabs: true });
+
+ // Expect no empty tabs.
+ expect(await app.tabBar.locator(".note-tab-wrapper").count()).toBe(1);
+});
diff --git a/e2e/support/app.ts b/e2e/support/app.ts
index b526638d9c..8ae430f1be 100644
--- a/e2e/support/app.ts
+++ b/e2e/support/app.ts
@@ -4,6 +4,7 @@ import type { BrowserContext } from "@playwright/test";
interface GotoOpts {
url?: string;
isMobile?: boolean;
+ preserveTabs?: boolean;
}
const BASE_URL = "http://127.0.0.1:8082";
@@ -14,8 +15,12 @@ export default class App {
readonly tabBar: Locator;
readonly noteTree: Locator;
+ readonly noteTreeActiveNote: Locator;
+ readonly noteTreeHoistedNote: Locator;
readonly launcherBar: Locator;
readonly currentNoteSplit: Locator;
+ readonly currentNoteSplitTitle: Locator;
+ readonly currentNoteSplitContent: Locator;
readonly sidebar: Locator;
constructor(page: Page, context: BrowserContext) {
@@ -24,12 +29,16 @@ export default class App {
this.tabBar = page.locator(".tab-row-widget-container");
this.noteTree = page.locator(".tree-wrapper");
+ this.noteTreeActiveNote = this.noteTree.locator(".fancytree-node.fancytree-active");
+ this.noteTreeHoistedNote = this.noteTree.locator(".fancytree-node", { has: page.locator(".unhoist-button") });
this.launcherBar = page.locator("#launcher-container");
this.currentNoteSplit = page.locator(".note-split:not(.hidden-ext)");
+ this.currentNoteSplitTitle = this.currentNoteSplit.locator(".note-title");
+ this.currentNoteSplitContent = this.currentNoteSplit.locator(".note-detail-printable.visible");
this.sidebar = page.locator("#right-pane");
}
- async goto({ url, isMobile }: GotoOpts = {}) {
+ async goto({ url, isMobile, preserveTabs }: GotoOpts = {}) {
await this.context.addCookies([
{
url: BASE_URL,
@@ -47,7 +56,9 @@ export default class App {
// Wait for the page to load.
if (url === "/") {
await expect(this.page.locator(".tree")).toContainText("Trilium Integration Test");
- await this.closeAllTabs();
+ if (!preserveTabs) {
+ await this.closeAllTabs();
+ }
}
}
diff --git a/electron-docs-main.ts b/electron-docs-main.ts
index 6fe09eaf71..71c7f5b939 100644
--- a/electron-docs-main.ts
+++ b/electron-docs-main.ts
@@ -7,7 +7,7 @@ import { initializeTranslations } from "./src/services/i18n.js";
import archiver, { type Archiver } from "archiver";
import type { WriteStream } from "fs";
import debounce from "./src/public/app/services/debounce.js";
-import { extractZip, importData, initializeDatabase, startElectron } from "./electron-utils.js";
+import { extractZip, initializeDatabase, startElectron } from "./electron-utils.js";
const NOTE_ID_USER_GUIDE = "pOsGYCXsbNQG";
const markdownPath = path.join("docs", "User Guide");
@@ -16,8 +16,7 @@ const htmlPath = path.join("src", "public", "app", "doc_notes", "en", "User Guid
async function main() {
await initializeTranslations();
const zipBuffer = await createImportZip();
- await initializeDatabase();
- await importData(zipBuffer, NOTE_ID_USER_GUIDE, "User Guide", "The sub-children of this note are automatically synced.");
+ await initializeDatabase(zipBuffer);
await startElectron();
await registerHandlers();
}
diff --git a/electron-utils.ts b/electron-utils.ts
index ebaefa13d6..c335187e1d 100644
--- a/electron-utils.ts
+++ b/electron-utils.ts
@@ -3,12 +3,12 @@ import fs from "fs/promises";
import fsExtra from "fs-extra";
import path from "path";
-export async function initializeDatabase() {
+export async function initializeDatabase(customDbBuffer?: Buffer) {
const sqlInit = (await import("./src/services/sql_init.js")).default;
cls.init(() => {
if (!sqlInit.isDbInitialized()) {
- sqlInit.createInitialDatabase(true);
+ sqlInit.createInitialDatabase(true, customDbBuffer);
}
});
}
@@ -17,48 +17,6 @@ export async function startElectron() {
await import("./electron-main.js");
}
-export function importData(input: Buffer, rootId: string, rootTitle: string, rootContent: string) {
- return new Promise((resolve, reject) => {
- cls.init(async () => {
- const beccaLoader = ((await import("./src/becca/becca_loader.js")).default);
- const notes = ((await import("./src/services/notes.js")).default);
- beccaLoader.load();
- const becca = ((await import("./src/becca/becca.js")).default);
- const utils = ((await import("./src/services/utils.js")).default);
- const eraseService = ((await import("./src/services/erase.js")).default);
- const deleteId = utils.randomString(10);
-
- const existingNote = becca.getNote(rootId);
- if (existingNote) {
- existingNote.deleteNote(deleteId);
- }
- eraseService.eraseNotesWithDeleteId(deleteId);
-
- const { note } = notes.createNewNoteWithTarget("into", "none_root", {
- parentNoteId: "root",
- noteId: rootId,
- title: rootTitle,
- content: rootContent,
- type: "text"
- });
-
- const TaskContext = (await import("./src/services/task_context.js")).default;
- const { importZip } = ((await import("./src/services/import/zip.js")).default);
- const context = new TaskContext("no-report");
- await importZip(context, input, note, { preserveIds: true });
-
- const { runOnDemandChecks } = (await import("./src/services/consistency_checks.js")).default;
- await runOnDemandChecks(true);
-
- becca.reset();
- beccaLoader.load();
-
- resolve();
- });
- });
-
-}
-
export async function extractZip(zipFilePath: string, outputPath: string) {
const deferred = (await import("./src/services/utils.js")).deferred;
diff --git a/eslint.config.js b/eslint.config.js
index 55ad4d9a26..4b4c23dacf 100644
--- a/eslint.config.js
+++ b/eslint.config.js
@@ -24,10 +24,11 @@ export default tseslint.config(
"@typescript-eslint/no-unused-vars": [
"error",
{
- "argsIgnorePattern": "^_",
- "varsIgnorePattern": "^_",
+ argsIgnorePattern: "^_",
+ varsIgnorePattern: "^_"
}
- ]
+ ],
+ "sort-imports": [ "error", { ignoreCase: false } ]
}
},
{
@@ -35,6 +36,7 @@ export default tseslint.config(
"build/*",
"dist/*",
"docs/*",
+ "demo/*",
"libraries/*",
"src/public/app-dist/*",
"src/public/app/doc_notes/*"
diff --git a/eslint.format.config.js b/eslint.format.config.js
new file mode 100644
index 0000000000..23fbb6caf2
--- /dev/null
+++ b/eslint.format.config.js
@@ -0,0 +1,48 @@
+import stylistic from "@stylistic/eslint-plugin";
+import tsParser from "@typescript-eslint/parser";
+
+// eslint config just for formatting rules
+// potentially to be merged with the linting rules into one single config,
+// once we have fixed the majority of lint errors
+
+// Go to https://eslint.style/rules/default/${rule_without_prefix} to check the rule details
+export const stylisticRules = {
+ "@stylistic/indent": [ "error", 4 ],
+ "@stylistic/quotes": [ "error", "double", { avoidEscape: true, allowTemplateLiterals: "always" } ],
+ "@stylistic/semi": [ "error", "always" ],
+ "@stylistic/quote-props": [ "error", "consistent-as-needed" ],
+ "@stylistic/max-len": [ "error", { code: 100 } ],
+ "@stylistic/comma-dangle": [ "error", "never" ],
+ "@stylistic/linebreak-style": [ "error", "unix" ],
+ "@stylistic/array-bracket-spacing": [ "error", "always" ],
+ "@stylistic/object-curly-spacing": [ "error", "always" ],
+ "@stylistic/padded-blocks": [ "error", { classes: "always" } ]
+};
+
+export default [
+ {
+ files: [ "**/*.{js,ts,mjs,cjs}" ],
+ languageOptions: {
+ parser: tsParser
+ },
+ plugins: {
+ "@stylistic": stylistic
+ },
+ rules: {
+ ...stylisticRules
+ }
+ },
+ {
+ ignores: [
+ "build/*",
+ "dist/*",
+ "docs/*",
+ "demo/*",
+ "libraries/*",
+ // TriliumNextTODO: check if we want to format packages here as well - for now skipping it
+ "packages/*",
+ "src/public/app-dist/*",
+ "src/public/app/doc_notes/*"
+ ]
+ }
+];
diff --git a/package-lock.json b/package-lock.json
index 3bd4e8918a..77e8afeaa5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -117,6 +117,7 @@
"@mind-elixir/node-menu": "1.0.5",
"@playwright/test": "1.51.1",
"@popperjs/core": "2.11.8",
+ "@stylistic/eslint-plugin": "4.2.0",
"@types/archiver": "6.0.3",
"@types/better-sqlite3": "7.6.12",
"@types/bootstrap": "5.2.10",
@@ -201,8 +202,7 @@
"webpack-dev-middleware": "7.4.2"
},
"optionalDependencies": {
- "appdmg": "0.6.6",
- "dprint": "0.49.1"
+ "appdmg": "0.6.6"
}
},
"node_modules/@ampproject/remapping": {
@@ -574,123 +574,6 @@
"node": ">=14.17.0"
}
},
- "node_modules/@dprint/darwin-arm64": {
- "version": "0.49.1",
- "resolved": "https://registry.npmjs.org/@dprint/darwin-arm64/-/darwin-arm64-0.49.1.tgz",
- "integrity": "sha512-ib6KcJWo/M5RJWXOQKhP664FG1hAvG7nrbkh+j8n+oXdzmbyDdXTP+zW+aM3/sIQUkGaZky1xy1j2VeScMEEHQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ]
- },
- "node_modules/@dprint/darwin-x64": {
- "version": "0.49.1",
- "resolved": "https://registry.npmjs.org/@dprint/darwin-x64/-/darwin-x64-0.49.1.tgz",
- "integrity": "sha512-vIVgnYxV7YYa1d6Uyz707RbgB9rwefGPam+rzaueFNPQjdOxPOTQDuMEJDS+Z3BlI00MfeoupIfIUGsXoM4dpQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ]
- },
- "node_modules/@dprint/linux-arm64-glibc": {
- "version": "0.49.1",
- "resolved": "https://registry.npmjs.org/@dprint/linux-arm64-glibc/-/linux-arm64-glibc-0.49.1.tgz",
- "integrity": "sha512-ZeIh6qMPWLBBifDtU0XadpK36b4WoaTqCOt0rWKfoTjq1RAt78EgqETWp43Dbr6et/HvTgYdoWF0ZNEu2FJFFA==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@dprint/linux-arm64-musl": {
- "version": "0.49.1",
- "resolved": "https://registry.npmjs.org/@dprint/linux-arm64-musl/-/linux-arm64-musl-0.49.1.tgz",
- "integrity": "sha512-/nuRyx+TykN6MqhlSCRs/t3o1XXlikiwTc9emWdzMeLGllYvJrcht9gRJ1/q1SqwCFhzgnD9H7roxxfji1tc+Q==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@dprint/linux-riscv64-glibc": {
- "version": "0.49.1",
- "resolved": "https://registry.npmjs.org/@dprint/linux-riscv64-glibc/-/linux-riscv64-glibc-0.49.1.tgz",
- "integrity": "sha512-RHBqrnvGO+xW4Oh0QuToBqWtkXMcfjqa1TqbBFF03yopFzZA2oRKX83PhjTWgd/IglaOns0BgmaLJy/JBSxOfQ==",
- "cpu": [
- "riscv64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@dprint/linux-x64-glibc": {
- "version": "0.49.1",
- "resolved": "https://registry.npmjs.org/@dprint/linux-x64-glibc/-/linux-x64-glibc-0.49.1.tgz",
- "integrity": "sha512-MjFE894mIQXOKBencuakKyzAI4KcDe/p0Y9lRp9YSw/FneR4QWH9VBH90h8fRxcIlWMArjFFJJAtsBnn5qgxeg==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@dprint/linux-x64-musl": {
- "version": "0.49.1",
- "resolved": "https://registry.npmjs.org/@dprint/linux-x64-musl/-/linux-x64-musl-0.49.1.tgz",
- "integrity": "sha512-CvGBWOksHgrL1uzYqtPFvZz0+E82BzgoCIEHJeuYaveEn37qWZS5jqoCm/vz6BfoivE1dVuyyOT78Begj9KxkQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@dprint/win32-arm64": {
- "version": "0.49.1",
- "resolved": "https://registry.npmjs.org/@dprint/win32-arm64/-/win32-arm64-0.49.1.tgz",
- "integrity": "sha512-gQa4s82lMcXjfdxjWBQun6IJlXdPZZaIj2/2cqXWVEOYPKxAZ/JvGzt2pPG+i73h9KHjNLIV8M9ckqEH3oHufg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@dprint/win32-x64": {
- "version": "0.49.1",
- "resolved": "https://registry.npmjs.org/@dprint/win32-x64/-/win32-x64-0.49.1.tgz",
- "integrity": "sha512-nPU6+hoVze5JJlgET7woYWElBw0IUaB/9XKTaglknQuUUfsmD75D9pkgJTxdIxl9Bg/i5O7c9wb3Nj4XNiTIfw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
- },
"node_modules/@electron-forge/cli": {
"version": "7.8.0",
"resolved": "https://registry.npmjs.org/@electron-forge/cli/-/cli-7.8.0.tgz",
@@ -4554,6 +4437,39 @@
"url": "https://github.com/sindresorhus/is?sponsor=1"
}
},
+ "node_modules/@stylistic/eslint-plugin": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-4.2.0.tgz",
+ "integrity": "sha512-8hXezgz7jexGHdo5WN6JBEIPHCSFyyU4vgbxevu4YLVS5vl+sxqAAGyXSzfNDyR6xMNSH5H1x67nsXcYMOHtZA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/utils": "^8.23.0",
+ "eslint-visitor-keys": "^4.2.0",
+ "espree": "^10.3.0",
+ "estraverse": "^5.3.0",
+ "picomatch": "^4.0.2"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "peerDependencies": {
+ "eslint": ">=9.0.0"
+ }
+ },
+ "node_modules/@stylistic/eslint-plugin/node_modules/picomatch": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
+ "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
"node_modules/@szmarczak/http-timer": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz",
@@ -9507,28 +9423,6 @@
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
- "node_modules/dprint": {
- "version": "0.49.1",
- "resolved": "https://registry.npmjs.org/dprint/-/dprint-0.49.1.tgz",
- "integrity": "sha512-pO9XH79SyXybj2Vhc9ITZMEI8cJkdlQQRoD8oEfPH6Jjpp/7WX5kIgECVd3DBOjjAdCSiW6R47v3gJBx/qZVkw==",
- "hasInstallScript": true,
- "license": "MIT",
- "optional": true,
- "bin": {
- "dprint": "bin.js"
- },
- "optionalDependencies": {
- "@dprint/darwin-arm64": "0.49.1",
- "@dprint/darwin-x64": "0.49.1",
- "@dprint/linux-arm64-glibc": "0.49.1",
- "@dprint/linux-arm64-musl": "0.49.1",
- "@dprint/linux-riscv64-glibc": "0.49.1",
- "@dprint/linux-x64-glibc": "0.49.1",
- "@dprint/linux-x64-musl": "0.49.1",
- "@dprint/win32-arm64": "0.49.1",
- "@dprint/win32-x64": "0.49.1"
- }
- },
"node_modules/draggabilly": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/draggabilly/-/draggabilly-3.0.0.tgz",
diff --git a/package.json b/package.json
index f5c057b86c..95ab4e8fe9 100644
--- a/package.json
+++ b/package.json
@@ -36,8 +36,8 @@
"electron:start-prod-nix-no-dir": "electron-rebuild --version 33.3.1 && npm run build:prepare-dist && cross-env TRILIUM_ENV=dev nix-shell -p electron_33 --run \"electron ./dist/electron-main.js --inspect=5858 .\"",
"electron:qstart": "npm run electron:switch && npm run electron:start",
"electron:switch": "electron-rebuild",
- "docs:edit": "cross-env NODE_OPTIONS=\"--import tsx\" TRILIUM_DATA_DIR=./data-docs TRILIUM_ENV=dev TRILIUM_PORT=37741 electron ./electron-docs-main.ts .",
- "docs:edit-nix": "electron-rebuild --version 33.3.1 && cross-env NODE_OPTIONS=\"--import tsx\" TRILIUM_DATA_DIR=./data-docs TRILIUM_PORT=37741 TRILIUM_ENV=dev nix-shell -p electron_33 --run \"electron ./electron-docs-main.ts .\"",
+ "docs:edit": "cross-env NODE_OPTIONS=\"--import tsx\" TRILIUM_DATA_DIR=./data-docs TRILIUM_ENV=dev TRILIUM_INTEGRATION_TEST=memory-no-store TRILIUM_PORT=37741 electron ./electron-docs-main.ts .",
+ "docs:edit-nix": "electron-rebuild --version 33.3.1 && cross-env NODE_OPTIONS=\"--import tsx\" TRILIUM_DATA_DIR=./data-docs TRILIUM_PORT=37741 TRILIUM_ENV=dev TRILIUM_INTEGRATION_TEST=memory-no-store nix-shell -p electron_33 --run \"electron ./electron-docs-main.ts .\"",
"demo:edit": "cross-env NODE_OPTIONS=\"--import tsx\" TRILIUM_DATA_DIR=./data-demo TRILIUM_ENV=dev TRILIUM_INTEGRATION_TEST=memory-no-store TRILIUM_PORT=37741 electron ./electron-edit-demo.ts .",
"electron-forge:start": "npm run build:prepare-dist && cd ./build && electron-forge start",
"electron-forge:make": "npm run build:prepare-dist && cross-env DEBUG=electron-windows-installer:* electron-forge make ./build",
@@ -59,8 +59,8 @@
"test:integration-mem-db": "cross-env TRILIUM_INTEGRATION_TEST=memory TRILIUM_PORT=8082 TRILIUM_DATA_DIR=./integration-tests/db nodemon src/main.ts",
"test:integration-mem-db-dev": "cross-env TRILIUM_INTEGRATION_TEST=memory TRILIUM_PORT=8082 TRILIUM_ENV=dev TRILIUM_DATA_DIR=./integration-tests/db nodemon src/main.ts",
"dev:watch-dist": "tsx ./bin/watch-dist.ts",
- "dev:format-check": "dprint check",
- "dev:format-fix": "dprint fmt",
+ "dev:format-check": "eslint -c eslint.format.config.js .",
+ "dev:format-fix": "eslint -c eslint.format.config.js . --fix",
"dev:linter-check": "eslint .",
"dev:linter-fix": "eslint . --fix",
"chore:update-build-info": "tsx bin/update-build-info.ts",
@@ -174,6 +174,7 @@
"@mind-elixir/node-menu": "1.0.5",
"@playwright/test": "1.51.1",
"@popperjs/core": "2.11.8",
+ "@stylistic/eslint-plugin": "4.2.0",
"@types/archiver": "6.0.3",
"@types/better-sqlite3": "7.6.12",
"@types/bootstrap": "5.2.10",
@@ -219,7 +220,7 @@
"bootstrap": "5.3.3",
"copy-webpack-plugin": "13.0.0",
"cross-env": "7.0.3",
- "css-loader": "7.1.2",
+ "css-loader": "7.1.2",
"electron": "35.1.2",
"eslint": "9.23.0",
"esm": "3.2.25",
@@ -258,7 +259,6 @@
"webpack-dev-middleware": "7.4.2"
},
"optionalDependencies": {
- "appdmg": "0.6.6",
- "dprint": "0.49.1"
+ "appdmg": "0.6.6"
}
}
diff --git a/src/public/app/components/tab_manager.ts b/src/public/app/components/tab_manager.ts
index a4d00a075c..937bd89821 100644
--- a/src/public/app/components/tab_manager.ts
+++ b/src/public/app/components/tab_manager.ts
@@ -75,7 +75,7 @@ export default class TabManager extends Component {
const filteredNoteContexts = noteContextsToOpen.filter((openTab: NoteContextState) => {
const noteId = treeService.getNoteIdFromUrl(openTab.notePath);
- if (noteId && !(noteId in froca.notes)) {
+ if (!noteId || !(noteId in froca.notes)) {
// note doesn't exist so don't try to open tab for it
return false;
}
diff --git a/src/public/app/services/doc_renderer.ts b/src/public/app/services/doc_renderer.ts
index ac1560d4c6..290adbb72f 100644
--- a/src/public/app/services/doc_renderer.ts
+++ b/src/public/app/services/doc_renderer.ts
@@ -14,8 +14,10 @@ export default function renderDoc(note: FNote) {
// fallback to english doc if no translation available
if (status === "error") {
const fallbackUrl = getUrl(docName, "en");
- $content.load(fallbackUrl, () => processContent(fallbackUrl, $content));
- resolve($content);
+ $content.load(fallbackUrl, () => {
+ processContent(fallbackUrl, $content)
+ resolve($content);
+ });
return;
}
diff --git a/src/public/app/set_password.ts b/src/public/app/set_password.ts
index ebf6b68a48..95e6cc2dad 100644
--- a/src/public/app/set_password.ts
+++ b/src/public/app/set_password.ts
@@ -1,4 +1,5 @@
import "../stylesheets/bootstrap.scss";
+import "../stylesheets/auth.css";
// @TriliumNextTODO: is this even needed anymore?
// @ts-ignore - module = undefined
diff --git a/src/public/app/widgets/buttons/global_menu.ts b/src/public/app/widgets/buttons/global_menu.ts
index 657813773e..d21e43b0dc 100644
--- a/src/public/app/widgets/buttons/global_menu.ts
+++ b/src/public/app/widgets/buttons/global_menu.ts
@@ -11,6 +11,7 @@ const TPL = /*html*/`
.global-menu {
width: 53px;
height: 53px;
+ flex-shrink: 0;
}
.global-menu .dropdown-menu {
diff --git a/src/public/app/widgets/containers/launcher_container.ts b/src/public/app/widgets/containers/launcher_container.ts
index 7fa833182d..87d25250e5 100644
--- a/src/public/app/widgets/containers/launcher_container.ts
+++ b/src/public/app/widgets/containers/launcher_container.ts
@@ -11,7 +11,19 @@ export default class LauncherContainer extends FlexContainer {
super(isHorizontalLayout ? "row" : "column");
this.id("launcher-container");
- this.css(isHorizontalLayout ? "width" : "height", "100%");
+
+ if (isHorizontalLayout) {
+ this.css("width", "100%");
+ this.css("height", "100%");
+ this.css("overflow-x", "auto");
+ this.css("overflow-y", "hidden");
+ } else {
+ this.css("height", "100%");
+ this.css("overflow-x", "hidden");
+ this.css("overflow-y", "auto");
+ }
+
+ this.css("scrollbar-gutter", "stable both-edges");
this.filling();
this.isHorizontalLayout = isHorizontalLayout;
diff --git a/src/public/app/widgets/dialogs/protected_session_password.ts b/src/public/app/widgets/dialogs/protected_session_password.ts
index b044a9b7f5..d839aac3b8 100644
--- a/src/public/app/widgets/dialogs/protected_session_password.ts
+++ b/src/public/app/widgets/dialogs/protected_session_password.ts
@@ -16,7 +16,7 @@ const TPL = /*html*/`