Active content is a generic name for powerful features in Trilium,
+ these range from customizing the UI to advanced scripting that can alter
+ your notes or even your PC.
+
Safe import
+
Active content problem of safety, especially when this active content
+ comes from a third-party such as if it is downloaded from a website and
+ then imported into Trilium.
+
When importing .zip
+ archives into Trilium, safe mode is active by default which will
+ try to prevent untrusted code from executing. For example, a custom widget needs
+ the #widgetlabel in
+ order to function; safe import works by renaming that label to #disabled:widget.
+
Safe mode
+
Sometimes active content can cause issues with the UI or the server, preventing
+ it from functioning properly. Safe mode allows
+ starting Trilium in such a way that active content is not loaded by default
+ at start-up, allowing the user to fix the problematic scripts or widgets.
+
Types of active content
+
These are the types of active content in Trilium, along with a few examples
+ of what untrusted content of that type could cause:
Can run custom code on the server of Trilium (Node.js environment), with
+ full access to the notes and the database.
+
Has access to all the unencrypted notes, but with full access to the database
+ it can completely destroy the data. It also has access to execute other
+ applications or alter the files and folders on the server).
Renders custom content inside a note, such as a dashboard or a new editor
+ that is not officially supported by Trilium.
+
Can affect the UI similar to front-end scripts or custom widgets since
+ the scripts are not completely encapsulated, or they can act similar to
+ a web view where they can collect data entered by the user.
Can alter the layout and style of the UI using CSS, applied regardless
+ of theme.
+
Generally less problematic than the rest of active content, but a badly
+ written CSS can affect the layout of the application, requiring the use
+ of Safe mode to
+ be able to use the application.
Generally are more contained and less prone to cause issues, but they
+ can cause performance issues (for example if the icon pack has millions
+ of icons in it).
+
+
+
+
+
Active content badge
+
Starting with v0.102.0, on the New Layout a
+ badge will be displayed near the note title, indicating that an active
+ content is detected. Clicking the badge will reveal a menu with various
+ options related to that content type, for example to open the documentation
+ or to configure the execution of scripts.
+
For some active content types, such as backend scripts with custom triggering
+ conditions a toggle button will appear. This makes it possible to easily
+ disable scripts or widgets, but also to re-enable them if an import was
+ made with safe mode active.
+
\ No newline at end of file
diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Themes/Icon Packs.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Themes/Icon Packs.html
index 243bc06cd4..190a1f070c 100644
--- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Themes/Icon Packs.html
+++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Themes/Icon Packs.html
@@ -29,10 +29,9 @@
Ideally, create a dedicated spot in your note tree where to place the
icon packs.
Right click the note where to put it and select Import into note.
Unlike front-end scripts which
+ run on the client / browser-side, back-end scripts run directly on the
+ Node.js environment of the Trilium server.
+
Back-end scripts can be used both on a Server Installation (where
+ it will run on the device the server is running on), or on the
+ Desktop Installation (where it will run on the PC).
+
Advantages of backend scripts
+
The benefit of backend scripts is that they can be pretty powerful, for
+ example to have access to the underlying system, for example it can read
+ files or execute processes.
+
However, the main benefit of backend scripts is that they have easier
+ access to the notes since the information about them is already loaded
+ in memory. Whereas on the client, notes have to be manually loaded first.
+
Creating a backend script
+
Create a new Code note
+ and select the language JS backend.
+
Running backend scripts
+
Backend scripts can be either run manually (via the Execute button on
+ the script page), or they can be triggered on certain events.
+
In addition, scripts can be run automatically when the server starts up,
+ on a fixed time interval or when a certain event occurs (such as an attribute
+ being modified). For more information, see the dedicated Events page.
+
Script API
+
Trilium exposes a set of APIs that can be directly consumed by scripts,
+ under the api object. For a reference of
+ this API, see Backend API.
\ No newline at end of file
diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Scripting/Backend scripts/Events.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Scripting/Backend scripts/Events.html
index d2866b0813..3e54232a5d 100644
--- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Scripting/Backend scripts/Events.html
+++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Scripting/Backend scripts/Events.html
@@ -5,139 +5,139 @@
Global events are attached to the script note via label. Simply create
e.g. "run" label with some of these values and script note will be executed
once the event occurs.
-
-
-
-
Label
-
Description
-
-
-
-
-
run
-
-
-
Defines on which events script should run. Possible values are:
-
-
frontendStartup - when Trilium frontend starts up (or is refreshed),
- but not on mobile.
-
mobileStartup - when Trilium frontend starts up (or is refreshed),
- on mobile.
-
backendStartup - when Trilium backend starts up
-
hourly - run once an hour. You can use additional label runAtHour to
- specify at which hour, on the back-end.
-
daily - run once a day, on the back-end
-
-
-
-
-
runOnInstance
-
-
Specifies that the script should only run on a particular Trilium instance.
-
-
-
runAtHour
-
-
On which hour should this run. Should be used together with #run=hourly.
- Can be defined multiple times for more runs during the day.
-
-
-
-
+
+
+
+
+
Label
+
Description
+
+
+
+
+
run
+
+
+
Defines on which events script should run. Possible values are:
+
+
backendStartup - when Trilium backend starts
+ up
+
hourly - run once an hour. You can use
+ additional label runAtHour to specify at
+ which hour, on the back-end.
+
daily - run once a day, on the back-end
+
+
+
+
+
runOnInstance
+
+
Specifies that the script should only run on a particular Trilium instance.
+
+
+
runAtHour
+
+
On which hour should this run. Should be used together with #run=hourly.
+ Can be defined multiple times for more runs during the day.
+
+
+
+
Entity events
Other events are bound to some entity, these are defined as relations -
meaning that script is triggered only if note has this script attached
to it through relations (or it can inherit it).
-
-
-
-
Relation
-
Trigger condition
-
Origin entity (see below)
-
-
-
-
-
runOnNoteCreation
-
-
executes when note is created on backend. Use this relation if you want
- to run the script for all notes created under a specific subtree. In that
- case, create it on the subtree root note and make it inheritable. A new
- note created within the subtree (any depth) will trigger the script.
-
The BNote that got created.
-
-
-
runOnChildNoteCreation
-
-
executes when new note is created under the note where this relation is
- defined
-
The BNote of the child that got created.
-
-
-
runOnNoteTitleChange
-
-
executes when note title is changed (includes note creation as well)
-
The BNote of the note whose title got changed.
-
-
-
runOnNoteContentChange
-
-
executes when note content is changed (includes note creation as well).
-
The BNote of the note whose content got
- changed.
-
-
-
runOnNoteChange
-
-
executes when note is changed (includes note creation as well). Does not
- include content changes
-
The BNote of the note that got changed.
-
-
-
runOnNoteDeletion
-
-
executes when note is being deleted
-
The BNote of the note that got (soft) deleted.
-
-
-
runOnBranchCreation
-
-
executes when a branch is created. Branch is a link between parent note
- and child note and is created e.g. when cloning or moving note.
-
The BBranch that got created.
-
-
-
runOnBranchChange
-
-
executes when a branch is updated. (since v0.62)
-
The BBranch that got changed.
-
-
-
runOnBranchDeletion
-
-
executes when a branch is deleted. Branch is a link between parent note
- and child note and is deleted e.g. when moving note (old branch/link is
- deleted).
-
The BBranch that got (soft) deleted.
-
-
-
runOnAttributeCreation
-
-
executes when new attribute is created for the note which defines this
- relation
-
The BAttribute that got created.
-
-
-
runOnAttributeChange
-
-
executes when the attribute is changed of a note which defines this relation.
- This is triggered also when the attribute is deleted
-
The BAttribute that got changed.
-
-
-
-
+
+
+
+
+
Relation
+
Trigger condition
+
Origin entity (see below)
+
+
+
+
+
runOnNoteCreation
+
+
executes when note is created on backend. Use this relation if you want
+ to run the script for all notes created under a specific subtree. In that
+ case, create it on the subtree root note and make it inheritable. A new
+ note created within the subtree (any depth) will trigger the script.
+
The BNote that got created.
+
+
+
runOnChildNoteCreation
+
+
executes when new note is created under the note where this relation is
+ defined
+
The BNote of the child that got created.
+
+
+
runOnNoteTitleChange
+
+
executes when note title is changed (includes note creation as well)
+
The BNote of the note whose title got changed.
+
+
+
runOnNoteContentChange
+
+
executes when note content is changed (includes note creation as well).
+
The BNote of the note whose content got
+ changed.
+
+
+
runOnNoteChange
+
+
executes when note is changed (includes note creation as well). Does not
+ include content changes
+
The BNote of the note that got changed.
+
+
+
runOnNoteDeletion
+
+
executes when note is being deleted
+
The BNote of the note that got (soft) deleted.
+
+
+
runOnBranchCreation
+
+
executes when a branch is created. Branch is a link between parent note
+ and child note and is created e.g. when cloning or moving note.
+
The BBranch that got created.
+
+
+
runOnBranchChange
+
+
executes when a branch is updated. (since v0.62)
+
The BBranch that got changed.
+
+
+
runOnBranchDeletion
+
+
executes when a branch is deleted. Branch is a link between parent note
+ and child note and is deleted e.g. when moving note (old branch/link is
+ deleted).
+
The BBranch that got (soft) deleted.
+
+
+
runOnAttributeCreation
+
+
executes when new attribute is created for the note which defines this
+ relation
+
The BAttribute that got created.
+
+
+
runOnAttributeChange
+
+
executes when the attribute is changed of a note which defines this relation.
+ This is triggered also when the attribute is deleted
+
The BAttribute that got changed.
+
+
+
+
Origin entity
When a script is run by an event such as the ones described above,
Frontend API
-
The frontend api supports two styles, regular scripts that are run with
- the current app and note context, and widgets that export an object to
- Trilium to be used in the UI. In both cases, the frontend api of Trilium
- is available to scripts running in the frontend context as global variable
- api. The members and methods of the api can be seen on the Script API page.
+
Front-end scripts are custom JavaScript notes that are run on the client
+ (browser environment)
+
There are four flavors of front-end scripts:
+
+
+
+
+
+
+
+
+
Regular scripts
+
These are run with the current app and note context. These can be run
+ either manually or automatically on start-up.
This allows rendering custom content inside a note, using either HTML
+ or Preact JSX.
+
+
+
+
+
For more advanced behaviors that do not require a user interface (e.g.
+ batch modifying notes), see Backend scripts.
Scripts
-
Scripts don't have any special requirements. They can be run at will using
- the execute button in the UI or they can be configured to run at certain
- times using Attributes on the note containing
- the script.
-
Global Events
-
This attribute is called #run and it can
- have any of the following values:
+
Scripts don't have any special requirements. They can be run manually
+ using the Execute button on the code note or they can be run automatically;
+ to do so, set the runlabel to
+ either:
-
frontendStartup - executes on frontend
- upon startup.
-
mobileStartup - executes on mobile frontend
- upon startup.
-
backendStartup - executes on backend upon
- startup.
-
hourly - executes once an hour on backend.
-
daily - executes once a day on backend.
-
-
Entity Events
-
These events are triggered by certain relations to
- other notes. Meaning that the script is triggered only if the note has
- this script attached to it through relations (or it can inherit it).
-
-
runOnNoteCreation - executes when note
- is created on backend.
-
runOnNoteTitleChange - executes when note
- title is changed (includes note creation as well).
-
runOnNoteContentChange - executes when
- note content is changed (includes note creation as well).
-
runOnNoteChange - executes when note is
- changed (includes note creation as well).
-
runOnNoteDeletion - executes when note
- is being deleted.
-
runOnBranchCreation - executes when a branch
- is created. Branch is a link between parent note and child note and is
- created e.g. when cloning or moving note.
-
runOnBranchDeletion - executes when a branch
- is delete. Branch is a link between parent note and child note and is deleted
- e.g. when moving note (old branch/link is deleted).
-
runOnChildNoteCreation - executes when
- new note is created under this note.
-
runOnAttributeCreation - executes when
- new attribute is created under this note.
-
runOnAttributeChange - executes when attribute
- is changed under this note.
+
frontendStartup - when Trilium frontend
+ starts up (or is refreshed), but not on mobile.
+
mobileStartup - when Trilium frontend starts
+ up (or is refreshed), on mobile.
+
Widgets
-
Conversely to scripts, widgets do have some specific requirements in order
- to work. A widget must:
+
Widgets require a certain format in order for Trilium to be able to integrate
+ them into the UI.
The front-end API of Trilium is available to all scripts running in the
+ front-end context as global variable api.
+ For a reference of the API, see Frontend API.
Tutorial
For more information on building widgets, take a look at Widget Basics.
\ No newline at end of file
diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets.html
index d46ac8b84f..416c15c107 100644
--- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets.html
+++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets.html
@@ -20,14 +20,15 @@
Let's start by creating a widget that shows a message near the content
@@ -61,76 +62,81 @@ export default defineWidget({
should appear underneath the content area.
Widget location (parent widget)
A widget can be placed in one of the following sections of the applications:
-
-
-
-
-
-
-
-
-
-
Value for parentWidget
-
-
Description
-
Sample widget
-
Special requirements
-
-
-
-
-
left-pane
-
-
Appears within the same pane that holds the Note Tree.
-
Same as above, with only a different parentWidget.
-
None.
-
-
-
center-pane
-
-
In the content area. If a split is open, the widget will span all of the
- splits.
-
See example above.
-
None.
-
-
-
note-detail-pane
-
-
-
In the content area, inside the note detail area. If a split is open,
- the widget will be contained inside the split.
The widget must export a class and not an instance of the class
- (e.g. no new) because it needs to be multiplied for each note,
- so that splits work correctly.
-
Since the class is exported instead of an instance, the parentWidget getter
- must be static, otherwise the widget is ignored.
The widget must export a class and not an
+ instance of the class (e.g. no new) because
+ it needs to be multiplied for each note, so that splits work correctly.
+
Since the class is exported instead of an
+ instance, the parentWidget getter must be
+ static, otherwise the widget is ignored.
Although not mandatory, it's best to use a RightPanelWidget instead
+ of a BasicWidget or a NoteContextAwareWidget.
+
+
+
+
+
To position the widget somewhere else, just change the value passed to
get parentWidget()for legacy widgets or the parent field
@@ -143,4 +149,13 @@ class="ck-table-resized">
to the Launch Bar.
See Launch Bar Widgets for
more information.
-
Custom position
\ No newline at end of file
+
Custom position
+
The position of a custom widget is defined via a position integer.
+
In legacy widgets:
class MyWidget extends api.BasicWidget {
+ // [..
+ get position() { return 10; }
+}
\ No newline at end of file
diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Scripting/Frontend Basics/Launch Bar Widgets.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Scripting/Frontend Basics/Launch Bar Widgets.html
index 3552ca4faa..c2b91ba4ed 100644
--- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Scripting/Frontend Basics/Launch Bar Widgets.html
+++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Scripting/Frontend Basics/Launch Bar Widgets.html
@@ -5,25 +5,31 @@
Unlike Custom Widgets,
the process of setting up a launch bar widget is slightly different:
-
Create a Code note of type JavaScript (front-end).
+
Create a Code note of type JavaScript (front-end) or JSX (for Preact-based
+ widgets).
The script itself uses the same concepts as Custom Widgets, including the use of a
NoteContextAwareWidgetor a BasicWidget (according
to needs).
\ No newline at end of file
diff --git a/docs/Developer Guide/Developer Guide/Documentation.md b/docs/Developer Guide/Developer Guide/Documentation.md
index 8b43e75bd5..6631466e38 100644
--- a/docs/Developer Guide/Developer Guide/Documentation.md
+++ b/docs/Developer Guide/Developer Guide/Documentation.md
@@ -1,5 +1,5 @@
# Documentation
-There are multiple types of documentation for Trilium:
+There are multiple types of documentation for Trilium:
* The _User Guide_ represents the user-facing documentation. This documentation can be browsed by users directly from within Trilium, by pressing F1.
* The _Developer's Guide_ represents a set of Markdown documents that present the internals of Trilium, for developers.
diff --git a/docs/User Guide/!!!meta.json b/docs/User Guide/!!!meta.json
index df7c61602d..817f450e42 100644
--- a/docs/User Guide/!!!meta.json
+++ b/docs/User Guide/!!!meta.json
@@ -6443,6 +6443,131 @@
"dataFileName": "3_Zen mode_image.png"
}
]
+ },
+ {
+ "isClone": false,
+ "noteId": "YzMcWlCVeW09",
+ "notePath": [
+ "pOsGYCXsbNQG",
+ "gh7bpGYxajRS",
+ "YzMcWlCVeW09"
+ ],
+ "title": "Active content",
+ "notePosition": 110,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bxs-widget",
+ "isInheritable": false,
+ "position": 30
+ },
+ {
+ "type": "label",
+ "name": "shareAlias",
+ "value": "active-content",
+ "isInheritable": false,
+ "position": 40
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "MgibgPcfeuGz",
+ "isInheritable": false,
+ "position": 50
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "1vHRoWCEjj0L",
+ "isInheritable": false,
+ "position": 70
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "yIhgI5H7A2Sm",
+ "isInheritable": false,
+ "position": 100
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "HcABDtFCkbFN",
+ "isInheritable": false,
+ "position": 110
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "RnaPdbciOfeq",
+ "isInheritable": false,
+ "position": 120
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "SPirpZypehBG",
+ "isInheritable": false,
+ "position": 130
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "mHbBMPDPkVV5",
+ "isInheritable": false,
+ "position": 150
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "AlhDUqhENtH7",
+ "isInheritable": false,
+ "position": 160
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "pKK96zzmvBGf",
+ "isInheritable": false,
+ "position": 170
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "gOKqSJgXLcIj",
+ "isInheritable": false,
+ "position": 180
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "64ZTlUPgEPtW",
+ "isInheritable": false,
+ "position": 190
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "HI6GBBIduIgv",
+ "isInheritable": false,
+ "position": 200
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "IjZS7iK5EXtb",
+ "isInheritable": false,
+ "position": 210
+ }
+ ],
+ "format": "markdown",
+ "dataFileName": "Active content.md",
+ "attachments": []
}
]
},
@@ -9884,6 +10009,13 @@
"value": "render-note",
"isInheritable": false,
"position": 70
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "yIhgI5H7A2Sm",
+ "isInheritable": false,
+ "position": 90
}
],
"format": "markdown",
@@ -16113,20 +16245,6 @@
"type": "text",
"mime": "text/markdown",
"attributes": [
- {
- "type": "relation",
- "name": "internalLink",
- "value": "GLks18SNjxmC",
- "isInheritable": false,
- "position": 10
- },
- {
- "type": "relation",
- "name": "internalLink",
- "value": "zEY4DaJG4YT5",
- "isInheritable": false,
- "position": 20
- },
{
"type": "relation",
"name": "internalLink",
@@ -16147,6 +16265,90 @@
"value": "bx bx-window",
"isInheritable": false,
"position": 40
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "Q2z6av6JZVWm",
+ "isInheritable": false,
+ "position": 50
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "GhurYZjh8e1V",
+ "isInheritable": false,
+ "position": 60
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "M8IppdwVHSjG",
+ "isInheritable": false,
+ "position": 70
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "MgibgPcfeuGz",
+ "isInheritable": false,
+ "position": 80
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "SPirpZypehBG",
+ "isInheritable": false,
+ "position": 90
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "RnaPdbciOfeq",
+ "isInheritable": false,
+ "position": 100
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "oPVyFC7WL2Lp",
+ "isInheritable": false,
+ "position": 110
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "4Gn3psZKsfSm",
+ "isInheritable": false,
+ "position": 120
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "xYmIYSP6wE3F",
+ "isInheritable": false,
+ "position": 130
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "HcABDtFCkbFN",
+ "isInheritable": false,
+ "position": 140
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "HI6GBBIduIgv",
+ "isInheritable": false,
+ "position": 150
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "GPERMystNGTB",
+ "isInheritable": false,
+ "position": 160
}
],
"format": "markdown",
@@ -16791,6 +16993,13 @@
"value": "launch-bar-widgets",
"isInheritable": false,
"position": 40
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "s8alTXmpFR61",
+ "isInheritable": false,
+ "position": 70
}
],
"format": "markdown",
@@ -17248,9 +17457,52 @@
"value": "bx bx-server",
"isInheritable": false,
"position": 40
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "yIhgI5H7A2Sm",
+ "isInheritable": false,
+ "position": 50
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "WOcw2SLH6tbX",
+ "isInheritable": false,
+ "position": 60
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "poXkQfguuA0U",
+ "isInheritable": false,
+ "position": 70
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "MEtfsqa5VwNi",
+ "isInheritable": false,
+ "position": 80
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "6f9hih2hXXZk",
+ "isInheritable": false,
+ "position": 90
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "GPERMystNGTB",
+ "isInheritable": false,
+ "position": 100
}
],
"format": "markdown",
+ "dataFileName": "Backend scripts.md",
"attachments": [],
"dirFileName": "Backend scripts",
"children": [
diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Active content.md b/docs/User Guide/User Guide/Basic Concepts and Features/Active content.md
new file mode 100644
index 0000000000..68aaec16f4
--- /dev/null
+++ b/docs/User Guide/User Guide/Basic Concepts and Features/Active content.md
@@ -0,0 +1,33 @@
+# Active content
+_Active content_ is a generic name for powerful features in Trilium, these range from customizing the UI to advanced scripting that can alter your notes or even your PC.
+
+## Safe import
+
+Active content problem of safety, especially when this active content comes from a third-party such as if it is downloaded from a website and then imported into Trilium.
+
+When [importing](Import%20%26%20Export.md) .zip archives into Trilium, _safe mode_ is active by default which will try to prevent untrusted code from executing. For example, a [custom widget](../Scripting/Frontend%20Basics/Custom%20Widgets.md) needs the `#widget` [label](../Advanced%20Usage/Attributes/Labels.md) in order to function; safe import works by renaming that label to `#disabled:widget`.
+
+## Safe mode
+
+Sometimes active content can cause issues with the UI or the server, preventing it from functioning properly. Safe mode allows starting Trilium in such a way that active content is not loaded by default at start-up, allowing the user to fix the problematic scripts or widgets.
+
+## Types of active content
+
+These are the types of active content in Trilium, along with a few examples of what untrusted content of that type could cause:
+
+| Name | Disabled on a safe [import](Import%20%26%20Export.md) | Description | Potential risks of untrusted code |
+| --- | --- | --- | --- |
+| [Front-end scripts](../Scripting/Frontend%20Basics.md) | Yes | Allow running arbitrary code on the client (UI) of Trilium, which can alter the user interface. | A malicious script can execute server-side code, access un-encrypted notes or change their contents. |
+| Custom Widgets | Yes | Can add new UI features to Trilium, for example by adding a new section in the Right Sidebar. | The UI can be altered in such a way that it can be used to extract sensitive information or it can simply cause the application to crash. |
+| Backend scripts | Yes | Can run custom code on the server of Trilium (Node.js environment), with full access to the notes and the database. | Has access to all the unencrypted notes, but with full access to the database it can completely destroy the data. It also has access to execute other applications or alter the files and folders on the server). |
+| Web View | Yes | Displays a website inside a note. | Can point to a phishing website which can collect the data (for example on a log in page). |
+| Render Note | Yes | Renders custom content inside a note, such as a dashboard or a new editor that is not officially supported by Trilium. | Can affect the UI similar to front-end scripts or custom widgets since the scripts are not completely encapsulated, or they can act similar to a web view where they can collect data entered by the user. |
+| Custom app-wide CSS | No | Can alter the layout and style of the UI using CSS, applied regardless of theme. | Generally less problematic than the rest of active content, but a badly written CSS can affect the layout of the application, requiring the use of Safe mode to be able to use the application. |
+| [Custom themes](../Theme%20development) | No | Can change the style of the entire UI. | Similar to custom app-wide CSS. |
+| Icon Packs | No | Introduces new icons that can be used for notes. | Generally are more contained and less prone to cause issues, but they can cause performance issues (for example if the icon pack has millions of icons in it). |
+
+## Active content badge
+
+Starting with v0.102.0, on the New Layout a badge will be displayed near the note title, indicating that an active content is detected. Clicking the badge will reveal a menu with various options related to that content type, for example to open the documentation or to configure the execution of scripts.
+
+For some active content types, such as backend scripts with custom triggering conditions a toggle button will appear. This makes it possible to easily disable scripts or widgets, but also to re-enable them if an import was made with safe mode active.
\ No newline at end of file
diff --git a/docs/User Guide/User Guide/Note Types/Render Note.md b/docs/User Guide/User Guide/Note Types/Render Note.md
index c0c4e4eeaa..60387ce507 100644
--- a/docs/User Guide/User Guide/Note Types/Render Note.md
+++ b/docs/User Guide/User Guide/Note Types/Render Note.md
@@ -1,11 +1,15 @@
# Render Note
-Render Note is used in Scripting. It works by displaying the HTML of a Code note, via an attribute.
+Render Note is a special case of [front-end scripting](../Scripting/Frontend%20Basics.md) which allows rendering custom content inside a note. This makes it possible to create custom dashboards, or to use a custom note editor.
+
+The content can either be a vanilla HTML, or Preact JSX.
## Creating a render note
-1. Create a Code note with the HTML language, with what needs to be displayed (for example `
Hello world.
`).
+1. Create a Code note with the:
+ 1. HTML language for the legacy/vanilla method, with what needs to be displayed (for example `
Hello world.
`).
+ 2. JSX for the Preact-based approach (see below).
2. Create a Render Note.
3. Assign the `renderNote` [relation](../Advanced%20Usage/Attributes.md) to point at the previously created code note.
@@ -44,7 +48,7 @@ Here are the steps to creating a simple render note:
2. Create a child Code note with JSX as the language.
As an example, use the following content:
- ```jsx
+ ```
export default function() {
return (
<>
diff --git a/docs/User Guide/User Guide/Scripting/Backend scripts.md b/docs/User Guide/User Guide/Scripting/Backend scripts.md
new file mode 100644
index 0000000000..7a6da5e3b7
--- /dev/null
+++ b/docs/User Guide/User Guide/Scripting/Backend scripts.md
@@ -0,0 +1,24 @@
+# Backend scripts
+Unlike [front-end scripts](Frontend%20Basics.md) which run on the client / browser-side, back-end scripts run directly on the Node.js environment of the Trilium server.
+
+Back-end scripts can be used both on a Server Installation (where it will run on the device the server is running on), or on the Desktop Installation (where it will run on the PC).
+
+## Advantages of backend scripts
+
+The benefit of backend scripts is that they can be pretty powerful, for example to have access to the underlying system, for example it can read files or execute processes.
+
+However, the main benefit of backend scripts is that they have easier access to the notes since the information about them is already loaded in memory. Whereas on the client, notes have to be manually loaded first.
+
+## Creating a backend script
+
+Create a new Code note and select the language _JS backend_.
+
+## Running backend scripts
+
+Backend scripts can be either run manually (via the Execute button on the script page), or they can be triggered on certain events.
+
+In addition, scripts can be run automatically when the server starts up, on a fixed time interval or when a certain event occurs (such as an attribute being modified). For more information, see the dedicated Events page.
+
+## Script API
+
+Trilium exposes a set of APIs that can be directly consumed by scripts, under the `api` object. For a reference of this API, see Backend API.
\ No newline at end of file
diff --git a/docs/User Guide/User Guide/Scripting/Backend scripts/Events.md b/docs/User Guide/User Guide/Scripting/Backend scripts/Events.md
index 27fedb9489..ff6f1973e4 100644
--- a/docs/User Guide/User Guide/Scripting/Backend scripts/Events.md
+++ b/docs/User Guide/User Guide/Scripting/Backend scripts/Events.md
@@ -5,7 +5,7 @@
Global events are attached to the script note via label. Simply create e.g. "run" label with some of these values and script note will be executed once the event occurs.
-
Label
Description
run
Defines on which events script should run. Possible values are:
frontendStartup - when Trilium frontend starts up (or is refreshed), but not on mobile.
mobileStartup - when Trilium frontend starts up (or is refreshed), on mobile.
backendStartup - when Trilium backend starts up
hourly - run once an hour. You can use additional label runAtHour to specify at which hour, on the back-end.
daily - run once a day, on the back-end
runOnInstance
Specifies that the script should only run on a particular Trilium instance.
runAtHour
On which hour should this run. Should be used together with #run=hourly. Can be defined multiple times for more runs during the day.
+
Label
Description
run
Defines on which events script should run. Possible values are:
backendStartup - when Trilium backend starts up
hourly - run once an hour. You can use additional label runAtHour to specify at which hour, on the back-end.
daily - run once a day, on the back-end
runOnInstance
Specifies that the script should only run on a particular Trilium instance.
runAtHour
On which hour should this run. Should be used together with #run=hourly. Can be defined multiple times for more runs during the day.
## Entity events
diff --git a/docs/User Guide/User Guide/Scripting/Frontend Basics.md b/docs/User Guide/User Guide/Scripting/Frontend Basics.md
index 13c47823dc..52118eba5a 100644
--- a/docs/User Guide/User Guide/Scripting/Frontend Basics.md
+++ b/docs/User Guide/User Guide/Scripting/Frontend Basics.md
@@ -1,56 +1,39 @@
# Frontend Basics
-## Frontend API
+Front-end scripts are custom JavaScript notes that are run on the client (browser environment)
-The frontend api supports two styles, regular scripts that are run with the current app and note context, and widgets that export an object to Trilium to be used in the UI. In both cases, the frontend api of Trilium is available to scripts running in the frontend context as global variable `api`. The members and methods of the api can be seen on the [Script API](Script%20API.md) page.
+There are four flavors of front-end scripts:
+
+| | |
+| --- | --- |
+| Regular scripts | These are run with the current app and note context. These can be run either manually or automatically on start-up. |
+| Custom Widgets | These can introduce new UI elements in various positions, such as near the Note Tree, content area or even the Right Sidebar. |
+| Launch Bar Widgets | Similar to Custom Widgets, but dedicated to the Launch Bar. These can simply introduce new buttons or graphical elements to the bar. |
+| Render Note | This allows rendering custom content inside a note, using either HTML or Preact JSX. |
+
+For more advanced behaviors that do not require a user interface (e.g. batch modifying notes), see Backend scripts.
## Scripts
-Scripts don't have any special requirements. They can be run at will using the execute button in the UI or they can be configured to run at certain times using [Attributes](../Advanced%20Usage/Attributes.md) on the note containing the script.
+Scripts don't have any special requirements. They can be run manually using the _Execute_ button on the code note or they can be run automatically; to do so, set the `run` [label](../Advanced%20Usage/Attributes/Labels.md) to either:
-### Global Events
+* `frontendStartup` - when Trilium frontend starts up (or is refreshed), but not on mobile.
+* `mobileStartup` - when Trilium frontend starts up (or is refreshed), on mobile.
-This attribute is called `#run` and it can have any of the following values:
-
-* `frontendStartup` - executes on frontend upon startup.
-* `mobileStartup` - executes on mobile frontend upon startup.
-* `backendStartup` - executes on backend upon startup.
-* `hourly` - executes once an hour on backend.
-* `daily` - executes once a day on backend.
-
-### Entity Events
-
-These events are triggered by certain [relations](../Advanced%20Usage/Attributes.md) to other notes. Meaning that the script is triggered only if the note has this script attached to it through relations (or it can inherit it).
-
-* `runOnNoteCreation` - executes when note is created on backend.
-* `runOnNoteTitleChange` - executes when note title is changed (includes note creation as well).
-* `runOnNoteContentChange` - executes when note content is changed (includes note creation as well).
-* `runOnNoteChange` - executes when note is changed (includes note creation as well).
-* `runOnNoteDeletion` - executes when note is being deleted.
-* `runOnBranchCreation` - executes when a branch is created. Branch is a link between parent note and child note and is created e.g. when cloning or moving note.
-* `runOnBranchDeletion` - executes when a branch is delete. Branch is a link between parent note and child note and is deleted e.g. when moving note (old branch/link is deleted).
-* `runOnChildNoteCreation` - executes when new note is created under this note.
-* `runOnAttributeCreation` - executes when new attribute is created under this note.
-* `runOnAttributeChange` - executes when attribute is changed under this note.
+> [!NOTE]
+> Backend scripts have more powerful triggering conditions, for example they can run automatically on a hourly or daily basis, but also on events such as when a note is created or an attribute is modified. See the server-side Events for more information.
## Widgets
-Conversely to scripts, widgets do have some specific requirements in order to work. A widget must:
+Widgets require a certain format in order for Trilium to be able to integrate them into the UI.
-* Extend [BasicWidget](https://triliumnext.github.io/Notes/frontend_api/BasicWidget.html) or one of it's subclasses.
-* Create a new instance and assign it to `module.exports`.
-* Define a `parentWidget` member to determine where it should be displayed.
-* Define a `position` (integer) that determines the location via sort order.
-* Have a `#widget` attribute on the containing note.
-* Create, render, and return your element in the render function.
- * For [BasicWidget](https://triliumnext.github.io/Notes/frontend_api/BasicWidget.html) and [NoteContextAwareWidget](https://triliumnext.github.io/Notes/frontend_api/NoteContextAwareWidget.html)you should create `this.$widget` and render it in `doRender()`.
- * For [RightPanelWidget](https://triliumnext.github.io/Notes/frontend_api/RightPanelWidget.html) the `this.$widget` and `doRender()` are already handled and you should instead return the value in `doRenderBody()`.
+* For legacy widgets, the script note must export a `BasicWidget` or a derived one (see Note context aware widget or Right pane widget).
+* For Preact widgets, a built-in helper called `defineWidget` needs to be used.
-### parentWidget
+For more information, see Custom Widgets.
-* `left-pane` - This renders the widget on the left side of the screen where the note tree lives.
-* `center-pane` - This renders the widget in the center of the layout in the same location that notes and splits appear.
-* `note-detail-pane` - This renders the widget _with_ the note in the center pane. This means it can appear multiple times with splits.
-* `right-pane` - This renders the widget to the right of any opened notes.
+## Script API
+
+The front-end API of Trilium is available to all scripts running in the front-end context as global variable `api`. For a reference of the API, see Frontend API.
### Tutorial
diff --git a/docs/User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets.md b/docs/User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets.md
index dec4cfd3fe..9963e37c1b 100644
--- a/docs/User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets.md
+++ b/docs/User Guide/User Guide/Scripting/Frontend Basics/Custom Widgets.md
@@ -63,7 +63,7 @@ export default defineWidget({
A widget can be placed in one of the following sections of the applications:
-
Value for parentWidget
Description
Sample widget
Special requirements
left-pane
Appears within the same pane that holds the Note Tree.
Same as above, with only a different parentWidget.
None.
center-pane
In the content area. If a split is open, the widget will span all of the splits.
See example above.
None.
note-detail-pane
In the content area, inside the note detail area. If a split is open, the widget will be contained inside the split.
The widget must export a class and not an instance of the class (e.g. no new) because it needs to be multiplied for each note, so that splits work correctly.
Since the class is exported instead of an instance, the parentWidget getter must be static, otherwise the widget is ignored.
The widget must export a class and not an instance of the class (e.g. no new) because it needs to be multiplied for each note, so that splits work correctly.
Since the class is exported instead of an instance, the parentWidget getter must be static, otherwise the widget is ignored.
Although not mandatory, it's best to use a RightPanelWidget instead of a BasicWidget or a NoteContextAwareWidget.
To position the widget somewhere else, just change the value passed to `get parentWidget()` for legacy widgets or the `parent` field for Preact. Do note that some positions such as `note-detail-pane` and `right-pane` have special requirements that need to be accounted for (see the table above).
@@ -71,4 +71,24 @@ To position the widget somewhere else, just change the value passed to `get pare
Launch bar widgets are similar to _Custom widgets_ but are specific to the Launch Bar. See Launch Bar Widgets for more information.
-## Custom position
\ No newline at end of file
+## Custom position
+
+The position of a custom widget is defined via a `position` integer.
+
+In legacy widgets:
+
+```
+class MyWidget extends api.BasicWidget {
+ // [..
+ get position() { return 10; }
+}
+```
+
+In Preact widgets:
+
+```
+export default defineWidget({
+ // [...]
+ position: 10
+});
+```
\ No newline at end of file
diff --git a/docs/User Guide/User Guide/Scripting/Frontend Basics/Launch Bar Widgets.md b/docs/User Guide/User Guide/Scripting/Frontend Basics/Launch Bar Widgets.md
index 7f9bef7a4d..e5d25b0198 100644
--- a/docs/User Guide/User Guide/Scripting/Frontend Basics/Launch Bar Widgets.md
+++ b/docs/User Guide/User Guide/Scripting/Frontend Basics/Launch Bar Widgets.md
@@ -5,12 +5,12 @@ Launch bar widgets are a subset of Custom Widgets, the process of setting up a launch bar widget is slightly different:
-1. Create a Code note of type _JavaScript (front-end)_.
+1. Create a Code note of type _JavaScript (front-end)_ or JSX (for Preact-based widgets).
* The script itself uses the same concepts as Custom Widgets, including the use of a `NoteContextAwareWidget` or a `BasicWidget` (according to needs).
- * As examples, see Note Title Widget and Analog Watch.
+ * As examples in both legacy and Preact format, see Note Title Widget and Analog Watch.
2. Don't set `#widget`, as that attribute is reserved for Custom Widgets.
3. In the Global menu, select _Configure launchbar_.
4. In the _Visible Launchers_ section, select _Add a custom widget_.
5. Give the newly created launcher a name (and optionally a name).
6. In the Promoted Attributes section, modify the _widget_ field to point to the newly created note.
-7. Refresh the UI.
\ No newline at end of file
+7. [Refresh](../../Troubleshooting/Refreshing%20the%20application.md) the UI.
\ No newline at end of file