diff --git a/.dprint.json b/.dprint.json
deleted file mode 100644
index 21e6f8585..000000000
--- 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 cd49e608f..17970ebe8 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 a2c35b3c5..0e2651b7c 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 a5836d2e3..b9c4db4f3 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 67ad6dcf2..37838fd13 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 7b0402fda..7f808d430 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 442b589a7..a2ad1c814 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 8ade8060c..f7738d104 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 ab0bb1e39..fa7c9bf94 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 181bcd9d5..02f245f00 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 a969d480a..0280cfca5 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 bda28e61d..3815c2477 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 b3390a5a7..0a7a96142 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 5c8d94aab..0ccc24cdf 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 67766fa8f..76c26d6f4 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 5e5481f1a..659d031fc 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 465483f72..40c7b1dbd 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 200e334ea..aa0495066 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 8c195571c..945acdfe5 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 a021b6511..6303bb28f 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 dd0ff17e4..32c33349d 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 db61a206e..99cc9dff3 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 9190649d1..da64e051a 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 5815baee8..91076bef0 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 e185bec24..9dec36737 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 d8f6d9aa4..7c11eb830 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 7be96288f..9d5060017 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 a486804b2..6dbfb9673 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 1d1578cb9..2b74cdefb 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 2faacd35b..60491d724 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 35e2e33a9..a2a063e33 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 c058f0db3..7a44f9f57 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 c09c3223e..f256cc6dd 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 ead4bba18..77105f456 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 312486bb4..d5fed8ae1 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 9280f70ec..f77cbec17 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 3ec642656..c75bc62dc 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 3e507e31a..e99138df6 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 1746f348d..2699374d6 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 dff47ba17..8bd9b8ad6 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 930efb82f..9d3c4fa77 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 b80c1f1e9..3fc9fcced 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 bf8aa08c6..db47586ac 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 af0c03be2..dd3c54455 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 4402ffa30..6416afb6f 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 e6df6f328..fe5a06a54 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 b526638d9..8ae430f1b 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 6fe09eaf7..71c7f5b93 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 ebaefa13d..c335187e1 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 55ad4d9a2..4b4c23dac 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 000000000..23fbb6caf
--- /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 3bd4e8918..77e8afeaa 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 f5c057b86..95ab4e8fe 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 a4d00a075..937bd8982 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 ac1560d4c..290adbb72 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 ebf6b68a4..95e6cc2da 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 657813773..d21e43b0d 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 7fa833182..87d25250e 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 b044a9b7f..d839aac3b 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*/`