Merge branch 'main' of https://github.com/TriliumNext/Trilium into feat/ui-improvements

This commit is contained in:
Adorian Doran 2025-11-02 23:00:20 +02:00
commit e6d2009605
15 changed files with 124 additions and 55 deletions

View File

@ -10,7 +10,7 @@ export const byNoteType: Record<Exclude<NoteType, "book">, string | null> = {
file: null,
image: null,
launcher: null,
mermaid: null,
mermaid: "s1aBHPd79XYj",
mindMap: null,
noteMap: null,
relationMap: null,

View File

@ -1450,10 +1450,6 @@
"etapi": {
"title": "ETAPI",
"description": "ETAPI is a REST API used to access Trilium instance programmatically, without UI.",
"see_more": "See more details in the {{- link_to_wiki}} and the {{- link_to_openapi_spec}} or the {{- link_to_swagger_ui }}.",
"wiki": "wiki",
"openapi_spec": "ETAPI OpenAPI spec",
"swagger_ui": "ETAPI Swagger UI",
"create_token": "Create new ETAPI token",
"existing_tokens": "Existing tokens",
"no_tokens_yet": "There are no tokens yet. Click on the button above to create one.",

View File

@ -2,7 +2,7 @@ import type { ComponentChildren } from "preact";
import { CSSProperties } from "preact/compat";
interface OptionsSectionProps {
title?: string;
title?: ComponentChildren;
children: ComponentChildren;
noCard?: boolean;
style?: CSSProperties;

View File

@ -11,6 +11,7 @@ import dialog from "../../../services/dialog";
import { formatDateTime } from "../../../utils/formatters";
import ActionButton from "../../react/ActionButton";
import { useTriliumEvent } from "../../react/hooks";
import HelpButton from "../../react/HelpButton";
type RenameTokenCallback = (tokenId: string, oldName: string) => Promise<void>;
type DeleteTokenCallback = (tokenId: string, name: string ) => Promise<void>;
@ -48,19 +49,13 @@ export default function EtapiSettings() {
message: t("etapi.token_created_message"),
defaultValue: authToken
});
}, []);
}, []);
return (
<OptionsSection title={t("etapi.title")}>
<FormText>
{t("etapi.description")}<br />
<RawHtml
html={t("etapi.see_more", {
link_to_wiki: `<a class="tn-link" href="https://triliumnext.github.io/Docs/Wiki/etapi.html">${t("etapi.wiki")}</a>`,
// TODO: We use window.open src/public/app/services/link.ts -> prevents regular click behavior on "a" element here because it's a relative path
link_to_openapi_spec: `<a class="tn-link" onclick="window.open('etapi/etapi.openapi.yaml')" href="etapi/etapi.openapi.yaml">${t("etapi.openapi_spec")}</a>`,
link_to_swagger_ui: `<a class="tn-link" href="#_help_f3xpgx6H01PW">${t("etapi.swagger_ui")}</a>`
})} />
{t("etapi.description")}
<HelpButton helpPage="pgxEVkzLl1OP" />
</FormText>
<Button
@ -68,6 +63,7 @@ export default function EtapiSettings() {
text={t("etapi.create_token")}
onClick={createTokenCallback}
/>
<hr />
<h5>{t("etapi.existing_tokens")}</h5>
@ -123,7 +119,7 @@ function TokenList({ tokens }: { tokens: EtapiToken[] }) {
text={t("etapi.rename_token")}
onClick={() => renameCallback(etapiTokenId, name)}
/>
<ActionButton
icon="bx bx-trash"
text={t("etapi.delete_token")}

File diff suppressed because one or more lines are too long

View File

@ -1,11 +1,13 @@
<aside class="admonition tip">
<p>For a quick start, consult the&nbsp;<a class="reference-link" href="#root/pgxEVkzLl1OP/_help_9qPsTWBorUhQ">API Reference</a>.</p>
</aside>
<p>ETAPI is Trilium's public/external REST API. It is available since Trilium
v0.50.</p>
<p>The documentation is in OpenAPI format, available <a href="https://github.com/TriliumNext/Trilium/blob/master/src/etapi/etapi.openapi.yaml">here</a>.</p>
<h2>API clients</h2>
<p>As an alternative to calling the API directly, there are client libraries
to simplify this</p>
<ul>
<li><a href="https://github.com/Nriver/trilium-py">trilium-py</a>, you can
<li data-list-item-id="e3342ddfa108f6c8c6c47d7d3da8b02fa"><a href="https://github.com/Nriver/trilium-py">trilium-py</a>, you can
use Python to communicate with Trilium.</li>
</ul>
<h2>Obtaining a token</h2>
@ -23,10 +25,10 @@ Authorization: ETAPITOKEN</code></pre>
<p>Since v0.56 you can also use basic auth format:</p><pre><code class="language-text-x-trilium-auto">GET https://myserver.com/etapi/app-info
Authorization: Basic BATOKEN</code></pre>
<ul>
<li>Where <code>BATOKEN = BASE64(username + ':' + password)</code> - this is
<li data-list-item-id="ec59ac570a3d2a846da38378a5f2428ed">Where <code>BATOKEN = BASE64(username + ':' + password)</code> - this is
a standard Basic Auth serialization</li>
<li>Where <code>username</code> is "etapi"</li>
<li>And <code>password</code> is the generated ETAPI token described above.</li>
<li data-list-item-id="e18e2e73ebecc949dd4a51cd9f8bb0b91">Where <code>username</code> is "etapi"</li>
<li data-list-item-id="ee892223f95cef4a53caec5477ab31edb">And <code>password</code> is the generated ETAPI token described above.</li>
</ul>
<p>Basic Auth is meant to be used with tools which support only basic auth.</p>
<h2>Interaction using Bash scripts</h2>
@ -42,10 +44,10 @@ NOTE_ID="i6ra4ZshJhgN"
curl "$SERVER/etapi/notes/$NOTE_ID/content" -H "Authorization: $TOKEN" </code></pre>
<p>Make sure to replace the values of:</p>
<ul>
<li><code>TOKEN</code> with your ETAPI token.</li>
<li><code>SERVER</code> with the correct protocol, host name and port to your
<li data-list-item-id="e68020f83acc951e180bb405d149a64a5"><code>TOKEN</code> with your ETAPI token.</li>
<li data-list-item-id="ef4c31df5f6d18811e7de0ee8ff95f3a7"><code>SERVER</code> with the correct protocol, host name and port to your
Trilium instance.</li>
<li><code>NOTE_ID</code> with an existing note ID to download.</li>
<li data-list-item-id="e25086bb4c54d32259f987f9366e22204"><code>NOTE_ID</code> with an existing note ID to download.</li>
</ul>
<p>As another example, to obtain a .zip export of a note and place it in
a directory called <code>out</code>, simply replace the last statement in

View File

@ -1,3 +1,8 @@
<aside class="admonition tip">
<p>For a quick understanding of the Mermaid syntax, see&nbsp;<a class="reference-link"
href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/s1aBHPd79XYj/_help_WWgeUaBb7UfC">Syntax reference</a>&nbsp;(official
documentation).</p>
</aside>
<figure class="image image-style-align-center">
<img style="aspect-ratio:886/663;" src="2_Mermaid Diagrams_image.png"
width="886" height="663">
@ -6,14 +11,13 @@
as flowchart, sequence diagram, class diagram, state diagram, pie charts,
etc., all using a text description of the chart instead of manually drawing
the diagram.</p>
<p>For the official documentation of Mermaid.js see <a href="https://mermaid.js.org/intro/">mermaid.js.org/intro/</a>.</p>
<h2>Layouts</h2>
<p>Depending on the chart being edited and user preference, there are two
layouts supported by the Mermaid note type:</p>
<ul>
<li>Horizontal, where the source code (editable part) is on the left side
<li data-list-item-id="e5998f20495a1079ee7b6e284dc4d14e4">Horizontal, where the source code (editable part) is on the left side
of the screen and the preview is to the right.</li>
<li>Vertical, where the source code is at the bottom of the screen and the
<li data-list-item-id="ebebfbd8cf2125c70056e3e9075d8681e">Vertical, where the source code is at the bottom of the screen and the
preview is at the top.</li>
</ul>
<p>It's possible to switch between the two layouts at any time by pressing
@ -21,44 +25,48 @@
<img src="Mermaid Diagrams_image.png">icon in the&nbsp;<a class="reference-link" href="#root/_help_XpOYSgsLkTJy">Floating buttons</a>&nbsp;area.</p>
<h2>Interaction</h2>
<ul>
<li>The source code of the diagram (in Mermaid format) is displayed on the
<li data-list-item-id="e67d8f093c4793e19e2ade2d58728ae81">The source code of the diagram (in Mermaid format) is displayed on the
left or bottom side of the note (depending on the layout).
<ul>
<li>Changing the diagram code will refresh automatically the diagram.</li>
<li data-list-item-id="e4d777ef787093815b961d734021ccc55">Changing the diagram code will refresh automatically the diagram.</li>
</ul>
</li>
<li>The preview of the diagram is displayed at the right or top side of the
<li data-list-item-id="e6faf589831e3252f8cda42f62248377a">The preview of the diagram is displayed at the right or top side of the
note (depending on the layout):
<ul>
<li>There are dedicated buttons at the bottom-right of the preview to control
<li data-list-item-id="e1dc5994137e511eb29657629d9e729a3">There are dedicated buttons at the bottom-right of the preview to control
the zoom in, zoom out or re-center the diagram:
<img src="1_Mermaid Diagrams_image.png">
</li>
<li>The preview can be moved around by holding the left mouse button and dragging.</li>
<li>Zooming can also be done by using the scroll wheel.</li>
<li>The zoom and position on the preview will remain fixed as the diagram
changes, to be able to work more easily with large diagrams.</li>
</ul>
<li data-list-item-id="e51812ca016db170ceb6814007a60eb10">The preview can be moved around by holding the left mouse button and dragging.</li>
<li
data-list-item-id="e617128e494ed43ca5d0f5c749a8c9208">Zooming can also be done by using the scroll wheel.</li>
<li data-list-item-id="e7b87c55d329003996861f24d8d162b85">The zoom and position on the preview will remain fixed as the diagram
changes, to be able to work more easily with large diagrams.</li>
</ul>
</li>
<li>The size of the source/preview panes can be adjusted by hovering over
<li data-list-item-id="e11cf4ecd9d2408ce5a46b949dea40b06">The size of the source/preview panes can be adjusted by hovering over
the border between them and dragging it with the mouse.</li>
<li>In the&nbsp;<a class="reference-link" href="#root/_help_XpOYSgsLkTJy">Floating buttons</a>&nbsp;area:
<li data-list-item-id="ebc96b0fe8366ef4e00561de1c866d53b">In the&nbsp;<a class="reference-link" href="#root/_help_XpOYSgsLkTJy">Floating buttons</a>&nbsp;area:
<ul>
<li>The source/preview can be laid out left-right or bottom-top via the <em>Move editing pane to the left / bottom</em> option.</li>
<li>Press <em>Lock editing</em> to automatically mark the note as read-only.
<li data-list-item-id="e12f31dc31db3c8be1fe87822ca2f451e">The source/preview can be laid out left-right or bottom-top via the <em>Move editing pane to the left / bottom</em> option.</li>
<li
data-list-item-id="ed29e7616e6c77105103a68b1e8a6f7b3">Press <em>Lock editing</em> to automatically mark the note as read-only.
In this mode, the code pane is hidden and the diagram is displayed full-size.
Similarly, press <em>Unlock editing</em> to mark a read-only note as editable.</li>
<li>Press the <em>Copy image reference to the clipboard</em> to be able to insert
the image representation of the diagram into a text note. See&nbsp;<a class="reference-link"
href="#root/_help_0Ofbk1aSuVRu">Image references</a>&nbsp;for more information.</li>
<li>Press the <em>Export diagram as SVG</em> to download a scalable/vector rendering
of the diagram. Can be used to present the diagram without degrading when
zooming.</li>
<li>Press the <em>Export diagram as PNG</em> to download a normal image (at
<li
data-list-item-id="e2bc7d5d8d1f8f02e61a6d86a3faae3b4">Press the <em>Copy image reference to the clipboard</em> to be able to insert
the image representation of the diagram into a text note. See&nbsp;<a class="reference-link"
href="#root/_help_0Ofbk1aSuVRu">Image references</a>&nbsp;for more information.</li>
<li
data-list-item-id="ecaac01dc52bce394f720be2826e82026">Press the <em>Export diagram as SVG</em> to download a scalable/vector rendering
of the diagram. Can be used to present the diagram without degrading when
zooming.</li>
<li data-list-item-id="e9c815090884a394d60e06628b9e38add">Press the <em>Export diagram as PNG</em> to download a normal image (at
1x scale, raster) of the diagram. Can be used to send the diagram in more
traditional channels such as e-mail.</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2>Errors in the diagram</h2>
<p>If there is an error in the source code, the error will be displayed in

View File

@ -98,6 +98,21 @@ describe("Hidden Subtree", () => {
expect(updatedBoardTemplate?.title).not.toBe("My renamed board");
});
it("enforces webviewSrc of templates", () => {
const apiRefNote = becca.getNote("_help_9qPsTWBorUhQ");
expect(apiRefNote).toBeDefined();
cls.init(() => {
apiRefNote!.setAttribute("label", "webViewSrc", "foo");
apiRefNote!.save();
hiddenSubtreeService.checkHiddenSubtree(true);
});
const updatedApiRefNote = becca.getNote("_help_9qPsTWBorUhQ");
expect(updatedApiRefNote).toBeDefined();
expect(updatedApiRefNote?.getLabelValue("webViewSrc")).not.toBe("foo");
});
it("maintains launchers hidden, if they were shown by default but moved by the user", () => {
const launcher = becca.getNote("_lbLlmChat");
const branch = launcher?.getParentBranches()[0];

View File

@ -451,8 +451,16 @@ function checkHiddenSubtreeRecursively(parentNoteId: string, item: HiddenSubtree
// Enforce attribute structure if needed.
if (item.enforceAttributes) {
for (const attribute of note.getAttributes()) {
if (!attrs.some(a => a.name === attribute.name)) {
// Remove unwanted attributes.
const attrDef = attrs.find(a => a.name === attribute.name);
if (!attrDef) {
attribute.markAsDeleted();
continue;
}
// Ensure value is consistent.
if (attribute.value !== attrDef.value) {
note.setAttributeValueById(attribute.attributeId, attrDef.value);
}
}
}

View File

@ -78,6 +78,7 @@ export function parseNoteMeta(noteMeta: NoteMeta, docNameRoot: string): HiddenSu
// Handle web views
if (noteMeta.type === "webView") {
item.type = "webView";
item.enforceAttributes = true;
}
// Handle children

View File

@ -8838,6 +8838,13 @@
"value": "bx bx-selection",
"isInheritable": false,
"position": 20
},
{
"type": "relation",
"name": "internalLink",
"value": "WWgeUaBb7UfC",
"isInheritable": false,
"position": 30
}
],
"format": "markdown",
@ -8921,6 +8928,33 @@
"dataFileName": "ELK layout_ELK on.svg"
}
]
},
{
"isClone": false,
"noteId": "WWgeUaBb7UfC",
"notePath": [
"pOsGYCXsbNQG",
"KSZ04uQ2D1St",
"s1aBHPd79XYj",
"WWgeUaBb7UfC"
],
"title": "Syntax reference",
"notePosition": 40,
"prefix": null,
"isExpanded": false,
"type": "webView",
"mime": "",
"attributes": [
{
"type": "label",
"name": "webViewSrc",
"value": "https://mermaid.js.org/intro/syntax-reference.html",
"isInheritable": false,
"position": 10
}
],
"dataFileName": "Syntax reference.dat",
"attachments": []
}
]
},
@ -12568,6 +12602,13 @@
"value": "bx bx-extension",
"isInheritable": false,
"position": 30
},
{
"type": "relation",
"name": "internalLink",
"value": "9qPsTWBorUhQ",
"isInheritable": false,
"position": 40
}
],
"format": "markdown",

