mirror of
https://github.com/TriliumNext/Notes.git
synced 2025-07-27 18:12:29 +08:00
Merge branch 'develop' into build_improve-electron-forge_v3
This commit is contained in:
commit
c1acaa0159
6
.github/workflows/dev.yml
vendored
6
.github/workflows/dev.yml
vendored
@ -1,9 +1,9 @@
|
|||||||
name: Dev
|
name: Dev
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches-ignore:
|
branches: [ develop ]
|
||||||
- 'develop'
|
pull_request:
|
||||||
- 'feature/update**'
|
branches: [ develop ]
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
"pOsGYCXsbNQG"
|
"pOsGYCXsbNQG"
|
||||||
],
|
],
|
||||||
"title": "User Guide",
|
"title": "User Guide",
|
||||||
"notePosition": 90,
|
"notePosition": 10,
|
||||||
"prefix": null,
|
"prefix": null,
|
||||||
"isExpanded": false,
|
"isExpanded": false,
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@ -1481,13 +1481,6 @@
|
|||||||
"type": "text",
|
"type": "text",
|
||||||
"mime": "text/markdown",
|
"mime": "text/markdown",
|
||||||
"attributes": [
|
"attributes": [
|
||||||
{
|
|
||||||
"type": "relation",
|
|
||||||
"name": "imageLink",
|
|
||||||
"value": "JXFeNgU8Xnp1",
|
|
||||||
"isInheritable": false,
|
|
||||||
"position": 10
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "relation",
|
"type": "relation",
|
||||||
"name": "internalLink",
|
"name": "internalLink",
|
||||||
@ -1516,13 +1509,6 @@
|
|||||||
"isInheritable": false,
|
"isInheritable": false,
|
||||||
"position": 50
|
"position": 50
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "relation",
|
|
||||||
"name": "internalLink",
|
|
||||||
"value": "BFs8mudNFgCS",
|
|
||||||
"isInheritable": false,
|
|
||||||
"position": 60
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "label",
|
"type": "label",
|
||||||
"name": "shareAlias",
|
"name": "shareAlias",
|
||||||
@ -1648,13 +1634,6 @@
|
|||||||
"isInheritable": false,
|
"isInheritable": false,
|
||||||
"position": 40
|
"position": 40
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "relation",
|
|
||||||
"name": "internalLink",
|
|
||||||
"value": "_lbSettings",
|
|
||||||
"isInheritable": false,
|
|
||||||
"position": 50
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "label",
|
"type": "label",
|
||||||
"name": "iconClass",
|
"name": "iconClass",
|
||||||
@ -6553,6 +6532,13 @@
|
|||||||
"value": "bx bx-question-mark",
|
"value": "bx bx-question-mark",
|
||||||
"isInheritable": false,
|
"isInheritable": false,
|
||||||
"position": 40
|
"position": 40
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "relation",
|
||||||
|
"name": "internalLink",
|
||||||
|
"value": "wy8So3yZZlH9",
|
||||||
|
"isInheritable": false,
|
||||||
|
"position": 80
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"format": "markdown",
|
"format": "markdown",
|
||||||
|
@ -15,4 +15,4 @@ After importing the ENEX file, go over the imported notes and resources to be su
|
|||||||
|
|
||||||
All resources (except for images) are created as note's attachments.
|
All resources (except for images) are created as note's attachments.
|
||||||
|
|
||||||
HTML inside ENEX files is not exactly valid so some formatting maybe broken or lost. You can report major problems into [Trilium issue tracker](https://github.com/TriliumNext/Notes/issues). %%{WARNING}%%
|
HTML inside ENEX files is not exactly valid so some formatting maybe broken or lost. You can report major problems into [Trilium issue tracker](https://github.com/TriliumNext/Notes/issues).
|
@ -1,23 +1,17 @@
|
|||||||
# FAQ
|
# FAQ
|
||||||
## Mac OS support
|
## macOS support
|
||||||
|
|
||||||
Originally, desktop builds of Trilium Notes has been available for Windows & Linux, but there has been a considerable demand for macOS build.
|
Originally, Trilium Notes considered the macOS build unsupported. TriliumNext commits to make the experience on macOS as good as possible.
|
||||||
|
|
||||||
So I made one, but I underestimated the differences and specifics of Mac platform which seems to require special handling in several places. My lack of knowledge and frankly willingness to learn & code Mac specific functionality resulted in a current state where [Trilium does not integrate well into the OS](https://github.com/TriliumNext/Notes/issues/511)
|
if you find any platform-specific issues, feel free to [report them](Troubleshooting/Reporting%20issues.md).
|
||||||
|
|
||||||
%%{WARNING}%%.
|
## Translation / localisation support
|
||||||
|
|
||||||
macOS build is from now on considered "unsupported". I will strive to keep it fundamentally functional, but I won't work on Mac specific features or integrations. Note that this is more of an acknowledgment of an existing state rather than sudden change of direction.
|
The original Trilium Notes application did not support multiple languages. Since we believe that internationalisation is a core part of an application, we have added support for it.
|
||||||
|
|
||||||
Of course, PRs are welcome.
|
Contributions to translations are welcome.
|
||||||
|
|
||||||
## Translation / localization support
|
## Multi-user support
|
||||||
|
|
||||||
Trilium is currently available only in English. Translation to other languages is not planned in the near/medium term because it brings a significant maintenance overhead. This decision might be revisited once Trilium stabilizes into a more mature product.
|
|
||||||
|
|
||||||
For Chinese, there's an unofficial fork [here](https://github.com/Nriver/trilium-translation). Use at your own risk.
|
|
||||||
|
|
||||||
## Multi user support
|
|
||||||
|
|
||||||
Common request is to allow multiple users collaborate, share notes etc. So far I'm resisting this because of these reasons:
|
Common request is to allow multiple users collaborate, share notes etc. So far I'm resisting this because of these reasons:
|
||||||
|
|
||||||
@ -41,7 +35,9 @@ No.
|
|||||||
|
|
||||||
These general purpose sync apps are not suitable to sync database files which are open and being worked on by another application. The result is that they will corrupt the database file, resulting in data loss and this message in the Trilium logs:
|
These general purpose sync apps are not suitable to sync database files which are open and being worked on by another application. The result is that they will corrupt the database file, resulting in data loss and this message in the Trilium logs:
|
||||||
|
|
||||||
> SqliteError: database disk image is malformed
|
```
|
||||||
|
SqliteError: database disk image is malformed
|
||||||
|
```
|
||||||
|
|
||||||
The only supported way to sync Trilium's data across the network is to use a [sync/web server](Installation%20%26%20Setup/Synchronization.md).
|
The only supported way to sync Trilium's data across the network is to use a [sync/web server](Installation%20%26%20Setup/Synchronization.md).
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ Let's assume you want to restore the weekly backup, here's how to do it:
|
|||||||
|
|
||||||
* find [data directory](Data%20directory.md) Trilium uses - easy way is to open "About Trilium Notes" from "Menu" in upper left corner and looking at "data directory"
|
* find [data directory](Data%20directory.md) Trilium uses - easy way is to open "About Trilium Notes" from "Menu" in upper left corner and looking at "data directory"
|
||||||
* I'll refer to `~/trilium-data` as data directory from now on
|
* I'll refer to `~/trilium-data` as data directory from now on
|
||||||
* find `~/trilium-data/backup/backup-weekly.db` - this is the [document](#root/xjSsCcvVZf6H)backup
|
* find `~/trilium-data/backup/backup-weekly.db` - this is the [document](#root/xjSsCcvVZf6H) backup
|
||||||
* at this point stop/kill Trilium
|
* at this point stop/kill Trilium
|
||||||
* delete `~/trilium-data/document.db`, `~/trilium-data/document.db-wal` and `~/trilium-data/document.db-shm` (latter two files are auto generated)
|
* delete `~/trilium-data/document.db`, `~/trilium-data/document.db-wal` and `~/trilium-data/document.db-shm` (latter two files are auto generated)
|
||||||
* copy and rename this `~/trilium-data/backup/backup-weekly.db` to `~/trilium-data/document.db`
|
* copy and rename this `~/trilium-data/backup/backup-weekly.db` to `~/trilium-data/document.db`
|
||||||
@ -40,4 +40,4 @@ noBackup=true
|
|||||||
|
|
||||||
You can also review the [configuration](../Advanced%20Usage/Configuration%20\(config.ini%20or%20e.md) file to provide all `config.ini` values as environment variables instead.
|
You can also review the [configuration](../Advanced%20Usage/Configuration%20\(config.ini%20or%20e.md) file to provide all `config.ini` values as environment variables instead.
|
||||||
|
|
||||||
See [sample config](https://github.com/TriliumNext/Notes/blob/master/config-sample.ini). %%{WARNING}%%
|
See [sample config](https://github.com/TriliumNext/Notes/blob/master/config-sample.ini).
|
@ -9,7 +9,8 @@ If you need help installing Docker, reference the [Docker Installation Docs](htt
|
|||||||
|
|
||||||
**Note:** Trilium's Docker container requires root privileges to operate correctly.
|
**Note:** Trilium's Docker container requires root privileges to operate correctly.
|
||||||
|
|
||||||
> \[!WARNING\] If you're using a SMB/CIFS share or folder as your Trilium data directory, [you'll need](https://github.com/TriliumNext/Notes/issues/415#issuecomment-2344824400) to add the mount options of `nobrl` and `noperm` when mounting your SMB share.
|
> [!WARNING]
|
||||||
|
> If you're using a SMB/CIFS share or folder as your Trilium data directory, [you'll need](https://github.com/TriliumNext/Notes/issues/415#issuecomment-2344824400) to add the mount options of `nobrl` and `noperm` when mounting your SMB share.
|
||||||
|
|
||||||
## Running with Docker Compose
|
## Running with Docker Compose
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ The recommended way is to use a Helm chart.
|
|||||||
|
|
||||||
## Root privileges
|
## Root privileges
|
||||||
|
|
||||||
> \[!NOTE\]
|
> [!NOTE]
|
||||||
> The Trilium container at this time needs to be run with root privileges. It will swap to UID and GID `1000:1000` to run the `node` process after execution though, so the main process doesn't run with root privileges.
|
> The Trilium container at this time needs to be run with root privileges. It will swap to UID and GID `1000:1000` to run the `node` process after execution though, so the main process doesn't run with root privileges.
|
||||||
|
|
||||||
The Trilium docker container needs to be run with root privileges. The node process inside the container will be started with reduced privileges (uid:gid 1000:1000) after some initialization logic. Please make sure that you don't use a security context (PodSecurityContext) which changes the user ID. To use a different uid:gid for file storage and the application, please use the `USER_UID` & `USER_GID` environment variables.
|
The Trilium docker container needs to be run with root privileges. The node process inside the container will be started with reduced privileges (uid:gid 1000:1000) after some initialization logic. Please make sure that you don't use a security context (PodSecurityContext) which changes the user ID. To use a different uid:gid for file storage and the application, please use the `USER_UID` & `USER_GID` environment variables.
|
||||||
|
@ -25,10 +25,12 @@ sudo apt install libpng16-16 libpng-dev pkg-config autoconf libtool build-essent
|
|||||||
|
|
||||||
### Download
|
### Download
|
||||||
|
|
||||||
You can either download source code zip/tar from [https://github.com/TriliumNext/Notes/releases/latest\]\]](https://github.com/TriliumNext/Notes/releases/latest%5D%5D) %%{WARNING}%%or clone git repository **from stable branch** with
|
You can either download source code zip/tar from [https://github.com/TriliumNext/Notes/releases/latest](https://github.com/TriliumNext/Notes/releases/latest).
|
||||||
|
|
||||||
|
For the latest version including betas, clone Git repository **from** `**master**` **branch** with:
|
||||||
|
|
||||||
```
|
```
|
||||||
git clone -b stable https://github.com/triliumnext/notes.git %%{WARNING}%%
|
git clone -b master https://github.com/triliumnext/notes.git
|
||||||
```
|
```
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
@ -3,9 +3,9 @@ This is essentially Trilium sources + node modules + node.js runtime packaged in
|
|||||||
|
|
||||||
## Steps
|
## Steps
|
||||||
|
|
||||||
* ssh into your server
|
* SSH into your server
|
||||||
* use `wget` (or `curl` or whatever) to download latest [trilium-linux-x64-server-\[VERSION\].xz](https://github.com/TriliumNext/Notes/releases/latest)%%{WARNING}%% (notice -server suffix) on your server
|
* use `wget` (or `curl`) to download latest `TriliumNextNotes-Server-[VERSION]-linux-x64.tar.xz` (notice `-Server` suffix) on your server.
|
||||||
* unpack the archive, e.g. using `tar -xf -d trilium-linux-x64-server-[VERSION].tar.xz`
|
* unpack the archive, e.g. using `tar -xf -d TriliumNextNotes-Server-[VERSION]-linux-x64.tar.xz`
|
||||||
* `cd trilium-linux-x64-server`
|
* `cd trilium-linux-x64-server`
|
||||||
* `./trilium.sh`
|
* `./trilium.sh`
|
||||||
* you can open the browser and open http://\[your-server-hostname\]:8080 and you should see Trilium initialization page
|
* you can open the browser and open http://\[your-server-hostname\]:8080 and you should see Trilium initialization page
|
||||||
@ -20,7 +20,7 @@ The problem with above steps is that once you close the SSH connection, the Tril
|
|||||||
* After downloading, extract and move Trilium:
|
* After downloading, extract and move Trilium:
|
||||||
|
|
||||||
```
|
```
|
||||||
tar -xvf trilium-linux-x64-server-[VERSION].tar.xz
|
tar -xvf TriliumNextNotes-Server-[VERSION]-linux-x64.tar.xz
|
||||||
sudo mv trilium-linux-x64-server /opt/trilium
|
sudo mv trilium-linux-x64-server /opt/trilium
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ If there's multiple clippings from the same page (and on the same day), then the
|
|||||||
**Extension is available from:**
|
**Extension is available from:**
|
||||||
|
|
||||||
* [Project release page](https://github.com/TriliumNext/web-clipper/releases) - .xpi for Firefox and .zip for Chromium based browsers.
|
* [Project release page](https://github.com/TriliumNext/web-clipper/releases) - .xpi for Firefox and .zip for Chromium based browsers.
|
||||||
* %%{WARNING}%% [Chrome Web Store](https://chromewebstore.google.com/detail/trilium-web-clipper/dfhgmnfclbebfobmblelddiejjcijbjm)
|
* [Chrome Web Store](https://chromewebstore.google.com/detail/trilium-web-clipper/dfhgmnfclbebfobmblelddiejjcijbjm)
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
|
@ -52,18 +52,22 @@ For each note of the calendar, the following attributes can be used:
|
|||||||
| `#calendar:color` | Similar to `#color`, but applies the color only for the event in the calendar and not for other places such as the note tree. |
|
| `#calendar:color` | Similar to `#color`, but applies the color only for the event in the calendar and not for other places such as the note tree. |
|
||||||
| `#iconClass` | If present, the icon of the note will be displayed to the left of the event title. |
|
| `#iconClass` | If present, the icon of the note will be displayed to the left of the event title. |
|
||||||
| `#calendar:title` | Changes the title of an event to point to an attribute of the note other than the title, either a label (e.g. `#assignee`) or a relation (e.g. `~for`). See _Advanced use-cases_ for more information. |
|
| `#calendar:title` | Changes the title of an event to point to an attribute of the note other than the title, either a label (e.g. `#assignee`) or a relation (e.g. `~for`). See _Advanced use-cases_ for more information. |
|
||||||
| `#calendar:promotedAttributes` | Allows displaying the value of one or more promoted attributes in the calendar like this:  <br> <br>`<br>#label:weight="promoted,number,single,precision=1"<br>#label:mood="promoted,alias=Mood,single,text"<br>#calendar:promotedAttributes="label:weight,label:mood" <br>` <br> <br>It can also be used with relations, case in which it will display the title of the target note: <br> <br>`<br>#relation:assignee="promoted,alias=Assignee,single,text"<br>#calendar:promotedAttributes="relation:assignee" <br>~assignee=@My assignee <br>` |
|
| `#calendar:displayedAttributes` | Allows displaying the value of one or more attributes in the calendar like this: <br><br><br><br>```<br>#weight="70"<br>#Mood="Good"<br>#calendar:displayedAttributes="weight,Mood"<br>```<br><br>It can also be used with relations, case in which it will display the title of the target note:<br><br>```<br>~assignee=@My assignee<br>#calendar:displayedAttributes="assignee"<br>``` |
|
||||||
| `#calendar:startDate` | Allows using a different label to represent the start date, other than `#startDate` (e.g. `#expiryDate`). The label name must be prefixed with `#`. If the label is not defined for a note, the default will be used instead. |
|
| `#calendar:startDate` | Allows using a different label to represent the start date, other than `startDate` (e.g. `expiryDate`). The label name **must not be** prefixed with `#`. If the label is not defined for a note, the default will be used instead. |
|
||||||
| `#calendar:endDate` | Allows using a different label to represent the start date, other than `#endDate`. The label name must be prefixed with `#`. If the label is not defined for a note, the default will be used instead. |
|
| `#calendar:endDate` | Allows using a different label to represent the start date, other than `endDate`. The label name **must not be** prefixed with `#`. If the label is not defined for a note, the default will be used instead. |
|
||||||
|
|
||||||
## How the calendar works
|
## How the calendar works
|
||||||
|
|
||||||
The calendar displays all the child notes of the book that have a `#startDate`. An `#endDate` can optionally be added.
|

|
||||||
|
|
||||||
|
The calendar displays all the child notes of the book that have a `#startDate`. An `#endDate` can optionally be added.
|
||||||
|
|
||||||
If editing the start date and end date from the note itself is desirable, the following attributes can be added to the book note:
|
If editing the start date and end date from the note itself is desirable, the following attributes can be added to the book note:
|
||||||
|
|
||||||
```
|
```
|
||||||
#viewType=calendar #label:startDate(inheritable)="promoted,alias=Start Date,single,date" #label:endDate(inheritable)="promoted,alias=End Date,single,date" #hidePromotedAttributes
|
#viewType=calendar #label:startDate(inheritable)="promoted,alias=Start Date,single,date"
|
||||||
|
#label:endDate(inheritable)="promoted,alias=End Date,single,date"
|
||||||
|
#hidePromotedAttributes
|
||||||
```
|
```
|
||||||
|
|
||||||
This will result in:
|
This will result in:
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# Content language & Right-to-left support
|
# Content language & Right-to-left support
|
||||||

|

|
||||||
|
|
||||||
A language hint can be provided for text notes. This option informs the browser or the desktop application about the language the note is written in (for example this might help with spellchecking), and it also determines whether the text is displayed from right-to-left for languages such as Arabic, Hebrew, etc.
|
A language hint can be provided for text notes. This option informs the browser or the desktop application about the language the note is written in (for example this might help with spellchecking), and it also determines whether the text is displayed from right-to-left for languages such as Arabic, Hebrew, etc.
|
||||||
|
|
||||||
|
@ -9,16 +9,11 @@
|
|||||||
|
|
||||||
1. [Server installation](Installation%20%26%20Setup/Server%20Installation.md)
|
1. [Server installation](Installation%20%26%20Setup/Server%20Installation.md)
|
||||||
2. [Mobile frontend](Installation%20%26%20Setup/Mobile%20Frontend.md) (optional)
|
2. [Mobile frontend](Installation%20%26%20Setup/Mobile%20Frontend.md) (optional)
|
||||||
3. [](https://heroku.com/deploy?template=https://github.com/feilongfl/trilium-heroku) %%{WARNING}%%
|
3. [PikaPods managed hosting](https://www.pikapods.com/pods?run=trilium-next)
|
||||||
4. [PikaPods managed hosting](https://www.pikapods.com/pods?run=trilium-next)
|
|
||||||
|
|
||||||
**Combination of server and desktop/laptop** - Install the application on both a server, for web access and data synchronization, and desktop instance(s). This allows all the data to be stored on the server and either accessed from the web browser, or the desktop application. The desktop application will sync and store the data locally so that it can be used when offline.
|
**Combination of server and desktop/laptop** - Install the application on both a server, for web access and data synchronisation, and desktop instance(s). This allows all the data to be stored on the server and either accessed from the web browser, or the desktop application. The desktop application will sync and store the data locally so that it can be used when offline.
|
||||||
|
|
||||||
1. [Server installation](Installation%20%26%20Setup/Server%20Installation.md)
|
1. [Server installation](Installation%20%26%20Setup/Server%20Installation.md)
|
||||||
2. [Mobile frontend](Installation%20%26%20Setup/Mobile%20Frontend.md) (optional)
|
2. [Mobile frontend](Installation%20%26%20Setup/Mobile%20Frontend.md) (optional)
|
||||||
3. [Desktop installation](Installation%20%26%20Setup/Desktop%20Installation.md)
|
3. [Desktop installation](Installation%20%26%20Setup/Desktop%20Installation.md)
|
||||||
4. [Synchronization](Installation%20%26%20Setup/Synchronization.md)
|
4. [Synchronization](Installation%20%26%20Setup/Synchronization.md)
|
||||||
|
|
||||||
## Basic concepts
|
|
||||||
|
|
||||||
1. Understand [Note](Basic%20Concepts/Note.md)
|
|
1
libraries/ckeditor/ckeditor-content.css
vendored
1
libraries/ckeditor/ckeditor-content.css
vendored
@ -27,6 +27,7 @@
|
|||||||
margin: 1.25em 0;
|
margin: 1.25em 0;
|
||||||
margin-right: 14px;
|
margin-right: 14px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ck-content .admonition p:last-child {
|
.ck-content .admonition p:last-child {
|
||||||
|
138
package-lock.json
generated
138
package-lock.json
generated
@ -20,7 +20,6 @@
|
|||||||
"@mermaid-js/layout-elk": "0.1.7",
|
"@mermaid-js/layout-elk": "0.1.7",
|
||||||
"@mind-elixir/node-menu": "1.0.4",
|
"@mind-elixir/node-menu": "1.0.4",
|
||||||
"@triliumnext/express-partial-content": "1.0.1",
|
"@triliumnext/express-partial-content": "1.0.1",
|
||||||
"@types/html-minifier": "4.0.5",
|
|
||||||
"archiver": "7.0.1",
|
"archiver": "7.0.1",
|
||||||
"async-mutex": "0.5.0",
|
"async-mutex": "0.5.0",
|
||||||
"autocomplete.js": "0.38.1",
|
"autocomplete.js": "0.38.1",
|
||||||
@ -53,7 +52,6 @@
|
|||||||
"fs-extra": "11.3.0",
|
"fs-extra": "11.3.0",
|
||||||
"helmet": "8.0.0",
|
"helmet": "8.0.0",
|
||||||
"html": "1.0.0",
|
"html": "1.0.0",
|
||||||
"html-minifier": "4.0.0",
|
|
||||||
"html2plaintext": "2.1.4",
|
"html2plaintext": "2.1.4",
|
||||||
"http-proxy-agent": "7.0.2",
|
"http-proxy-agent": "7.0.2",
|
||||||
"https-proxy-agent": "7.0.6",
|
"https-proxy-agent": "7.0.6",
|
||||||
@ -5247,16 +5245,6 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/clean-css": {
|
|
||||||
"version": "4.2.11",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/clean-css/-/clean-css-4.2.11.tgz",
|
|
||||||
"integrity": "sha512-Y8n81lQVTAfP2TOdtJJEsCoYl1AnOkqDqMvXb9/7pfgZZ7r8YrEyurrAvAoAjHOGXKRybay+5CsExqIH6liccw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@types/node": "*",
|
|
||||||
"source-map": "^0.6.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@types/cls-hooked": {
|
"node_modules/@types/cls-hooked": {
|
||||||
"version": "4.3.9",
|
"version": "4.3.9",
|
||||||
"resolved": "https://registry.npmjs.org/@types/cls-hooked/-/cls-hooked-4.3.9.tgz",
|
"resolved": "https://registry.npmjs.org/@types/cls-hooked/-/cls-hooked-4.3.9.tgz",
|
||||||
@ -5705,17 +5693,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@types/html-minifier": {
|
|
||||||
"version": "4.0.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/html-minifier/-/html-minifier-4.0.5.tgz",
|
|
||||||
"integrity": "sha512-LfE7f7MFd+YUfZnlBz8W43P4NgSObWiqyKapANsWCj63Aqeqli8/9gVsGP4CwC8jPpTTYlTopKCk9rJSuht/ew==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@types/clean-css": "*",
|
|
||||||
"@types/relateurl": "*",
|
|
||||||
"@types/uglify-js": "*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@types/http-cache-semantics": {
|
"node_modules/@types/http-cache-semantics": {
|
||||||
"version": "4.0.4",
|
"version": "4.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz",
|
||||||
@ -5957,12 +5934,6 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/relateurl": {
|
|
||||||
"version": "0.2.33",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/relateurl/-/relateurl-0.2.33.tgz",
|
|
||||||
"integrity": "sha512-bTQCKsVbIdzLqZhLkF5fcJQreE4y1ro4DIyVrlDNSCJRRwHhB8Z+4zXXa8jN6eDvc2HbRsEYgbvrnGvi54EpSw==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/@types/responselike": {
|
"node_modules/@types/responselike": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz",
|
||||||
@ -6133,15 +6104,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@types/uglify-js": {
|
|
||||||
"version": "3.17.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.17.5.tgz",
|
|
||||||
"integrity": "sha512-TU+fZFBTBcXj/GpDpDaBmgWk/gn96kMZ+uocaFUlV2f8a6WdMzzI44QBCmGcCiYR0Y6ZlNRiyUyKKt5nl/lbzQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"source-map": "^0.6.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@types/unist": {
|
"node_modules/@types/unist": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
|
||||||
@ -8080,16 +8042,6 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/camel-case": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"no-case": "^2.2.0",
|
|
||||||
"upper-case": "^1.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/caniuse-lite": {
|
"node_modules/caniuse-lite": {
|
||||||
"version": "1.0.30001703",
|
"version": "1.0.30001703",
|
||||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001703.tgz",
|
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001703.tgz",
|
||||||
@ -8331,18 +8283,6 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"node_modules/clean-css": {
|
|
||||||
"version": "4.2.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz",
|
|
||||||
"integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"source-map": "~0.6.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/clean-stack": {
|
"node_modules/clean-stack": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
|
||||||
@ -13034,33 +12974,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/html-minifier": {
|
|
||||||
"version": "4.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-4.0.0.tgz",
|
|
||||||
"integrity": "sha512-aoGxanpFPLg7MkIl/DDFYtb0iWz7jMFGqFhvEDZga6/4QTjneiD8I/NXL1x5aaoCp7FSIT6h/OhykDdPsbtMig==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"camel-case": "^3.0.0",
|
|
||||||
"clean-css": "^4.2.1",
|
|
||||||
"commander": "^2.19.0",
|
|
||||||
"he": "^1.2.0",
|
|
||||||
"param-case": "^2.1.1",
|
|
||||||
"relateurl": "^0.2.7",
|
|
||||||
"uglify-js": "^3.5.1"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"html-minifier": "cli.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/html-minifier/node_modules/commander": {
|
|
||||||
"version": "2.20.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
|
||||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/html2plaintext": {
|
"node_modules/html2plaintext": {
|
||||||
"version": "2.1.4",
|
"version": "2.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/html2plaintext/-/html2plaintext-2.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/html2plaintext/-/html2plaintext-2.1.4.tgz",
|
||||||
@ -14803,12 +14716,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/lower-case": {
|
|
||||||
"version": "1.1.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz",
|
|
||||||
"integrity": "sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/lowercase-keys": {
|
"node_modules/lowercase-keys": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
|
||||||
@ -16032,15 +15939,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/no-case": {
|
|
||||||
"version": "2.3.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz",
|
|
||||||
"integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"lower-case": "^1.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/node-abi": {
|
"node_modules/node-abi": {
|
||||||
"version": "3.71.0",
|
"version": "3.71.0",
|
||||||
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.71.0.tgz",
|
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.71.0.tgz",
|
||||||
@ -16671,15 +16569,6 @@
|
|||||||
"wheel": "^1.0.0"
|
"wheel": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/param-case": {
|
|
||||||
"version": "2.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz",
|
|
||||||
"integrity": "sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"no-case": "^2.2.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/parent-module": {
|
"node_modules/parent-module": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
||||||
@ -18227,15 +18116,6 @@
|
|||||||
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
|
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/relateurl": {
|
|
||||||
"version": "0.2.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz",
|
|
||||||
"integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/repeat-string": {
|
"node_modules/repeat-string": {
|
||||||
"version": "1.6.1",
|
"version": "1.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
|
||||||
@ -20778,18 +20658,6 @@
|
|||||||
"integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==",
|
"integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/uglify-js": {
|
|
||||||
"version": "3.19.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz",
|
|
||||||
"integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==",
|
|
||||||
"license": "BSD-2-Clause",
|
|
||||||
"bin": {
|
|
||||||
"uglifyjs": "bin/uglifyjs"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.8.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/uid-safe": {
|
"node_modules/uid-safe": {
|
||||||
"version": "2.1.5",
|
"version": "2.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
|
||||||
@ -20994,12 +20862,6 @@
|
|||||||
"browserslist": ">= 4.21.0"
|
"browserslist": ">= 4.21.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/upper-case": {
|
|
||||||
"version": "1.1.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz",
|
|
||||||
"integrity": "sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/uri-js": {
|
"node_modules/uri-js": {
|
||||||
"version": "4.4.1",
|
"version": "4.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||||
|
@ -80,7 +80,6 @@
|
|||||||
"@mermaid-js/layout-elk": "0.1.7",
|
"@mermaid-js/layout-elk": "0.1.7",
|
||||||
"@mind-elixir/node-menu": "1.0.4",
|
"@mind-elixir/node-menu": "1.0.4",
|
||||||
"@triliumnext/express-partial-content": "1.0.1",
|
"@triliumnext/express-partial-content": "1.0.1",
|
||||||
"@types/html-minifier": "4.0.5",
|
|
||||||
"archiver": "7.0.1",
|
"archiver": "7.0.1",
|
||||||
"async-mutex": "0.5.0",
|
"async-mutex": "0.5.0",
|
||||||
"autocomplete.js": "0.38.1",
|
"autocomplete.js": "0.38.1",
|
||||||
@ -113,7 +112,6 @@
|
|||||||
"fs-extra": "11.3.0",
|
"fs-extra": "11.3.0",
|
||||||
"helmet": "8.0.0",
|
"helmet": "8.0.0",
|
||||||
"html": "1.0.0",
|
"html": "1.0.0",
|
||||||
"html-minifier": "4.0.0",
|
|
||||||
"html2plaintext": "2.1.4",
|
"html2plaintext": "2.1.4",
|
||||||
"http-proxy-agent": "7.0.2",
|
"http-proxy-agent": "7.0.2",
|
||||||
"https-proxy-agent": "7.0.6",
|
"https-proxy-agent": "7.0.6",
|
||||||
|
42
src/public/app/doc_notes/en/User Guide/!!!meta.json
generated
42
src/public/app/doc_notes/en/User Guide/!!!meta.json
generated
@ -9,9 +9,9 @@
|
|||||||
"pOsGYCXsbNQG"
|
"pOsGYCXsbNQG"
|
||||||
],
|
],
|
||||||
"title": "User Guide",
|
"title": "User Guide",
|
||||||
"notePosition": 110,
|
"notePosition": 10,
|
||||||
"prefix": null,
|
"prefix": null,
|
||||||
"isExpanded": false,
|
"isExpanded": true,
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"mime": "text/html",
|
"mime": "text/html",
|
||||||
"attributes": [],
|
"attributes": [],
|
||||||
@ -1481,13 +1481,6 @@
|
|||||||
"type": "text",
|
"type": "text",
|
||||||
"mime": "text/markdown",
|
"mime": "text/markdown",
|
||||||
"attributes": [
|
"attributes": [
|
||||||
{
|
|
||||||
"type": "relation",
|
|
||||||
"name": "imageLink",
|
|
||||||
"value": "JXFeNgU8Xnp1",
|
|
||||||
"isInheritable": false,
|
|
||||||
"position": 10
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "relation",
|
"type": "relation",
|
||||||
"name": "internalLink",
|
"name": "internalLink",
|
||||||
@ -1516,13 +1509,6 @@
|
|||||||
"isInheritable": false,
|
"isInheritable": false,
|
||||||
"position": 50
|
"position": 50
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "relation",
|
|
||||||
"name": "internalLink",
|
|
||||||
"value": "BFs8mudNFgCS",
|
|
||||||
"isInheritable": false,
|
|
||||||
"position": 60
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "label",
|
"type": "label",
|
||||||
"name": "shareAlias",
|
"name": "shareAlias",
|
||||||
@ -1552,7 +1538,7 @@
|
|||||||
"title": "Basic Concepts",
|
"title": "Basic Concepts",
|
||||||
"notePosition": 60,
|
"notePosition": 60,
|
||||||
"prefix": null,
|
"prefix": null,
|
||||||
"isExpanded": false,
|
"isExpanded": true,
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"mime": "text/html",
|
"mime": "text/html",
|
||||||
"attributes": [
|
"attributes": [
|
||||||
@ -1648,13 +1634,6 @@
|
|||||||
"isInheritable": false,
|
"isInheritable": false,
|
||||||
"position": 40
|
"position": 40
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "relation",
|
|
||||||
"name": "internalLink",
|
|
||||||
"value": "_lbSettings",
|
|
||||||
"isInheritable": false,
|
|
||||||
"position": 50
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "label",
|
"type": "label",
|
||||||
"name": "iconClass",
|
"name": "iconClass",
|
||||||
@ -3073,7 +3052,7 @@
|
|||||||
"title": "Import & Export",
|
"title": "Import & Export",
|
||||||
"notePosition": 90,
|
"notePosition": 90,
|
||||||
"prefix": null,
|
"prefix": null,
|
||||||
"isExpanded": false,
|
"isExpanded": true,
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"mime": "text/html",
|
"mime": "text/html",
|
||||||
"attributes": [],
|
"attributes": [],
|
||||||
@ -5554,7 +5533,7 @@
|
|||||||
"title": "Installation & Setup",
|
"title": "Installation & Setup",
|
||||||
"notePosition": 160,
|
"notePosition": 160,
|
||||||
"prefix": null,
|
"prefix": null,
|
||||||
"isExpanded": false,
|
"isExpanded": true,
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"mime": "text/html",
|
"mime": "text/html",
|
||||||
"attributes": [
|
"attributes": [
|
||||||
@ -5629,7 +5608,7 @@
|
|||||||
"title": "Server Installation",
|
"title": "Server Installation",
|
||||||
"notePosition": 20,
|
"notePosition": 20,
|
||||||
"prefix": null,
|
"prefix": null,
|
||||||
"isExpanded": false,
|
"isExpanded": true,
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"mime": "text/markdown",
|
"mime": "text/markdown",
|
||||||
"attributes": [
|
"attributes": [
|
||||||
@ -5742,7 +5721,7 @@
|
|||||||
"title": "1. Installing the server",
|
"title": "1. Installing the server",
|
||||||
"notePosition": 10,
|
"notePosition": 10,
|
||||||
"prefix": null,
|
"prefix": null,
|
||||||
"isExpanded": false,
|
"isExpanded": true,
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"mime": "text/html",
|
"mime": "text/html",
|
||||||
"attributes": [],
|
"attributes": [],
|
||||||
@ -6553,6 +6532,13 @@
|
|||||||
"value": "bx bx-question-mark",
|
"value": "bx bx-question-mark",
|
||||||
"isInheritable": false,
|
"isInheritable": false,
|
||||||
"position": 40
|
"position": 40
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "relation",
|
||||||
|
"name": "internalLink",
|
||||||
|
"value": "wy8So3yZZlH9",
|
||||||
|
"isInheritable": false,
|
||||||
|
"position": 80
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"format": "html",
|
"format": "html",
|
||||||
|
@ -28,8 +28,7 @@
|
|||||||
<h2>Limitations</h2>
|
<h2>Limitations</h2>
|
||||||
<p>All resources (except for images) are created as note's attachments.</p>
|
<p>All resources (except for images) are created as note's attachments.</p>
|
||||||
<p>HTML inside ENEX files is not exactly valid so some formatting maybe broken
|
<p>HTML inside ENEX files is not exactly valid so some formatting maybe broken
|
||||||
or lost. You can report major problems into <a href="https://github.com/TriliumNext/Notes/issues">Trilium issue tracker</a>.
|
or lost. You can report major problems into <a href="https://github.com/TriliumNext/Notes/issues">Trilium issue tracker</a>.</p>
|
||||||
%%{WARNING}%%</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
@ -13,27 +13,16 @@
|
|||||||
<h1 data-trilium-h1>FAQ</h1>
|
<h1 data-trilium-h1>FAQ</h1>
|
||||||
|
|
||||||
<div class="ck-content">
|
<div class="ck-content">
|
||||||
<h2>Mac OS support</h2>
|
<h2>macOS support</h2>
|
||||||
<p>Originally, desktop builds of Trilium Notes has been available for Windows
|
<p>Originally, Trilium Notes considered the macOS build unsupported. TriliumNext
|
||||||
& Linux, but there has been a considerable demand for macOS build.</p>
|
commits to make the experience on macOS as good as possible.</p>
|
||||||
<p>So I made one, but I underestimated the differences and specifics of Mac
|
<p>if you find any platform-specific issues, feel free to <a href="Troubleshooting/Reporting%20issues.html">report them</a>.</p>
|
||||||
platform which seems to require special handling in several places. My
|
<h2>Translation / localisation support</h2>
|
||||||
lack of knowledge and frankly willingness to learn & code Mac specific
|
<p>The original Trilium Notes application did not support multiple languages.
|
||||||
functionality resulted in a current state where <a href="https://github.com/TriliumNext/Notes/issues/511">Trilium does not integrate well into the OS</a> </p>
|
Since we believe that internationalisation is a core part of an application,
|
||||||
<p>%%{WARNING}%%.</p>
|
we have added support for it.</p>
|
||||||
<p>macOS build is from now on considered "unsupported". I will strive to
|
<p>Contributions to translations are welcome.</p>
|
||||||
keep it fundamentally functional, but I won't work on Mac specific features
|
<h2>Multi-user support</h2>
|
||||||
or integrations. Note that this is more of an acknowledgment of an existing
|
|
||||||
state rather than sudden change of direction.</p>
|
|
||||||
<p>Of course, PRs are welcome.</p>
|
|
||||||
<h2>Translation / localization support</h2>
|
|
||||||
<p>Trilium is currently available only in English. Translation to other languages
|
|
||||||
is not planned in the near/medium term because it brings a significant
|
|
||||||
maintenance overhead. This decision might be revisited once Trilium stabilizes
|
|
||||||
into a more mature product.</p>
|
|
||||||
<p>For Chinese, there's an unofficial fork <a href="https://github.com/Nriver/trilium-translation">here</a>.
|
|
||||||
Use at your own risk.</p>
|
|
||||||
<h2>Multi user support</h2>
|
|
||||||
<p>Common request is to allow multiple users collaborate, share notes etc.
|
<p>Common request is to allow multiple users collaborate, share notes etc.
|
||||||
So far I'm resisting this because of these reasons:</p>
|
So far I'm resisting this because of these reasons:</p>
|
||||||
<ul>
|
<ul>
|
||||||
@ -68,10 +57,7 @@
|
|||||||
<p>These general purpose sync apps are not suitable to sync database files
|
<p>These general purpose sync apps are not suitable to sync database files
|
||||||
which are open and being worked on by another application. The result is
|
which are open and being worked on by another application. The result is
|
||||||
that they will corrupt the database file, resulting in data loss and this
|
that they will corrupt the database file, resulting in data loss and this
|
||||||
message in the Trilium logs:</p>
|
message in the Trilium logs:</p><pre><code class="language-text-x-trilium-auto">SqliteError: database disk image is malformed</code></pre>
|
||||||
<blockquote>
|
|
||||||
<p>SqliteError: database disk image is malformed</p>
|
|
||||||
</blockquote>
|
|
||||||
<p>The only supported way to sync Trilium's data across the network is to
|
<p>The only supported way to sync Trilium's data across the network is to
|
||||||
use a <a href="Installation%20%26%20Setup/Synchronization.html">sync/web server</a>.</p>
|
use a <a href="Installation%20%26%20Setup/Synchronization.html">sync/web server</a>.</p>
|
||||||
<h2>Why database instead of flat files?</h2>
|
<h2>Why database instead of flat files?</h2>
|
||||||
|
@ -63,8 +63,7 @@
|
|||||||
noBackup=true</code></pre>
|
noBackup=true</code></pre>
|
||||||
<p>You can also review the <a href="../Advanced%20Usage/Configuration%20(config.ini%20or%20e.html">configuration</a> file
|
<p>You can also review the <a href="../Advanced%20Usage/Configuration%20(config.ini%20or%20e.html">configuration</a> file
|
||||||
to provide all <code>config.ini</code> values as environment variables instead.</p>
|
to provide all <code>config.ini</code> values as environment variables instead.</p>
|
||||||
<p>See <a href="https://github.com/TriliumNext/Notes/blob/master/config-sample.ini">sample config</a>.
|
<p>See <a href="https://github.com/TriliumNext/Notes/blob/master/config-sample.ini">sample config</a>.</p>
|
||||||
%%{WARNING}%%</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
@ -23,12 +23,12 @@
|
|||||||
</p>
|
</p>
|
||||||
<p><strong>Note:</strong> Trilium's Docker container requires root privileges
|
<p><strong>Note:</strong> Trilium's Docker container requires root privileges
|
||||||
to operate correctly.</p>
|
to operate correctly.</p>
|
||||||
<blockquote>
|
<aside class="admonition warning">
|
||||||
<p>[!WARNING] If you're using a SMB/CIFS share or folder as your Trilium
|
<p>If you're using a SMB/CIFS share or folder as your Trilium data directory,
|
||||||
data directory, <a href="https://github.com/TriliumNext/Notes/issues/415#issuecomment-2344824400">you'll need</a> to
|
<a
|
||||||
add the mount options of <code>nobrl</code> and <code>noperm</code> when mounting
|
href="https://github.com/TriliumNext/Notes/issues/415#issuecomment-2344824400">you'll need</a>to add the mount options of <code>nobrl</code> and <code>noperm</code> when
|
||||||
your SMB share.</p>
|
mounting your SMB share.</p>
|
||||||
</blockquote>
|
</aside>
|
||||||
<h2>Running with Docker Compose</h2>
|
<h2>Running with Docker Compose</h2>
|
||||||
<h3>Grab the latest docker-compose.yml:</h3><pre><code class="language-text-x-trilium-auto">wget https://raw.githubusercontent.com/TriliumNext/Notes/master/docker-compose.yml</code></pre>
|
<h3>Grab the latest docker-compose.yml:</h3><pre><code class="language-text-x-trilium-auto">wget https://raw.githubusercontent.com/TriliumNext/Notes/master/docker-compose.yml</code></pre>
|
||||||
<p>Optionally, edit the <code>docker-compose.yml</code> file to configure the
|
<p>Optionally, edit the <code>docker-compose.yml</code> file to configure the
|
||||||
|
@ -18,12 +18,11 @@
|
|||||||
own Kubernetes deployment.</p>
|
own Kubernetes deployment.</p>
|
||||||
<p>The recommended way is to use a Helm chart.</p>
|
<p>The recommended way is to use a Helm chart.</p>
|
||||||
<h2>Root privileges</h2>
|
<h2>Root privileges</h2>
|
||||||
<blockquote>
|
<aside class="admonition note">
|
||||||
<p>[!NOTE]
|
<p>The Trilium container at this time needs to be run with root privileges.
|
||||||
<br>The Trilium container at this time needs to be run with root privileges.
|
|
||||||
It will swap to UID and GID <code>1000:1000</code> to run the <code>node</code> process
|
It will swap to UID and GID <code>1000:1000</code> to run the <code>node</code> process
|
||||||
after execution though, so the main process doesn't run with root privileges.</p>
|
after execution though, so the main process doesn't run with root privileges.</p>
|
||||||
</blockquote>
|
</aside>
|
||||||
<p>The Trilium docker container needs to be run with root privileges. The
|
<p>The Trilium docker container needs to be run with root privileges. The
|
||||||
node process inside the container will be started with reduced privileges
|
node process inside the container will be started with reduced privileges
|
||||||
(uid:gid 1000:1000) after some initialization logic. Please make sure that
|
(uid:gid 1000:1000) after some initialization logic. Please make sure that
|
||||||
|
@ -29,8 +29,8 @@
|
|||||||
its derivatives (like Ubuntu) below:</p><pre><code class="language-text-x-trilium-auto">sudo apt install libpng16-16 libpng-dev pkg-config autoconf libtool build-essential nasm libx11-dev libxkbfile-dev</code></pre>
|
its derivatives (like Ubuntu) below:</p><pre><code class="language-text-x-trilium-auto">sudo apt install libpng16-16 libpng-dev pkg-config autoconf libtool build-essential nasm libx11-dev libxkbfile-dev</code></pre>
|
||||||
<h2>Installation</h2>
|
<h2>Installation</h2>
|
||||||
<h3>Download</h3>
|
<h3>Download</h3>
|
||||||
<p>You can either download source code zip/tar from <a href="https://github.com/TriliumNext/Notes/releases/latest%5D%5D">https://github.com/TriliumNext/Notes/releases/latest]]</a> %%{WARNING}%%or
|
<p>You can either download source code zip/tar from <a href="https://github.com/TriliumNext/Notes/releases/latest">https://github.com/TriliumNext/Notes/releases/latest</a>.</p>
|
||||||
clone git repository <strong>from stable branch</strong> with</p><pre><code class="language-text-x-trilium-auto">git clone -b stable https://github.com/triliumnext/notes.git %%{WARNING}%%</code></pre>
|
<p>For the latest version including betas, clone Git repository <strong>from </strong><code><strong>master</strong></code><strong> branch</strong> with:</p><pre><code class="language-text-x-trilium-auto">git clone -b master https://github.com/triliumnext/notes.git</code></pre>
|
||||||
<h2>Installation</h2><pre><code class="language-text-x-trilium-auto">cd trilium
|
<h2>Installation</h2><pre><code class="language-text-x-trilium-auto">cd trilium
|
||||||
|
|
||||||
# download all node dependencies
|
# download all node dependencies
|
||||||
|
@ -17,12 +17,10 @@
|
|||||||
into one 7z file.</p>
|
into one 7z file.</p>
|
||||||
<h2>Steps</h2>
|
<h2>Steps</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li>ssh into your server</li>
|
<li>SSH into your server</li>
|
||||||
<li>use <code>wget</code> (or <code>curl</code> or whatever) to download latest
|
<li>use <code>wget</code> (or <code>curl</code>) to download latest <code>TriliumNextNotes-Server-[VERSION]-linux-x64.tar.xz</code> (notice <code>-Server</code> suffix)
|
||||||
<a
|
on your server.</li>
|
||||||
href="https://github.com/TriliumNext/Notes/releases/latest">trilium-linux-x64-server-[VERSION].xz</a>%%{WARNING}%% (notice -server
|
<li>unpack the archive, e.g. using <code>tar -xf -d TriliumNextNotes-Server-[VERSION]-linux-x64.tar.xz</code>
|
||||||
suffix) on your server</li>
|
|
||||||
<li>unpack the archive, e.g. using <code>tar -xf -d trilium-linux-x64-server-[VERSION].tar.xz</code>
|
|
||||||
</li>
|
</li>
|
||||||
<li><code>cd trilium-linux-x64-server</code>
|
<li><code>cd trilium-linux-x64-server</code>
|
||||||
</li>
|
</li>
|
||||||
@ -41,7 +39,7 @@
|
|||||||
<h2>Configure Trilium to auto-run on boot with systemd</h2>
|
<h2>Configure Trilium to auto-run on boot with systemd</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li>After downloading, extract and move Trilium:</li>
|
<li>After downloading, extract and move Trilium:</li>
|
||||||
</ul><pre><code class="language-text-x-trilium-auto">tar -xvf trilium-linux-x64-server-[VERSION].tar.xz
|
</ul><pre><code class="language-text-x-trilium-auto">tar -xvf TriliumNextNotes-Server-[VERSION]-linux-x64.tar.xz
|
||||||
sudo mv trilium-linux-x64-server /opt/trilium</code></pre>
|
sudo mv trilium-linux-x64-server /opt/trilium</code></pre>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Create the service:</li>
|
<li>Create the service:</li>
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
<ul>
|
<ul>
|
||||||
<li><a href="https://github.com/TriliumNext/web-clipper/releases">Project release page</a> -
|
<li><a href="https://github.com/TriliumNext/web-clipper/releases">Project release page</a> -
|
||||||
.xpi for Firefox and .zip for Chromium based browsers.</li>
|
.xpi for Firefox and .zip for Chromium based browsers.</li>
|
||||||
<li>%%{WARNING}%% <a href="https://chromewebstore.google.com/detail/trilium-web-clipper/dfhgmnfclbebfobmblelddiejjcijbjm">Chrome Web Store</a>
|
<li><a href="https://chromewebstore.google.com/detail/trilium-web-clipper/dfhgmnfclbebfobmblelddiejjcijbjm">Chrome Web Store</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h2>Configuration</h2>
|
<h2>Configuration</h2>
|
||||||
|
@ -21,34 +21,36 @@
|
|||||||
<p>Unlike other Book view types, the Calendar view also allows some kind
|
<p>Unlike other Book view types, the Calendar view also allows some kind
|
||||||
of interaction, such as moving events around as well as creating new ones.</p>
|
of interaction, such as moving events around as well as creating new ones.</p>
|
||||||
<h2>Creating a calendar</h2>
|
<h2>Creating a calendar</h2>
|
||||||
<table>
|
<figure class="table">
|
||||||
<thead>
|
<table>
|
||||||
<tr>
|
<thead>
|
||||||
<th></th>
|
<tr>
|
||||||
<th></th>
|
<th> </th>
|
||||||
<th></th>
|
<th> </th>
|
||||||
</tr>
|
<th> </th>
|
||||||
</thead>
|
</tr>
|
||||||
<tbody>
|
</thead>
|
||||||
<tr>
|
<tbody>
|
||||||
<td>1</td>
|
<tr>
|
||||||
<td>
|
<td>1</td>
|
||||||
<img src="3_Calendar View_image.png" alt="">
|
<td>
|
||||||
</td>
|
<img src="3_Calendar View_image.png" alt="">
|
||||||
<td>The Calendar View works only for Book note types. To create a new note,
|
</td>
|
||||||
right click on the note tree on the left and select Insert note after,
|
<td>The Calendar View works only for Book note types. To create a new note,
|
||||||
or Insert child note and then select <em>Book</em>.</td>
|
right click on the note tree on the left and select Insert note after,
|
||||||
</tr>
|
or Insert child note and then select <em>Book</em>.</td>
|
||||||
<tr>
|
</tr>
|
||||||
<td>2</td>
|
<tr>
|
||||||
<td>
|
<td>2</td>
|
||||||
<img src="5_Calendar View_image.png" alt="">
|
<td>
|
||||||
</td>
|
<img src="5_Calendar View_image.png" alt="">
|
||||||
<td>Once created, the “View type” of the Book needs changed to “Calendar”,
|
</td>
|
||||||
by selecting the “Book Properties” tab in the ribbon.</td>
|
<td>Once created, the “View type” of the Book needs changed to “Calendar”,
|
||||||
</tr>
|
by selecting the “Book Properties” tab in the ribbon.</td>
|
||||||
</tbody>
|
</tr>
|
||||||
</table>
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</figure>
|
||||||
<h2>Creating a new event/note</h2>
|
<h2>Creating a new event/note</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Clicking on a day will create a new child note and assign it to that particular
|
<li>Clicking on a day will create a new child note and assign it to that particular
|
||||||
@ -81,226 +83,242 @@
|
|||||||
</ul>
|
</ul>
|
||||||
<h2>Configuring the calendar</h2>
|
<h2>Configuring the calendar</h2>
|
||||||
<p>The following attributes can be added to the book type:</p>
|
<p>The following attributes can be added to the book type:</p>
|
||||||
<table>
|
<figure class="table">
|
||||||
<thead>
|
<table>
|
||||||
<tr>
|
<thead>
|
||||||
<th>Name</th>
|
<tr>
|
||||||
<th>Description</th>
|
<th>Name</th>
|
||||||
</tr>
|
<th>Description</th>
|
||||||
</thead>
|
</tr>
|
||||||
<tbody>
|
</thead>
|
||||||
<tr>
|
<tbody>
|
||||||
<td><code>#calendar:hideWeekends</code>
|
<tr>
|
||||||
</td>
|
<td><code>#calendar:hideWeekends</code>
|
||||||
<td>When present (regardless of value), it will hide Saturday and Sundays
|
</td>
|
||||||
from the calendar.</td>
|
<td>When present (regardless of value), it will hide Saturday and Sundays
|
||||||
</tr>
|
from the calendar.</td>
|
||||||
<tr>
|
</tr>
|
||||||
<td><code>#calendar:weekNumbers</code>
|
<tr>
|
||||||
</td>
|
<td><code>#calendar:weekNumbers</code>
|
||||||
<td>When present (regardless of value), it will show the number of the week
|
</td>
|
||||||
on the calendar.</td>
|
<td>When present (regardless of value), it will show the number of the week
|
||||||
</tr>
|
on the calendar.</td>
|
||||||
<tr>
|
</tr>
|
||||||
<td><code>~child:template</code>
|
<tr>
|
||||||
</td>
|
<td><code>~child:template</code>
|
||||||
<td>Defines the template for newly created notes in the calendar (via dragging
|
</td>
|
||||||
or clicking).</td>
|
<td>Defines the template for newly created notes in the calendar (via dragging
|
||||||
</tr>
|
or clicking).</td>
|
||||||
</tbody>
|
</tr>
|
||||||
</table>
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</figure>
|
||||||
<p>In addition, the first day of the week can be either Sunday or Monday
|
<p>In addition, the first day of the week can be either Sunday or Monday
|
||||||
and can be adjusted from the application settings.</p>
|
and can be adjusted from the application settings.</p>
|
||||||
<h2>Configuring the calendar events</h2>
|
<h2>Configuring the calendar events</h2>
|
||||||
<p>For each note of the calendar, the following attributes can be used:</p>
|
<p>For each note of the calendar, the following attributes can be used:</p>
|
||||||
<table>
|
<figure
|
||||||
<thead>
|
class="table">
|
||||||
<tr>
|
<table>
|
||||||
<th>Name</th>
|
<thead>
|
||||||
<th>Description</th>
|
<tr>
|
||||||
</tr>
|
<th>Name</th>
|
||||||
</thead>
|
<th>Description</th>
|
||||||
<tbody>
|
</tr>
|
||||||
<tr>
|
</thead>
|
||||||
<td><code>#startDate</code>
|
<tbody>
|
||||||
</td>
|
<tr>
|
||||||
<td>The date the event starts, which will display it in the calendar. The
|
<td><code>#startDate</code>
|
||||||
format is <code>YYYY-MM-DD</code> (year, month and day separated by a minus
|
</td>
|
||||||
sign).</td>
|
<td>The date the event starts, which will display it in the calendar. The
|
||||||
</tr>
|
format is <code>YYYY-MM-DD</code> (year, month and day separated by a minus
|
||||||
<tr>
|
sign).</td>
|
||||||
<td><code>#endDate</code>
|
</tr>
|
||||||
</td>
|
<tr>
|
||||||
<td>Similar to <code>startDate</code>, mentions the end date if the event spans
|
<td><code>#endDate</code>
|
||||||
across multiple days. The date is inclusive, so the end day is also considered.
|
</td>
|
||||||
The attribute can be missing for single-day events.</td>
|
<td>Similar to <code>startDate</code>, mentions the end date if the event spans
|
||||||
</tr>
|
across multiple days. The date is inclusive, so the end day is also considered.
|
||||||
<tr>
|
The attribute can be missing for single-day events.</td>
|
||||||
<td><code>#color</code>
|
</tr>
|
||||||
</td>
|
<tr>
|
||||||
<td>Displays the event with a specified color (named such as <code>red</code>, <code>gray</code> or
|
<td><code>#color</code>
|
||||||
hex such as <code>#FF0000</code>). This will also change the color of the
|
</td>
|
||||||
note in other places such as the note tree.</td>
|
<td>Displays the event with a specified color (named such as <code>red</code>, <code>gray</code> or
|
||||||
</tr>
|
hex such as <code>#FF0000</code>). This will also change the color of the
|
||||||
<tr>
|
note in other places such as the note tree.</td>
|
||||||
<td><code>#calendar:color</code>
|
</tr>
|
||||||
</td>
|
<tr>
|
||||||
<td>Similar to <code>#color</code>, but applies the color only for the event
|
<td><code>#calendar:color</code>
|
||||||
in the calendar and not for other places such as the note tree.</td>
|
</td>
|
||||||
</tr>
|
<td>Similar to <code>#color</code>, but applies the color only for the event
|
||||||
<tr>
|
in the calendar and not for other places such as the note tree.</td>
|
||||||
<td><code>#iconClass</code>
|
</tr>
|
||||||
</td>
|
<tr>
|
||||||
<td>If present, the icon of the note will be displayed to the left of the
|
<td><code>#iconClass</code>
|
||||||
event title.</td>
|
</td>
|
||||||
</tr>
|
<td>If present, the icon of the note will be displayed to the left of the
|
||||||
<tr>
|
event title.</td>
|
||||||
<td><code>#calendar:title</code>
|
</tr>
|
||||||
</td>
|
<tr>
|
||||||
<td>Changes the title of an event to point to an attribute of the note other
|
<td><code>#calendar:title</code>
|
||||||
than the title, either a label (e.g. <code>#assignee</code>) or a relation
|
</td>
|
||||||
(e.g. <code>~for</code>). See <em>Advanced use-cases</em> for more information.</td>
|
<td>Changes the title of an event to point to an attribute of the note other
|
||||||
</tr>
|
than the title, either a label (e.g. <code>#assignee</code>) or a relation
|
||||||
<tr>
|
(e.g. <code>~for</code>). See <em>Advanced use-cases</em> for more information.</td>
|
||||||
<td><code>#calendar:promotedAttributes</code>
|
</tr>
|
||||||
</td>
|
<tr>
|
||||||
<td>Allows displaying the value of one or more promoted attributes in the
|
<td><code>#calendar:displayedAttributes</code>
|
||||||
calendar like this:
|
</td>
|
||||||
<img src="13_Calendar View_image.png" alt="">
|
<td>
|
||||||
<br>
|
<p>Allows displaying the value of one or more attributes in the calendar
|
||||||
<br><code><br>#label:weight="promoted,number,single,precision=1"<br>#label:mood="promoted,alias=Mood,single,text"<br>#calendar:promotedAttributes="label:weight,label:mood" <br></code>
|
like this: </p>
|
||||||
<br>
|
<p>
|
||||||
<br>It can also be used with relations, case in which it will display the
|
<img src="13_Calendar View_image.png" alt="">
|
||||||
title of the target note:
|
</p><pre><code class="language-text-x-trilium-auto">#weight="70"
|
||||||
<br>
|
#Mood="Good"
|
||||||
<br><code><br>#relation:assignee="promoted,alias=Assignee,single,text"<br>#calendar:promotedAttributes="relation:assignee" <br>~assignee=@My assignee <br></code>
|
#calendar:displayedAttributes="weight,Mood"</code></pre>
|
||||||
</td>
|
<p>It can also be used with relations, case in which it will display the
|
||||||
</tr>
|
title of the target note:</p><pre><code class="language-text-x-trilium-auto">~assignee=@My assignee
|
||||||
<tr>
|
#calendar:displayedAttributes="assignee"</code></pre>
|
||||||
<td><code>#calendar:startDate</code>
|
</td>
|
||||||
</td>
|
</tr>
|
||||||
<td>Allows using a different label to represent the start date, other than <code>#startDate</code> (e.g. <code>#expiryDate</code>).
|
<tr>
|
||||||
The label name must be prefixed with <code>#</code>. If the label is not
|
<td><code>#calendar:startDate</code>
|
||||||
defined for a note, the default will be used instead.</td>
|
</td>
|
||||||
</tr>
|
<td>Allows using a different label to represent the start date, other than <code>startDate</code> (e.g. <code>expiryDate</code>).
|
||||||
<tr>
|
The label name <strong>must not be</strong> prefixed with <code>#</code>.
|
||||||
<td><code>#calendar:endDate</code>
|
If the label is not defined for a note, the default will be used instead.</td>
|
||||||
</td>
|
</tr>
|
||||||
<td>Allows using a different label to represent the start date, other than <code>#endDate</code>.
|
<tr>
|
||||||
The label name must be prefixed with <code>#</code>. If the label is not
|
<td><code>#calendar:endDate</code>
|
||||||
defined for a note, the default will be used instead.</td>
|
</td>
|
||||||
</tr>
|
<td>Allows using a different label to represent the start date, other than <code>endDate</code>.
|
||||||
</tbody>
|
The label name <strong>must not be</strong> prefixed with <code>#</code>.
|
||||||
</table>
|
If the label is not defined for a note, the default will be used instead.</td>
|
||||||
<h2>How the calendar works</h2>
|
</tr>
|
||||||
<p>
|
</tbody>
|
||||||
<img src="17_Calendar View_image.png" alt="">The calendar displays all the child notes of the book that have a <code>#startDate</code>.
|
</table>
|
||||||
An <code>#endDate</code> can optionally be added.</p>
|
</figure>
|
||||||
<p>If editing the start date and end date from the note itself is desirable,
|
<h2>How the calendar works</h2>
|
||||||
the following attributes can be added to the book note:</p><pre><code class="language-text-x-trilium-auto">#viewType=calendar #label:startDate(inheritable)="promoted,alias=Start Date,single,date" #label:endDate(inheritable)="promoted,alias=End Date,single,date" #hidePromotedAttributes </code></pre>
|
<p>
|
||||||
<p>This will result in:</p>
|
<img src="17_Calendar View_image.png" alt="">
|
||||||
<p>
|
</p>
|
||||||
<img src="14_Calendar View_image.png" alt="">
|
<p>The calendar displays all the child notes of the book that have a <code>#startDate</code>.
|
||||||
</p>
|
An <code>#endDate</code> can optionally be added.</p>
|
||||||
<p>When not used in a Journal, the calendar is recursive. That is, it will
|
<p>If editing the start date and end date from the note itself is desirable,
|
||||||
look for events not just in its child notes but also in the children of
|
the following attributes can be added to the book note:</p><pre><code class="language-text-x-trilium-auto">#viewType=calendar #label:startDate(inheritable)="promoted,alias=Start Date,single,date"
|
||||||
these child notes.</p>
|
#label:endDate(inheritable)="promoted,alias=End Date,single,date"
|
||||||
<h2>Use-cases</h2>
|
#hidePromotedAttributes </code></pre>
|
||||||
<h3>Using with the Journal / calendar</h3>
|
<p>This will result in:</p>
|
||||||
<p>It is possible to integrate the calendar view into the Journal with day
|
<p>
|
||||||
notes. In order to do so change the note type of the Journal note (calendar
|
<img src="14_Calendar View_image.png" alt="">
|
||||||
root) to Book and then select the Calendar View.</p>
|
</p>
|
||||||
<p>Based on the <code>#calendarRoot</code> (or <code>#workspaceCalendarRoot</code>)
|
<p>When not used in a Journal, the calendar is recursive. That is, it will
|
||||||
attribute, the calendar will know that it's in a calendar and apply the
|
look for events not just in its child notes but also in the children of
|
||||||
following:</p>
|
these child notes.</p>
|
||||||
<ul>
|
<h2>Use-cases</h2>
|
||||||
<li>The calendar events are now rendered based on their <code>dateNote</code> attribute
|
<h3>Using with the Journal / calendar</h3>
|
||||||
rather than <code>startDate</code>.</li>
|
<p>It is possible to integrate the calendar view into the Journal with day
|
||||||
<li>Interactive editing such as dragging over an empty era or resizing an
|
notes. In order to do so change the note type of the Journal note (calendar
|
||||||
event is no longer possible.</li>
|
root) to Book and then select the Calendar View.</p>
|
||||||
<li>Clicking on the empty space on a date will automatically open that day's
|
<p>Based on the <code>#calendarRoot</code> (or <code>#workspaceCalendarRoot</code>)
|
||||||
note or create it if it does not exist.</li>
|
attribute, the calendar will know that it's in a calendar and apply the
|
||||||
<li>Direct children of a day note will be displayed on the calendar despite
|
following:</p>
|
||||||
not having a <code>dateNote</code> attribute. Children of the child notes
|
<ul>
|
||||||
will not be displayed.</li>
|
<li>The calendar events are now rendered based on their <code>dateNote</code> attribute
|
||||||
</ul>
|
rather than <code>startDate</code>.</li>
|
||||||
<p>
|
<li>Interactive editing such as dragging over an empty era or resizing an
|
||||||
<img src="12_Calendar View_image.png" alt="">
|
event is no longer possible.</li>
|
||||||
</p>
|
<li>Clicking on the empty space on a date will automatically open that day's
|
||||||
<h3>Using a different attribute as event title</h3>
|
note or create it if it does not exist.</li>
|
||||||
<p>By default, events are displayed on the calendar by their note title.
|
<li>Direct children of a day note will be displayed on the calendar despite
|
||||||
However, it is possible to configure a different attribute to be displayed
|
not having a <code>dateNote</code> attribute. Children of the child notes
|
||||||
instead.</p>
|
will not be displayed.</li>
|
||||||
<p>To do so, assign <code>#calendar:title</code> to the child note (not the
|
</ul>
|
||||||
calendar/book note), with the value being <code>#name</code> where <code>name</code> can
|
<p>
|
||||||
be any label. The attribute can also come through inheritance such as a
|
<img src="12_Calendar View_image.png" alt="">
|
||||||
template attribute. If the note does not have the requested label, the
|
</p>
|
||||||
title of the note will be used instead.</p>
|
<h3>Using a different attribute as event title</h3>
|
||||||
<table>
|
<p>By default, events are displayed on the calendar by their note title.
|
||||||
<thead>
|
However, it is possible to configure a different attribute to be displayed
|
||||||
<tr>
|
instead.</p>
|
||||||
<th></th>
|
<p>To do so, assign <code>#calendar:title</code> to the child note (not the
|
||||||
<th></th>
|
calendar/book note), with the value being <code>#name</code> where <code>name</code> can
|
||||||
</tr>
|
be any label. The attribute can also come through inheritance such as a
|
||||||
</thead>
|
template attribute. If the note does not have the requested label, the
|
||||||
<tbody>
|
title of the note will be used instead.</p>
|
||||||
<tr>
|
<figure class="table">
|
||||||
<td>
|
<table>
|
||||||
<img src="7_Calendar View_image.png" alt="">
|
<thead>
|
||||||
</td>
|
<tr>
|
||||||
<td>
|
<th> </th>
|
||||||
<img src="9_Calendar View_image.png" alt="">
|
<th> </th>
|
||||||
</td>
|
</tr>
|
||||||
</tr>
|
</thead>
|
||||||
</tbody>
|
<tbody>
|
||||||
</table>
|
<tr>
|
||||||
<h3>Using a relation attribute as event title</h3>
|
<td>
|
||||||
<p>Similarly to using an attribute, use <code>#calendar:title</code> and set
|
<img src="7_Calendar View_image.png" alt="">
|
||||||
it to <code>~name</code> where <code>name</code> is the name of the relation
|
</td>
|
||||||
to use.</p>
|
<td>
|
||||||
<p>Moreover, if there are more relations of the same name, they will be displayed
|
<img src="9_Calendar View_image.png" alt="">
|
||||||
as multiple events coming from the same note.</p>
|
</td>
|
||||||
<table>
|
</tr>
|
||||||
<thead>
|
</tbody>
|
||||||
<tr>
|
</table>
|
||||||
<th></th>
|
</figure>
|
||||||
<th></th>
|
<h3>Using a relation attribute as event title</h3>
|
||||||
</tr>
|
<p>Similarly to using an attribute, use <code>#calendar:title</code> and set
|
||||||
</thead>
|
it to <code>~name</code> where <code>name</code> is the name of the relation
|
||||||
<tbody>
|
to use.</p>
|
||||||
<tr>
|
<p>Moreover, if there are more relations of the same name, they will be displayed
|
||||||
<td>
|
as multiple events coming from the same note.</p>
|
||||||
<img src="8_Calendar View_image.png" alt="">
|
<figure class="table">
|
||||||
</td>
|
<table>
|
||||||
<td>
|
<thead>
|
||||||
<img src="10_Calendar View_image.png" alt="">
|
<tr>
|
||||||
</td>
|
<th> </th>
|
||||||
</tr>
|
<th> </th>
|
||||||
</tbody>
|
</tr>
|
||||||
</table>
|
</thead>
|
||||||
<p>Note that it's even possible to have a <code>#calendar:title</code> on the
|
<tbody>
|
||||||
target note (e.g. “John Smith”) which will try to render an attribute of
|
<tr>
|
||||||
it. Note that it's not possible to use a relation here as well for safety
|
<td>
|
||||||
reasons (an accidental recursion of attributes could cause the application
|
<img src="8_Calendar View_image.png" alt="">
|
||||||
to loop infinitely).</p>
|
</td>
|
||||||
<table>
|
<td>
|
||||||
<thead>
|
<img src="10_Calendar View_image.png" alt="">
|
||||||
<tr>
|
</td>
|
||||||
<th></th>
|
</tr>
|
||||||
<th></th>
|
</tbody>
|
||||||
</tr>
|
</table>
|
||||||
</thead>
|
</figure>
|
||||||
<tbody>
|
<p>Note that it's even possible to have a <code>#calendar:title</code> on the
|
||||||
<tr>
|
target note (e.g. “John Smith”) which will try to render an attribute of
|
||||||
<td>
|
it. Note that it's not possible to use a relation here as well for safety
|
||||||
<img src="15_Calendar View_image.png" alt="">
|
reasons (an accidental recursion of attributes could cause the application
|
||||||
</td>
|
to loop infinitely).</p>
|
||||||
<td>
|
<figure class="table">
|
||||||
<img src="2_Calendar View_image.png" alt="">
|
<table>
|
||||||
</td>
|
<thead>
|
||||||
</tr>
|
<tr>
|
||||||
</tbody>
|
<th> </th>
|
||||||
</table>
|
<th> </th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<img src="15_Calendar View_image.png" alt="">
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<img src="2_Calendar View_image.png" alt="">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</figure>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
<div class="ck-content">
|
<div class="ck-content">
|
||||||
<p>
|
<p>
|
||||||
<img src="api/images/ZOupAe21YiqT/Content language & Right-t.png"
|
<img src="api/images/4yHAD34xyvAl/Content language & Right-t.png"
|
||||||
alt="">
|
alt="">
|
||||||
</p>
|
</p>
|
||||||
<p>A language hint can be provided for text notes. This option informs the
|
<p>A language hint can be provided for text notes. This option informs the
|
||||||
|
@ -27,12 +27,11 @@
|
|||||||
<li><a href="Installation%20%26%20Setup/Server%20Installation.html">Server installation</a>
|
<li><a href="Installation%20%26%20Setup/Server%20Installation.html">Server installation</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="Installation%20%26%20Setup/Mobile%20Frontend.html">Mobile frontend</a> (optional)</li>
|
<li><a href="Installation%20%26%20Setup/Mobile%20Frontend.html">Mobile frontend</a> (optional)</li>
|
||||||
<li><a href="https://heroku.com/deploy?template=https://github.com/feilongfl/trilium-heroku"><img src="Attachments/home-button.svg" alt="Deploy"></a>%%{WARNING}%%</li>
|
|
||||||
<li><a href="https://www.pikapods.com/pods?run=trilium-next">PikaPods managed hosting</a>
|
<li><a href="https://www.pikapods.com/pods?run=trilium-next">PikaPods managed hosting</a>
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
<p><strong>Combination of server and desktop/laptop</strong> - Install the
|
<p><strong>Combination of server and desktop/laptop</strong> - Install the
|
||||||
application on both a server, for web access and data synchronization,
|
application on both a server, for web access and data synchronisation,
|
||||||
and desktop instance(s). This allows all the data to be stored on the server
|
and desktop instance(s). This allows all the data to be stored on the server
|
||||||
and either accessed from the web browser, or the desktop application. The
|
and either accessed from the web browser, or the desktop application. The
|
||||||
desktop application will sync and store the data locally so that it can
|
desktop application will sync and store the data locally so that it can
|
||||||
@ -46,11 +45,6 @@
|
|||||||
<li><a href="Installation%20%26%20Setup/Synchronization.html">Synchronization</a>
|
<li><a href="Installation%20%26%20Setup/Synchronization.html">Synchronization</a>
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
<h2>Basic concepts</h2>
|
|
||||||
<ol>
|
|
||||||
<li>Understand <a href="Basic%20Concepts/Note.html">Note</a>
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
26
src/public/app/doc_notes/en/User Guide/style.css
generated
26
src/public/app/doc_notes/en/User Guide/style.css
generated
@ -17,6 +17,32 @@
|
|||||||
margin: 0 !important;
|
margin: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ck-content .admonition {
|
||||||
|
--accent-color: var(--card-border-color);
|
||||||
|
border: 1px solid var(--accent-color);
|
||||||
|
box-shadow: var(--card-box-shadow);
|
||||||
|
background: var(--card-background-color);
|
||||||
|
border-radius: 0.5em;
|
||||||
|
padding: 1em;
|
||||||
|
margin: 1.25em 0;
|
||||||
|
margin-right: 14px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ck-content .admonition p:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ck-content .admonition p, h2 {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ck-content .admonition.note { --accent-color: #69c7ff; }
|
||||||
|
.ck-content .admonition.tip { --accent-color: #40c025; }
|
||||||
|
.ck-content .admonition.important { --accent-color: #9839f7; }
|
||||||
|
.ck-content .admonition.caution { --accent-color: #ff2e2e; }
|
||||||
|
.ck-content .admonition.warning { --accent-color: #e2aa03; }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CKEditor 5 (v41.0.0) content styles.
|
* CKEditor 5 (v41.0.0) content styles.
|
||||||
* Generated on Fri, 26 Jan 2024 10:23:49 GMT.
|
* Generated on Fri, 26 Jan 2024 10:23:49 GMT.
|
||||||
|
@ -6,15 +6,15 @@ import appContext from "../components/app_context.js";
|
|||||||
import { t } from "./i18n.js";
|
import { t } from "./i18n.js";
|
||||||
|
|
||||||
interface UploadFilesOptions {
|
interface UploadFilesOptions {
|
||||||
safeImport: boolean;
|
safeImport?: boolean;
|
||||||
shrinkImages: boolean;
|
shrinkImages: boolean | "true" | "false";
|
||||||
textImportedAsText: boolean;
|
textImportedAsText?: boolean;
|
||||||
codeImportedAsCode: boolean;
|
codeImportedAsCode?: boolean;
|
||||||
explodeArchives: boolean;
|
explodeArchives?: boolean;
|
||||||
replaceUnderscoresWithSpaces: boolean;
|
replaceUnderscoresWithSpaces?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function uploadFiles(entityType: string, parentNoteId: string, files: string[], options: UploadFilesOptions) {
|
export async function uploadFiles(entityType: string, parentNoteId: string, files: string[] | File[], options: UploadFilesOptions) {
|
||||||
if (!["notes", "attachments"].includes(entityType)) {
|
if (!["notes", "attachments"].includes(entityType)) {
|
||||||
throw new Error(`Unrecognized import entity type '${entityType}'.`);
|
throw new Error(`Unrecognized import entity type '${entityType}'.`);
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,7 @@ export const MIME_TYPES_DICT: readonly MimeTypeDefinition[] = Object.freeze([
|
|||||||
{ title: "PEG.js", mime: "null" },
|
{ title: "PEG.js", mime: "null" },
|
||||||
{ title: "Perl", mime: "text/x-perl", default: true },
|
{ title: "Perl", mime: "text/x-perl", default: true },
|
||||||
{ title: "PGP", mime: "application/pgp" },
|
{ title: "PGP", mime: "application/pgp" },
|
||||||
{ title: "PHP", mime: "text/x-php", default: true },
|
{ title: "PHP", mime: "text/x-php", default: true, highlightJs: "php" },
|
||||||
{ title: "Pig", mime: "text/x-pig" },
|
{ title: "Pig", mime: "text/x-pig" },
|
||||||
{ title: "PLSQL", mime: "text/x-plsql", highlightJs: "sql" },
|
{ title: "PLSQL", mime: "text/x-plsql", highlightJs: "sql" },
|
||||||
{ title: "PostgreSQL", mime: "text/x-pgsql", highlightJs: "pgsql" },
|
{ title: "PostgreSQL", mime: "text/x-pgsql", highlightJs: "pgsql" },
|
||||||
@ -135,7 +135,7 @@ export const MIME_TYPES_DICT: readonly MimeTypeDefinition[] = Object.freeze([
|
|||||||
{ title: "Ruby", mime: "text/x-ruby", highlightJs: "ruby", default: true },
|
{ title: "Ruby", mime: "text/x-ruby", highlightJs: "ruby", default: true },
|
||||||
{ title: "Rust", mime: "text/x-rustsrc", highlightJs: "rust" },
|
{ title: "Rust", mime: "text/x-rustsrc", highlightJs: "rust" },
|
||||||
{ title: "SAS", mime: "text/x-sas", highlightJs: "sas" },
|
{ title: "SAS", mime: "text/x-sas", highlightJs: "sas" },
|
||||||
{ title: "Sass", mime: "text/x-sass" },
|
{ title: "Sass", mime: "text/x-sass", highlightJs: "scss" },
|
||||||
{ title: "Scala", mime: "text/x-scala" },
|
{ title: "Scala", mime: "text/x-scala" },
|
||||||
{ title: "Scheme", mime: "text/x-scheme" },
|
{ title: "Scheme", mime: "text/x-scheme" },
|
||||||
{ title: "SCSS", mime: "text/x-scss", highlightJs: "scss" },
|
{ title: "SCSS", mime: "text/x-scss", highlightJs: "scss" },
|
||||||
@ -169,7 +169,7 @@ export const MIME_TYPES_DICT: readonly MimeTypeDefinition[] = Object.freeze([
|
|||||||
{ title: "TTCN", mime: "text/x-ttcn" },
|
{ title: "TTCN", mime: "text/x-ttcn" },
|
||||||
{ title: "Turtle", mime: "text/turtle" },
|
{ title: "Turtle", mime: "text/turtle" },
|
||||||
{ title: "Twig", mime: "text/x-twig", highlightJs: "twig" },
|
{ title: "Twig", mime: "text/x-twig", highlightJs: "twig" },
|
||||||
{ title: "TypeScript-JSX", mime: "text/typescript-jsx" },
|
{ title: "TypeScript-JSX", mime: "text/typescript-jsx", highlightJs: "typescript" },
|
||||||
{ title: "TypeScript", mime: "application/typescript", highlightJs: "typescript" },
|
{ title: "TypeScript", mime: "application/typescript", highlightJs: "typescript" },
|
||||||
{ title: "VB.NET", mime: "text/x-vb", highlightJs: "vbnet" },
|
{ title: "VB.NET", mime: "text/x-vb", highlightJs: "vbnet" },
|
||||||
{ title: "VBScript", mime: "text/vbscript", highlightJs: "vbscript" },
|
{ title: "VBScript", mime: "text/vbscript", highlightJs: "vbscript" },
|
||||||
|
@ -27,14 +27,19 @@ const TPL = `
|
|||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
export default class ProtectedSessionPasswordDialog extends BasicWidget {
|
export default class ProtectedSessionPasswordDialog extends BasicWidget {
|
||||||
|
|
||||||
|
private modal!: bootstrap.Modal;
|
||||||
|
private $passwordForm!: JQuery<HTMLElement>;
|
||||||
|
private $passwordInput!: JQuery<HTMLElement>;
|
||||||
|
|
||||||
doRender() {
|
doRender() {
|
||||||
this.$widget = $(TPL);
|
this.$widget = $(TPL);
|
||||||
this.modal = Modal.getOrCreateInstance(this.$widget);
|
this.modal = Modal.getOrCreateInstance(this.$widget[0]);
|
||||||
|
|
||||||
this.$passwordForm = this.$widget.find(".protected-session-password-form");
|
this.$passwordForm = this.$widget.find(".protected-session-password-form");
|
||||||
this.$passwordInput = this.$widget.find(".protected-session-password");
|
this.$passwordInput = this.$widget.find(".protected-session-password");
|
||||||
this.$passwordForm.on("submit", () => {
|
this.$passwordForm.on("submit", () => {
|
||||||
const password = this.$passwordInput.val();
|
const password = String(this.$passwordInput.val());
|
||||||
this.$passwordInput.val("");
|
this.$passwordInput.val("");
|
||||||
|
|
||||||
protectedSessionService.setupProtectedSession(password);
|
protectedSessionService.setupProtectedSession(password);
|
@ -1,6 +1,6 @@
|
|||||||
import { formatDateTime } from "../../utils/formatters.js";
|
import { formatDateTime } from "../../utils/formatters.js";
|
||||||
import { t } from "../../services/i18n.js";
|
import { t } from "../../services/i18n.js";
|
||||||
import appContext from "../../components/app_context.js";
|
import appContext, { type EventData } from "../../components/app_context.js";
|
||||||
import BasicWidget from "../basic_widget.js";
|
import BasicWidget from "../basic_widget.js";
|
||||||
import dialogService from "../../services/dialog.js";
|
import dialogService from "../../services/dialog.js";
|
||||||
import froca from "../../services/froca.js";
|
import froca from "../../services/froca.js";
|
||||||
@ -28,10 +28,23 @@ const TPL = `
|
|||||||
</div>
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
|
// TODO: Deduplicate with server.
|
||||||
|
interface RecentChangesRow {
|
||||||
|
noteId: string;
|
||||||
|
date: string;
|
||||||
|
}
|
||||||
|
|
||||||
export default class RecentChangesDialog extends BasicWidget {
|
export default class RecentChangesDialog extends BasicWidget {
|
||||||
|
|
||||||
|
private ancestorNoteId?: string;
|
||||||
|
|
||||||
|
private modal!: bootstrap.Modal;
|
||||||
|
private $content!: JQuery<HTMLElement>;
|
||||||
|
private $eraseDeletedNotesNow!: JQuery<HTMLElement>;
|
||||||
|
|
||||||
doRender() {
|
doRender() {
|
||||||
this.$widget = $(TPL);
|
this.$widget = $(TPL);
|
||||||
this.modal = Modal.getOrCreateInstance(this.$widget);
|
this.modal = Modal.getOrCreateInstance(this.$widget[0]);
|
||||||
|
|
||||||
this.$content = this.$widget.find(".recent-changes-content");
|
this.$content = this.$widget.find(".recent-changes-content");
|
||||||
this.$eraseDeletedNotesNow = this.$widget.find(".erase-deleted-notes-now-button");
|
this.$eraseDeletedNotesNow = this.$widget.find(".erase-deleted-notes-now-button");
|
||||||
@ -44,7 +57,7 @@ export default class RecentChangesDialog extends BasicWidget {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async showRecentChangesEvent({ ancestorNoteId }) {
|
async showRecentChangesEvent({ ancestorNoteId }: EventData<"showRecentChanges">) {
|
||||||
this.ancestorNoteId = ancestorNoteId;
|
this.ancestorNoteId = ancestorNoteId;
|
||||||
|
|
||||||
await this.refresh();
|
await this.refresh();
|
||||||
@ -57,7 +70,7 @@ export default class RecentChangesDialog extends BasicWidget {
|
|||||||
this.ancestorNoteId = hoistedNoteService.getHoistedNoteId();
|
this.ancestorNoteId = hoistedNoteService.getHoistedNoteId();
|
||||||
}
|
}
|
||||||
|
|
||||||
const recentChangesRows = await server.get(`recent-changes/${this.ancestorNoteId}`);
|
const recentChangesRows = await server.get<RecentChangesRow[]>(`recent-changes/${this.ancestorNoteId}`);
|
||||||
|
|
||||||
// preload all notes into cache
|
// preload all notes into cache
|
||||||
await froca.getNotes(
|
await froca.getNotes(
|
||||||
@ -110,7 +123,7 @@ export default class RecentChangesDialog extends BasicWidget {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const note = await froca.getNote(change.noteId);
|
const note = await froca.getNote(change.noteId);
|
||||||
const notePath = note.getBestNotePathString();
|
const notePath = note?.getBestNotePathString();
|
||||||
|
|
||||||
if (notePath) {
|
if (notePath) {
|
||||||
$noteLink = await linkService.createLink(notePath, {
|
$noteLink = await linkService.createLink(notePath, {
|
||||||
@ -118,7 +131,7 @@ export default class RecentChangesDialog extends BasicWidget {
|
|||||||
showNotePath: true
|
showNotePath: true
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
$noteLink = $("<span>").text(note.title);
|
$noteLink = $("<span>").text(note?.title ?? "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,9 +144,7 @@ export default class RecentChangesDialog extends BasicWidget {
|
|||||||
appContext.tabManager.getActiveContext().setNote(change.noteId);
|
appContext.tabManager.getActiveContext().setNote(change.noteId);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.addClass(() => {
|
.toggleClass("deleted-note", !!change.current_isDeleted)
|
||||||
if (change.current_isDeleted) return "deleted-note";
|
|
||||||
})
|
|
||||||
.append($("<span>").text(formattedTime).attr("title", change.date))
|
.append($("<span>").text(formattedTime).attr("title", change.date))
|
||||||
.append($noteLink.addClass("note-title"))
|
.append($noteLink.addClass("note-title"))
|
||||||
);
|
);
|
||||||
@ -143,7 +154,7 @@ export default class RecentChangesDialog extends BasicWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
groupByDate(rows) {
|
groupByDate(rows: RecentChangesRow[]) {
|
||||||
const groupedByDate = new Map();
|
const groupedByDate = new Map();
|
||||||
|
|
||||||
for (const row of rows) {
|
for (const row of rows) {
|
@ -1,3 +1,4 @@
|
|||||||
|
import type { EventData } from "../../components/app_context.js";
|
||||||
import { t } from "../../services/i18n.js";
|
import { t } from "../../services/i18n.js";
|
||||||
import server from "../../services/server.js";
|
import server from "../../services/server.js";
|
||||||
import utils from "../../services/utils.js";
|
import utils from "../../services/utils.js";
|
||||||
@ -79,6 +80,10 @@ const TPL = `<div class="sort-child-notes-dialog modal mx-auto" tabindex="-1" ro
|
|||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
export default class SortChildNotesDialog extends BasicWidget {
|
export default class SortChildNotesDialog extends BasicWidget {
|
||||||
|
|
||||||
|
private parentNoteId?: string;
|
||||||
|
private $form!: JQuery<HTMLElement>;
|
||||||
|
|
||||||
doRender() {
|
doRender() {
|
||||||
this.$widget = $(TPL);
|
this.$widget = $(TPL);
|
||||||
this.$form = this.$widget.find(".sort-child-notes-form");
|
this.$form = this.$widget.find(".sort-child-notes-form");
|
||||||
@ -96,7 +101,7 @@ export default class SortChildNotesDialog extends BasicWidget {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async sortChildNotesEvent({ node }) {
|
async sortChildNotesEvent({ node }: EventData<"sortChildNotes">) {
|
||||||
this.parentNoteId = node.data.noteId;
|
this.parentNoteId = node.data.noteId;
|
||||||
|
|
||||||
utils.openDialog(this.$widget);
|
utils.openDialog(this.$widget);
|
@ -5,6 +5,7 @@ import importService from "../../services/import.js";
|
|||||||
import options from "../../services/options.js";
|
import options from "../../services/options.js";
|
||||||
import BasicWidget from "../basic_widget.js";
|
import BasicWidget from "../basic_widget.js";
|
||||||
import { Modal, Tooltip } from "bootstrap";
|
import { Modal, Tooltip } from "bootstrap";
|
||||||
|
import type { EventData } from "../../components/app_context.js";
|
||||||
|
|
||||||
const TPL = `
|
const TPL = `
|
||||||
<div class="upload-attachments-dialog modal fade mx-auto" tabindex="-1" role="dialog">
|
<div class="upload-attachments-dialog modal fade mx-auto" tabindex="-1" role="dialog">
|
||||||
@ -42,6 +43,15 @@ const TPL = `
|
|||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
export default class UploadAttachmentsDialog extends BasicWidget {
|
export default class UploadAttachmentsDialog extends BasicWidget {
|
||||||
|
|
||||||
|
private parentNoteId: string | null;
|
||||||
|
private modal!: bootstrap.Modal;
|
||||||
|
private $form!: JQuery<HTMLElement>;
|
||||||
|
private $noteTitle!: JQuery<HTMLElement>;
|
||||||
|
private $fileUploadInput!: JQuery<HTMLInputElement>;
|
||||||
|
private $uploadButton!: JQuery<HTMLElement>;
|
||||||
|
private $shrinkImagesCheckbox!: JQuery<HTMLElement>;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
@ -50,7 +60,7 @@ export default class UploadAttachmentsDialog extends BasicWidget {
|
|||||||
|
|
||||||
doRender() {
|
doRender() {
|
||||||
this.$widget = $(TPL);
|
this.$widget = $(TPL);
|
||||||
this.modal = Modal.getOrCreateInstance(this.$widget);
|
this.modal = Modal.getOrCreateInstance(this.$widget[0]);
|
||||||
|
|
||||||
this.$form = this.$widget.find(".upload-attachment-form");
|
this.$form = this.$widget.find(".upload-attachment-form");
|
||||||
this.$noteTitle = this.$widget.find(".upload-attachment-note-title");
|
this.$noteTitle = this.$widget.find(".upload-attachment-note-title");
|
||||||
@ -61,7 +71,9 @@ export default class UploadAttachmentsDialog extends BasicWidget {
|
|||||||
this.$form.on("submit", () => {
|
this.$form.on("submit", () => {
|
||||||
// disabling so that import is not triggered again.
|
// disabling so that import is not triggered again.
|
||||||
this.$uploadButton.attr("disabled", "disabled");
|
this.$uploadButton.attr("disabled", "disabled");
|
||||||
this.uploadAttachments(this.parentNoteId);
|
if (this.parentNoteId) {
|
||||||
|
this.uploadAttachments(this.parentNoteId);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -73,12 +85,12 @@ export default class UploadAttachmentsDialog extends BasicWidget {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Tooltip.getOrCreateInstance(this.$widget.find('[data-bs-toggle="tooltip"]'), {
|
Tooltip.getOrCreateInstance(this.$widget.find('[data-bs-toggle="tooltip"]')[0], {
|
||||||
html: true
|
html: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async showUploadAttachmentsDialogEvent({ noteId }) {
|
async showUploadAttachmentsDialogEvent({ noteId }: EventData<"showUploadAttachmentsDialog">) {
|
||||||
this.parentNoteId = noteId;
|
this.parentNoteId = noteId;
|
||||||
|
|
||||||
this.$fileUploadInput.val("").trigger("change"); // to trigger upload button disabling listener below
|
this.$fileUploadInput.val("").trigger("change"); // to trigger upload button disabling listener below
|
||||||
@ -89,10 +101,12 @@ export default class UploadAttachmentsDialog extends BasicWidget {
|
|||||||
utils.openDialog(this.$widget);
|
utils.openDialog(this.$widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
async uploadAttachments(parentNoteId) {
|
async uploadAttachments(parentNoteId: string) {
|
||||||
const files = Array.from(this.$fileUploadInput[0].files); // shallow copy since we're resetting the upload button below
|
const files = Array.from(this.$fileUploadInput[0].files ?? []); // shallow copy since we're resetting the upload button below
|
||||||
|
|
||||||
const boolToString = ($el) => ($el.is(":checked") ? "true" : "false");
|
function boolToString($el: JQuery<HTMLElement>): "true" | "false" {
|
||||||
|
return ($el.is(":checked") ? "true" : "false");
|
||||||
|
}
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
shrinkImages: boolToString(this.$shrinkImagesCheckbox)
|
shrinkImages: boolToString(this.$shrinkImagesCheckbox)
|
@ -39,8 +39,8 @@ describe("Building events", () => {
|
|||||||
|
|
||||||
it("supports custom start date", async () => {
|
it("supports custom start date", async () => {
|
||||||
const noteIds = buildNotes([
|
const noteIds = buildNotes([
|
||||||
{ title: "Note 1", "#myStartDate": "2025-05-05", "#calendar:startDate": "#myStartDate" },
|
{ title: "Note 1", "#myStartDate": "2025-05-05", "#calendar:startDate": "myStartDate" },
|
||||||
{ title: "Note 2", "#startDate": "2025-05-07", "#calendar:startDate": "#myStartDate" },
|
{ title: "Note 2", "#startDate": "2025-05-07", "#calendar:startDate": "myStartDate" },
|
||||||
]);
|
]);
|
||||||
const events = await CalendarView.buildEvents(noteIds);
|
const events = await CalendarView.buildEvents(noteIds);
|
||||||
|
|
||||||
@ -59,10 +59,10 @@ describe("Building events", () => {
|
|||||||
|
|
||||||
it("supports custom start date and end date", async () => {
|
it("supports custom start date and end date", async () => {
|
||||||
const noteIds = buildNotes([
|
const noteIds = buildNotes([
|
||||||
{ title: "Note 1", "#myStartDate": "2025-05-05", "#myEndDate": "2025-05-05", "#calendar:startDate": "#myStartDate", "#calendar:endDate": "#myEndDate" },
|
{ title: "Note 1", "#myStartDate": "2025-05-05", "#myEndDate": "2025-05-05", "#calendar:startDate": "myStartDate", "#calendar:endDate": "myEndDate" },
|
||||||
{ title: "Note 2", "#myStartDate": "2025-05-07", "#endDate": "2025-05-08", "#calendar:startDate": "#myStartDate", "#calendar:endDate": "#myEndDate" },
|
{ title: "Note 2", "#myStartDate": "2025-05-07", "#endDate": "2025-05-08", "#calendar:startDate": "myStartDate", "#calendar:endDate": "myEndDate" },
|
||||||
{ title: "Note 3", "#startDate": "2025-05-05", "#myEndDate": "2025-05-05", "#calendar:startDate": "#myStartDate", "#calendar:endDate": "#myEndDate" },
|
{ title: "Note 3", "#startDate": "2025-05-05", "#myEndDate": "2025-05-05", "#calendar:startDate": "myStartDate", "#calendar:endDate": "myEndDate" },
|
||||||
{ title: "Note 4", "#startDate": "2025-05-07", "#myEndDate": "2025-05-08", "#calendar:startDate": "#myStartDate", "#calendar:endDate": "#myEndDate" },
|
{ title: "Note 4", "#startDate": "2025-05-07", "#myEndDate": "2025-05-08", "#calendar:startDate": "myStartDate", "#calendar:endDate": "myEndDate" },
|
||||||
]);
|
]);
|
||||||
const events = await CalendarView.buildEvents(noteIds);
|
const events = await CalendarView.buildEvents(noteIds);
|
||||||
|
|
||||||
@ -75,8 +75,8 @@ describe("Building events", () => {
|
|||||||
|
|
||||||
it("supports label as custom title", async () => {
|
it("supports label as custom title", async () => {
|
||||||
const noteIds = buildNotes([
|
const noteIds = buildNotes([
|
||||||
{ title: "Note 1", "#myTitle": "My Custom Title 1", "#startDate": "2025-05-05", "#calendar:title": "#myTitle" },
|
{ title: "Note 1", "#myTitle": "My Custom Title 1", "#startDate": "2025-05-05", "#calendar:title": "myTitle" },
|
||||||
{ title: "Note 2", "#startDate": "2025-05-07", "#calendar:title": "#myTitle" },
|
{ title: "Note 2", "#startDate": "2025-05-07", "#calendar:title": "myTitle" },
|
||||||
]);
|
]);
|
||||||
const events = await CalendarView.buildEvents(noteIds);
|
const events = await CalendarView.buildEvents(noteIds);
|
||||||
|
|
||||||
@ -88,8 +88,8 @@ describe("Building events", () => {
|
|||||||
it("supports relation as custom title", async () => {
|
it("supports relation as custom title", async () => {
|
||||||
const noteIds = buildNotes([
|
const noteIds = buildNotes([
|
||||||
{ id: "mySharedTitle", title: "My shared title" },
|
{ id: "mySharedTitle", title: "My shared title" },
|
||||||
{ title: "Note 1", "~myTitle": "mySharedTitle", "#startDate": "2025-05-05", "#calendar:title": "~myTitle" },
|
{ title: "Note 1", "~myTitle": "mySharedTitle", "#startDate": "2025-05-05", "#calendar:title": "myTitle" },
|
||||||
{ title: "Note 2", "#startDate": "2025-05-07", "#calendar:title": "~myTitle" },
|
{ title: "Note 2", "#startDate": "2025-05-07", "#calendar:title": "myTitle" },
|
||||||
]);
|
]);
|
||||||
const events = await CalendarView.buildEvents(noteIds);
|
const events = await CalendarView.buildEvents(noteIds);
|
||||||
|
|
||||||
@ -100,23 +100,9 @@ describe("Building events", () => {
|
|||||||
|
|
||||||
it("supports relation as custom title with custom label", async () => {
|
it("supports relation as custom title with custom label", async () => {
|
||||||
const noteIds = buildNotes([
|
const noteIds = buildNotes([
|
||||||
{ id: "mySharedTitle", title: "My custom title", "#myTitle": "My shared custom title", "#calendar:title": "#myTitle" },
|
{ id: "mySharedTitle", title: "My custom title", "#myTitle": "My shared custom title", "#calendar:title": "myTitle" },
|
||||||
{ title: "Note 1", "~myTitle": "mySharedTitle", "#startDate": "2025-05-05", "#calendar:title": "~myTitle" },
|
{ title: "Note 1", "~myTitle": "mySharedTitle", "#startDate": "2025-05-05", "#calendar:title": "myTitle" },
|
||||||
{ title: "Note 2", "#startDate": "2025-05-07", "#calendar:title": "~myTitle" },
|
{ title: "Note 2", "#startDate": "2025-05-07", "#calendar:title": "myTitle" },
|
||||||
]);
|
|
||||||
const events = await CalendarView.buildEvents(noteIds);
|
|
||||||
|
|
||||||
expect(events).toHaveLength(2);
|
|
||||||
expect(events[0]).toMatchObject({ title: "My shared custom title", start: "2025-05-05" });
|
|
||||||
expect(events[1]).toMatchObject({ title: "Note 2", start: "2025-05-07" });
|
|
||||||
});
|
|
||||||
|
|
||||||
it("discards relation as custom title with custom relation", async () => {
|
|
||||||
const noteIds = buildNotes([
|
|
||||||
{ id: "myParentNote", title: "My parent note" },
|
|
||||||
{ id: "mySharedTitle", title: "My custom title", "~myTitle": "myParentNote", "#calendar:title": "~myTitle" },
|
|
||||||
{ title: "Note 1", "~myTitle": "mySharedTitle", "#startDate": "2025-05-05", "#calendar:title": "~myTitle" },
|
|
||||||
{ title: "Note 2", "#startDate": "2025-05-07", "#calendar:title": "~myTitle" },
|
|
||||||
]);
|
]);
|
||||||
const events = await CalendarView.buildEvents(noteIds);
|
const events = await CalendarView.buildEvents(noteIds);
|
||||||
|
|
||||||
@ -135,15 +121,15 @@ describe("Promoted attributes", () => {
|
|||||||
"#mood": "happy",
|
"#mood": "happy",
|
||||||
"#label:weight": "promoted,number,single,precision=1",
|
"#label:weight": "promoted,number,single,precision=1",
|
||||||
"#label:mood": "promoted,alias=Mood,single,text",
|
"#label:mood": "promoted,alias=Mood,single,text",
|
||||||
"#calendar:promotedAttributes": "label:weight,label:mood"
|
"#calendar:displayedAttributes": "weight,mood"
|
||||||
});
|
});
|
||||||
|
|
||||||
const event = await CalendarView.buildEvent(note, "2025-04-04");
|
const event = await CalendarView.buildEvent(note, "2025-04-04");
|
||||||
expect(event).toHaveLength(1);
|
expect(event).toHaveLength(1);
|
||||||
expect(event[0]?.promotedAttributes).toMatchObject({
|
expect(event[0]?.promotedAttributes).toMatchObject([
|
||||||
weight: "75",
|
[ "weight", "75" ],
|
||||||
Mood: "happy"
|
[ "mood", "happy" ]
|
||||||
})
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("supports relations", async () => {
|
it("supports relations", async () => {
|
||||||
@ -152,14 +138,14 @@ describe("Promoted attributes", () => {
|
|||||||
"~assignee": buildNote({
|
"~assignee": buildNote({
|
||||||
"title": "Target note"
|
"title": "Target note"
|
||||||
}).noteId,
|
}).noteId,
|
||||||
"#calendar:promotedAttributes": "relation:assignee",
|
"#calendar:displayedAttributes": "assignee",
|
||||||
"#relation:assignee": "promoted,alias=Assignee,single,text",
|
"#relation:assignee": "promoted,alias=Assignee,single,text",
|
||||||
});
|
});
|
||||||
|
|
||||||
const event = await CalendarView.buildEvent(note, "2025-04-04");
|
const event = await CalendarView.buildEvent(note, "2025-04-04");
|
||||||
expect(event).toHaveLength(1);
|
expect(event).toHaveLength(1);
|
||||||
expect(event[0]?.promotedAttributes).toMatchObject({
|
expect(event[0]?.promotedAttributes).toMatchObject([
|
||||||
"Assignee": "Target note"
|
[ "assignee", "Target note" ]
|
||||||
})
|
])
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1733,6 +1733,7 @@ footer.file-footer button {
|
|||||||
margin-right: 14px;
|
margin-right: 14px;
|
||||||
position: relative;
|
position: relative;
|
||||||
padding-left: 2.5em;
|
padding-left: 2.5em;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ck-content .admonition p:last-child {
|
.ck-content .admonition p:last-child {
|
||||||
|
@ -272,7 +272,7 @@ describe("data_dir.ts unit tests", async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("#getDataDirs()", () => {
|
describe("#getDataDirs()", () => {
|
||||||
const envKeys: Omit<keyof ReturnType<typeof getDataDirs>, "TRILIUM_DATA_DIR">[] = ["DOCUMENT_PATH", "BACKUP_DIR", "LOG_DIR", "ANONYMIZED_DB_DIR", "CONFIG_INI_PATH"];
|
const envKeys: Omit<keyof ReturnType<typeof getDataDirs>, "TRILIUM_DATA_DIR">[] = ["DOCUMENT_PATH", "BACKUP_DIR", "LOG_DIR", "ANONYMIZED_DB_DIR", "CONFIG_INI_PATH", "TMP_DIR"];
|
||||||
|
|
||||||
const setMockedEnv = (prefix: string | null) => {
|
const setMockedEnv = (prefix: string | null) => {
|
||||||
envKeys.forEach((key) => {
|
envKeys.forEach((key) => {
|
||||||
|
@ -40,12 +40,7 @@ describe("markdown", () => {
|
|||||||
# another one
|
# another one
|
||||||
Hello, world
|
Hello, world
|
||||||
`, "title");
|
`, "title");
|
||||||
expect(result).toBe(trimIndentation`\
|
expect(result).toBe(`<h2>Hello</h2><h2>world</h2><h2>another one</h2><p>Hello, world</p>`);
|
||||||
<h2>Hello</h2>
|
|
||||||
<h2>world</h2>
|
|
||||||
<h2>another one</h2>
|
|
||||||
<p>Hello, world</p>
|
|
||||||
`);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@ -54,7 +49,7 @@ describe("markdown", () => {
|
|||||||
# What's new
|
# What's new
|
||||||
Hi there
|
Hi there
|
||||||
`, "What's new")
|
`, "What's new")
|
||||||
expect(result).toBe(`\n<p>Hi there</p>\n`);
|
expect(result).toBe(`<p>Hi there</p>`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("trims unnecessary whitespace", () => {
|
it("trims unnecessary whitespace", () => {
|
||||||
@ -67,10 +62,16 @@ Title
|
|||||||
code block 1
|
code block 1
|
||||||
second line 2
|
second line 2
|
||||||
\`\`\`
|
\`\`\`
|
||||||
|
|
||||||
|
* Hello
|
||||||
|
* world
|
||||||
|
|
||||||
|
1. Hello
|
||||||
|
2. World
|
||||||
`;
|
`;
|
||||||
const expected = `\
|
const expected = `\
|
||||||
<h2>Heading 1</h2><p>Title</p><pre><code class="language-text-x-trilium-auto">code block 1
|
<h2>Heading 1</h2><p>Title</p><pre><code class="language-text-x-trilium-auto">code block 1
|
||||||
second line 2</code></pre>`;
|
second line 2</code></pre><ul><li>Hello</li><li>world</li></ul><ol><li>Hello</li><li>World</li></ol>`;
|
||||||
expect(markdownService.renderToHtml(input, "Troubleshooting")).toBe(expected);
|
expect(markdownService.renderToHtml(input, "Troubleshooting")).toBe(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -98,7 +99,7 @@ second line 2</code></pre>`;
|
|||||||
|
|
||||||
After`;
|
After`;
|
||||||
const expected = `<p>Before</p><aside class="admonition note"><p>This is a note.</p></aside><aside class="admonition tip"><p>This is a tip.</p></aside><aside class="admonition important"><p>This is a very important information.</p></aside><aside class="admonition caution"><p>This is a caution.</p></aside><aside class="admonition warning"><h2>Title goes here</h2><p>This is a warning.</p></aside><p>After</p>`;
|
const expected = `<p>Before</p><aside class="admonition note"><p>This is a note.</p></aside><aside class="admonition tip"><p>This is a tip.</p></aside><aside class="admonition important"><p>This is a very important information.</p></aside><aside class="admonition caution"><p>This is a caution.</p></aside><aside class="admonition warning"><h2>Title goes here</h2><p>This is a warning.</p></aside><p>After</p>`;
|
||||||
expect(markdownService.renderToHtml(input, "Title")).toBe(expected);
|
expect(markdownService.renderToHtml(input, "Title")).toStrictEqual(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -1,36 +1,61 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
import { parse, Renderer, type Tokens } from "marked";
|
import { parse, Renderer, type Tokens } from "marked";
|
||||||
import { minify as minifyHtml } from "html-minifier";
|
|
||||||
|
|
||||||
// Keep renderer code up to date with https://github.com/markedjs/marked/blob/master/src/Renderer.ts.
|
/**
|
||||||
const renderer = new Renderer({ async: false });
|
* Keep renderer code up to date with https://github.com/markedjs/marked/blob/master/src/Renderer.ts.
|
||||||
renderer.code = ({ text, lang, escaped }: Tokens.Code) => {
|
*/
|
||||||
if (!text) {
|
class CustomMarkdownRenderer extends Renderer {
|
||||||
return "";
|
|
||||||
|
heading(data: Tokens.Heading): string {
|
||||||
|
return super.heading(data).trimEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
const ckEditorLanguage = getNormalizedMimeFromMarkdownLanguage(lang);
|
paragraph(data: Tokens.Paragraph): string {
|
||||||
return `<pre><code class="language-${ckEditorLanguage}">${text}</code></pre>`;
|
return super.paragraph(data).trimEnd();
|
||||||
};
|
}
|
||||||
renderer.blockquote = ({ tokens }: Tokens.Blockquote) => {
|
|
||||||
const body = renderer.parser.parse(tokens);
|
|
||||||
|
|
||||||
const admonitionMatch = /^<p>\[\!([A-Z]+)\]/.exec(body);
|
code({ text, lang }: Tokens.Code): string {
|
||||||
if (Array.isArray(admonitionMatch) && admonitionMatch.length === 2) {
|
if (!text) {
|
||||||
const type = admonitionMatch[1].toLowerCase();
|
return "";
|
||||||
|
|
||||||
if (ADMONITION_TYPE_MAPPINGS[type]) {
|
|
||||||
const bodyWithoutHeader = body
|
|
||||||
.replace(/^<p>\[\!([A-Z]+)\]/, "<p>")
|
|
||||||
.replace(/^<p><\/p>/, ""); // Having a heading will generate an empty paragraph that we need to remove.
|
|
||||||
|
|
||||||
return `<aside class="admonition ${type}">\n${bodyWithoutHeader}</aside>\n`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ckEditorLanguage = getNormalizedMimeFromMarkdownLanguage(lang);
|
||||||
|
return `<pre><code class="language-${ckEditorLanguage}">${text}</code></pre>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return `<blockquote>\n${body}</blockquote>\n`;
|
list(token: Tokens.List): string {
|
||||||
};
|
return super.list(token)
|
||||||
|
.replace("\n", "") // we replace the first one only.
|
||||||
|
.trimEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
listitem(item: Tokens.ListItem): string {
|
||||||
|
return super.listitem(item).trimEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote({ tokens }: Tokens.Blockquote): string {
|
||||||
|
const body = renderer.parser.parse(tokens);
|
||||||
|
|
||||||
|
const admonitionMatch = /^<p>\[\!([A-Z]+)\]/.exec(body);
|
||||||
|
if (Array.isArray(admonitionMatch) && admonitionMatch.length === 2) {
|
||||||
|
const type = admonitionMatch[1].toLowerCase();
|
||||||
|
|
||||||
|
if (ADMONITION_TYPE_MAPPINGS[type]) {
|
||||||
|
const bodyWithoutHeader = body
|
||||||
|
.replace(/^<p>\[\!([A-Z]+)\]\s*/, "<p>")
|
||||||
|
.replace(/^<p><\/p>/, ""); // Having a heading will generate an empty paragraph that we need to remove.
|
||||||
|
|
||||||
|
return `<aside class="admonition ${type}">${bodyWithoutHeader.trim()}</aside>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return `<blockquote>${body}</blockquote>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const renderer = new CustomMarkdownRenderer({ async: false });
|
||||||
|
|
||||||
import htmlSanitizer from "../html_sanitizer.js";
|
import htmlSanitizer from "../html_sanitizer.js";
|
||||||
import importUtils from "./utils.js";
|
import importUtils from "./utils.js";
|
||||||
@ -46,9 +71,6 @@ function renderToHtml(content: string, title: string) {
|
|||||||
// h1 handling needs to come before sanitization
|
// h1 handling needs to come before sanitization
|
||||||
html = importUtils.handleH1(html, title);
|
html = importUtils.handleH1(html, title);
|
||||||
html = htmlSanitizer.sanitize(html);
|
html = htmlSanitizer.sanitize(html);
|
||||||
html = minifyHtml(html, {
|
|
||||||
collapseWhitespace: true
|
|
||||||
});
|
|
||||||
|
|
||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ describe("processNoteContent", () => {
|
|||||||
it("supports markdown note with UTF-16", async () => {
|
it("supports markdown note with UTF-16", async () => {
|
||||||
const { importedNote } = await testImport("UTF-16LE Text Note.md", "text/markdown");
|
const { importedNote } = await testImport("UTF-16LE Text Note.md", "text/markdown");
|
||||||
expect(importedNote.mime).toBe("text/html");
|
expect(importedNote.mime).toBe("text/html");
|
||||||
expect(importedNote.getContent().toString()).toBe("<h2>Hello world</h2>\n<p>Plain text goes here.</p>\n");
|
expect(importedNote.getContent().toString()).toBe("<h2>Hello world</h2><p>Plain text goes here.</p>");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("supports excalidraw note", async () => {
|
it("supports excalidraw note", async () => {
|
||||||
|
@ -13,9 +13,9 @@ export function getHelpHiddenSubtreeData() {
|
|||||||
const appDir = path.join(srcRoot, "public", isDev ? "app" : "app-dist");
|
const appDir = path.join(srcRoot, "public", isDev ? "app" : "app-dist");
|
||||||
const helpDir = path.join(appDir, "doc_notes", "en", "User Guide");
|
const helpDir = path.join(appDir, "doc_notes", "en", "User Guide");
|
||||||
const metaFilePath = path.join(helpDir, "!!!meta.json");
|
const metaFilePath = path.join(helpDir, "!!!meta.json");
|
||||||
const metaFileContent = JSON.parse(fs.readFileSync(metaFilePath).toString("utf-8"));
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const metaFileContent = JSON.parse(fs.readFileSync(metaFilePath).toString("utf-8"));
|
||||||
return parseNoteMetaFile(metaFileContent as NoteMetaFile);
|
return parseNoteMetaFile(metaFileContent as NoteMetaFile);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn(e);
|
console.warn(e);
|
||||||
|
@ -27,6 +27,7 @@ describe("Share API test", () => {
|
|||||||
it("requests password for password-protected share", async () => {
|
it("requests password for password-protected share", async () => {
|
||||||
await supertest(app)
|
await supertest(app)
|
||||||
.get("/share/YjlPRj2E9fOV")
|
.get("/share/YjlPRj2E9fOV")
|
||||||
|
.expect(401)
|
||||||
.expect("WWW-Authenticate", 'Basic realm="User Visible Realm", charset="UTF-8"');
|
.expect("WWW-Authenticate", 'Basic realm="User Visible Realm", charset="UTF-8"');
|
||||||
expect(cannotSetHeadersCount).toBe(0);
|
expect(cannotSetHeadersCount).toBe(0);
|
||||||
});
|
});
|
||||||
|
@ -131,6 +131,7 @@ function renderImageAttachment(image: SNote, res: Response, attachmentName: stri
|
|||||||
function register(router: Router) {
|
function register(router: Router) {
|
||||||
function renderNote(note: SNote, req: Request, res: Response) {
|
function renderNote(note: SNote, req: Request, res: Response) {
|
||||||
if (!note) {
|
if (!note) {
|
||||||
|
console.log("Unable to find note ", note);
|
||||||
res.status(404).render("share/404");
|
res.status(404).render("share/404");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user