View File

@ -1,7 +1,8 @@
# ETAPI (REST API)
ETAPI is Trilium's public/external REST API. It is available since Trilium v0.50.
> [!TIP]
> For a quick start, consult the <a class="reference-link" href="ETAPI%20(REST%20API)/API%20Reference.dat">API Reference</a>.
The documentation is in OpenAPI format, available [here](https://github.com/TriliumNext/Trilium/blob/master/src/etapi/etapi.openapi.yaml).
ETAPI is Trilium's public/external REST API. It is available since Trilium v0.50.
## API clients

View File

@ -1,10 +1,11 @@
# Mermaid Diagrams
> [!TIP]
> For a quick understanding of the Mermaid syntax, see <a class="reference-link" href="Mermaid%20Diagrams/Syntax%20reference.dat">Syntax reference</a> (official documentation).
<figure class="image image-style-align-center"><img style="aspect-ratio:886/663;" src="2_Mermaid Diagrams_image.png" width="886" height="663"></figure>
Trilium supports Mermaid, which adds support for various diagrams such as flowchart, sequence diagram, class diagram, state diagram, pie charts, etc., all using a text description of the chart instead of manually drawing the diagram.
For the official documentation of Mermaid.js see [mermaid.js.org/intro/](https://mermaid.js.org/intro/).
## Layouts
Depending on the chart being edited and user preference, there are two layouts supported by the Mermaid note type: